blob: 96828de46d9bc3ece3521bd309503f50e8b6806c [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 Lama7f454d2014-07-24 12:04:06 -070023 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
Gopichand Nakkala92f07d82013-01-08 21:16:34 -080026 */
Kiet Lam842dad02014-02-18 18:44:02 -080027
28
Kiet Lama7f454d2014-07-24 12:04:06 -070029
30
Jeff Johnson295189b2012-06-20 16:38:30 -070031/*========================================================================
32
33 \file wlan_hdd_main.c
34
35 \brief WLAN Host Device Driver implementation
36
37 Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved.
38
39 Qualcomm Confidential and Proprietary.
40
41 ========================================================================*/
42
43/**=========================================================================
44
45 EDIT HISTORY FOR FILE
46
47
48 This section contains comments describing changes made to the module.
49 Notice that changes are listed in reverse chronological order.
50
51
52 $Header:$ $DateTime: $ $Author: $
53
54
55 when who what, where, why
56 -------- --- --------------------------------------------------------
57 04/5/09 Shailender Created module.
58 02/24/10 Sudhir.S.Kohalli Added to support param for SoftAP module
59 06/03/10 js - Added support to hostapd driven deauth/disassoc/mic failure
60 ==========================================================================*/
61
62/*--------------------------------------------------------------------------
63 Include Files
64 ------------------------------------------------------------------------*/
65//#include <wlan_qct_driver.h>
66#include <wlan_hdd_includes.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070067#include <vos_api.h>
68#include <vos_sched.h>
69#include <vos_power.h>
70#include <linux/etherdevice.h>
71#include <linux/firmware.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070072#ifdef ANI_BUS_TYPE_PLATFORM
73#include <linux/wcnss_wlan.h>
74#endif //ANI_BUS_TYPE_PLATFORM
75#ifdef ANI_BUS_TYPE_PCI
76#include "wcnss_wlan.h"
77#endif /* ANI_BUS_TYPE_PCI */
78#include <wlan_hdd_tx_rx.h>
79#include <palTimer.h>
80#include <wniApi.h>
81#include <wlan_nlink_srv.h>
82#include <wlan_btc_svc.h>
83#include <wlan_hdd_cfg.h>
84#include <wlan_ptt_sock_svc.h>
Vinay Krishna Erannad938c422014-03-10 17:14:21 +053085#include <wlan_logging_sock_svc.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070086#include <wlan_hdd_wowl.h>
87#include <wlan_hdd_misc.h>
88#include <wlan_hdd_wext.h>
89#ifdef WLAN_BTAMP_FEATURE
90#include <bap_hdd_main.h>
91#include <bapInternal.h>
92#endif // WLAN_BTAMP_FEATURE
Sushant Kaushik4b7cb302014-01-06 17:45:01 +053093#include "wlan_hdd_trace.h"
94#include "vos_types.h"
95#include "vos_trace.h"
Jeff Johnson295189b2012-06-20 16:38:30 -070096#include <linux/wireless.h>
97#include <net/cfg80211.h>
Vinay Krishna Erannad9cbdb32014-01-16 12:59:10 +053098#include <linux/inetdevice.h>
99#include <net/addrconf.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700100#include "wlan_hdd_cfg80211.h"
101#include "wlan_hdd_p2p.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700102#include <linux/rtnetlink.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700103int wlan_hdd_ftm_start(hdd_context_t *pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700104#include "sapApi.h"
105#include <linux/semaphore.h>
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -0700106#include <linux/ctype.h>
Arun Kumar Khandavalli74fe3032014-03-17 20:35:34 +0530107#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0))
108#include <soc/qcom/subsystem_restart.h>
109#else
Jeff Johnson295189b2012-06-20 16:38:30 -0700110#include <mach/subsystem_restart.h>
Arun Kumar Khandavalli74fe3032014-03-17 20:35:34 +0530111#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700112#include <wlan_hdd_hostapd.h>
113#include <wlan_hdd_softap_tx_rx.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700114#include "cfgApi.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700115#include "wlan_hdd_dev_pwr.h"
116#ifdef WLAN_BTAMP_FEATURE
117#include "bap_hdd_misc.h"
118#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700119#include "wlan_qct_pal_trace.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700120#include "qwlan_version.h"
Yathish9f22e662012-12-10 14:21:35 -0800121#include "wlan_qct_wda.h"
Chilam NG571c65a2013-01-19 12:27:36 +0530122#ifdef FEATURE_WLAN_TDLS
123#include "wlan_hdd_tdls.h"
124#endif
Yue Ma0d4891e2013-08-06 17:01:45 -0700125#include "wlan_hdd_debugfs.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700126
127#ifdef MODULE
128#define WLAN_MODULE_NAME module_name(THIS_MODULE)
129#else
130#define WLAN_MODULE_NAME "wlan"
131#endif
132
133#ifdef TIMER_MANAGER
134#define TIMER_MANAGER_STR " +TIMER_MANAGER"
135#else
136#define TIMER_MANAGER_STR ""
137#endif
138
139#ifdef MEMORY_DEBUG
140#define MEMORY_DEBUG_STR " +MEMORY_DEBUG"
141#else
142#define MEMORY_DEBUG_STR ""
143#endif
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530144#define MAX_WAIT_FOR_ROC_COMPLETION 3
Jeff Johnson295189b2012-06-20 16:38:30 -0700145/* the Android framework expects this param even though we don't use it */
146#define BUF_LEN 20
Jeff Johnson76052702013-04-16 13:55:05 -0700147static char fwpath_buffer[BUF_LEN];
148static struct kparam_string fwpath = {
149 .string = fwpath_buffer,
150 .maxlen = BUF_LEN,
151};
Arif Hussain66559122013-11-21 10:11:40 -0800152
153static char *country_code;
154static int enable_11d = -1;
155static int enable_dfs_chan_scan = -1;
c_hpothu92367912014-05-01 15:18:17 +0530156static int gbcnMissRate = -1;
Arif Hussain66559122013-11-21 10:11:40 -0800157
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700158#ifndef MODULE
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700159static int wlan_hdd_inited;
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700160#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700161
Jeff Johnsone7245742012-09-05 17:12:55 -0700162/*
Jeff Johnson72a40512013-12-19 10:14:15 -0800163 * spinlock for synchronizing asynchronous request/response
164 * (full description of use in wlan_hdd_main.h)
165 */
166DEFINE_SPINLOCK(hdd_context_lock);
167
168/*
Jeff Johnsone7245742012-09-05 17:12:55 -0700169 * The rate at which the driver sends RESTART event to supplicant
170 * once the function 'vos_wlanRestart()' is called
171 *
172 */
173#define WLAN_HDD_RESTART_RETRY_DELAY_MS 5000 /* 5 second */
174#define WLAN_HDD_RESTART_RETRY_MAX_CNT 5 /* 5 retries */
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -0700175
176/*
177 * Size of Driver command strings from upper layer
178 */
179#define SIZE_OF_SETROAMMODE 11 /* size of SETROAMMODE */
180#define SIZE_OF_GETROAMMODE 11 /* size of GETROAMMODE */
181
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -0800182#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda5cecb202013-10-08 09:13:25 -0700183#define TID_MIN_VALUE 0
184#define TID_MAX_VALUE 15
185static VOS_STATUS hdd_get_tsm_stats(hdd_adapter_t *pAdapter, const tANI_U8 tid,
186 tAniTrafStrmMetrics* pTsmMetrics);
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -0800187static VOS_STATUS hdd_parse_ese_beacon_req(tANI_U8 *pValue,
188 tCsrEseBeaconReq *pEseBcnReq);
189#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -0700190
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +0530191static VOS_STATUS wlan_hdd_init_channels_for_cc(hdd_context_t *pHddCtx);
Atul Mittal1d722422014-03-19 11:15:07 +0530192/*
193 * Maximum buffer size used for returning the data back to user space
194 */
195#define WLAN_MAX_BUF_SIZE 1024
196#define WLAN_PRIV_DATA_MAX_LEN 8192
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -0700197
c_hpothu92367912014-05-01 15:18:17 +0530198//wait time for beacon miss rate.
199#define BCN_MISS_RATE_TIME 500
200
Sameer Thalappil50dc0092013-02-19 17:23:33 -0800201#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -0700202static struct wake_lock wlan_wake_lock;
Jeff Johnsone7245742012-09-05 17:12:55 -0700203#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700204/* set when SSR is needed after unload */
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -0700205static e_hdd_ssr_required isSsrRequired = HDD_SSR_NOT_REQUIRED;
Jeff Johnson295189b2012-06-20 16:38:30 -0700206
207//internal function declaration
Jeff Johnsone7245742012-09-05 17:12:55 -0700208static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx);
209static void wlan_hdd_restart_init(hdd_context_t *pHddCtx);
210static void wlan_hdd_restart_deinit(hdd_context_t *pHddCtx);
211void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback);
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800212void hdd_set_wlan_suspend_mode(bool suspend);
Jeff Johnsone7245742012-09-05 17:12:55 -0700213
Jeff Johnson295189b2012-06-20 16:38:30 -0700214v_U16_t hdd_select_queue(struct net_device *dev,
215 struct sk_buff *skb);
216
217#ifdef WLAN_FEATURE_PACKET_FILTERING
218static void hdd_set_multicast_list(struct net_device *dev);
219#endif
220
221void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter);
222
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -0800223#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -0800224void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand);
225static VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels);
Srinivas Girigowda100eb322013-03-15 16:48:20 -0700226static VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid,
227 tANI_U8 *pChannel, tANI_U8 *pDwellTime,
228 tANI_U8 **pBuf, tANI_U8 *pBufLen);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -0700229static VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue,
230 tANI_U8 *pTargetApBssid,
231 tANI_U8 *pChannel);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800232#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -0800233#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda5cecb202013-10-08 09:13:25 -0700234VOS_STATUS hdd_parse_get_cckm_ie(tANI_U8 *pValue, tANI_U8 **pCckmIe, tANI_U8 *pCckmIeLen);
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -0800235#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -0700236
Mihir Shetee1093ba2014-01-21 20:13:32 +0530237static VOS_STATUS wlan_hdd_init_channels(hdd_context_t *pHddCtx);
Sushant Kaushik8bc7df22014-04-09 17:55:29 +0530238const char * hdd_device_modetoString(v_U8_t device_mode)
239{
240 switch(device_mode)
241 {
242 CASE_RETURN_STRING( WLAN_HDD_INFRA_STATION );
243 CASE_RETURN_STRING( WLAN_HDD_SOFTAP );
244 CASE_RETURN_STRING( WLAN_HDD_P2P_CLIENT );
245 CASE_RETURN_STRING( WLAN_HDD_P2P_GO );
246 CASE_RETURN_STRING( WLAN_HDD_MONITOR);
247 CASE_RETURN_STRING( WLAN_HDD_FTM );
248 CASE_RETURN_STRING( WLAN_HDD_IBSS );
249 CASE_RETURN_STRING( WLAN_HDD_P2P_DEVICE );
250 default:
251 return "device_mode Unknown";
252 }
253}
Mihir Shetee1093ba2014-01-21 20:13:32 +0530254
Jeff Johnson295189b2012-06-20 16:38:30 -0700255static int hdd_netdev_notifier_call(struct notifier_block * nb,
256 unsigned long state,
257 void *ndev)
258{
259 struct net_device *dev = ndev;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700260 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson27cee452013-03-27 11:10:24 -0700261 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700262#ifdef WLAN_BTAMP_FEATURE
263 VOS_STATUS status;
Jeff Johnson295189b2012-06-20 16:38:30 -0700264#endif
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +0530265 long result;
Jeff Johnson295189b2012-06-20 16:38:30 -0700266
267 //Make sure that this callback corresponds to our device.
Jeff Johnson27cee452013-03-27 11:10:24 -0700268 if ((strncmp(dev->name, "wlan", 4)) &&
Amar Singhal4c723bd2013-03-25 18:14:15 -0700269 (strncmp(dev->name, "p2p", 3)))
270 return NOTIFY_DONE;
271
Jeff Johnson295189b2012-06-20 16:38:30 -0700272 if (!dev->ieee80211_ptr)
Jeff Johnson27cee452013-03-27 11:10:24 -0700273 return NOTIFY_DONE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700274
Jeff Johnson27cee452013-03-27 11:10:24 -0700275 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -0700276 {
Jeff Johnsona8a1a482012-12-12 16:49:33 -0800277 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Adapter Null Pointer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700278 VOS_ASSERT(0);
279 return NOTIFY_DONE;
280 }
281
Jeff Johnson27cee452013-03-27 11:10:24 -0700282 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
283 if (NULL == pHddCtx)
284 {
285 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Context Null Pointer", __func__);
286 VOS_ASSERT(0);
287 return NOTIFY_DONE;
288 }
Sameer Thalappil14067972014-01-23 14:54:54 -0800289 if (pHddCtx->isLogpInProgress)
290 return NOTIFY_DONE;
291
Jeff Johnson27cee452013-03-27 11:10:24 -0700292
293 hddLog(VOS_TRACE_LEVEL_INFO, "%s: %s New Net Device State = %lu",
294 __func__, dev->name, state);
Jeff Johnson295189b2012-06-20 16:38:30 -0700295
296 switch (state) {
297 case NETDEV_REGISTER:
298 break;
299
300 case NETDEV_UNREGISTER:
301 break;
302
303 case NETDEV_UP:
304 break;
305
306 case NETDEV_DOWN:
307 break;
308
309 case NETDEV_CHANGE:
Jeff Johnsone7245742012-09-05 17:12:55 -0700310 if(TRUE == pAdapter->isLinkUpSvcNeeded)
311 complete(&pAdapter->linkup_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700312 break;
313
314 case NETDEV_GOING_DOWN:
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +0530315 result = wlan_hdd_scan_abort(pAdapter);
Girish Gowli4bf7a632014-06-12 13:42:11 +0530316 if (result < 0)
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +0530317 {
318 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
319 "%s: Timeout occurred while waiting for abortscan %ld",
320 __func__, result);
Jeff Johnson295189b2012-06-20 16:38:30 -0700321 }
322 else
323 {
324 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +0530325 "%s: Scan Abort Successful" , __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700326 }
327#ifdef WLAN_BTAMP_FEATURE
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700328 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: disabling AMP", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700329 status = WLANBAP_StopAmp();
330 if(VOS_STATUS_SUCCESS != status )
331 {
332 pHddCtx->isAmpAllowed = VOS_TRUE;
333 hddLog(VOS_TRACE_LEVEL_FATAL,
334 "%s: Failed to stop AMP", __func__);
335 }
336 else
337 {
338 //a state m/c implementation in PAL is TBD to avoid this delay
339 msleep(500);
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700340 if ( pHddCtx->isAmpAllowed )
341 {
342 WLANBAP_DeregisterFromHCI();
343 pHddCtx->isAmpAllowed = VOS_FALSE;
344 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700345 }
346#endif //WLAN_BTAMP_FEATURE
347 break;
348
349 default:
350 break;
351 }
352
353 return NOTIFY_DONE;
354}
355
356struct notifier_block hdd_netdev_notifier = {
357 .notifier_call = hdd_netdev_notifier_call,
358};
359
360/*---------------------------------------------------------------------------
361 * Function definitions
362 *-------------------------------------------------------------------------*/
Jeff Johnson295189b2012-06-20 16:38:30 -0700363void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx);
364void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -0700365//variable to hold the insmod parameters
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700366static int con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -0700367#ifndef MODULE
368/* current con_mode - used only for statically linked driver
369 * con_mode is changed by userspace to indicate a mode change which will
370 * result in calling the module exit and init functions. The module
371 * exit function will clean up based on the value of con_mode prior to it
372 * being changed by userspace. So curr_con_mode records the current con_mode
373 * for exit when con_mode becomes the next mode for init
374 */
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700375static int curr_con_mode;
Jeff Johnson295189b2012-06-20 16:38:30 -0700376#endif
377
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -0800378/**---------------------------------------------------------------------------
379
380 \brief hdd_vos_trace_enable() - Configure initial VOS Trace enable
381
382 Called immediately after the cfg.ini is read in order to configure
383 the desired trace levels.
384
385 \param - moduleId - module whose trace level is being configured
386 \param - bitmask - bitmask of log levels to be enabled
387
388 \return - void
389
390 --------------------------------------------------------------------------*/
391static void hdd_vos_trace_enable(VOS_MODULE_ID moduleId, v_U32_t bitmask)
392{
393 wpt_tracelevel level;
394
395 /* if the bitmask is the default value, then a bitmask was not
396 specified in cfg.ini, so leave the logging level alone (it
397 will remain at the "compiled in" default value) */
398 if (CFG_VOS_TRACE_ENABLE_DEFAULT == bitmask)
399 {
400 return;
401 }
402
403 /* a mask was specified. start by disabling all logging */
404 vos_trace_setValue(moduleId, VOS_TRACE_LEVEL_NONE, 0);
405
406 /* now cycle through the bitmask until all "set" bits are serviced */
407 level = VOS_TRACE_LEVEL_FATAL;
408 while (0 != bitmask)
409 {
410 if (bitmask & 1)
411 {
412 vos_trace_setValue(moduleId, level, 1);
413 }
414 level++;
415 bitmask >>= 1;
416 }
417}
418
419
Jeff Johnson295189b2012-06-20 16:38:30 -0700420/**---------------------------------------------------------------------------
421
422 \brief hdd_wdi_trace_enable() - Configure initial WDI Trace enable
423
424 Called immediately after the cfg.ini is read in order to configure
425 the desired trace levels in the WDI.
426
427 \param - moduleId - module whose trace level is being configured
428 \param - bitmask - bitmask of log levels to be enabled
429
430 \return - void
431
432 --------------------------------------------------------------------------*/
433static void hdd_wdi_trace_enable(wpt_moduleid moduleId, v_U32_t bitmask)
434{
435 wpt_tracelevel level;
436
437 /* if the bitmask is the default value, then a bitmask was not
438 specified in cfg.ini, so leave the logging level alone (it
439 will remain at the "compiled in" default value) */
440 if (CFG_WDI_TRACE_ENABLE_DEFAULT == bitmask)
441 {
442 return;
443 }
444
445 /* a mask was specified. start by disabling all logging */
446 wpalTraceSetLevel(moduleId, eWLAN_PAL_TRACE_LEVEL_NONE, 0);
447
448 /* now cycle through the bitmask until all "set" bits are serviced */
449 level = eWLAN_PAL_TRACE_LEVEL_FATAL;
450 while (0 != bitmask)
451 {
452 if (bitmask & 1)
453 {
454 wpalTraceSetLevel(moduleId, level, 1);
455 }
456 level++;
457 bitmask >>= 1;
458 }
459}
Jeff Johnson295189b2012-06-20 16:38:30 -0700460
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530461/*
462 * FUNCTION: wlan_hdd_validate_context
463 * This function is used to check the HDD context
464 */
465int wlan_hdd_validate_context(hdd_context_t *pHddCtx)
466{
467 ENTER();
468
469 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
470 {
471 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
472 "%s: HDD context is Null", __func__);
473 return -ENODEV;
474 }
475
476 if (pHddCtx->isLogpInProgress)
477 {
478 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
479 "%s: LOGP in Progress. Ignore!!!", __func__);
480 return -EAGAIN;
481 }
482
Mihir Shete18156292014-03-11 15:38:30 +0530483 if (WLAN_HDD_IS_LOAD_UNLOAD_IN_PROGRESS(pHddCtx))
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530484 {
485 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
486 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
487 return -EAGAIN;
488 }
489 return 0;
490}
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700491#ifdef CONFIG_ENABLE_LINUX_REG
492void hdd_checkandupdate_phymode( hdd_context_t *pHddCtx)
493{
494 hdd_adapter_t *pAdapter = NULL;
495 hdd_station_ctx_t *pHddStaCtx = NULL;
496 eCsrPhyMode phyMode;
497 hdd_config_t *cfg_param = NULL;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530498
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700499 if (NULL == pHddCtx)
500 {
501 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
502 "HDD Context is null !!");
503 return ;
504 }
505
506 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
507 if (NULL == pAdapter)
508 {
509 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
510 "pAdapter is null !!");
511 return ;
512 }
513
514 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
515 if (NULL == pHddStaCtx)
516 {
517 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
518 "pHddStaCtx is null !!");
519 return ;
520 }
521
522 cfg_param = pHddCtx->cfg_ini;
523 if (NULL == cfg_param)
524 {
525 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
526 "cfg_params not available !!");
527 return ;
528 }
529
530 phyMode = sme_GetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter));
531
532 if (!pHddCtx->isVHT80Allowed)
533 {
534 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
535 (eCSR_DOT11_MODE_11ac == phyMode) ||
536 (eCSR_DOT11_MODE_11ac_ONLY == phyMode))
537 {
538 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
539 "Setting phymode to 11n!!");
540 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter), eCSR_DOT11_MODE_11n);
541 }
542 }
543 else
544 {
545 /*New country Supports 11ac as well resetting value back from .ini*/
546 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter),
547 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->dot11Mode));
548 return ;
549 }
550
551 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
552 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode) ||
553 (eCSR_CFG_DOT11_MODE_11AC == pHddStaCtx->conn_info.dot11Mode)))
554 {
555 VOS_STATUS vosStatus;
556
557 // need to issue a disconnect to CSR.
558 INIT_COMPLETION(pAdapter->disconnect_comp_var);
559 vosStatus = sme_RoamDisconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
560 pAdapter->sessionId,
561 eCSR_DISCONNECT_REASON_UNSPECIFIED );
562
563 if (VOS_STATUS_SUCCESS == vosStatus)
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530564 {
565 long ret;
566
567 ret = wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700568 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530569 if (0 >= ret)
570 hddLog(LOGE, FL("failure waiting for disconnect_comp_var %ld"),
571 ret);
572 }
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700573
574 }
575}
576#else
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530577void hdd_checkandupdate_phymode( hdd_adapter_t *pAdapter, char *country_code)
578{
579 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
580 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
581 hdd_config_t *cfg_param;
582 eCsrPhyMode phyMode;
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530583 long ret;
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530584
585 if (NULL == pHddCtx)
586 {
587 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
588 "HDD Context is null !!");
589 return ;
590 }
591
592 cfg_param = pHddCtx->cfg_ini;
593
594 if (NULL == cfg_param)
595 {
596 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
597 "cfg_params not available !!");
598 return ;
599 }
600
601 phyMode = sme_GetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter));
602
603 if (NULL != strstr(cfg_param->listOfNon11acCountryCode, country_code))
604 {
605 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
606 (eCSR_DOT11_MODE_11ac == phyMode) ||
607 (eCSR_DOT11_MODE_11ac_ONLY == phyMode))
608 {
609 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
610 "Setting phymode to 11n!!");
611 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter), eCSR_DOT11_MODE_11n);
612 }
613 }
614 else
615 {
616 /*New country Supports 11ac as well resetting value back from .ini*/
617 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter),
618 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->dot11Mode));
619 return ;
620 }
621
622 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
623 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode) ||
624 (eCSR_CFG_DOT11_MODE_11AC == pHddStaCtx->conn_info.dot11Mode)))
625 {
626 VOS_STATUS vosStatus;
627
628 // need to issue a disconnect to CSR.
629 INIT_COMPLETION(pAdapter->disconnect_comp_var);
630 vosStatus = sme_RoamDisconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
631 pAdapter->sessionId,
632 eCSR_DISCONNECT_REASON_UNSPECIFIED );
633
634 if (VOS_STATUS_SUCCESS == vosStatus)
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530635 {
636 ret = wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530637 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530638 if (ret <= 0)
639 {
640 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
641 "wait on disconnect_comp_var is failed %ld", ret);
642 }
643 }
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530644
645 }
646}
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700647#endif //CONFIG_ENABLE_LINUX_REG
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530648
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700649void hdd_checkandupdate_dfssetting( hdd_adapter_t *pAdapter, char *country_code)
650{
651 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
652 hdd_config_t *cfg_param;
653
654 if (NULL == pHddCtx)
655 {
656 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
657 "HDD Context is null !!");
658 return ;
659 }
660
661 cfg_param = pHddCtx->cfg_ini;
662
663 if (NULL == cfg_param)
664 {
665 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
666 "cfg_params not available !!");
667 return ;
668 }
669
Agarwal Ashish738843c2014-09-25 12:27:56 +0530670 if (NULL != strstr(cfg_param->listOfNonDfsCountryCode, country_code) ||
671 pHddCtx->disable_dfs_flag == TRUE)
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700672 {
673 /*New country doesn't support DFS */
674 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), 0);
675 }
676 else
677 {
678 /*New country Supports DFS as well resetting value back from .ini*/
679 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), cfg_param->enableDFSChnlScan);
680 }
681
682}
683
Rajeev79dbe4c2013-10-05 11:03:42 +0530684#ifdef FEATURE_WLAN_BATCH_SCAN
685
686/**---------------------------------------------------------------------------
687
688 \brief hdd_extract_assigned_int_from_str() - Extracts assigned integer from
689 input string
690
691 This function extracts assigned integer from string in below format:
692 "STRING=10" : extracts integer 10 from this string
693
694 \param - pInPtr Pointer to input string
695 \param - base Base for string to int conversion(10 for decimal 16 for hex)
696 \param - pOutPtr Pointer to variable in which extracted integer needs to be
697 assigned
698 \param - pLastArg to tell whether it is last arguement in input string or
699 not
700
701 \return - NULL for failure cases
702 pointer to next arguement in input string for success cases
703 --------------------------------------------------------------------------*/
704static tANI_U8 *
705hdd_extract_assigned_int_from_str
706(
707 tANI_U8 *pInPtr,
708 tANI_U8 base,
709 tANI_U32 *pOutPtr,
710 tANI_U8 *pLastArg
711)
712{
713 int tempInt;
714 int v = 0;
715 char buf[32];
716 int val = 0;
717 *pLastArg = FALSE;
718
719 pInPtr = strnchr(pInPtr, strlen(pInPtr), EQUALS_TO_ASCII_VALUE);
720 if (NULL == pInPtr)
721 {
722 return NULL;
723 }
724
725 pInPtr++;
726
727 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
728
729 val = sscanf(pInPtr, "%32s ", buf);
730 if (val < 0 && val > strlen(pInPtr))
731 {
732 return NULL;
733 }
734 pInPtr += val;
735 v = kstrtos32(buf, base, &tempInt);
736 if (v < 0)
737 {
738 return NULL;
739 }
Rajeev Kumar4d93d842014-01-02 18:31:21 -0800740 if (tempInt < 0)
741 {
742 tempInt = 0;
743 }
Rajeev79dbe4c2013-10-05 11:03:42 +0530744 *pOutPtr = tempInt;
745
746 pInPtr = strnchr(pInPtr, strlen(pInPtr), SPACE_ASCII_VALUE);
747 if (NULL == pInPtr)
748 {
749 *pLastArg = TRUE;
750 return NULL;
751 }
752 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
753
754 return pInPtr;
755}
756
757/**---------------------------------------------------------------------------
758
759 \brief hdd_extract_assigned_char_from_str() - Extracts assigned char from
760 input string
761
762 This function extracts assigned character from string in below format:
763 "STRING=A" : extracts char 'A' from this string
764
765 \param - pInPtr Pointer to input string
766 \param - pOutPtr Pointer to variable in which extracted char needs to be
767 assigned
768 \param - pLastArg to tell whether it is last arguement in input string or
769 not
770
771 \return - NULL for failure cases
772 pointer to next arguement in input string for success cases
773 --------------------------------------------------------------------------*/
774static tANI_U8 *
775hdd_extract_assigned_char_from_str
776(
777 tANI_U8 *pInPtr,
778 tANI_U8 *pOutPtr,
779 tANI_U8 *pLastArg
780)
781{
782 *pLastArg = FALSE;
783
784 pInPtr = strnchr(pInPtr, strlen(pInPtr), EQUALS_TO_ASCII_VALUE);
785 if (NULL == pInPtr)
786 {
787 return NULL;
788 }
789
790 pInPtr++;
791
792 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
793
794 *pOutPtr = *pInPtr;
795
796 pInPtr = strnchr(pInPtr, strlen(pInPtr), SPACE_ASCII_VALUE);
797 if (NULL == pInPtr)
798 {
799 *pLastArg = TRUE;
800 return NULL;
801 }
802 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
803
804 return pInPtr;
805}
806
807
808/**---------------------------------------------------------------------------
809
810 \brief hdd_parse_set_batchscan_command () - HDD parse set batch scan command
811
812 This function parses set batch scan command in below format:
813 WLS_BATCHING_SET <space> followed by below arguements
814 "SCANFREQ=XX" : Optional defaults to 30 sec
815 "MSCAN=XX" : Required number of scans to attempt to batch
816 "BESTN=XX" : Best Network (RSSI) defaults to 16
817 "CHANNEL=<X,Y>" : optional defaults to all channels, can list 'A'or` B.
818 A. implies only 5 GHz , B. implies only 2.4GHz
819 "RTT=X" : optional defaults to 0
820 returns the MIN of MSCAN or the max # of scans firmware can cache or -1 on
821 error
822
823 For example input commands:
824 1) WLS_BATCHING_SET SCANFREQ=60 MSCAN=10 BESTN=20 CHANNEL=A RTT=0 -> This is
825 translated into set batch scan with following parameters:
826 a) Frequence 60 seconds
827 b) Batch 10 scans together
828 c) Best RSSI to be 20
829 d) 5GHz band only
830 e) RTT is equal to 0
831
832 \param - pValue Pointer to input channel list
833 \param - pHddSetBatchScanReq Pointer to HDD batch scan request structure
834
835 \return - 0 for success non-zero for failure
836
837 --------------------------------------------------------------------------*/
838static int
839hdd_parse_set_batchscan_command
840(
841 tANI_U8 *pValue,
842 tSirSetBatchScanReq *pHddSetBatchScanReq
843)
844{
845 tANI_U8 *inPtr = pValue;
846 tANI_U8 val = 0;
847 tANI_U8 lastArg = 0;
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800848 tANI_U32 nScanFreq;
849 tANI_U32 nMscan;
850 tANI_U32 nBestN;
851 tANI_U8 ucRfBand;
852 tANI_U32 nRtt;
Rajeev Kumarc933d982013-11-18 20:04:20 -0800853 tANI_U32 temp;
Rajeev79dbe4c2013-10-05 11:03:42 +0530854
855 /*initialize default values*/
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800856 nScanFreq = HDD_SET_BATCH_SCAN_DEFAULT_FREQ;
857 ucRfBand = HDD_SET_BATCH_SCAN_DEFAULT_BAND;
858 nRtt = 0;
859 nBestN = HDD_SET_BATCH_SCAN_BEST_NETWORK;
Rajeev79dbe4c2013-10-05 11:03:42 +0530860
861 /*go to space after WLS_BATCHING_SET command*/
862 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
863 /*no argument after the command*/
864 if (NULL == inPtr)
865 {
866 return -EINVAL;
867 }
868
869 /*no space after the command*/
870 else if (SPACE_ASCII_VALUE != *inPtr)
871 {
872 return -EINVAL;
873 }
874
875 /*removing empty spaces*/
876 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
877
878 /*no argument followed by spaces*/
879 if ('\0' == *inPtr)
880 {
881 return -EINVAL;
882 }
883
884 /*check and parse SCANFREQ*/
885 if ((strncmp(inPtr, "SCANFREQ", 8) == 0))
886 {
887 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumarc933d982013-11-18 20:04:20 -0800888 &temp, &lastArg);
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800889
Rajeev Kumarc933d982013-11-18 20:04:20 -0800890 if (0 != temp)
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800891 {
Rajeev Kumarc933d982013-11-18 20:04:20 -0800892 nScanFreq = temp;
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800893 }
894
Rajeev79dbe4c2013-10-05 11:03:42 +0530895 if ( (NULL == inPtr) || (TRUE == lastArg))
896 {
897 return -EINVAL;
898 }
899 }
900
901 /*check and parse MSCAN*/
902 if ((strncmp(inPtr, "MSCAN", 5) == 0))
903 {
904 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800905 &nMscan, &lastArg);
906
907 if (0 == nMscan)
908 {
909 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
910 "invalid MSCAN=%d", nMscan);
911 return -EINVAL;
912 }
913
Rajeev79dbe4c2013-10-05 11:03:42 +0530914 if (TRUE == lastArg)
915 {
916 goto done;
917 }
918 else if (NULL == inPtr)
919 {
920 return -EINVAL;
921 }
922 }
923 else
924 {
925 return -EINVAL;
926 }
927
928 /*check and parse BESTN*/
929 if ((strncmp(inPtr, "BESTN", 5) == 0))
930 {
931 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumarc933d982013-11-18 20:04:20 -0800932 &temp, &lastArg);
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800933
Rajeev Kumarc933d982013-11-18 20:04:20 -0800934 if (0 != temp)
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800935 {
Rajeev Kumarc933d982013-11-18 20:04:20 -0800936 nBestN = temp;
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800937 }
938
Rajeev79dbe4c2013-10-05 11:03:42 +0530939 if (TRUE == lastArg)
940 {
941 goto done;
942 }
943 else if (NULL == inPtr)
944 {
945 return -EINVAL;
946 }
947 }
948
949 /*check and parse CHANNEL*/
950 if ((strncmp(inPtr, "CHANNEL", 7) == 0))
951 {
952 inPtr = hdd_extract_assigned_char_from_str(inPtr, &val, &lastArg);
Rajeev Kumarc933d982013-11-18 20:04:20 -0800953
Rajeev79dbe4c2013-10-05 11:03:42 +0530954 if (('A' == val) || ('a' == val))
955 {
c_hpothuebf89732014-02-25 13:00:24 +0530956 ucRfBand = HDD_SET_BATCH_SCAN_5GHz_BAND_ONLY;
Rajeev79dbe4c2013-10-05 11:03:42 +0530957 }
958 else if (('B' == val) || ('b' == val))
959 {
c_hpothuebf89732014-02-25 13:00:24 +0530960 ucRfBand = HDD_SET_BATCH_SCAN_24GHz_BAND_ONLY;
Rajeev79dbe4c2013-10-05 11:03:42 +0530961 }
962 else
963 {
Rajeev Kumarc933d982013-11-18 20:04:20 -0800964 ucRfBand = HDD_SET_BATCH_SCAN_DEFAULT_BAND;
965 }
966
967 if (TRUE == lastArg)
968 {
969 goto done;
970 }
971 else if (NULL == inPtr)
972 {
Rajeev79dbe4c2013-10-05 11:03:42 +0530973 return -EINVAL;
974 }
975 }
976
977 /*check and parse RTT*/
978 if ((strncmp(inPtr, "RTT", 3) == 0))
979 {
980 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800981 &nRtt, &lastArg);
Rajeev79dbe4c2013-10-05 11:03:42 +0530982 if (TRUE == lastArg)
983 {
984 goto done;
985 }
986 if (NULL == inPtr)
987 {
988 return -EINVAL;
989 }
990 }
991
992
993done:
994
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800995 pHddSetBatchScanReq->scanFrequency = nScanFreq;
996 pHddSetBatchScanReq->numberOfScansToBatch = nMscan;
997 pHddSetBatchScanReq->bestNetwork = nBestN;
998 pHddSetBatchScanReq->rfBand = ucRfBand;
999 pHddSetBatchScanReq->rtt = nRtt;
1000
Rajeev79dbe4c2013-10-05 11:03:42 +05301001 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1002 "Received WLS_BATCHING_SET with SCANFREQ=%d "
1003 "MSCAN=%d BESTN=%d CHANNEL=%d RTT=%d",
1004 pHddSetBatchScanReq->scanFrequency,
1005 pHddSetBatchScanReq->numberOfScansToBatch,
1006 pHddSetBatchScanReq->bestNetwork,
1007 pHddSetBatchScanReq->rfBand,
1008 pHddSetBatchScanReq->rtt);
1009
1010 return 0;
1011}/*End of hdd_parse_set_batchscan_command*/
1012
1013/**---------------------------------------------------------------------------
1014
1015 \brief hdd_set_batch_scan_req_callback () - This function is called after
1016 receiving set batch scan response from FW and it saves set batch scan
1017 response data FW to HDD context and sets the completion event on
1018 which hdd_ioctl is waiting
1019
1020 \param - callbackContext Pointer to HDD adapter
1021 \param - pRsp Pointer to set batch scan response data received from FW
1022
1023 \return - nothing
1024
1025 --------------------------------------------------------------------------*/
1026static void hdd_set_batch_scan_req_callback
1027(
1028 void *callbackContext,
1029 tSirSetBatchScanRsp *pRsp
1030)
1031{
1032 hdd_adapter_t* pAdapter = (hdd_adapter_t*)callbackContext;
1033 tSirSetBatchScanRsp *pHddSetBatchScanRsp;
1034
1035 /*sanity check*/
1036 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
1037 {
1038 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1039 "%s: Invalid pAdapter magic", __func__);
1040 VOS_ASSERT(0);
1041 return;
1042 }
1043 pHddSetBatchScanRsp = &pAdapter->hddSetBatchScanRsp;
1044
1045 /*save set batch scan response*/
1046 pHddSetBatchScanRsp->nScansToBatch = pRsp->nScansToBatch;
1047
1048 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1049 "Received set batch scan rsp from FW with nScansToBatch=%d",
1050 pHddSetBatchScanRsp->nScansToBatch);
1051
1052 pAdapter->hdd_wait_for_set_batch_scan_rsp = FALSE;
1053 complete(&pAdapter->hdd_set_batch_scan_req_var);
1054
1055 return;
1056}/*End of hdd_set_batch_scan_req_callback*/
1057
1058
1059/**---------------------------------------------------------------------------
1060
1061 \brief hdd_populate_batch_scan_rsp_queue () - This function stores AP meta
1062 info in hdd batch scan response queue
1063
1064 \param - pAdapter Pointer to hdd adapter
1065 \param - pAPMetaInfo Pointer to access point meta info
1066 \param - scanId scan ID of batch scan response
1067 \param - isLastAp tells whether AP is last AP in batch scan response or not
1068
1069 \return - nothing
1070
1071 --------------------------------------------------------------------------*/
1072static void hdd_populate_batch_scan_rsp_queue( hdd_adapter_t* pAdapter,
1073 tpSirBatchScanNetworkInfo pApMetaInfo, tANI_U32 scanId, v_BOOL_t isLastAp)
1074{
1075 tHddBatchScanRsp *pHead;
1076 tHddBatchScanRsp *pNode;
1077 tHddBatchScanRsp *pPrev;
1078 tHddBatchScanRsp *pTemp;
1079 tANI_U8 ssidLen;
1080
1081 /*head of hdd batch scan response queue*/
1082 pHead = pAdapter->pBatchScanRsp;
1083
1084 pNode = (tHddBatchScanRsp *)vos_mem_malloc(sizeof(tHddBatchScanRsp));
1085 if (NULL == pNode)
1086 {
1087 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1088 "%s: Could not allocate memory", __func__);
1089 VOS_ASSERT(0);
1090 return;
1091 }
1092
1093 vos_mem_copy(pNode->ApInfo.bssid, pApMetaInfo->bssid,
1094 sizeof(pNode->ApInfo.bssid));
1095 ssidLen = strlen(pApMetaInfo->ssid);
1096 if (SIR_MAX_SSID_SIZE < ssidLen)
1097 {
1098 /*invalid scan result*/
1099 vos_mem_free(pNode);
1100 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1101 "%s: Invalid AP meta info ssidlen %d", __func__, ssidLen);
1102 return;
1103 }
1104 vos_mem_copy(pNode->ApInfo.ssid, pApMetaInfo->ssid, ssidLen);
1105 /*null terminate ssid*/
1106 pNode->ApInfo.ssid[ssidLen] = '\0';
1107 pNode->ApInfo.ch = pApMetaInfo->ch;
1108 pNode->ApInfo.rssi = pApMetaInfo->rssi;
1109 pNode->ApInfo.age = pApMetaInfo->timestamp;
1110 pNode->ApInfo.batchId = scanId;
1111 pNode->ApInfo.isLastAp = isLastAp;
1112
1113 pNode->pNext = NULL;
1114 if (NULL == pHead)
1115 {
1116 pAdapter->pBatchScanRsp = pNode;
1117 }
1118 else
1119 {
1120 pTemp = pHead;
1121 while (NULL != pTemp)
1122 {
1123 pPrev = pTemp;
1124 pTemp = pTemp->pNext;
1125 }
1126 pPrev->pNext = pNode;
1127 }
1128
1129 return;
1130}/*End of hdd_populate_batch_scan_rsp_queue*/
1131
1132/**---------------------------------------------------------------------------
1133
1134 \brief hdd_batch_scan_result_ind_callback () - This function is called after
1135 receiving batch scan response indication from FW. It saves get batch scan
1136 response data in HDD batch scan response queue. This callback sets the
1137 completion event on which hdd_ioctl is waiting only after getting complete
1138 batch scan response data from FW
1139
1140 \param - callbackContext Pointer to HDD adapter
1141 \param - pRsp Pointer to get batch scan response data received from FW
1142
1143 \return - nothing
1144
1145 --------------------------------------------------------------------------*/
1146static void hdd_batch_scan_result_ind_callback
1147(
1148 void *callbackContext,
1149 void *pRsp
1150)
1151{
1152 v_BOOL_t isLastAp;
1153 tANI_U32 numApMetaInfo;
Rajeev Kumarce651e42013-10-21 18:57:15 -07001154 tANI_U32 numNetworkInScanList;
Rajeev79dbe4c2013-10-05 11:03:42 +05301155 tANI_U32 numberScanList;
1156 tANI_U32 nextScanListOffset;
1157 tANI_U32 nextApMetaInfoOffset;
1158 hdd_adapter_t* pAdapter;
1159 tpSirBatchScanList pScanList;
1160 tpSirBatchScanNetworkInfo pApMetaInfo;
1161 tpSirBatchScanResultIndParam pBatchScanRsp;/*batch scan rsp data from FW*/
1162 tSirSetBatchScanReq *pReq;
1163
1164 pAdapter = (hdd_adapter_t *)callbackContext;
1165 /*sanity check*/
Rajeev Kumar5286bb92013-12-05 11:52:10 -08001166 if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
Rajeev79dbe4c2013-10-05 11:03:42 +05301167 {
1168 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1169 "%s: Invalid pAdapter magic", __func__);
1170 VOS_ASSERT(0);
1171 return;
1172 }
1173
1174 /*initialize locals*/
1175 pReq = &pAdapter->hddSetBatchScanReq;
1176 pBatchScanRsp = (tpSirBatchScanResultIndParam)pRsp;
1177 isLastAp = FALSE;
1178 numApMetaInfo = 0;
Rajeev Kumarce651e42013-10-21 18:57:15 -07001179 numNetworkInScanList = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05301180 numberScanList = 0;
1181 nextScanListOffset = 0;
1182 nextApMetaInfoOffset = 0;
1183 pScanList = NULL;
1184 pApMetaInfo = NULL;
1185
1186 if ((NULL == pBatchScanRsp) || (NULL == pReq))
1187 {
1188 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1189 "%s: pBatchScanRsp is %p pReq %p", __func__, pBatchScanRsp, pReq);
1190 isLastAp = TRUE;
1191 goto done;
1192 }
1193
1194 pAdapter->numScanList = numberScanList = pBatchScanRsp->numScanLists;
1195 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1196 "Batch scan rsp: numberScalList %d", numberScanList);
1197
1198 if ((!numberScanList) || (numberScanList > pReq->numberOfScansToBatch))
1199 {
1200 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1201 "%s: numberScanList %d", __func__, numberScanList);
1202 isLastAp = TRUE;
1203 goto done;
1204 }
1205
1206 while (numberScanList)
1207 {
Rajeev Kumarce651e42013-10-21 18:57:15 -07001208 pScanList = (tpSirBatchScanList)((tANI_U8 *)pBatchScanRsp->scanResults +
Rajeev79dbe4c2013-10-05 11:03:42 +05301209 nextScanListOffset);
1210 if (NULL == pScanList)
1211 {
1212 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1213 "%s: pScanList is %p", __func__, pScanList);
1214 isLastAp = TRUE;
1215 goto done;
1216 }
Rajeev Kumarce651e42013-10-21 18:57:15 -07001217 numNetworkInScanList = numApMetaInfo = pScanList->numNetworksInScanList;
Rajeev79dbe4c2013-10-05 11:03:42 +05301218 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumarce651e42013-10-21 18:57:15 -07001219 "Batch scan rsp: numApMetaInfo %d scanId %d",
1220 numApMetaInfo, pScanList->scanId);
Rajeev79dbe4c2013-10-05 11:03:42 +05301221
1222 if ((!numApMetaInfo) || (numApMetaInfo > pReq->bestNetwork))
1223 {
1224 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1225 "%s: numApMetaInfo %d", __func__, numApMetaInfo);
1226 isLastAp = TRUE;
1227 goto done;
1228 }
1229
Rajeev Kumarce651e42013-10-21 18:57:15 -07001230 /*Initialize next AP meta info offset for next scan list*/
1231 nextApMetaInfoOffset = 0;
1232
Rajeev79dbe4c2013-10-05 11:03:42 +05301233 while (numApMetaInfo)
1234 {
1235 pApMetaInfo = (tpSirBatchScanNetworkInfo)(pScanList->scanList +
1236 nextApMetaInfoOffset);
1237 if (NULL == pApMetaInfo)
1238 {
1239 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1240 "%s: pApMetaInfo is %p", __func__, pApMetaInfo);
1241 isLastAp = TRUE;
1242 goto done;
1243 }
1244 /*calculate AP age*/
1245 pApMetaInfo->timestamp =
1246 pBatchScanRsp->timestamp - pApMetaInfo->timestamp;
1247
1248 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
Arif Hussaina7c8e412013-11-20 11:06:42 -08001249 "%s: bssId "MAC_ADDRESS_STR
1250 " ch %d rssi %d timestamp %d", __func__,
1251 MAC_ADDR_ARRAY(pApMetaInfo->bssid),
1252 pApMetaInfo->ch, pApMetaInfo->rssi,
1253 pApMetaInfo->timestamp);
Rajeev79dbe4c2013-10-05 11:03:42 +05301254
1255 /*mark last AP in batch scan response*/
1256 if ((TRUE == pBatchScanRsp->isLastResult) &&
1257 (1 == numberScanList) && (1 == numApMetaInfo))
1258 {
1259 isLastAp = TRUE;
1260 }
1261
1262 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1263 /*store batch scan repsonse in hdd queue*/
1264 hdd_populate_batch_scan_rsp_queue(pAdapter, pApMetaInfo,
1265 pScanList->scanId, isLastAp);
1266 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1267
1268 nextApMetaInfoOffset += sizeof(tSirBatchScanNetworkInfo);
1269 numApMetaInfo--;
1270 }
1271
Rajeev Kumarce651e42013-10-21 18:57:15 -07001272 nextScanListOffset += ((sizeof(tSirBatchScanList) - sizeof(tANI_U8))
1273 + (sizeof(tSirBatchScanNetworkInfo)
1274 * numNetworkInScanList));
Rajeev79dbe4c2013-10-05 11:03:42 +05301275 numberScanList--;
1276 }
1277
1278done:
1279
1280 /*notify hdd_ioctl only if complete batch scan rsp is received and it was
1281 requested from hdd_ioctl*/
1282 if ((TRUE == pAdapter->hdd_wait_for_get_batch_scan_rsp) &&
1283 (TRUE == isLastAp))
1284 {
1285 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
1286 complete(&pAdapter->hdd_get_batch_scan_req_var);
1287 }
1288
1289 return;
1290}/*End of hdd_batch_scan_result_ind_callback*/
1291
1292/**---------------------------------------------------------------------------
1293
1294 \brief hdd_format_batch_scan_rsp () - This function formats batch scan
1295 response as per batch scan FR request format by putting proper markers
1296
1297 \param - pDest pointer to destination buffer
1298 \param - cur_len current length
1299 \param - tot_len total remaining size which can be written to user space
1300 \param - pApMetaInfo Pointer to get batch scan response AP meta info
1301 \param - pAdapter Pointer to HDD adapter
1302
1303 \return - ret no of characters written
1304
1305 --------------------------------------------------------------------------*/
1306static tANI_U32
1307hdd_format_batch_scan_rsp
1308(
1309 tANI_U8 *pDest,
1310 tANI_U32 cur_len,
1311 tANI_U32 tot_len,
1312 tHddBatchScanRsp *pApMetaInfo,
1313 hdd_adapter_t* pAdapter
1314)
1315{
1316 tANI_U32 ret = 0;
1317 tANI_U32 rem_len = 0;
1318 tANI_U8 temp_len = 0;
1319 tANI_U8 temp_total_len = 0;
1320 tANI_U8 temp[HDD_BATCH_SCAN_AP_META_INFO_SIZE];
1321 tANI_U8 *pTemp = temp;
1322
1323 /*Batch scan reponse needs to be returned to user space in
1324 following format:
1325 "scancount=X\n" where X is the number of scans in current batch
1326 batch
1327 "trunc\n" optional present if current scan truncated
1328 "bssid=XX:XX:XX:XX:XX:XX\n"
1329 "ssid=XXXX\n"
1330 "freq=X\n" frequency in Mhz
1331 "level=XX\n"
1332 "age=X\n" ms
1333 "dist=X\n" cm (-1 if not available)
1334 "errror=X\n" (-1if not available)
1335 "====\n" (end of ap marker)
1336 "####\n" (end of scan marker)
1337 "----\n" (end of results)*/
1338 /*send scan result in above format to user space based on
1339 available length*/
1340 /*The GET response may have more data than the driver can return in its
1341 buffer. In that case the buffer should be filled to the nearest complete
1342 scan, ending with "%%%%".Subsequent callsshould return the remaining data
1343 starting with the next scan (optional .trunc\n., .apcount=X\n., etc).
1344 The final buffer should end with "----\n"*/
1345
1346 /*sanity*/
1347 if (cur_len > tot_len)
1348 {
1349 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1350 "%s: invaid cur_len %d tot_len %d", __func__, cur_len, tot_len);
1351 return 0;
1352 }
1353 else
1354 {
1355 rem_len = (tot_len - cur_len);
1356 }
1357
1358 /*end scan marker*/
1359 if (pApMetaInfo->ApInfo.batchId != pAdapter->prev_batch_id)
1360 {
1361 temp_len = snprintf(pTemp, sizeof(temp), "####\n");
1362 pTemp += temp_len;
1363 temp_total_len += temp_len;
1364 }
1365
1366 /*bssid*/
1367 temp_len = snprintf(pTemp, sizeof(temp),
1368 "bssid=0x%x:0x%x:0x%x:0x%x:0x%x:0x%x\n",
1369 pApMetaInfo->ApInfo.bssid[0], pApMetaInfo->ApInfo.bssid[1],
1370 pApMetaInfo->ApInfo.bssid[2], pApMetaInfo->ApInfo.bssid[3],
1371 pApMetaInfo->ApInfo.bssid[4], pApMetaInfo->ApInfo.bssid[5]);
1372 pTemp += temp_len;
1373 temp_total_len += temp_len;
1374
1375 /*ssid*/
1376 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "ssid=%s\n",
1377 pApMetaInfo->ApInfo.ssid);
1378 pTemp += temp_len;
1379 temp_total_len += temp_len;
1380
1381 /*freq*/
1382 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "freq=%d\n",
Rajeev Kumarc40f7512013-11-04 14:13:23 -08001383 sme_ChnToFreq(pApMetaInfo->ApInfo.ch));
Rajeev79dbe4c2013-10-05 11:03:42 +05301384 pTemp += temp_len;
1385 temp_total_len += temp_len;
1386
1387 /*level*/
1388 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "level=%d\n",
1389 pApMetaInfo->ApInfo.rssi);
1390 pTemp += temp_len;
1391 temp_total_len += temp_len;
1392
1393 /*age*/
Jeff Johnson02797792013-10-26 19:17:13 -07001394 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "age=%d\n",
Rajeev79dbe4c2013-10-05 11:03:42 +05301395 pApMetaInfo->ApInfo.age);
1396 pTemp += temp_len;
1397 temp_total_len += temp_len;
1398
1399 /*dist*/
1400 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "dist=-1\n");
1401 pTemp += temp_len;
1402 temp_total_len += temp_len;
1403
1404 /*error*/
1405 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "error=-1\n");
1406 pTemp += temp_len;
1407 temp_total_len += temp_len;
1408
1409 /*end AP marker*/
1410 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "====\n");
1411 pTemp += temp_len;
1412 temp_total_len += temp_len;
1413
1414 /*last AP in batch scan response*/
1415 if(TRUE == pApMetaInfo->ApInfo.isLastAp)
1416 {
1417 /*end scan marker*/
1418 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "####\n");
1419 pTemp += temp_len;
1420 temp_total_len += temp_len;
1421
1422 /*end batch scan result marker*/
1423 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "----\n");
1424 pTemp += temp_len;
1425 temp_total_len += temp_len;
Kiet Lamaa8e15a2014-02-11 23:30:06 -08001426
Rajeev79dbe4c2013-10-05 11:03:42 +05301427 }
1428
1429 if (temp_total_len < rem_len)
1430 {
1431 ret = temp_total_len + 1;
1432 strlcpy(pDest, temp, ret);
1433 pAdapter->isTruncated = FALSE;
1434 }
1435 else
1436 {
1437 pAdapter->isTruncated = TRUE;
1438 if (rem_len >= strlen("%%%%"))
1439 {
Rajeev Kumarc933d982013-11-18 20:04:20 -08001440 ret = snprintf(pDest, sizeof(temp), "%%%%");
Rajeev79dbe4c2013-10-05 11:03:42 +05301441 }
Rajeev Kumarc933d982013-11-18 20:04:20 -08001442 else
Rajeev79dbe4c2013-10-05 11:03:42 +05301443 {
1444 ret = 0;
1445 }
1446 }
1447
1448 return ret;
1449
1450}/*End of hdd_format_batch_scan_rsp*/
1451
1452/**---------------------------------------------------------------------------
1453
1454 \brief hdd_populate_user_batch_scan_rsp() - This function populates user data
1455 buffer starting with head of hdd batch scan response queue
1456
1457 \param - pAdapter Pointer to HDD adapter
1458 \param - pDest Pointer to user data buffer
1459 \param - cur_len current offset in user buffer
1460 \param - rem_len remaining no of bytes in user buffer
1461
1462 \return - number of bytes written in user buffer
1463
1464 --------------------------------------------------------------------------*/
1465
1466tANI_U32 hdd_populate_user_batch_scan_rsp
1467(
1468 hdd_adapter_t* pAdapter,
1469 tANI_U8 *pDest,
1470 tANI_U32 cur_len,
1471 tANI_U32 rem_len
1472)
1473{
1474 tHddBatchScanRsp *pHead;
1475 tHddBatchScanRsp *pPrev;
1476 tANI_U32 len;
1477
Rajeev79dbe4c2013-10-05 11:03:42 +05301478 pAdapter->isTruncated = FALSE;
1479
1480 /*head of hdd batch scan response queue*/
1481 pHead = pAdapter->pBatchScanRsp;
1482 while (pHead)
1483 {
1484 len = hdd_format_batch_scan_rsp(pDest, cur_len, rem_len, pHead,
1485 pAdapter);
1486 pDest += len;
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07001487 pDest--;
Rajeev79dbe4c2013-10-05 11:03:42 +05301488 cur_len += len;
1489 if(TRUE == pAdapter->isTruncated)
1490 {
1491 /*result is truncated return rest of scan rsp in next req*/
1492 cur_len = rem_len;
1493 break;
1494 }
1495 pPrev = pHead;
1496 pHead = pHead->pNext;
1497 pAdapter->pBatchScanRsp = pHead;
Rajeev Kumarbe17d8b2014-01-10 15:39:45 -08001498 if (TRUE == pPrev->ApInfo.isLastAp)
1499 {
1500 pAdapter->prev_batch_id = 0;
1501 }
1502 else
1503 {
1504 pAdapter->prev_batch_id = pPrev->ApInfo.batchId;
1505 }
Rajeev79dbe4c2013-10-05 11:03:42 +05301506 vos_mem_free(pPrev);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08001507 pPrev = NULL;
Rajeev79dbe4c2013-10-05 11:03:42 +05301508 }
1509
1510 return cur_len;
1511}/*End of hdd_populate_user_batch_scan_rsp*/
1512
1513/**---------------------------------------------------------------------------
1514
1515 \brief hdd_return_batch_scan_rsp_to_user () - This function returns batch
1516 scan response data from HDD queue to user space
1517 It does following in detail:
1518 a) if HDD has enough data in its queue then it 1st copies data to user
1519 space and then send get batch scan indication message to FW. In this
1520 case it does not wait on any event and batch scan response data will
1521 be populated in HDD response queue in MC thread context after receiving
1522 indication from FW
1523 b) else send get batch scan indication message to FW and wait on an event
1524 which will be set once HDD receives complete batch scan response from
1525 FW and then this function returns batch scan response to user space
1526
1527 \param - pAdapter Pointer to HDD adapter
1528 \param - pPrivData Pointer to priv_data
1529
1530 \return - 0 for success -EFAULT for failure
1531
1532 --------------------------------------------------------------------------*/
1533
1534int hdd_return_batch_scan_rsp_to_user
1535(
1536 hdd_adapter_t* pAdapter,
1537 hdd_priv_data_t *pPrivData,
1538 tANI_U8 *command
1539)
1540{
1541 tANI_U8 *pDest;
1542 tANI_U32 count = 0;
1543 tANI_U32 len = 0;
1544 tANI_U32 cur_len = 0;
1545 tANI_U32 rem_len = 0;
1546 eHalStatus halStatus;
1547 unsigned long rc;
1548 tSirTriggerBatchScanResultInd *pReq;
1549
1550 pReq = &pAdapter->hddTriggerBatchScanResultInd;
1551 pReq->param = 0;/*batch scan client*/
1552 pDest = (tANI_U8 *)(command + pPrivData->used_len);
1553 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
1554
1555 cur_len = pPrivData->used_len;
1556 if (pPrivData->total_len > pPrivData->used_len)
1557 {
1558 rem_len = pPrivData->total_len - pPrivData->used_len;
1559 }
1560 else
1561 {
1562 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1563 "%s: Invalid user data buffer total_len %d used_len %d",
1564 __func__, pPrivData->total_len, pPrivData->used_len);
1565 return -EFAULT;
1566 }
1567
1568 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1569 len = hdd_populate_user_batch_scan_rsp(pAdapter, pDest,
1570 cur_len, rem_len);
1571 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1572
1573 /*enough scan result available in cache to return to user space or
1574 scan result needs to be fetched 1st from fw and then return*/
Rajeev Kumar99db6262013-11-11 15:23:36 -08001575 if (len == cur_len)
Rajeev79dbe4c2013-10-05 11:03:42 +05301576 {
1577 pAdapter->hdd_wait_for_get_batch_scan_rsp = TRUE;
1578 halStatus = sme_TriggerBatchScanResultInd(
1579 WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
1580 pAdapter->sessionId, hdd_batch_scan_result_ind_callback,
1581 pAdapter);
1582 if ( eHAL_STATUS_SUCCESS == halStatus )
1583 {
1584 if (TRUE == pAdapter->hdd_wait_for_get_batch_scan_rsp)
1585 {
1586 INIT_COMPLETION(pAdapter->hdd_get_batch_scan_req_var);
1587 rc = wait_for_completion_timeout(
1588 &pAdapter->hdd_get_batch_scan_req_var,
1589 msecs_to_jiffies(HDD_GET_BATCH_SCAN_RSP_TIME_OUT));
1590 if (0 == rc)
1591 {
1592 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1593 "%s: Timeout waiting to fetch batch scan rsp from fw",
1594 __func__);
1595 return -EFAULT;
1596 }
1597 }
1598
1599 len = snprintf(pDest, HDD_BATCH_SCAN_AP_META_INFO_SIZE,
Jeff Johnson02797792013-10-26 19:17:13 -07001600 "scancount=%u\n", pAdapter->numScanList);
Rajeev79dbe4c2013-10-05 11:03:42 +05301601 pDest += len;
1602 cur_len += len;
1603
1604 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1605 len = hdd_populate_user_batch_scan_rsp(pAdapter, pDest,
1606 cur_len, rem_len);
1607 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1608
1609 count = 0;
1610 len = (len - pPrivData->used_len);
1611 pDest = (command + pPrivData->used_len);
1612 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar99db6262013-11-11 15:23:36 -08001613 "NEW BATCH SCAN RESULT:");
Rajeev79dbe4c2013-10-05 11:03:42 +05301614 while(count < len)
1615 {
1616 printk("%c", *(pDest + count));
1617 count++;
1618 }
1619 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1620 "%s: copy %d data to user buffer", __func__, len);
1621 if (copy_to_user(pPrivData->buf, pDest, len))
1622 {
1623 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1624 "%s: failed to copy data to user buffer", __func__);
1625 return -EFAULT;
1626 }
1627 }
1628 else
1629 {
1630 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1631 "sme_GetBatchScanScan returned failure halStatus %d",
1632 halStatus);
1633 return -EINVAL;
1634 }
1635 }
1636 else
1637 {
Rajeev79dbe4c2013-10-05 11:03:42 +05301638 count = 0;
1639 len = (len - pPrivData->used_len);
1640 pDest = (command + pPrivData->used_len);
1641 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar99db6262013-11-11 15:23:36 -08001642 "REMAINING TRUNCATED BATCH SCAN RESULT:");
Rajeev79dbe4c2013-10-05 11:03:42 +05301643 while(count < len)
1644 {
1645 printk("%c", *(pDest + count));
1646 count++;
1647 }
Rajeev Kumar99db6262013-11-11 15:23:36 -08001648 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1649 "%s: copy %d data to user buffer", __func__, len);
Rajeev79dbe4c2013-10-05 11:03:42 +05301650 if (copy_to_user(pPrivData->buf, pDest, len))
1651 {
1652 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1653 "%s: failed to copy data to user buffer", __func__);
1654 return -EFAULT;
1655 }
Rajeev79dbe4c2013-10-05 11:03:42 +05301656 }
1657
1658 return 0;
1659} /*End of hdd_return_batch_scan_rsp_to_user*/
1660
Rajeev Kumar8b373292014-01-08 20:36:55 -08001661
1662/**---------------------------------------------------------------------------
1663
1664 \brief hdd_handle_batch_scan_ioctl () - This function handles WLS_BATCHING
1665 IOCTLs from user space. Following BATCH SCAN DEV IOCTs are handled:
1666 WLS_BATCHING VERSION
1667 WLS_BATCHING SET
1668 WLS_BATCHING GET
1669 WLS_BATCHING STOP
1670
1671 \param - pAdapter Pointer to HDD adapter
1672 \param - pPrivdata Pointer to priv_data
1673 \param - command Pointer to command
1674
1675 \return - 0 for success -EFAULT for failure
1676
1677 --------------------------------------------------------------------------*/
1678
1679int hdd_handle_batch_scan_ioctl
1680(
1681 hdd_adapter_t *pAdapter,
1682 hdd_priv_data_t *pPrivdata,
1683 tANI_U8 *command
1684)
1685{
1686 int ret = 0;
Yue Mae36e3552014-03-05 17:06:20 -08001687 hdd_context_t *pHddCtx;
1688
1689 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
1690 ret = wlan_hdd_validate_context(pHddCtx);
1691 if (ret)
1692 {
1693 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1694 "%s: HDD context is not valid!", __func__);
1695 goto exit;
1696 }
Rajeev Kumar8b373292014-01-08 20:36:55 -08001697
1698 if (strncmp(command, "WLS_BATCHING VERSION", 20) == 0)
1699 {
1700 char extra[32];
1701 tANI_U8 len = 0;
1702 tANI_U8 version = HDD_BATCH_SCAN_VERSION;
1703
1704 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
1705 {
1706 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1707 "%s: Batch scan feature is not supported by FW", __func__);
1708 ret = -EINVAL;
1709 goto exit;
1710 }
1711
1712 len = scnprintf(extra, sizeof(extra), "WLS_BATCHING_VERSION %d",
1713 version);
1714 if (copy_to_user(pPrivdata->buf, &extra, len + 1))
1715 {
1716 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1717 "%s: failed to copy data to user buffer", __func__);
1718 ret = -EFAULT;
1719 goto exit;
1720 }
1721 ret = HDD_BATCH_SCAN_VERSION;
1722 }
1723 else if (strncmp(command, "WLS_BATCHING SET", 16) == 0)
1724 {
1725 int status;
1726 tANI_U8 *value = (command + 16);
1727 eHalStatus halStatus;
1728 unsigned long rc;
1729 tSirSetBatchScanReq *pReq = &pAdapter->hddSetBatchScanReq;
1730 tSirSetBatchScanRsp *pRsp = &pAdapter->hddSetBatchScanRsp;
1731
1732 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
1733 {
1734 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1735 "%s: Batch scan feature is not supported by FW", __func__);
1736 ret = -EINVAL;
1737 goto exit;
1738 }
1739
1740 if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) &&
1741 (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) &&
1742 (WLAN_HDD_P2P_GO != pAdapter->device_mode) &&
1743 (WLAN_HDD_P2P_DEVICE != pAdapter->device_mode))
1744 {
1745 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Sushant Kaushik8bc7df22014-04-09 17:55:29 +05301746 "Received WLS_BATCHING SET command in invalid mode %s (%d) "
Rajeev Kumar8b373292014-01-08 20:36:55 -08001747 "WLS_BATCHING_SET is only allowed in infra STA/P2P client mode",
Sushant Kaushik8bc7df22014-04-09 17:55:29 +05301748 hdd_device_modetoString(pAdapter->device_mode),
1749 pAdapter->device_mode);
Rajeev Kumar8b373292014-01-08 20:36:55 -08001750 ret = -EINVAL;
1751 goto exit;
1752 }
1753
1754 status = hdd_parse_set_batchscan_command(value, pReq);
1755 if (status)
1756 {
1757 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1758 "Invalid WLS_BATCHING SET command");
1759 ret = -EINVAL;
1760 goto exit;
1761 }
1762
1763
1764 pAdapter->hdd_wait_for_set_batch_scan_rsp = TRUE;
1765 halStatus = sme_SetBatchScanReq(WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
1766 pAdapter->sessionId, hdd_set_batch_scan_req_callback,
1767 pAdapter);
1768
1769 if ( eHAL_STATUS_SUCCESS == halStatus )
1770 {
Mahesh A Saptasagar5f568172014-05-14 17:02:33 +05301771 char extra[32];
1772 tANI_U8 len = 0;
1773 tANI_U8 mScan = 0;
1774
Rajeev Kumar8b373292014-01-08 20:36:55 -08001775 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1776 "sme_SetBatchScanReq returned success halStatus %d",
1777 halStatus);
1778 if (TRUE == pAdapter->hdd_wait_for_set_batch_scan_rsp)
1779 {
1780 INIT_COMPLETION(pAdapter->hdd_set_batch_scan_req_var);
1781 rc = wait_for_completion_timeout(
1782 &pAdapter->hdd_set_batch_scan_req_var,
1783 msecs_to_jiffies(HDD_SET_BATCH_SCAN_REQ_TIME_OUT));
1784 if (0 == rc)
1785 {
1786 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1787 "%s: Timeout waiting for set batch scan to complete",
1788 __func__);
1789 ret = -EINVAL;
1790 goto exit;
1791 }
1792 }
1793 if ( !pRsp->nScansToBatch )
1794 {
1795 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1796 "%s: Received set batch scan failure response from FW",
1797 __func__);
1798 ret = -EINVAL;
1799 goto exit;
1800 }
1801 /*As per the Batch Scan Framework API we should return the MIN of
1802 either MSCAN or the max # of scans firmware can cache*/
Mahesh A Saptasagar5f568172014-05-14 17:02:33 +05301803 mScan = MIN(pReq->numberOfScansToBatch , pRsp->nScansToBatch);
Rajeev Kumar8b373292014-01-08 20:36:55 -08001804
1805 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STARTED;
1806
1807 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1808 "%s: request MSCAN %d response MSCAN %d ret %d",
Mahesh A Saptasagar5f568172014-05-14 17:02:33 +05301809 __func__, pReq->numberOfScansToBatch, pRsp->nScansToBatch, mScan);
1810 len = scnprintf(extra, sizeof(extra), "%d", mScan);
1811 if (copy_to_user(pPrivdata->buf, &extra, len + 1))
1812 {
1813 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1814 "%s: failed to copy MSCAN value to user buffer", __func__);
1815 ret = -EFAULT;
1816 goto exit;
1817 }
Rajeev Kumar8b373292014-01-08 20:36:55 -08001818 }
1819 else
1820 {
1821 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1822 "sme_SetBatchScanReq returned failure halStatus %d",
1823 halStatus);
1824 ret = -EINVAL;
1825 goto exit;
1826 }
1827 }
1828 else if (strncmp(command, "WLS_BATCHING STOP", 17) == 0)
1829 {
1830 eHalStatus halStatus;
1831 tSirStopBatchScanInd *pInd = &pAdapter->hddStopBatchScanInd;
1832 pInd->param = 0;
1833
1834 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
1835 {
1836 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1837 "%s: Batch scan feature is not supported by FW", __func__);
1838 ret = -EINVAL;
1839 goto exit;
1840 }
1841
1842 if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState)
1843 {
1844 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1845 "Batch scan is not yet enabled batch scan state %d",
1846 pAdapter->batchScanState);
1847 ret = -EINVAL;
1848 goto exit;
1849 }
1850
Kiet Lamaa8e15a2014-02-11 23:30:06 -08001851 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1852 hdd_deinit_batch_scan(pAdapter);
1853 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1854
Rajeev Kumar8b373292014-01-08 20:36:55 -08001855 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
1856
1857 halStatus = sme_StopBatchScanInd(WLAN_HDD_GET_HAL_CTX(pAdapter), pInd,
1858 pAdapter->sessionId);
1859 if ( eHAL_STATUS_SUCCESS == halStatus )
1860 {
1861 ret = 0;
1862 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1863 "sme_StopBatchScanInd returned success halStatus %d",
1864 halStatus);
1865 }
1866 else
1867 {
1868 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1869 "sme_StopBatchScanInd returned failure halStatus %d",
1870 halStatus);
1871 ret = -EINVAL;
1872 goto exit;
1873 }
1874 }
1875 else if (strncmp(command, "WLS_BATCHING GET", 16) == 0)
1876 {
1877 tANI_U32 remain_len;
1878
1879 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
1880 {
1881 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1882 "%s: Batch scan feature is not supported by FW", __func__);
1883 ret = -EINVAL;
1884 goto exit;
1885 }
1886
1887 if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState)
1888 {
1889 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1890 "Batch scan is not yet enabled could not return results"
1891 "Batch Scan state %d",
1892 pAdapter->batchScanState);
1893 ret = -EINVAL;
1894 goto exit;
1895 }
1896
1897 pPrivdata->used_len = 16;
1898 remain_len = pPrivdata->total_len - pPrivdata->used_len;
1899 if (remain_len < pPrivdata->total_len)
1900 {
1901 /*Clear previous batch scan response data if any*/
1902 vos_mem_zero((tANI_U8 *)(command + pPrivdata->used_len), remain_len);
1903 }
1904 else
1905 {
1906 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1907 "Invalid total length from user space can't fetch batch"
1908 " scan response total_len %d used_len %d remain len %d",
1909 pPrivdata->total_len, pPrivdata->used_len, remain_len);
1910 ret = -EINVAL;
1911 goto exit;
1912 }
1913 ret = hdd_return_batch_scan_rsp_to_user(pAdapter, pPrivdata, command);
1914 }
1915
1916exit:
1917
1918 return ret;
1919}
1920
1921
Rajeev79dbe4c2013-10-05 11:03:42 +05301922#endif/*End of FEATURE_WLAN_BATCH_SCAN*/
1923
c_hpothu92367912014-05-01 15:18:17 +05301924static void getBcnMissRateCB(VOS_STATUS status, int bcnMissRate, void *data)
1925{
c_hpothu39eb1e32014-06-26 16:31:50 +05301926 bcnMissRateContext_t *pCBCtx;
1927
1928 if (NULL == data)
1929 {
1930 hddLog(VOS_TRACE_LEVEL_ERROR, FL("argument data is NULL"));
1931 return;
1932 }
c_hpothu92367912014-05-01 15:18:17 +05301933
1934 /* there is a race condition that exists between this callback
1935 function and the caller since the caller could time out either
1936 before or while this code is executing. we use a spinlock to
1937 serialize these actions */
1938 spin_lock(&hdd_context_lock);
1939
c_hpothu39eb1e32014-06-26 16:31:50 +05301940 pCBCtx = (bcnMissRateContext_t *)data;
c_hpothu92367912014-05-01 15:18:17 +05301941 gbcnMissRate = -1;
1942
c_hpothu39eb1e32014-06-26 16:31:50 +05301943 if (pCBCtx->magic != BCN_MISS_RATE_CONTEXT_MAGIC)
c_hpothu92367912014-05-01 15:18:17 +05301944 {
1945 hddLog(VOS_TRACE_LEVEL_ERROR,
c_hpothu39eb1e32014-06-26 16:31:50 +05301946 FL("invalid context magic: %08x"), pCBCtx->magic);
c_hpothu92367912014-05-01 15:18:17 +05301947 spin_unlock(&hdd_context_lock);
1948 return ;
1949 }
1950
1951 if (VOS_STATUS_SUCCESS == status)
1952 {
c_hpothu39eb1e32014-06-26 16:31:50 +05301953 gbcnMissRate = bcnMissRate;
c_hpothu92367912014-05-01 15:18:17 +05301954 }
c_hpothu39eb1e32014-06-26 16:31:50 +05301955 else
1956 {
1957 hddLog(VOS_TRACE_LEVEL_ERROR, FL("failed to get bcnMissRate"));
1958 }
1959
c_hpothu92367912014-05-01 15:18:17 +05301960 complete(&(pCBCtx->completion));
1961 spin_unlock(&hdd_context_lock);
1962
1963 return;
1964}
1965
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05301966static int hdd_get_dwell_time(hdd_config_t *pCfg, tANI_U8 *command, char *extra, tANI_U8 n, tANI_U8 *len)
1967{
1968 int ret = 0;
1969
1970 if (!pCfg || !command || !extra || !len)
1971 {
1972 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1973 "%s: argument passsed for GETDWELLTIME is incorrect", __func__);
1974 ret = -EINVAL;
1975 return ret;
1976 }
1977
1978 if (strncmp(command, "GETDWELLTIME ACTIVE MAX", 23) == 0)
1979 {
1980 *len = scnprintf(extra, n, "GETDWELLTIME ACTIVE MAX %u\n",
1981 (int)pCfg->nActiveMaxChnTime);
1982 return ret;
1983 }
1984 else if (strncmp(command, "GETDWELLTIME ACTIVE MIN", 23) == 0)
1985 {
1986 *len = scnprintf(extra, n, "GETDWELLTIME ACTIVE MIN %u\n",
1987 (int)pCfg->nActiveMinChnTime);
1988 return ret;
1989 }
1990 else if (strncmp(command, "GETDWELLTIME PASSIVE MAX", 24) == 0)
1991 {
1992 *len = scnprintf(extra, n, "GETDWELLTIME PASSIVE MAX %u\n",
1993 (int)pCfg->nPassiveMaxChnTime);
1994 return ret;
1995 }
1996 else if (strncmp(command, "GETDWELLTIME PASSIVE MIN", 24) == 0)
1997 {
1998 *len = scnprintf(extra, n, "GETDWELLTIME PASSIVE MIN %u\n",
1999 (int)pCfg->nPassiveMinChnTime);
2000 return ret;
2001 }
Rajesh Babu Prathipati0fd227e2014-07-05 12:50:00 +05302002 else if (strncmp(command, "GETDWELLTIME", 12) == 0)
2003 {
2004 *len = scnprintf(extra, n, "GETDWELLTIME %u \n",
2005 (int)pCfg->nActiveMaxChnTime);
2006 return ret;
2007 }
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302008 else
2009 {
2010 ret = -EINVAL;
2011 }
2012
2013 return ret;
2014}
2015
2016static int hdd_set_dwell_time(hdd_adapter_t *pAdapter, tANI_U8 *command)
2017{
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302018 tHalHandle hHal;
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302019 hdd_config_t *pCfg;
2020 tANI_U8 *value = command;
2021 int val = 0, ret = 0, temp = 0;
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302022 tSmeConfigParams smeConfig;
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302023
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302024 if (!pAdapter || !command || !(pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini)
2025 || !(hHal = (WLAN_HDD_GET_HAL_CTX(pAdapter))))
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302026 {
2027 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2028 "%s: argument passed for SETDWELLTIME is incorrect", __func__);
2029 ret = -EINVAL;
2030 return ret;
2031 }
2032
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302033 vos_mem_zero(&smeConfig, sizeof(smeConfig));
2034 sme_GetConfigParam(hHal, &smeConfig);
2035
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302036 if (strncmp(command, "SETDWELLTIME ACTIVE MAX", 23) == 0 )
2037 {
2038 value = value + 24;
2039 temp = kstrtou32(value, 10, &val);
2040 if (temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_MIN ||
2041 val > CFG_ACTIVE_MAX_CHANNEL_TIME_MAX )
2042 {
2043 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2044 "%s: argument passed for SETDWELLTIME ACTIVE MAX is incorrect", __func__);
2045 ret = -EFAULT;
2046 return ret;
2047 }
2048 pCfg->nActiveMaxChnTime = val;
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302049 smeConfig.csrConfig.nActiveMaxChnTime = val;
2050 sme_UpdateConfig(hHal, &smeConfig);
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302051 }
2052 else if (strncmp(command, "SETDWELLTIME ACTIVE MIN", 23) == 0)
2053 {
2054 value = value + 24;
2055 temp = kstrtou32(value, 10, &val);
2056 if (temp !=0 || val < CFG_ACTIVE_MIN_CHANNEL_TIME_MIN ||
2057 val > CFG_ACTIVE_MIN_CHANNEL_TIME_MAX )
2058 {
2059 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2060 "%s: argument passsed for SETDWELLTIME ACTIVE MIN is incorrect", __func__);
2061 ret = -EFAULT;
2062 return ret;
2063 }
2064 pCfg->nActiveMinChnTime = val;
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302065 smeConfig.csrConfig.nActiveMinChnTime = val;
2066 sme_UpdateConfig(hHal, &smeConfig);
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302067 }
2068 else if (strncmp(command, "SETDWELLTIME PASSIVE MAX", 24) == 0)
2069 {
2070 value = value + 25;
2071 temp = kstrtou32(value, 10, &val);
2072 if (temp != 0 || val < CFG_PASSIVE_MAX_CHANNEL_TIME_MIN ||
2073 val > CFG_PASSIVE_MAX_CHANNEL_TIME_MAX )
2074 {
2075 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2076 "%s: argument passed for SETDWELLTIME PASSIVE MAX is incorrect", __func__);
2077 ret = -EFAULT;
2078 return ret;
2079 }
2080 pCfg->nPassiveMaxChnTime = val;
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302081 smeConfig.csrConfig.nPassiveMaxChnTime = val;
2082 sme_UpdateConfig(hHal, &smeConfig);
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302083 }
2084 else if (strncmp(command, "SETDWELLTIME PASSIVE MIN", 24) == 0)
2085 {
2086 value = value + 25;
2087 temp = kstrtou32(value, 10, &val);
2088 if (temp != 0 || val < CFG_PASSIVE_MIN_CHANNEL_TIME_MIN ||
2089 val > CFG_PASSIVE_MIN_CHANNEL_TIME_MAX )
2090 {
2091 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2092 "%s: argument passed for SETDWELLTIME PASSIVE MIN is incorrect", __func__);
2093 ret = -EFAULT;
2094 return ret;
2095 }
2096 pCfg->nPassiveMinChnTime = val;
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302097 smeConfig.csrConfig.nPassiveMinChnTime = val;
2098 sme_UpdateConfig(hHal, &smeConfig);
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302099 }
Rajesh Babu Prathipati0fd227e2014-07-05 12:50:00 +05302100 else if (strncmp(command, "SETDWELLTIME", 12) == 0)
2101 {
2102 value = value + 13;
2103 temp = kstrtou32(value, 10, &val);
2104 if (temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_MIN ||
2105 val > CFG_ACTIVE_MAX_CHANNEL_TIME_MAX )
2106 {
2107 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2108 "%s: argument passed for SETDWELLTIME is incorrect", __func__);
2109 ret = -EFAULT;
2110 return ret;
2111 }
2112 pCfg->nActiveMaxChnTime = val;
2113 smeConfig.csrConfig.nActiveMaxChnTime = val;
2114 sme_UpdateConfig(hHal, &smeConfig);
2115 }
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302116 else
2117 {
2118 ret = -EINVAL;
2119 }
2120
2121 return ret;
2122}
2123
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002124static int hdd_driver_command(hdd_adapter_t *pAdapter,
2125 hdd_priv_data_t *ppriv_data)
Jeff Johnson295189b2012-06-20 16:38:30 -07002126{
Jeff Johnson295189b2012-06-20 16:38:30 -07002127 hdd_priv_data_t priv_data;
2128 tANI_U8 *command = NULL;
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002129 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07002130
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002131 /*
2132 * Note that valid pointers are provided by caller
2133 */
Jeff Johnson295189b2012-06-20 16:38:30 -07002134
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002135 /* copy to local struct to avoid numerous changes to legacy code */
2136 priv_data = *ppriv_data;
Jeff Johnson295189b2012-06-20 16:38:30 -07002137
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002138 if (priv_data.total_len <= 0 ||
2139 priv_data.total_len > WLAN_PRIV_DATA_MAX_LEN)
Sameer Thalappil8ef3a0e2013-04-05 14:36:04 -07002140 {
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002141 hddLog(VOS_TRACE_LEVEL_WARN,
2142 "%s:invalid priv_data.total_len(%d)!!!", __func__,
2143 priv_data.total_len);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07002144 ret = -EINVAL;
2145 goto exit;
2146 }
2147
2148 /* Allocate +1 for '\0' */
2149 command = kmalloc(priv_data.total_len + 1, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07002150 if (!command)
2151 {
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002152 hddLog(VOS_TRACE_LEVEL_ERROR,
2153 "%s: failed to allocate memory", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002154 ret = -ENOMEM;
2155 goto exit;
2156 }
2157
2158 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
2159 {
2160 ret = -EFAULT;
2161 goto exit;
2162 }
2163
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002164 /* Make sure the command is NUL-terminated */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07002165 command[priv_data.total_len] = '\0';
2166
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002167 /* at one time the following block of code was conditional. braces
2168 * have been retained to avoid re-indenting the legacy code
2169 */
Jeff Johnson295189b2012-06-20 16:38:30 -07002170 {
2171 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2172
2173 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07002174 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -07002175
2176 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
2177 {
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302178 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2179 TRACE_CODE_HDD_P2P_DEV_ADDR_IOCTL,
2180 pAdapter->sessionId, (unsigned)
2181 (*(pHddCtx->p2pDeviceAddress.bytes+2)<<24 |
2182 *(pHddCtx->p2pDeviceAddress.bytes+3)<<16 |
2183 *(pHddCtx->p2pDeviceAddress.bytes+4)<<8 |
2184 *(pHddCtx->p2pDeviceAddress.bytes+5))));
Jeff Johnson295189b2012-06-20 16:38:30 -07002185 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
2186 sizeof(tSirMacAddr)))
2187 {
2188 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Arif Hussain6d2a3322013-11-17 19:50:10 -08002189 "%s: failed to copy data to user buffer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002190 ret = -EFAULT;
2191 }
2192 }
Amar Singhal0974e402013-02-12 14:27:46 -08002193 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07002194 {
Amar Singhal0974e402013-02-12 14:27:46 -08002195 tANI_U8 *ptr = command ;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002196
Jeff Johnson295189b2012-06-20 16:38:30 -07002197 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -08002198
2199 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -07002200 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07002201 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -08002202 "%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 -07002203 /* Change band request received */
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002204 ret = hdd_setBand_helper(pAdapter->dev, ptr);
Abhishek Singh2ec36ab2014-08-07 16:14:25 +05302205 if(ret < 0)
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302206 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002207 "%s: failed to set band ret=%d", __func__, ret);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002208 }
Kiet Lamf040f472013-11-20 21:15:23 +05302209 else if(strncmp(command, "SETWMMPS", 8) == 0)
2210 {
2211 tANI_U8 *ptr = command;
2212 ret = hdd_wmmps_helper(pAdapter, ptr);
2213 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07002214 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
2215 {
2216 char *country_code;
2217
2218 country_code = command + 8;
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07002219
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002220 INIT_COMPLETION(pAdapter->change_country_code);
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07002221 hdd_checkandupdate_dfssetting(pAdapter, country_code);
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -07002222#ifndef CONFIG_ENABLE_LINUX_REG
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +05302223 hdd_checkandupdate_phymode(pAdapter, country_code);
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -07002224#endif
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002225 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal,
2226 (void *)(tSmeChangeCountryCallback)
2227 wlan_hdd_change_country_code_callback,
Abhishek Singha306a442013-11-07 18:39:01 +05302228 country_code, pAdapter, pHddCtx->pvosContext, eSIR_TRUE, eSIR_TRUE);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002229 if (eHAL_STATUS_SUCCESS == ret)
2230 {
2231 ret = wait_for_completion_interruptible_timeout(
2232 &pAdapter->change_country_code,
2233 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
2234 if (0 >= ret)
2235 {
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002236 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: SME while setting country code timed out %d",
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302237 __func__, ret);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002238 }
2239 }
2240 else
Jeff Johnson32d95a32012-09-10 13:15:23 -07002241 {
2242 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002243 "%s: SME Change Country code fail ret=%d", __func__, ret);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002244 ret = -EINVAL;
Jeff Johnson32d95a32012-09-10 13:15:23 -07002245 }
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002246
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07002247 }
2248 /*
2249 command should be a string having format
2250 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
2251 */
Amar Singhal0974e402013-02-12 14:27:46 -08002252 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07002253 {
Amar Singhal0974e402013-02-12 14:27:46 -08002254 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07002255
2256 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002257 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07002258
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -08002259 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -07002260 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -08002261 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
2262 {
2263 int suspend = 0;
2264 tANI_U8 *ptr = (tANI_U8*)command + 15;
2265
2266 suspend = *ptr - '0';
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302267 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2268 TRACE_CODE_HDD_SETSUSPENDMODE_IOCTL,
2269 pAdapter->sessionId, suspend));
Sameer Thalappil45931fb2013-02-01 11:18:05 -08002270 hdd_set_wlan_suspend_mode(suspend);
2271 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002272#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
2273 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
2274 {
2275 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002276 tANI_S8 rssi = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002277 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
2278 eHalStatus status = eHAL_STATUS_SUCCESS;
2279
2280 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
2281 value = value + 15;
2282
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002283 /* Convert the value from ascii to integer */
2284 ret = kstrtos8(value, 10, &rssi);
2285 if (ret < 0)
2286 {
2287 /* If the input value is greater than max value of datatype, then also
2288 kstrtou8 fails */
2289 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2290 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdafa7157d2013-10-31 10:14:22 -07002291 __func__,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002292 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
2293 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
2294 ret = -EINVAL;
2295 goto exit;
2296 }
2297
Srinivas Girigowdade697412013-02-14 16:31:48 -08002298 lookUpThreshold = abs(rssi);
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002299
Srinivas Girigowdade697412013-02-14 16:31:48 -08002300 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
2301 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
2302 {
2303 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2304 "Neighbor lookup threshold value %d is out of range"
2305 " (Min: %d Max: %d)", lookUpThreshold,
2306 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
2307 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
2308 ret = -EINVAL;
2309 goto exit;
2310 }
2311
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302312 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2313 TRACE_CODE_HDD_SETROAMTRIGGER_IOCTL,
2314 pAdapter->sessionId, lookUpThreshold));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002315 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2316 "%s: Received Command to Set Roam trigger"
2317 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
2318
2319 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
2320 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
2321 if (eHAL_STATUS_SUCCESS != status)
2322 {
2323 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2324 "%s: Failed to set roam trigger, try again", __func__);
2325 ret = -EPERM;
2326 goto exit;
2327 }
2328
2329 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
mukul sharmad6e1fdd2014-06-23 19:19:09 +05302330 pHddCtx->cfg_ini->nNeighborReassocRssiThreshold = lookUpThreshold + 5;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002331 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
2332 }
2333 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
2334 {
2335 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
2336 int rssi = (-1) * lookUpThreshold;
2337 char extra[32];
2338 tANI_U8 len = 0;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302339 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2340 TRACE_CODE_HDD_GETROAMTRIGGER_IOCTL,
2341 pAdapter->sessionId, lookUpThreshold));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002342 len = scnprintf(extra, sizeof(extra), "%s %d", command, rssi);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002343 if (copy_to_user(priv_data.buf, &extra, len + 1))
2344 {
2345 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2346 "%s: failed to copy data to user buffer", __func__);
2347 ret = -EFAULT;
2348 goto exit;
2349 }
2350 }
2351 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
2352 {
2353 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002354 tANI_U8 roamScanPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002355 tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002356
Srinivas Girigowdade697412013-02-14 16:31:48 -08002357 /* input refresh period is in terms of seconds */
2358 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
2359 value = value + 18;
2360 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002361 ret = kstrtou8(value, 10, &roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002362 if (ret < 0)
2363 {
2364 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002365 kstrtou8 fails */
Srinivas Girigowdade697412013-02-14 16:31:48 -08002366 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002367 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdade697412013-02-14 16:31:48 -08002368 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07002369 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
2370 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002371 ret = -EINVAL;
2372 goto exit;
2373 }
2374
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002375 if ((roamScanPeriod < (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000)) ||
2376 (roamScanPeriod > (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000)))
Srinivas Girigowdade697412013-02-14 16:31:48 -08002377 {
2378 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002379 "Roam scan period value %d is out of range"
2380 " (Min: %d Max: %d)", roamScanPeriod,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07002381 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
2382 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002383 ret = -EINVAL;
2384 goto exit;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302385 }
2386 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2387 TRACE_CODE_HDD_SETROAMSCANPERIOD_IOCTL,
2388 pAdapter->sessionId, roamScanPeriod));
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002389 neighborEmptyScanRefreshPeriod = roamScanPeriod * 1000;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002390
2391 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2392 "%s: Received Command to Set roam scan period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002393 " (Empty Scan refresh period) = %d", __func__, roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002394
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002395 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod;
2396 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002397 }
2398 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
2399 {
2400 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
2401 char extra[32];
2402 tANI_U8 len = 0;
2403
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302404 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2405 TRACE_CODE_HDD_GETROAMSCANPERIOD_IOCTL,
2406 pAdapter->sessionId, nEmptyScanRefreshPeriod));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002407 len = scnprintf(extra, sizeof(extra), "%s %d",
2408 "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002409 /* Returned value is in units of seconds */
2410 if (copy_to_user(priv_data.buf, &extra, len + 1))
2411 {
2412 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2413 "%s: failed to copy data to user buffer", __func__);
2414 ret = -EFAULT;
2415 goto exit;
2416 }
2417 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002418 else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0)
2419 {
2420 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002421 tANI_U8 roamScanRefreshPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002422 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002423
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002424 /* input refresh period is in terms of seconds */
2425 /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */
2426 value = value + 25;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002427
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002428 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002429 ret = kstrtou8(value, 10, &roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002430 if (ret < 0)
2431 {
2432 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002433 kstrtou8 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002434 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002435 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002436 __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002437 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
2438 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
2439 ret = -EINVAL;
2440 goto exit;
2441 }
2442
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002443 if ((roamScanRefreshPeriod < (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000)) ||
2444 (roamScanRefreshPeriod > (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000)))
2445 {
2446 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2447 "Neighbor scan results refresh period value %d is out of range"
2448 " (Min: %d Max: %d)", roamScanRefreshPeriod,
2449 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
2450 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
2451 ret = -EINVAL;
2452 goto exit;
2453 }
2454 neighborScanRefreshPeriod = roamScanRefreshPeriod * 1000;
2455
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002456 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2457 "%s: Received Command to Set roam scan refresh period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002458 " (Scan refresh period) = %d", __func__, roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002459
2460 pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod;
2461 sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
2462 }
2463 else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0)
2464 {
2465 tANI_U16 value = sme_getNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
2466 char extra[32];
2467 tANI_U8 len = 0;
2468
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002469 len = scnprintf(extra, sizeof(extra), "%s %d",
2470 "GETROAMSCANREFRESHPERIOD", (value/1000));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002471 /* Returned value is in units of seconds */
2472 if (copy_to_user(priv_data.buf, &extra, len + 1))
2473 {
2474 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2475 "%s: failed to copy data to user buffer", __func__);
2476 ret = -EFAULT;
2477 goto exit;
2478 }
2479 }
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07002480#ifdef FEATURE_WLAN_LFR
2481 /* SETROAMMODE */
2482 else if (strncmp(command, "SETROAMMODE", SIZE_OF_SETROAMMODE) == 0)
2483 {
2484 tANI_U8 *value = command;
2485 tANI_BOOLEAN roamMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
2486
2487 /* Move pointer to ahead of SETROAMMODE<delimiter> */
2488 value = value + SIZE_OF_SETROAMMODE + 1;
2489
2490 /* Convert the value from ascii to integer */
2491 ret = kstrtou8(value, SIZE_OF_SETROAMMODE, &roamMode);
2492 if (ret < 0)
2493 {
2494 /* If the input value is greater than max value of datatype, then also
2495 kstrtou8 fails */
2496 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2497 "%s: kstrtou8 failed range [%d - %d]", __func__,
2498 CFG_LFR_FEATURE_ENABLED_MIN,
2499 CFG_LFR_FEATURE_ENABLED_MAX);
2500 ret = -EINVAL;
2501 goto exit;
2502 }
2503 if ((roamMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
2504 (roamMode > CFG_LFR_FEATURE_ENABLED_MAX))
2505 {
2506 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2507 "Roam Mode value %d is out of range"
2508 " (Min: %d Max: %d)", roamMode,
2509 CFG_LFR_FEATURE_ENABLED_MIN,
2510 CFG_LFR_FEATURE_ENABLED_MAX);
2511 ret = -EINVAL;
2512 goto exit;
2513 }
2514
2515 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2516 "%s: Received Command to Set Roam Mode = %d", __func__, roamMode);
2517 /*
2518 * Note that
2519 * SETROAMMODE 0 is to enable LFR while
2520 * SETROAMMODE 1 is to disable LFR, but
2521 * NotifyIsFastRoamIniFeatureEnabled 0/1 is to enable/disable.
2522 * So, we have to invert the value to call sme_UpdateIsFastRoamIniFeatureEnabled.
2523 */
2524 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
2525 roamMode = CFG_LFR_FEATURE_ENABLED_MAX; /* Roam enable */
2526 else
2527 roamMode = CFG_LFR_FEATURE_ENABLED_MIN; /* Roam disable */
2528
2529 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = roamMode;
2530 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), roamMode);
2531 }
2532 /* GETROAMMODE */
2533 else if (strncmp(priv_data.buf, "GETROAMMODE", SIZE_OF_GETROAMMODE) == 0)
2534 {
2535 tANI_BOOLEAN roamMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2536 char extra[32];
2537 tANI_U8 len = 0;
2538
2539 /*
2540 * roamMode value shall be inverted because the sementics is different.
2541 */
2542 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
2543 roamMode = CFG_LFR_FEATURE_ENABLED_MAX;
2544 else
2545 roamMode = CFG_LFR_FEATURE_ENABLED_MIN;
2546
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002547 len = scnprintf(extra, sizeof(extra), "%s %d", command, roamMode);
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07002548 if (copy_to_user(priv_data.buf, &extra, len + 1))
2549 {
2550 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2551 "%s: failed to copy data to user buffer", __func__);
2552 ret = -EFAULT;
2553 goto exit;
2554 }
2555 }
2556#endif
Srinivas Girigowdade697412013-02-14 16:31:48 -08002557#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002558#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -08002559 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
2560 {
2561 tANI_U8 *value = command;
2562 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
2563
2564 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
2565 value = value + 13;
2566 /* Convert the value from ascii to integer */
2567 ret = kstrtou8(value, 10, &roamRssiDiff);
2568 if (ret < 0)
2569 {
2570 /* If the input value is greater than max value of datatype, then also
2571 kstrtou8 fails */
2572 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2573 "%s: kstrtou8 failed range [%d - %d]", __func__,
2574 CFG_ROAM_RSSI_DIFF_MIN,
2575 CFG_ROAM_RSSI_DIFF_MAX);
2576 ret = -EINVAL;
2577 goto exit;
2578 }
2579
2580 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
2581 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
2582 {
2583 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2584 "Roam rssi diff value %d is out of range"
2585 " (Min: %d Max: %d)", roamRssiDiff,
2586 CFG_ROAM_RSSI_DIFF_MIN,
2587 CFG_ROAM_RSSI_DIFF_MAX);
2588 ret = -EINVAL;
2589 goto exit;
2590 }
2591
2592 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2593 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
2594
2595 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
2596 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
2597 }
2598 else if (strncmp(priv_data.buf, "GETROAMDELTA", 12) == 0)
2599 {
2600 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
2601 char extra[32];
2602 tANI_U8 len = 0;
2603
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302604 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2605 TRACE_CODE_HDD_GETROAMDELTA_IOCTL,
2606 pAdapter->sessionId, roamRssiDiff));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002607 len = scnprintf(extra, sizeof(extra), "%s %d",
2608 command, roamRssiDiff);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002609 if (copy_to_user(priv_data.buf, &extra, len + 1))
2610 {
2611 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2612 "%s: failed to copy data to user buffer", __func__);
2613 ret = -EFAULT;
2614 goto exit;
2615 }
2616 }
2617#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002618#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -08002619 else if (strncmp(command, "GETBAND", 7) == 0)
2620 {
2621 int band = -1;
2622 char extra[32];
2623 tANI_U8 len = 0;
2624 hdd_getBand_helper(pHddCtx, &band);
2625
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302626 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2627 TRACE_CODE_HDD_GETBAND_IOCTL,
2628 pAdapter->sessionId, band));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002629 len = scnprintf(extra, sizeof(extra), "%s %d", command, band);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002630 if (copy_to_user(priv_data.buf, &extra, len + 1))
2631 {
2632 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2633 "%s: failed to copy data to user buffer", __func__);
2634 ret = -EFAULT;
2635 goto exit;
2636 }
2637 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002638 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
2639 {
2640 tANI_U8 *value = command;
2641 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2642 tANI_U8 numChannels = 0;
2643 eHalStatus status = eHAL_STATUS_SUCCESS;
2644
2645 status = hdd_parse_channellist(value, ChannelList, &numChannels);
2646 if (eHAL_STATUS_SUCCESS != status)
2647 {
2648 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2649 "%s: Failed to parse channel list information", __func__);
2650 ret = -EINVAL;
2651 goto exit;
2652 }
2653
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302654 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2655 TRACE_CODE_HDD_SETROAMSCANCHANNELS_IOCTL,
2656 pAdapter->sessionId, numChannels));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002657 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
2658 {
2659 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2660 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
2661 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
2662 ret = -EINVAL;
2663 goto exit;
2664 }
2665 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
2666 numChannels);
2667 if (eHAL_STATUS_SUCCESS != status)
2668 {
2669 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2670 "%s: Failed to update channel list information", __func__);
2671 ret = -EINVAL;
2672 goto exit;
2673 }
2674 }
2675 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
2676 {
2677 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2678 tANI_U8 numChannels = 0;
Jeff Johnson51b67782013-04-05 12:35:41 -07002679 tANI_U8 j = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002680 char extra[128] = {0};
Jeff Johnson51b67782013-04-05 12:35:41 -07002681 int len;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002682
2683 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
2684 ChannelList, &numChannels ))
2685 {
2686 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2687 "%s: failed to get roam scan channel list", __func__);
2688 ret = -EFAULT;
2689 goto exit;
2690 }
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302691 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2692 TRACE_CODE_HDD_GETROAMSCANCHANNELS_IOCTL,
2693 pAdapter->sessionId, numChannels));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002694 /* output channel list is of the format
2695 [Number of roam scan channels][Channel1][Channel2]... */
2696 /* copy the number of channels in the 0th index */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002697 len = scnprintf(extra, sizeof(extra), "%s %d", command, numChannels);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002698 for (j = 0; (j < numChannels); j++)
2699 {
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002700 len += scnprintf(extra + len, sizeof(extra) - len, " %d",
2701 ChannelList[j]);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002702 }
2703
2704 if (copy_to_user(priv_data.buf, &extra, len + 1))
2705 {
2706 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2707 "%s: failed to copy data to user buffer", __func__);
2708 ret = -EFAULT;
2709 goto exit;
2710 }
2711 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002712 else if (strncmp(command, "GETCCXMODE", 10) == 0)
2713 {
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002714 tANI_BOOLEAN eseMode = sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002715 char extra[32];
2716 tANI_U8 len = 0;
2717
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002718 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002719 then this operation is not permitted (return FAILURE) */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002720 if (eseMode &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002721 hdd_is_okc_mode_enabled(pHddCtx) &&
2722 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2723 {
2724 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002725 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002726 " hence this operation is not permitted!", __func__);
2727 ret = -EPERM;
2728 goto exit;
2729 }
2730
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002731 len = scnprintf(extra, sizeof(extra), "%s %d",
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002732 "GETCCXMODE", eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002733 if (copy_to_user(priv_data.buf, &extra, len + 1))
2734 {
2735 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2736 "%s: failed to copy data to user buffer", __func__);
2737 ret = -EFAULT;
2738 goto exit;
2739 }
2740 }
2741 else if (strncmp(command, "GETOKCMODE", 10) == 0)
2742 {
2743 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
2744 char extra[32];
2745 tANI_U8 len = 0;
2746
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002747 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002748 then this operation is not permitted (return FAILURE) */
2749 if (okcMode &&
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002750 sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002751 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2752 {
2753 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002754 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002755 " hence this operation is not permitted!", __func__);
2756 ret = -EPERM;
2757 goto exit;
2758 }
2759
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002760 len = scnprintf(extra, sizeof(extra), "%s %d",
2761 "GETOKCMODE", okcMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002762 if (copy_to_user(priv_data.buf, &extra, len + 1))
2763 {
2764 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2765 "%s: failed to copy data to user buffer", __func__);
2766 ret = -EFAULT;
2767 goto exit;
2768 }
2769 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002770 else if (strncmp(command, "GETFASTROAM", 11) == 0)
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002771 {
2772 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2773 char extra[32];
2774 tANI_U8 len = 0;
2775
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002776 len = scnprintf(extra, sizeof(extra), "%s %d",
2777 "GETFASTROAM", lfrMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002778 if (copy_to_user(priv_data.buf, &extra, len + 1))
2779 {
2780 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2781 "%s: failed to copy data to user buffer", __func__);
2782 ret = -EFAULT;
2783 goto exit;
2784 }
2785 }
2786 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
2787 {
2788 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2789 char extra[32];
2790 tANI_U8 len = 0;
2791
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002792 len = scnprintf(extra, sizeof(extra), "%s %d",
2793 "GETFASTTRANSITION", ft);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002794 if (copy_to_user(priv_data.buf, &extra, len + 1))
2795 {
2796 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2797 "%s: failed to copy data to user buffer", __func__);
2798 ret = -EFAULT;
2799 goto exit;
2800 }
2801 }
2802 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
2803 {
2804 tANI_U8 *value = command;
2805 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
2806
2807 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
2808 value = value + 26;
2809 /* Convert the value from ascii to integer */
2810 ret = kstrtou8(value, 10, &minTime);
2811 if (ret < 0)
2812 {
2813 /* If the input value is greater than max value of datatype, then also
2814 kstrtou8 fails */
2815 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2816 "%s: kstrtou8 failed range [%d - %d]", __func__,
2817 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
2818 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
2819 ret = -EINVAL;
2820 goto exit;
2821 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002822 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
2823 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
2824 {
2825 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2826 "scan min channel time value %d is out of range"
2827 " (Min: %d Max: %d)", minTime,
2828 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
2829 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
2830 ret = -EINVAL;
2831 goto exit;
2832 }
2833
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302834 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2835 TRACE_CODE_HDD_SETROAMSCANCHANNELMINTIME_IOCTL,
2836 pAdapter->sessionId, minTime));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002837 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2838 "%s: Received Command to change channel min time = %d", __func__, minTime);
2839
2840 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
2841 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
2842 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002843 else if (strncmp(command, "SENDACTIONFRAME", 15) == 0)
2844 {
2845 tANI_U8 *value = command;
2846 tANI_U8 channel = 0;
2847 tANI_U8 dwellTime = 0;
2848 tANI_U8 bufLen = 0;
2849 tANI_U8 *buf = NULL;
2850 tSirMacAddr targetApBssid;
2851 eHalStatus status = eHAL_STATUS_SUCCESS;
2852 struct ieee80211_channel chan;
2853 tANI_U8 finalLen = 0;
2854 tANI_U8 *finalBuf = NULL;
2855 tANI_U8 temp = 0;
2856 u64 cookie;
2857 hdd_station_ctx_t *pHddStaCtx = NULL;
2858 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2859
2860 /* if not associated, no need to send action frame */
2861 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2862 {
2863 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2864 ret = -EINVAL;
2865 goto exit;
2866 }
2867
2868 status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel,
2869 &dwellTime, &buf, &bufLen);
2870 if (eHAL_STATUS_SUCCESS != status)
2871 {
2872 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2873 "%s: Failed to parse send action frame data", __func__);
2874 ret = -EINVAL;
2875 goto exit;
2876 }
2877
2878 /* if the target bssid is different from currently associated AP,
2879 then no need to send action frame */
2880 if (VOS_TRUE != vos_mem_compare(targetApBssid,
2881 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2882 {
2883 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__);
2884 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002885 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002886 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002887 goto exit;
2888 }
2889
2890 /* if the channel number is different from operating channel then
2891 no need to send action frame */
2892 if (channel != pHddStaCtx->conn_info.operationChannel)
2893 {
2894 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2895 "%s: channel(%d) is different from operating channel(%d)",
2896 __func__, channel, pHddStaCtx->conn_info.operationChannel);
2897 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002898 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002899 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002900 goto exit;
2901 }
2902 chan.center_freq = sme_ChnToFreq(channel);
2903
2904 finalLen = bufLen + 24;
2905 finalBuf = vos_mem_malloc(finalLen);
2906 if (NULL == finalBuf)
2907 {
2908 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__);
2909 ret = -ENOMEM;
Jeff Johnson11c33152013-04-16 17:52:40 -07002910 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002911 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002912 goto exit;
2913 }
2914 vos_mem_zero(finalBuf, finalLen);
2915
2916 /* Fill subtype */
2917 temp = SIR_MAC_MGMT_ACTION << 4;
2918 vos_mem_copy(finalBuf + 0, &temp, sizeof(temp));
2919
2920 /* Fill type */
2921 temp = SIR_MAC_MGMT_FRAME;
2922 vos_mem_copy(finalBuf + 2, &temp, sizeof(temp));
2923
2924 /* Fill destination address (bssid of the AP) */
2925 vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid));
2926
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07002927 /* Fill source address (STA mac address) */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002928 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
2929
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07002930 /* Fill BSSID (AP mac address) */
2931 vos_mem_copy(finalBuf + 16, targetApBssid, sizeof(targetApBssid));
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002932
2933 /* Fill received buffer from 24th address */
2934 vos_mem_copy(finalBuf + 24, buf, bufLen);
2935
Jeff Johnson11c33152013-04-16 17:52:40 -07002936 /* done with the parsed buffer */
2937 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002938 buf = NULL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002939
DARAM SUDHA39eede62014-02-12 11:16:40 +05302940 wlan_hdd_mgmt_tx( NULL,
Yue Maf49ba872013-08-19 12:04:25 -07002941#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2942 &(pAdapter->wdev),
2943#else
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002944 pAdapter->dev,
Yue Maf49ba872013-08-19 12:04:25 -07002945#endif
2946 &chan, 0,
2947#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
2948 NL80211_CHAN_HT20, 1,
2949#endif
2950 dwellTime, finalBuf, finalLen, 1,
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002951 1, &cookie );
2952 vos_mem_free(finalBuf);
2953 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002954 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
2955 {
2956 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
2957 char extra[32];
2958 tANI_U8 len = 0;
2959
2960 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002961 len = scnprintf(extra, sizeof(extra), "%s %d",
2962 "GETROAMSCANCHANNELMINTIME", val);
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302963 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2964 TRACE_CODE_HDD_GETROAMSCANCHANNELMINTIME_IOCTL,
2965 pAdapter->sessionId, val));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002966 if (copy_to_user(priv_data.buf, &extra, len + 1))
2967 {
2968 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2969 "%s: failed to copy data to user buffer", __func__);
2970 ret = -EFAULT;
2971 goto exit;
2972 }
2973 }
2974 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
2975 {
2976 tANI_U8 *value = command;
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002977 tANI_U16 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002978
2979 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
2980 value = value + 19;
2981 /* Convert the value from ascii to integer */
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002982 ret = kstrtou16(value, 10, &maxTime);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002983 if (ret < 0)
2984 {
2985 /* If the input value is greater than max value of datatype, then also
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002986 kstrtou16 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002987 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002988 "%s: kstrtou16 failed range [%d - %d]", __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002989 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
2990 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
2991 ret = -EINVAL;
2992 goto exit;
2993 }
2994
2995 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
2996 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
2997 {
2998 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2999 "lfr mode value %d is out of range"
3000 " (Min: %d Max: %d)", maxTime,
3001 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
3002 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
3003 ret = -EINVAL;
3004 goto exit;
3005 }
3006
3007 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3008 "%s: Received Command to change channel max time = %d", __func__, maxTime);
3009
3010 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
3011 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
3012 }
3013 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
3014 {
3015 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
3016 char extra[32];
3017 tANI_U8 len = 0;
3018
3019 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003020 len = scnprintf(extra, sizeof(extra), "%s %d",
3021 "GETSCANCHANNELTIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003022 if (copy_to_user(priv_data.buf, &extra, len + 1))
3023 {
3024 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3025 "%s: failed to copy data to user buffer", __func__);
3026 ret = -EFAULT;
3027 goto exit;
3028 }
3029 }
3030 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
3031 {
3032 tANI_U8 *value = command;
3033 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
3034
3035 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
3036 value = value + 16;
3037 /* Convert the value from ascii to integer */
3038 ret = kstrtou16(value, 10, &val);
3039 if (ret < 0)
3040 {
3041 /* If the input value is greater than max value of datatype, then also
3042 kstrtou16 fails */
3043 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3044 "%s: kstrtou16 failed range [%d - %d]", __func__,
3045 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
3046 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
3047 ret = -EINVAL;
3048 goto exit;
3049 }
3050
3051 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
3052 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
3053 {
3054 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3055 "scan home time value %d is out of range"
3056 " (Min: %d Max: %d)", val,
3057 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
3058 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
3059 ret = -EINVAL;
3060 goto exit;
3061 }
3062
3063 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3064 "%s: Received Command to change scan home time = %d", __func__, val);
3065
3066 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
3067 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
3068 }
3069 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
3070 {
3071 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
3072 char extra[32];
3073 tANI_U8 len = 0;
3074
3075 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003076 len = scnprintf(extra, sizeof(extra), "%s %d",
3077 "GETSCANHOMETIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003078 if (copy_to_user(priv_data.buf, &extra, len + 1))
3079 {
3080 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3081 "%s: failed to copy data to user buffer", __func__);
3082 ret = -EFAULT;
3083 goto exit;
3084 }
3085 }
3086 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
3087 {
3088 tANI_U8 *value = command;
3089 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
3090
3091 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
3092 value = value + 17;
3093 /* Convert the value from ascii to integer */
3094 ret = kstrtou8(value, 10, &val);
3095 if (ret < 0)
3096 {
3097 /* If the input value is greater than max value of datatype, then also
3098 kstrtou8 fails */
3099 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3100 "%s: kstrtou8 failed range [%d - %d]", __func__,
3101 CFG_ROAM_INTRA_BAND_MIN,
3102 CFG_ROAM_INTRA_BAND_MAX);
3103 ret = -EINVAL;
3104 goto exit;
3105 }
3106
3107 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
3108 (val > CFG_ROAM_INTRA_BAND_MAX))
3109 {
3110 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3111 "intra band mode value %d is out of range"
3112 " (Min: %d Max: %d)", val,
3113 CFG_ROAM_INTRA_BAND_MIN,
3114 CFG_ROAM_INTRA_BAND_MAX);
3115 ret = -EINVAL;
3116 goto exit;
3117 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003118 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3119 "%s: Received Command to change intra band = %d", __func__, val);
3120
3121 pHddCtx->cfg_ini->nRoamIntraBand = val;
3122 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
3123 }
3124 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
3125 {
3126 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
3127 char extra[32];
3128 tANI_U8 len = 0;
3129
3130 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003131 len = scnprintf(extra, sizeof(extra), "%s %d",
3132 "GETROAMINTRABAND", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003133 if (copy_to_user(priv_data.buf, &extra, len + 1))
3134 {
3135 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3136 "%s: failed to copy data to user buffer", __func__);
3137 ret = -EFAULT;
3138 goto exit;
3139 }
3140 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003141 else if (strncmp(command, "SETSCANNPROBES", 14) == 0)
3142 {
3143 tANI_U8 *value = command;
3144 tANI_U8 nProbes = CFG_ROAM_SCAN_N_PROBES_DEFAULT;
3145
3146 /* Move pointer to ahead of SETSCANNPROBES<delimiter> */
3147 value = value + 15;
3148 /* Convert the value from ascii to integer */
3149 ret = kstrtou8(value, 10, &nProbes);
3150 if (ret < 0)
3151 {
3152 /* If the input value is greater than max value of datatype, then also
3153 kstrtou8 fails */
3154 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3155 "%s: kstrtou8 failed range [%d - %d]", __func__,
3156 CFG_ROAM_SCAN_N_PROBES_MIN,
3157 CFG_ROAM_SCAN_N_PROBES_MAX);
3158 ret = -EINVAL;
3159 goto exit;
3160 }
3161
3162 if ((nProbes < CFG_ROAM_SCAN_N_PROBES_MIN) ||
3163 (nProbes > CFG_ROAM_SCAN_N_PROBES_MAX))
3164 {
3165 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3166 "NProbes value %d is out of range"
3167 " (Min: %d Max: %d)", nProbes,
3168 CFG_ROAM_SCAN_N_PROBES_MIN,
3169 CFG_ROAM_SCAN_N_PROBES_MAX);
3170 ret = -EINVAL;
3171 goto exit;
3172 }
3173
3174 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3175 "%s: Received Command to Set nProbes = %d", __func__, nProbes);
3176
3177 pHddCtx->cfg_ini->nProbes = nProbes;
3178 sme_UpdateRoamScanNProbes((tHalHandle)(pHddCtx->hHal), nProbes);
3179 }
3180 else if (strncmp(priv_data.buf, "GETSCANNPROBES", 14) == 0)
3181 {
3182 tANI_U8 val = sme_getRoamScanNProbes((tHalHandle)(pHddCtx->hHal));
3183 char extra[32];
3184 tANI_U8 len = 0;
3185
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003186 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003187 if (copy_to_user(priv_data.buf, &extra, len + 1))
3188 {
3189 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3190 "%s: failed to copy data to user buffer", __func__);
3191 ret = -EFAULT;
3192 goto exit;
3193 }
3194 }
3195 else if (strncmp(command, "SETSCANHOMEAWAYTIME", 19) == 0)
3196 {
3197 tANI_U8 *value = command;
3198 tANI_U16 homeAwayTime = CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT;
3199
3200 /* Move pointer to ahead of SETSCANHOMEAWAYTIME<delimiter> */
3201 /* input value is in units of msec */
3202 value = value + 20;
3203 /* Convert the value from ascii to integer */
3204 ret = kstrtou16(value, 10, &homeAwayTime);
3205 if (ret < 0)
3206 {
3207 /* If the input value is greater than max value of datatype, then also
3208 kstrtou8 fails */
3209 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3210 "%s: kstrtou8 failed range [%d - %d]", __func__,
3211 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
3212 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
3213 ret = -EINVAL;
3214 goto exit;
3215 }
3216
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003217 if ((homeAwayTime < CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN) ||
3218 (homeAwayTime > CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX))
3219 {
3220 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3221 "homeAwayTime value %d is out of range"
3222 " (Min: %d Max: %d)", homeAwayTime,
3223 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
3224 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
3225 ret = -EINVAL;
3226 goto exit;
3227 }
3228
3229 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3230 "%s: Received Command to Set scan away time = %d", __func__, homeAwayTime);
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07003231 if (pHddCtx->cfg_ini->nRoamScanHomeAwayTime != homeAwayTime)
3232 {
3233 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
3234 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_TRUE);
3235 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003236 }
3237 else if (strncmp(priv_data.buf, "GETSCANHOMEAWAYTIME", 19) == 0)
3238 {
3239 tANI_U16 val = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
3240 char extra[32];
3241 tANI_U8 len = 0;
3242
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003243 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003244 if (copy_to_user(priv_data.buf, &extra, len + 1))
3245 {
3246 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3247 "%s: failed to copy data to user buffer", __func__);
3248 ret = -EFAULT;
3249 goto exit;
3250 }
3251 }
3252 else if (strncmp(command, "REASSOC", 7) == 0)
3253 {
3254 tANI_U8 *value = command;
3255 tANI_U8 channel = 0;
3256 tSirMacAddr targetApBssid;
3257 eHalStatus status = eHAL_STATUS_SUCCESS;
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07003258#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
3259 tCsrHandoffRequest handoffInfo;
3260#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003261 hdd_station_ctx_t *pHddStaCtx = NULL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003262 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3263
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003264 /* if not associated, no need to proceed with reassoc */
3265 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3266 {
3267 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
3268 ret = -EINVAL;
3269 goto exit;
3270 }
3271
3272 status = hdd_parse_reassoc_command_data(value, targetApBssid, &channel);
3273 if (eHAL_STATUS_SUCCESS != status)
3274 {
3275 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3276 "%s: Failed to parse reassoc command data", __func__);
3277 ret = -EINVAL;
3278 goto exit;
3279 }
3280
3281 /* if the target bssid is same as currently associated AP,
3282 then no need to proceed with reassoc */
3283 if (VOS_TRUE == vos_mem_compare(targetApBssid,
3284 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
3285 {
3286 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Reassoc BSSID is same as currently associated AP bssid",__func__);
3287 ret = -EINVAL;
3288 goto exit;
3289 }
3290
3291 /* Check channel number is a valid channel number */
3292 if(VOS_STATUS_SUCCESS !=
3293 wlan_hdd_validate_operation_channel(pAdapter, channel))
3294 {
3295 hddLog(VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08003296 "%s: Invalid Channel [%d]", __func__, channel);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003297 return -EINVAL;
3298 }
3299
3300 /* Proceed with reassoc */
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07003301#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
3302 handoffInfo.channel = channel;
3303 vos_mem_copy(handoffInfo.bssid, targetApBssid, sizeof(tSirMacAddr));
3304 sme_HandoffRequest(pHddCtx->hHal, &handoffInfo);
3305#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003306 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07003307 else if (strncmp(command, "SETWESMODE", 10) == 0)
3308 {
3309 tANI_U8 *value = command;
3310 tANI_BOOLEAN wesMode = CFG_ENABLE_WES_MODE_NAME_DEFAULT;
3311
3312 /* Move pointer to ahead of SETWESMODE<delimiter> */
3313 value = value + 11;
3314 /* Convert the value from ascii to integer */
3315 ret = kstrtou8(value, 10, &wesMode);
3316 if (ret < 0)
3317 {
3318 /* If the input value is greater than max value of datatype, then also
3319 kstrtou8 fails */
3320 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3321 "%s: kstrtou8 failed range [%d - %d]", __func__,
3322 CFG_ENABLE_WES_MODE_NAME_MIN,
3323 CFG_ENABLE_WES_MODE_NAME_MAX);
3324 ret = -EINVAL;
3325 goto exit;
3326 }
3327
3328 if ((wesMode < CFG_ENABLE_WES_MODE_NAME_MIN) ||
3329 (wesMode > CFG_ENABLE_WES_MODE_NAME_MAX))
3330 {
3331 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3332 "WES Mode value %d is out of range"
3333 " (Min: %d Max: %d)", wesMode,
3334 CFG_ENABLE_WES_MODE_NAME_MIN,
3335 CFG_ENABLE_WES_MODE_NAME_MAX);
3336 ret = -EINVAL;
3337 goto exit;
3338 }
3339 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3340 "%s: Received Command to Set WES Mode rssi diff = %d", __func__, wesMode);
3341
3342 pHddCtx->cfg_ini->isWESModeEnabled = wesMode;
3343 sme_UpdateWESMode((tHalHandle)(pHddCtx->hHal), wesMode);
3344 }
3345 else if (strncmp(priv_data.buf, "GETWESMODE", 10) == 0)
3346 {
3347 tANI_BOOLEAN wesMode = sme_GetWESMode((tHalHandle)(pHddCtx->hHal));
3348 char extra[32];
3349 tANI_U8 len = 0;
3350
Arif Hussain826d9412013-11-12 16:44:54 -08003351 len = scnprintf(extra, sizeof(extra), "%s %d", command, wesMode);
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07003352 if (copy_to_user(priv_data.buf, &extra, len + 1))
3353 {
3354 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3355 "%s: failed to copy data to user buffer", __func__);
3356 ret = -EFAULT;
3357 goto exit;
3358 }
3359 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003360#endif /* WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_ESE || FEATURE_WLAN_LFR */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003361#ifdef FEATURE_WLAN_LFR
3362 else if (strncmp(command, "SETFASTROAM", 11) == 0)
3363 {
3364 tANI_U8 *value = command;
3365 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
3366
3367 /* Move pointer to ahead of SETFASTROAM<delimiter> */
3368 value = value + 12;
3369 /* Convert the value from ascii to integer */
3370 ret = kstrtou8(value, 10, &lfrMode);
3371 if (ret < 0)
3372 {
3373 /* If the input value is greater than max value of datatype, then also
3374 kstrtou8 fails */
3375 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3376 "%s: kstrtou8 failed range [%d - %d]", __func__,
3377 CFG_LFR_FEATURE_ENABLED_MIN,
3378 CFG_LFR_FEATURE_ENABLED_MAX);
3379 ret = -EINVAL;
3380 goto exit;
3381 }
3382
3383 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
3384 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
3385 {
3386 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3387 "lfr mode value %d is out of range"
3388 " (Min: %d Max: %d)", lfrMode,
3389 CFG_LFR_FEATURE_ENABLED_MIN,
3390 CFG_LFR_FEATURE_ENABLED_MAX);
3391 ret = -EINVAL;
3392 goto exit;
3393 }
3394
3395 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3396 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
3397
3398 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
3399 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
3400 }
3401#endif
3402#ifdef WLAN_FEATURE_VOWIFI_11R
3403 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
3404 {
3405 tANI_U8 *value = command;
3406 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
3407
3408 /* Move pointer to ahead of SETFASTROAM<delimiter> */
3409 value = value + 18;
3410 /* Convert the value from ascii to integer */
3411 ret = kstrtou8(value, 10, &ft);
3412 if (ret < 0)
3413 {
3414 /* If the input value is greater than max value of datatype, then also
3415 kstrtou8 fails */
3416 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3417 "%s: kstrtou8 failed range [%d - %d]", __func__,
3418 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
3419 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
3420 ret = -EINVAL;
3421 goto exit;
3422 }
3423
3424 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
3425 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
3426 {
3427 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3428 "ft mode value %d is out of range"
3429 " (Min: %d Max: %d)", ft,
3430 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
3431 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
3432 ret = -EINVAL;
3433 goto exit;
3434 }
3435
3436 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3437 "%s: Received Command to change ft mode = %d", __func__, ft);
3438
3439 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
3440 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
3441 }
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05303442
3443 else if (strncmp(command, "FASTREASSOC", 11) == 0)
3444 {
3445 tANI_U8 *value = command;
3446 tSirMacAddr targetApBssid;
3447 tANI_U8 trigger = 0;
3448 eHalStatus status = eHAL_STATUS_SUCCESS;
3449 hdd_station_ctx_t *pHddStaCtx = NULL;
3450 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3451
3452 /* if not associated, no need to proceed with reassoc */
3453 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3454 {
3455 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
3456 ret = -EINVAL;
3457 goto exit;
3458 }
3459
3460 status = hdd_parse_reassoc_command_data(value, targetApBssid, &trigger);
3461 if (eHAL_STATUS_SUCCESS != status)
3462 {
3463 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3464 "%s: Failed to parse reassoc command data", __func__);
3465 ret = -EINVAL;
3466 goto exit;
3467 }
3468
3469 /* if the target bssid is same as currently associated AP,
3470 then no need to proceed with reassoc */
3471 if (VOS_TRUE == vos_mem_compare(targetApBssid,
3472 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
3473 {
3474 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3475 "%s:11r Reassoc BSSID is same as currently associated AP bssid",
3476 __func__);
3477 ret = -EINVAL;
3478 goto exit;
3479 }
3480
3481 /* Proceed with scan/roam */
3482 smeIssueFastRoamNeighborAPEvent(WLAN_HDD_GET_HAL_CTX(pAdapter),
3483 &targetApBssid[0],
3484 (tSmeFastRoamTrigger)(trigger));
3485 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003486#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003487#ifdef FEATURE_WLAN_ESE
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003488 else if (strncmp(command, "SETCCXMODE", 10) == 0)
3489 {
3490 tANI_U8 *value = command;
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003491 tANI_U8 eseMode = CFG_ESE_FEATURE_ENABLED_DEFAULT;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003492
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003493 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003494 then this operation is not permitted (return FAILURE) */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003495 if (sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003496 hdd_is_okc_mode_enabled(pHddCtx) &&
3497 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
3498 {
3499 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003500 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003501 " hence this operation is not permitted!", __func__);
3502 ret = -EPERM;
3503 goto exit;
3504 }
3505
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003506 /* Move pointer to ahead of SETCCXMODE<delimiter> */
3507 value = value + 11;
3508 /* Convert the value from ascii to integer */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003509 ret = kstrtou8(value, 10, &eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003510 if (ret < 0)
3511 {
3512 /* If the input value is greater than max value of datatype, then also
3513 kstrtou8 fails */
3514 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3515 "%s: kstrtou8 failed range [%d - %d]", __func__,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003516 CFG_ESE_FEATURE_ENABLED_MIN,
3517 CFG_ESE_FEATURE_ENABLED_MAX);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003518 ret = -EINVAL;
3519 goto exit;
3520 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003521 if ((eseMode < CFG_ESE_FEATURE_ENABLED_MIN) ||
3522 (eseMode > CFG_ESE_FEATURE_ENABLED_MAX))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003523 {
3524 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003525 "Ese mode value %d is out of range"
3526 " (Min: %d Max: %d)", eseMode,
3527 CFG_ESE_FEATURE_ENABLED_MIN,
3528 CFG_ESE_FEATURE_ENABLED_MAX);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003529 ret = -EINVAL;
3530 goto exit;
3531 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003532 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003533 "%s: Received Command to change ese mode = %d", __func__, eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003534
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003535 pHddCtx->cfg_ini->isEseIniFeatureEnabled = eseMode;
3536 sme_UpdateIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal), eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003537 }
3538#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003539 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
3540 {
3541 tANI_U8 *value = command;
3542 tANI_BOOLEAN roamScanControl = 0;
3543
3544 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
3545 value = value + 19;
3546 /* Convert the value from ascii to integer */
3547 ret = kstrtou8(value, 10, &roamScanControl);
3548 if (ret < 0)
3549 {
3550 /* If the input value is greater than max value of datatype, then also
3551 kstrtou8 fails */
3552 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3553 "%s: kstrtou8 failed ", __func__);
3554 ret = -EINVAL;
3555 goto exit;
3556 }
3557
3558 if (0 != roamScanControl)
3559 {
3560 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3561 "roam scan control invalid value = %d",
3562 roamScanControl);
3563 ret = -EINVAL;
3564 goto exit;
3565 }
3566 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3567 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
3568
3569 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
3570 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003571#ifdef FEATURE_WLAN_OKC
3572 else if (strncmp(command, "SETOKCMODE", 10) == 0)
3573 {
3574 tANI_U8 *value = command;
3575 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
3576
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003577 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003578 then this operation is not permitted (return FAILURE) */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003579 if (sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003580 hdd_is_okc_mode_enabled(pHddCtx) &&
3581 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
3582 {
3583 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003584 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003585 " hence this operation is not permitted!", __func__);
3586 ret = -EPERM;
3587 goto exit;
3588 }
3589
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003590 /* Move pointer to ahead of SETOKCMODE<delimiter> */
3591 value = value + 11;
3592 /* Convert the value from ascii to integer */
3593 ret = kstrtou8(value, 10, &okcMode);
3594 if (ret < 0)
3595 {
3596 /* If the input value is greater than max value of datatype, then also
3597 kstrtou8 fails */
3598 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3599 "%s: kstrtou8 failed range [%d - %d]", __func__,
3600 CFG_OKC_FEATURE_ENABLED_MIN,
3601 CFG_OKC_FEATURE_ENABLED_MAX);
3602 ret = -EINVAL;
3603 goto exit;
3604 }
3605
3606 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
3607 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
3608 {
3609 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3610 "Okc mode value %d is out of range"
3611 " (Min: %d Max: %d)", okcMode,
3612 CFG_OKC_FEATURE_ENABLED_MIN,
3613 CFG_OKC_FEATURE_ENABLED_MAX);
3614 ret = -EINVAL;
3615 goto exit;
3616 }
3617
3618 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3619 "%s: Received Command to change okc mode = %d", __func__, okcMode);
3620
3621 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
3622 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07003623#endif /* FEATURE_WLAN_OKC */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003624 else if (strncmp(priv_data.buf, "GETROAMSCANCONTROL", 18) == 0)
3625 {
3626 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
3627 char extra[32];
3628 tANI_U8 len = 0;
3629
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003630 len = scnprintf(extra, sizeof(extra), "%s %d",
3631 command, roamScanControl);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003632 if (copy_to_user(priv_data.buf, &extra, len + 1))
3633 {
3634 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3635 "%s: failed to copy data to user buffer", __func__);
3636 ret = -EFAULT;
3637 goto exit;
3638 }
3639 }
Gopichand Nakkala227c7f32013-06-26 22:44:57 +05303640#ifdef WLAN_FEATURE_PACKET_FILTERING
3641 else if (strncmp(command, "ENABLE_PKTFILTER_IPV6", 21) == 0)
3642 {
3643 tANI_U8 filterType = 0;
3644 tANI_U8 *value = command;
3645
3646 /* Move pointer to ahead of ENABLE_PKTFILTER_IPV6<delimiter> */
3647 value = value + 22;
3648
3649 /* Convert the value from ascii to integer */
3650 ret = kstrtou8(value, 10, &filterType);
3651 if (ret < 0)
3652 {
3653 /* If the input value is greater than max value of datatype,
3654 * then also kstrtou8 fails
3655 */
3656 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3657 "%s: kstrtou8 failed range ", __func__);
3658 ret = -EINVAL;
3659 goto exit;
3660 }
3661
3662 if (filterType != 0 && filterType != 1)
3663 {
3664 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3665 "%s: Accepted Values are 0 and 1 ", __func__);
3666 ret = -EINVAL;
3667 goto exit;
3668 }
3669 wlan_hdd_setIPv6Filter(WLAN_HDD_GET_CTX(pAdapter), filterType,
3670 pAdapter->sessionId);
3671 }
3672#endif
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303673 else if (strncmp(command, "BTCOEXMODE", 10) == 0 )
3674 {
Kiet Lamad161252014-07-22 11:23:32 -07003675 char *dhcpPhase;
Satyanarayana Dash1faea4f2014-09-22 16:21:04 +05303676 int ret;
3677
Kiet Lamad161252014-07-22 11:23:32 -07003678 dhcpPhase = command + 11;
3679 if ('1' == *dhcpPhase)
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303680 {
c_hpothu9b781ba2013-12-30 20:57:45 +05303681 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Kiet Lamad161252014-07-22 11:23:32 -07003682 FL("send DHCP START indication"));
c_hpothu9b781ba2013-12-30 20:57:45 +05303683
3684 pHddCtx->btCoexModeSet = TRUE;
Kiet Lamad161252014-07-22 11:23:32 -07003685
Satyanarayana Dash1faea4f2014-09-22 16:21:04 +05303686 ret = wlan_hdd_scan_abort(pAdapter);
3687 if (ret < 0)
3688 {
3689 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3690 FL("failed to abort existing scan %d"), ret);
3691 }
3692
Kiet Lamad161252014-07-22 11:23:32 -07003693 sme_DHCPStartInd(pHddCtx->hHal, pAdapter->device_mode,
3694 pAdapter->sessionId);
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303695 }
Kiet Lamad161252014-07-22 11:23:32 -07003696 else if ('2' == *dhcpPhase)
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303697 {
c_hpothu9b781ba2013-12-30 20:57:45 +05303698 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Kiet Lamad161252014-07-22 11:23:32 -07003699 FL("send DHCP STOP indication"));
c_hpothu9b781ba2013-12-30 20:57:45 +05303700
3701 pHddCtx->btCoexModeSet = FALSE;
Kiet Lamad161252014-07-22 11:23:32 -07003702
3703 sme_DHCPStopInd(pHddCtx->hHal, pAdapter->device_mode,
3704 pAdapter->sessionId);
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303705 }
3706 }
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07003707 else if (strncmp(command, "SCAN-ACTIVE", 11) == 0)
3708 {
c_hpothudbefd3e2014-04-28 15:59:47 +05303709 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3710 FL("making default scan to ACTIVE"));
3711 pHddCtx->scan_info.scan_mode = eSIR_ACTIVE_SCAN;
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07003712 }
3713 else if (strncmp(command, "SCAN-PASSIVE", 12) == 0)
3714 {
c_hpothudbefd3e2014-04-28 15:59:47 +05303715 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3716 FL("making default scan to PASSIVE"));
3717 pHddCtx->scan_info.scan_mode = eSIR_PASSIVE_SCAN;
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07003718 }
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303719 else if (strncmp(command, "GETDWELLTIME", 12) == 0)
3720 {
3721 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3722 char extra[32];
3723 tANI_U8 len = 0;
3724
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05303725 memset(extra, 0, sizeof(extra));
3726 ret = hdd_get_dwell_time(pCfg, command, extra, sizeof(extra), &len);
3727 if (ret != 0 || copy_to_user(priv_data.buf, &extra, len + 1))
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303728 {
3729 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3730 "%s: failed to copy data to user buffer", __func__);
3731 ret = -EFAULT;
3732 goto exit;
3733 }
3734 ret = len;
3735 }
3736 else if (strncmp(command, "SETDWELLTIME", 12) == 0)
3737 {
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05303738 ret = hdd_set_dwell_time(pAdapter, command);
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303739 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07003740 else if ( strncasecmp(command, "MIRACAST", 8) == 0 )
3741 {
3742 tANI_U8 filterType = 0;
3743 tANI_U8 *value;
3744 value = command + 9;
3745
3746 /* Convert the value from ascii to integer */
3747 ret = kstrtou8(value, 10, &filterType);
3748 if (ret < 0)
3749 {
3750 /* If the input value is greater than max value of datatype,
3751 * then also kstrtou8 fails
3752 */
3753 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3754 "%s: kstrtou8 failed range ", __func__);
3755 ret = -EINVAL;
3756 goto exit;
3757 }
3758 if ((filterType < WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL ) ||
3759 (filterType > WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL))
3760 {
3761 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3762 "%s: Accepted Values are 0 to 2. 0-Disabled, 1-Source,"
3763 " 2-Sink ", __func__);
3764 ret = -EINVAL;
3765 goto exit;
3766 }
3767 //Filtertype value should be either 0-Disabled, 1-Source, 2-sink
3768 pHddCtx->drvr_miracast = filterType;
3769 hdd_tx_rx_pkt_cnt_stat_timer_handler(pHddCtx);
Ganesh Kondabattini8f6e3b32014-08-25 16:07:54 +05303770 sme_SetMiracastMode(pHddCtx->hHal, pHddCtx->drvr_miracast);
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07003771 }
Leo Chang614d2072013-08-22 14:59:44 -07003772 else if (strncmp(command, "SETMCRATE", 9) == 0)
3773 {
Leo Chang614d2072013-08-22 14:59:44 -07003774 tANI_U8 *value = command;
3775 int targetRate;
Leo Chang1f98cbd2013-10-17 15:03:52 -07003776 tSirRateUpdateInd *rateUpdate;
3777 eHalStatus status;
Leo Chang614d2072013-08-22 14:59:44 -07003778
3779 /* Only valid for SAP mode */
3780 if (WLAN_HDD_SOFTAP != pAdapter->device_mode)
3781 {
3782 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3783 "%s: SAP mode is not running", __func__);
3784 ret = -EFAULT;
3785 goto exit;
3786 }
3787
3788 /* Move pointer to ahead of SETMCRATE<delimiter> */
3789 /* input value is in units of hundred kbps */
3790 value = value + 10;
3791 /* Convert the value from ascii to integer, decimal base */
3792 ret = kstrtouint(value, 10, &targetRate);
3793
Leo Chang1f98cbd2013-10-17 15:03:52 -07003794 rateUpdate = (tSirRateUpdateInd *)vos_mem_malloc(sizeof(tSirRateUpdateInd));
3795 if (NULL == rateUpdate)
Leo Chang614d2072013-08-22 14:59:44 -07003796 {
Leo Chang1f98cbd2013-10-17 15:03:52 -07003797 hddLog(VOS_TRACE_LEVEL_ERROR,
3798 "%s: SETMCRATE indication alloc fail", __func__);
3799 ret = -EFAULT;
3800 goto exit;
3801 }
3802 vos_mem_zero(rateUpdate, sizeof(tSirRateUpdateInd ));
3803
3804 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3805 "MC Target rate %d", targetRate);
3806 /* Ignore unicast */
3807 rateUpdate->ucastDataRate = -1;
3808 rateUpdate->mcastDataRate24GHz = targetRate;
3809 rateUpdate->mcastDataRate5GHz = targetRate;
3810 rateUpdate->mcastDataRate24GHzTxFlag = 0;
3811 rateUpdate->mcastDataRate5GHzTxFlag = 0;
3812 status = sme_SendRateUpdateInd(pHddCtx->hHal, rateUpdate);
3813 if (eHAL_STATUS_SUCCESS != status)
3814 {
3815 hddLog(VOS_TRACE_LEVEL_ERROR,
3816 "%s: SET_MC_RATE failed", __func__);
3817 vos_mem_free(rateUpdate);
3818 ret = -EFAULT;
3819 goto exit;
Leo Chang614d2072013-08-22 14:59:44 -07003820 }
3821 }
Rajeev79dbe4c2013-10-05 11:03:42 +05303822#ifdef FEATURE_WLAN_BATCH_SCAN
Rajeev Kumar8b373292014-01-08 20:36:55 -08003823 else if (strncmp(command, "WLS_BATCHING", 12) == 0)
Rajeev79dbe4c2013-10-05 11:03:42 +05303824 {
Rajeev Kumar8b373292014-01-08 20:36:55 -08003825 ret = hdd_handle_batch_scan_ioctl(pAdapter, &priv_data, command);
Rajeev79dbe4c2013-10-05 11:03:42 +05303826 }
3827#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003828#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003829 else if (strncmp(command, "SETCCXROAMSCANCHANNELS", 22) == 0)
3830 {
3831 tANI_U8 *value = command;
3832 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
3833 tANI_U8 numChannels = 0;
3834 eHalStatus status = eHAL_STATUS_SUCCESS;
3835
3836 status = hdd_parse_channellist(value, ChannelList, &numChannels);
3837 if (eHAL_STATUS_SUCCESS != status)
3838 {
3839 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3840 "%s: Failed to parse channel list information", __func__);
3841 ret = -EINVAL;
3842 goto exit;
3843 }
3844
3845 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
3846 {
3847 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3848 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
3849 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
3850 ret = -EINVAL;
3851 goto exit;
3852 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003853 status = sme_SetEseRoamScanChannelList((tHalHandle)(pHddCtx->hHal),
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003854 ChannelList,
3855 numChannels);
3856 if (eHAL_STATUS_SUCCESS != status)
3857 {
3858 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3859 "%s: Failed to update channel list information", __func__);
3860 ret = -EINVAL;
3861 goto exit;
3862 }
3863 }
3864 else if (strncmp(command, "GETTSMSTATS", 11) == 0)
3865 {
3866 tANI_U8 *value = command;
3867 char extra[128] = {0};
3868 int len = 0;
3869 tANI_U8 tid = 0;
3870 hdd_station_ctx_t *pHddStaCtx = NULL;
3871 tAniTrafStrmMetrics tsmMetrics;
3872 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3873
3874 /* if not associated, return error */
3875 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3876 {
3877 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:Not associated!",__func__);
3878 ret = -EINVAL;
3879 goto exit;
3880 }
3881
3882 /* Move pointer to ahead of GETTSMSTATS<delimiter> */
3883 value = value + 12;
3884 /* Convert the value from ascii to integer */
3885 ret = kstrtou8(value, 10, &tid);
3886 if (ret < 0)
3887 {
3888 /* If the input value is greater than max value of datatype, then also
3889 kstrtou8 fails */
3890 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3891 "%s: kstrtou8 failed range [%d - %d]", __func__,
3892 TID_MIN_VALUE,
3893 TID_MAX_VALUE);
3894 ret = -EINVAL;
3895 goto exit;
3896 }
3897
3898 if ((tid < TID_MIN_VALUE) || (tid > TID_MAX_VALUE))
3899 {
3900 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3901 "tid value %d is out of range"
3902 " (Min: %d Max: %d)", tid,
3903 TID_MIN_VALUE,
3904 TID_MAX_VALUE);
3905 ret = -EINVAL;
3906 goto exit;
3907 }
3908
3909 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3910 "%s: Received Command to get tsm stats tid = %d", __func__, tid);
3911
3912 if (VOS_STATUS_SUCCESS != hdd_get_tsm_stats(pAdapter, tid, &tsmMetrics))
3913 {
3914 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3915 "%s: failed to get tsm stats", __func__);
3916 ret = -EFAULT;
3917 goto exit;
3918 }
3919
3920 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3921 "UplinkPktQueueDly(%d)\n"
3922 "UplinkPktQueueDlyHist[0](%d)\n"
3923 "UplinkPktQueueDlyHist[1](%d)\n"
3924 "UplinkPktQueueDlyHist[2](%d)\n"
3925 "UplinkPktQueueDlyHist[3](%d)\n"
Arun Kumar Khandavallie8768212014-02-17 16:43:34 +05303926 "UplinkPktTxDly(%u)\n"
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003927 "UplinkPktLoss(%d)\n"
3928 "UplinkPktCount(%d)\n"
3929 "RoamingCount(%d)\n"
3930 "RoamingDly(%d)", tsmMetrics.UplinkPktQueueDly,
3931 tsmMetrics.UplinkPktQueueDlyHist[0],
3932 tsmMetrics.UplinkPktQueueDlyHist[1],
3933 tsmMetrics.UplinkPktQueueDlyHist[2],
3934 tsmMetrics.UplinkPktQueueDlyHist[3],
3935 tsmMetrics.UplinkPktTxDly, tsmMetrics.UplinkPktLoss,
3936 tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount, tsmMetrics.RoamingDly);
3937
3938 /* Output TSM stats is of the format
3939 GETTSMSTATS [PktQueueDly] [PktQueueDlyHist[0]]:[PktQueueDlyHist[1]] ...[RoamingDly]
3940 eg., GETTSMSTATS 10 1:0:0:161 20 1 17 8 39800 */
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003941 len = scnprintf(extra, sizeof(extra), "%s %d %d:%d:%d:%d %u %d %d %d %d", command,
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003942 tsmMetrics.UplinkPktQueueDly, tsmMetrics.UplinkPktQueueDlyHist[0],
3943 tsmMetrics.UplinkPktQueueDlyHist[1], tsmMetrics.UplinkPktQueueDlyHist[2],
3944 tsmMetrics.UplinkPktQueueDlyHist[3], tsmMetrics.UplinkPktTxDly,
3945 tsmMetrics.UplinkPktLoss, tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount,
3946 tsmMetrics.RoamingDly);
3947
3948 if (copy_to_user(priv_data.buf, &extra, len + 1))
3949 {
3950 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3951 "%s: failed to copy data to user buffer", __func__);
3952 ret = -EFAULT;
3953 goto exit;
3954 }
3955 }
3956 else if (strncmp(command, "SETCCKMIE", 9) == 0)
3957 {
3958 tANI_U8 *value = command;
3959 tANI_U8 *cckmIe = NULL;
3960 tANI_U8 cckmIeLen = 0;
3961 eHalStatus status = eHAL_STATUS_SUCCESS;
3962
3963 status = hdd_parse_get_cckm_ie(value, &cckmIe, &cckmIeLen);
3964 if (eHAL_STATUS_SUCCESS != status)
3965 {
3966 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3967 "%s: Failed to parse cckm ie data", __func__);
3968 ret = -EINVAL;
3969 goto exit;
3970 }
3971
3972 if (cckmIeLen > DOT11F_IE_RSN_MAX_LEN)
3973 {
3974 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3975 "%s: CCKM Ie input length is more than max[%d]", __func__,
3976 DOT11F_IE_RSN_MAX_LEN);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08003977 vos_mem_free(cckmIe);
3978 cckmIe = NULL;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003979 ret = -EINVAL;
3980 goto exit;
3981 }
3982 sme_SetCCKMIe((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, cckmIe, cckmIeLen);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08003983 vos_mem_free(cckmIe);
3984 cckmIe = NULL;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003985 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003986 else if (strncmp(command, "CCXBEACONREQ", 12) == 0)
3987 {
3988 tANI_U8 *value = command;
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003989 tCsrEseBeaconReq eseBcnReq;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003990 eHalStatus status = eHAL_STATUS_SUCCESS;
Srinivas Girigowda0c6d7fe2014-05-28 18:18:10 -07003991
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003992 status = hdd_parse_ese_beacon_req(value, &eseBcnReq);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003993 if (eHAL_STATUS_SUCCESS != status)
3994 {
3995 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003996 "%s: Failed to parse ese beacon req", __func__);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003997 ret = -EINVAL;
3998 goto exit;
3999 }
Srinivas Girigowda0c6d7fe2014-05-28 18:18:10 -07004000 if (!hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))) {
4001 hddLog(VOS_TRACE_LEVEL_INFO, FL("Not associated"));
4002 hdd_indicateEseBcnReportNoResults (pAdapter,
4003 eseBcnReq.bcnReq[0].measurementToken,
4004 0x02, //BIT(1) set for measurement done
4005 0); // no BSS
4006 goto exit;
4007 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004008
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004009 status = sme_SetEseBeaconRequest((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, &eseBcnReq);
4010 if (eHAL_STATUS_SUCCESS != status)
4011 {
4012 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4013 "%s: sme_SetEseBeaconRequest failed (%d)", __func__, status);
4014 ret = -EINVAL;
4015 goto exit;
4016 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004017 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004018#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
c_hpothu92367912014-05-01 15:18:17 +05304019 else if (strncmp(command, "GETBCNMISSRATE", 14) == 0)
4020 {
4021 eHalStatus status;
4022 char buf[32], len;
4023 long waitRet;
4024 bcnMissRateContext_t getBcnMissRateCtx;
4025
4026 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4027
4028 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
4029 {
4030 hddLog(VOS_TRACE_LEVEL_WARN,
4031 FL("GETBCNMISSRATE: STA is not in connected state"));
4032 ret = -1;
4033 goto exit;
4034 }
4035
4036 init_completion(&(getBcnMissRateCtx.completion));
4037 getBcnMissRateCtx.magic = BCN_MISS_RATE_CONTEXT_MAGIC;
4038
4039 status = sme_getBcnMissRate((tHalHandle)(pHddCtx->hHal),
4040 pAdapter->sessionId,
4041 (void *)getBcnMissRateCB,
4042 (void *)(&getBcnMissRateCtx));
4043 if( eHAL_STATUS_SUCCESS != status)
4044 {
4045 hddLog(VOS_TRACE_LEVEL_INFO,
4046 FL("GETBCNMISSRATE: fail to post WDA cmd"));
4047 ret = -EINVAL;
4048 goto exit;
4049 }
4050
4051 waitRet = wait_for_completion_interruptible_timeout
4052 (&getBcnMissRateCtx.completion, BCN_MISS_RATE_TIME);
4053 if(waitRet <= 0)
4054 {
4055 hddLog(VOS_TRACE_LEVEL_ERROR,
4056 FL("failed to wait on bcnMissRateComp %d"), ret);
4057
4058 //Make magic number to zero so that callback is not called.
4059 spin_lock(&hdd_context_lock);
4060 getBcnMissRateCtx.magic = 0x0;
4061 spin_unlock(&hdd_context_lock);
4062 ret = -EINVAL;
4063 goto exit;
4064 }
4065
4066 hddLog(VOS_TRACE_LEVEL_INFO,
4067 FL("GETBCNMISSRATE: bcnMissRate: %d"), gbcnMissRate);
4068
4069 len = snprintf(buf, sizeof(buf), "GETBCNMISSRATE %d", gbcnMissRate);
4070 if (copy_to_user(priv_data.buf, &buf, len + 1))
4071 {
4072 hddLog(VOS_TRACE_LEVEL_ERROR,
4073 "%s: failed to copy data to user buffer", __func__);
4074 ret = -EFAULT;
4075 goto exit;
4076 }
4077 ret = len;
4078 }
Atul Mittal87ec2422014-09-24 13:12:50 +05304079#ifdef FEATURE_WLAN_TDLS
4080 else if (strncmp(command, "TDLSSECONDARYCHANNELOFFSET", 26) == 0) {
4081 tANI_U8 *value = command;
4082 int set_value;
4083 /* Move pointer to ahead of TDLSOFFCH*/
4084 value += 26;
4085 sscanf(value, "%d", &set_value);
4086 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4087 "%s: Tdls offchannel offset:%d",
4088 __func__, set_value);
4089 ret = iw_set_tdlssecoffchanneloffset(pHddCtx, set_value);
4090 if (ret < 0)
4091 {
4092 ret = -EINVAL;
4093 goto exit;
4094 }
4095
4096 } else if (strncmp(command, "TDLSOFFCHANNELMODE", 18) == 0) {
4097 tANI_U8 *value = command;
4098 int set_value;
4099 /* Move pointer to ahead of tdlsoffchnmode*/
4100 value += 18;
4101 sscanf(value, "%d", &set_value);
4102 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4103 "%s: Tdls offchannel mode:%d",
4104 __func__, set_value);
4105 ret = iw_set_tdlsoffchannelmode(pAdapter, set_value);
4106 if (ret < 0)
4107 {
4108 ret = -EINVAL;
4109 goto exit;
4110 }
4111 } else if (strncmp(command, "TDLSOFFCHANNEL", 14) == 0) {
4112 tANI_U8 *value = command;
4113 int set_value;
4114 /* Move pointer to ahead of TDLSOFFCH*/
4115 value += 14;
4116 sscanf(value, "%d", &set_value);
4117 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4118 "%s: Tdls offchannel num: %d",
4119 __func__, set_value);
4120 ret = iw_set_tdlsoffchannel(pHddCtx, set_value);
4121 if (ret < 0)
4122 {
4123 ret = -EINVAL;
4124 goto exit;
4125 }
4126 }
4127#endif
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07004128 else {
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05304129 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
4130 TRACE_CODE_HDD_UNSUPPORTED_IOCTL,
4131 pAdapter->sessionId, 0));
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07004132 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
4133 __func__, command);
4134 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004135 }
4136exit:
4137 if (command)
4138 {
4139 kfree(command);
4140 }
4141 return ret;
4142}
4143
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07004144#ifdef CONFIG_COMPAT
4145static int hdd_driver_compat_ioctl(hdd_adapter_t *pAdapter, struct ifreq *ifr)
4146{
4147 struct {
4148 compat_uptr_t buf;
4149 int used_len;
4150 int total_len;
4151 } compat_priv_data;
4152 hdd_priv_data_t priv_data;
4153 int ret = 0;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004154
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07004155 /*
4156 * Note that pAdapter and ifr have already been verified by caller,
4157 * and HDD context has also been validated
4158 */
4159 if (copy_from_user(&compat_priv_data, ifr->ifr_data,
4160 sizeof(compat_priv_data))) {
4161 ret = -EFAULT;
4162 goto exit;
4163 }
4164 priv_data.buf = compat_ptr(compat_priv_data.buf);
4165 priv_data.used_len = compat_priv_data.used_len;
4166 priv_data.total_len = compat_priv_data.total_len;
4167 ret = hdd_driver_command(pAdapter, &priv_data);
4168 exit:
4169 return ret;
4170}
4171#else /* CONFIG_COMPAT */
4172static int hdd_driver_compat_ioctl(hdd_adapter_t *pAdapter, struct ifreq *ifr)
4173{
4174 /* will never be invoked */
4175 return 0;
4176}
4177#endif /* CONFIG_COMPAT */
4178
4179static int hdd_driver_ioctl(hdd_adapter_t *pAdapter, struct ifreq *ifr)
4180{
4181 hdd_priv_data_t priv_data;
4182 int ret = 0;
4183
4184 /*
4185 * Note that pAdapter and ifr have already been verified by caller,
4186 * and HDD context has also been validated
4187 */
4188 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(priv_data))) {
4189 ret = -EFAULT;
4190 } else {
4191 ret = hdd_driver_command(pAdapter, &priv_data);
4192 }
4193 return ret;
4194}
4195
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05304196int __hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07004197{
4198 hdd_adapter_t *pAdapter;
4199 hdd_context_t *pHddCtx;
4200 int ret;
4201
4202 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4203 if (NULL == pAdapter) {
4204 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4205 "%s: HDD adapter context is Null", __func__);
4206 ret = -ENODEV;
4207 goto exit;
4208 }
4209 if (dev != pAdapter->dev) {
4210 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4211 "%s: HDD adapter/dev inconsistency", __func__);
4212 ret = -ENODEV;
4213 goto exit;
4214 }
4215
4216 if ((!ifr) || (!ifr->ifr_data)) {
4217 ret = -EINVAL;
4218 goto exit;
4219 }
4220
4221 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4222 ret = wlan_hdd_validate_context(pHddCtx);
4223 if (ret) {
4224 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4225 "%s: invalid context", __func__);
4226 ret = -EBUSY;
4227 goto exit;
4228 }
4229
4230 switch (cmd) {
4231 case (SIOCDEVPRIVATE + 1):
4232 if (is_compat_task())
4233 ret = hdd_driver_compat_ioctl(pAdapter, ifr);
4234 else
4235 ret = hdd_driver_ioctl(pAdapter, ifr);
4236 break;
4237 default:
4238 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unknown ioctl %d",
4239 __func__, cmd);
4240 ret = -EINVAL;
4241 break;
4242 }
4243 exit:
4244 return ret;
4245}
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004246
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05304247int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
4248{
4249 int ret;
4250
4251 vos_ssr_protect(__func__);
4252 ret = __hdd_ioctl(dev, ifr, cmd);
4253 vos_ssr_unprotect(__func__);
4254
4255 return ret;
4256}
4257
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004258#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004259/**---------------------------------------------------------------------------
4260
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004261 \brief hdd_parse_ese_beacon_req() - Parse ese beacon request
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004262
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004263 This function parses the ese beacon request passed in the format
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004264 CCXBEACONREQ<space><Number of fields><space><Measurement token>
4265 <space>Channel 1<space>Scan Mode <space>Meas Duration<space>Channel N
4266 <space>Scan Mode N<space>Meas Duration N
4267 if the Number of bcn req fields (N) does not match with the actual number of fields passed
4268 then take N.
4269 <Meas Token><Channel><Scan Mode> and <Meas Duration> are treated as one pair
4270 For example, CCXBEACONREQ 2 1 1 1 30 2 44 0 40.
4271 This function does not take care of removing duplicate channels from the list
4272
4273 \param - pValue Pointer to data
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004274 \param - pEseBcnReq output pointer to store parsed ie information
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004275
4276 \return - 0 for success non-zero for failure
4277
4278 --------------------------------------------------------------------------*/
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004279static VOS_STATUS hdd_parse_ese_beacon_req(tANI_U8 *pValue,
4280 tCsrEseBeaconReq *pEseBcnReq)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004281{
4282 tANI_U8 *inPtr = pValue;
4283 int tempInt = 0;
4284 int j = 0, i = 0, v = 0;
4285 char buf[32];
4286
4287 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4288 /*no argument after the command*/
4289 if (NULL == inPtr)
4290 {
4291 return -EINVAL;
4292 }
4293 /*no space after the command*/
4294 else if (SPACE_ASCII_VALUE != *inPtr)
4295 {
4296 return -EINVAL;
4297 }
4298
4299 /*removing empty spaces*/
4300 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
4301
4302 /*no argument followed by spaces*/
4303 if ('\0' == *inPtr) return -EINVAL;
4304
4305 /*getting the first argument ie measurement token*/
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004306 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004307 if (1 != v) return -EINVAL;
4308
4309 v = kstrtos32(buf, 10, &tempInt);
4310 if ( v < 0) return -EINVAL;
4311
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004312 pEseBcnReq->numBcnReqIe = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004313
4314 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004315 "Number of Bcn Req Ie fields(%d)", pEseBcnReq->numBcnReqIe);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004316
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004317 for (j = 0; j < (pEseBcnReq->numBcnReqIe); j++)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004318 {
4319 for (i = 0; i < 4; i++)
4320 {
4321 /*inPtr pointing to the beginning of first space after number of ie fields*/
4322 inPtr = strpbrk( inPtr, " " );
4323 /*no ie data after the number of ie fields argument*/
4324 if (NULL == inPtr) return -EINVAL;
4325
4326 /*removing empty space*/
4327 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
4328
4329 /*no ie data after the number of ie fields argument and spaces*/
4330 if ( '\0' == *inPtr ) return -EINVAL;
4331
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004332 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004333 if (1 != v) return -EINVAL;
4334
4335 v = kstrtos32(buf, 10, &tempInt);
4336 if (v < 0) return -EINVAL;
4337
4338 switch (i)
4339 {
4340 case 0: /* Measurement token */
4341 if (tempInt <= 0)
4342 {
4343 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4344 "Invalid Measurement Token(%d)", tempInt);
4345 return -EINVAL;
4346 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004347 pEseBcnReq->bcnReq[j].measurementToken = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004348 break;
4349
4350 case 1: /* Channel number */
4351 if ((tempInt <= 0) ||
4352 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4353 {
4354 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4355 "Invalid Channel Number(%d)", tempInt);
4356 return -EINVAL;
4357 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004358 pEseBcnReq->bcnReq[j].channel = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004359 break;
4360
4361 case 2: /* Scan mode */
Varun Reddy Yeturu0b18d5a2013-12-04 11:42:23 -08004362 if ((tempInt < eSIR_PASSIVE_SCAN) || (tempInt > eSIR_BEACON_TABLE))
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004363 {
4364 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4365 "Invalid Scan Mode(%d) Expected{0|1|2}", tempInt);
4366 return -EINVAL;
4367 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004368 pEseBcnReq->bcnReq[j].scanMode= tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004369 break;
4370
4371 case 3: /* Measurement duration */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004372 if (((tempInt <= 0) && (pEseBcnReq->bcnReq[j].scanMode != eSIR_BEACON_TABLE)) ||
4373 ((tempInt < 0) && (pEseBcnReq->bcnReq[j].scanMode == eSIR_BEACON_TABLE)))
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004374 {
4375 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4376 "Invalid Measurement Duration(%d)", tempInt);
4377 return -EINVAL;
4378 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004379 pEseBcnReq->bcnReq[j].measurementDuration = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004380 break;
4381 }
4382 }
4383 }
4384
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004385 for (j = 0; j < pEseBcnReq->numBcnReqIe; j++)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004386 {
4387 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arun Kumar Khandavallie8768212014-02-17 16:43:34 +05304388 "Index(%d) Measurement Token(%u)Channel(%u) Scan Mode(%u) Measurement Duration(%u)\n",
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004389 j,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004390 pEseBcnReq->bcnReq[j].measurementToken,
4391 pEseBcnReq->bcnReq[j].channel,
4392 pEseBcnReq->bcnReq[j].scanMode,
4393 pEseBcnReq->bcnReq[j].measurementDuration);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004394 }
4395
4396 return VOS_STATUS_SUCCESS;
4397}
4398
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004399static void hdd_GetTsmStatsCB( tAniTrafStrmMetrics tsmMetrics, const tANI_U32 staId, void *pContext )
4400{
4401 struct statsContext *pStatsContext = NULL;
4402 hdd_adapter_t *pAdapter = NULL;
4403
4404 if (NULL == pContext)
4405 {
4406 hddLog(VOS_TRACE_LEVEL_ERROR,
4407 "%s: Bad param, pContext [%p]",
4408 __func__, pContext);
4409 return;
4410 }
4411
Jeff Johnson72a40512013-12-19 10:14:15 -08004412 /* there is a race condition that exists between this callback
4413 function and the caller since the caller could time out either
4414 before or while this code is executing. we use a spinlock to
4415 serialize these actions */
4416 spin_lock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004417
4418 pStatsContext = pContext;
4419 pAdapter = pStatsContext->pAdapter;
4420 if ((NULL == pAdapter) || (STATS_CONTEXT_MAGIC != pStatsContext->magic))
4421 {
4422 /* the caller presumably timed out so there is nothing we can do */
Jeff Johnson72a40512013-12-19 10:14:15 -08004423 spin_unlock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004424 hddLog(VOS_TRACE_LEVEL_WARN,
4425 "%s: Invalid context, pAdapter [%p] magic [%08x]",
4426 __func__, pAdapter, pStatsContext->magic);
4427 return;
4428 }
4429
Jeff Johnson72a40512013-12-19 10:14:15 -08004430 /* context is valid so caller is still waiting */
4431
4432 /* paranoia: invalidate the magic */
4433 pStatsContext->magic = 0;
4434
4435 /* copy over the tsm stats */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004436 pAdapter->tsmStats.UplinkPktQueueDly = tsmMetrics.UplinkPktQueueDly;
4437 vos_mem_copy(pAdapter->tsmStats.UplinkPktQueueDlyHist,
4438 tsmMetrics.UplinkPktQueueDlyHist,
4439 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
4440 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
4441 pAdapter->tsmStats.UplinkPktTxDly = tsmMetrics.UplinkPktTxDly;
4442 pAdapter->tsmStats.UplinkPktLoss = tsmMetrics.UplinkPktLoss;
4443 pAdapter->tsmStats.UplinkPktCount = tsmMetrics.UplinkPktCount;
4444 pAdapter->tsmStats.RoamingCount = tsmMetrics.RoamingCount;
4445 pAdapter->tsmStats.RoamingDly = tsmMetrics.RoamingDly;
4446
Jeff Johnson72a40512013-12-19 10:14:15 -08004447 /* notify the caller */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004448 complete(&pStatsContext->completion);
Jeff Johnson72a40512013-12-19 10:14:15 -08004449
4450 /* serialization is complete */
4451 spin_unlock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004452}
4453
4454
4455
4456static VOS_STATUS hdd_get_tsm_stats(hdd_adapter_t *pAdapter, const tANI_U8 tid,
4457 tAniTrafStrmMetrics* pTsmMetrics)
4458{
4459 hdd_station_ctx_t *pHddStaCtx = NULL;
4460 eHalStatus hstatus;
Jeff Johnson72a40512013-12-19 10:14:15 -08004461 VOS_STATUS vstatus = VOS_STATUS_SUCCESS;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004462 long lrc;
4463 struct statsContext context;
4464 hdd_context_t *pHddCtx = NULL;
4465
4466 if (NULL == pAdapter)
4467 {
4468 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: pAdapter is NULL", __func__);
4469 return VOS_STATUS_E_FAULT;
4470 }
4471
4472 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4473 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4474
4475 /* we are connected prepare our callback context */
4476 init_completion(&context.completion);
4477 context.pAdapter = pAdapter;
4478 context.magic = STATS_CONTEXT_MAGIC;
4479
4480 /* query tsm stats */
4481 hstatus = sme_GetTsmStats(pHddCtx->hHal, hdd_GetTsmStatsCB,
4482 pHddStaCtx->conn_info.staId[ 0 ],
4483 pHddStaCtx->conn_info.bssId,
4484 &context, pHddCtx->pvosContext, tid);
4485
4486 if (eHAL_STATUS_SUCCESS != hstatus)
4487 {
Jeff Johnson72a40512013-12-19 10:14:15 -08004488 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unable to retrieve statistics",
4489 __func__);
4490 vstatus = VOS_STATUS_E_FAULT;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004491 }
4492 else
4493 {
4494 /* request was sent -- wait for the response */
4495 lrc = wait_for_completion_interruptible_timeout(&context.completion,
4496 msecs_to_jiffies(WLAN_WAIT_TIME_STATS));
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004497 if (lrc <= 0)
4498 {
4499 hddLog(VOS_TRACE_LEVEL_ERROR,
4500 "%s: SME %s while retrieving statistics",
4501 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson72a40512013-12-19 10:14:15 -08004502 vstatus = VOS_STATUS_E_TIMEOUT;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004503 }
4504 }
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004505
Jeff Johnson72a40512013-12-19 10:14:15 -08004506 /* either we never sent a request, we sent a request and received a
4507 response or we sent a request and timed out. if we never sent a
4508 request or if we sent a request and got a response, we want to
4509 clear the magic out of paranoia. if we timed out there is a
4510 race condition such that the callback function could be
4511 executing at the same time we are. of primary concern is if the
4512 callback function had already verified the "magic" but had not
4513 yet set the completion variable when a timeout occurred. we
4514 serialize these activities by invalidating the magic while
4515 holding a shared spinlock which will cause us to block if the
4516 callback is currently executing */
4517 spin_lock(&hdd_context_lock);
4518 context.magic = 0;
4519 spin_unlock(&hdd_context_lock);
4520
4521 if (VOS_STATUS_SUCCESS == vstatus)
4522 {
4523 pTsmMetrics->UplinkPktQueueDly = pAdapter->tsmStats.UplinkPktQueueDly;
4524 vos_mem_copy(pTsmMetrics->UplinkPktQueueDlyHist,
4525 pAdapter->tsmStats.UplinkPktQueueDlyHist,
4526 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
4527 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
4528 pTsmMetrics->UplinkPktTxDly = pAdapter->tsmStats.UplinkPktTxDly;
4529 pTsmMetrics->UplinkPktLoss = pAdapter->tsmStats.UplinkPktLoss;
4530 pTsmMetrics->UplinkPktCount = pAdapter->tsmStats.UplinkPktCount;
4531 pTsmMetrics->RoamingCount = pAdapter->tsmStats.RoamingCount;
4532 pTsmMetrics->RoamingDly = pAdapter->tsmStats.RoamingDly;
4533 }
4534 return vstatus;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004535}
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004536#endif /*FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004537
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004538#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -08004539void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
4540{
4541 eCsrBand band = -1;
4542 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
4543 switch (band)
4544 {
4545 case eCSR_BAND_ALL:
4546 *pBand = WLAN_HDD_UI_BAND_AUTO;
4547 break;
4548
4549 case eCSR_BAND_24:
4550 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
4551 break;
4552
4553 case eCSR_BAND_5G:
4554 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
4555 break;
4556
4557 default:
4558 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
4559 *pBand = -1;
4560 break;
4561 }
4562}
4563
4564/**---------------------------------------------------------------------------
4565
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004566 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
4567
4568 This function parses the send action frame data passed in the format
4569 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
4570
Srinivas Girigowda56076852013-08-20 14:00:50 -07004571 \param - pValue Pointer to input data
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004572 \param - pTargetApBssid Pointer to target Ap bssid
4573 \param - pChannel Pointer to the Target AP channel
4574 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
4575 \param - pBuf Pointer to data
4576 \param - pBufLen Pointer to data length
4577
4578 \return - 0 for success non-zero for failure
4579
4580 --------------------------------------------------------------------------*/
4581VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
4582 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
4583{
4584 tANI_U8 *inPtr = pValue;
4585 tANI_U8 *dataEnd;
4586 int tempInt;
4587 int j = 0;
4588 int i = 0;
4589 int v = 0;
4590 tANI_U8 tempBuf[32];
4591 tANI_U8 tempByte = 0;
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004592 /* 12 hexa decimal digits, 5 ':' and '\0' */
4593 tANI_U8 macAddress[18];
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004594
4595 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4596 /*no argument after the command*/
4597 if (NULL == inPtr)
4598 {
4599 return -EINVAL;
4600 }
4601
4602 /*no space after the command*/
4603 else if (SPACE_ASCII_VALUE != *inPtr)
4604 {
4605 return -EINVAL;
4606 }
4607
4608 /*removing empty spaces*/
4609 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4610
4611 /*no argument followed by spaces*/
4612 if ('\0' == *inPtr)
4613 {
4614 return -EINVAL;
4615 }
4616
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004617 v = sscanf(inPtr, "%17s", macAddress);
4618 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004619 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004620 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4621 "Invalid MAC address or All hex inputs are not read (%d)", v);
4622 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004623 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004624
4625 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
4626 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
4627 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
4628 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
4629 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
4630 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004631
4632 /* point to the next argument */
4633 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4634 /*no argument after the command*/
4635 if (NULL == inPtr) return -EINVAL;
4636
4637 /*removing empty spaces*/
4638 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4639
4640 /*no argument followed by spaces*/
4641 if ('\0' == *inPtr)
4642 {
4643 return -EINVAL;
4644 }
4645
4646 /*getting the next argument ie the channel number */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004647 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004648 if (1 != v) return -EINVAL;
4649
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004650 v = kstrtos32(tempBuf, 10, &tempInt);
Agarwal Ashish353b3a82014-04-08 14:55:11 +05304651 if ( v < 0 || tempInt <= 0 || tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX )
Kiet Lambe150c22013-11-21 16:30:32 +05304652 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004653
4654 *pChannel = tempInt;
4655
4656 /* point to the next argument */
4657 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4658 /*no argument after the command*/
4659 if (NULL == inPtr) return -EINVAL;
4660 /*removing empty spaces*/
4661 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4662
4663 /*no argument followed by spaces*/
4664 if ('\0' == *inPtr)
4665 {
4666 return -EINVAL;
4667 }
4668
4669 /*getting the next argument ie the dwell time */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004670 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004671 if (1 != v) return -EINVAL;
4672
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004673 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda5a6e0672014-01-09 14:42:57 -08004674 if ( v < 0 || tempInt < 0) return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004675
4676 *pDwellTime = tempInt;
4677
4678 /* point to the next argument */
4679 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4680 /*no argument after the command*/
4681 if (NULL == inPtr) return -EINVAL;
4682 /*removing empty spaces*/
4683 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4684
4685 /*no argument followed by spaces*/
4686 if ('\0' == *inPtr)
4687 {
4688 return -EINVAL;
4689 }
4690
4691 /* find the length of data */
4692 dataEnd = inPtr;
4693 while(('\0' != *dataEnd) )
4694 {
4695 dataEnd++;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004696 }
Kiet Lambe150c22013-11-21 16:30:32 +05304697 *pBufLen = dataEnd - inPtr ;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004698 if ( *pBufLen <= 0) return -EINVAL;
4699
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07004700 /* Allocate the number of bytes based on the number of input characters
4701 whether it is even or odd.
4702 if the number of input characters are even, then we need N/2 byte.
4703 if the number of input characters are odd, then we need do (N+1)/2 to
4704 compensate rounding off.
4705 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
4706 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
4707 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004708 if (NULL == *pBuf)
4709 {
4710 hddLog(VOS_TRACE_LEVEL_FATAL,
4711 "%s: vos_mem_alloc failed ", __func__);
4712 return -EINVAL;
4713 }
4714
4715 /* the buffer received from the upper layer is character buffer,
4716 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
4717 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
4718 and f0 in 3rd location */
4719 for (i = 0, j = 0; j < *pBufLen; j += 2)
4720 {
Kiet Lambe150c22013-11-21 16:30:32 +05304721 if( j+1 == *pBufLen)
4722 {
4723 tempByte = hdd_parse_hex(inPtr[j]);
4724 }
4725 else
4726 {
4727 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
4728 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004729 (*pBuf)[i++] = tempByte;
4730 }
4731 *pBufLen = i;
4732 return VOS_STATUS_SUCCESS;
4733}
4734
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004735/**---------------------------------------------------------------------------
4736
Srinivas Girigowdade697412013-02-14 16:31:48 -08004737 \brief hdd_parse_channellist() - HDD Parse channel list
4738
4739 This function parses the channel list passed in the format
4740 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004741 if the Number of channels (N) does not match with the actual number of channels passed
4742 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
4743 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
4744 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
4745 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08004746
4747 \param - pValue Pointer to input channel list
4748 \param - ChannelList Pointer to local output array to record channel list
4749 \param - pNumChannels Pointer to number of roam scan channels
4750
4751 \return - 0 for success non-zero for failure
4752
4753 --------------------------------------------------------------------------*/
4754VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
4755{
4756 tANI_U8 *inPtr = pValue;
4757 int tempInt;
4758 int j = 0;
4759 int v = 0;
4760 char buf[32];
4761
4762 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4763 /*no argument after the command*/
4764 if (NULL == inPtr)
4765 {
4766 return -EINVAL;
4767 }
4768
4769 /*no space after the command*/
4770 else if (SPACE_ASCII_VALUE != *inPtr)
4771 {
4772 return -EINVAL;
4773 }
4774
4775 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004776 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08004777
4778 /*no argument followed by spaces*/
4779 if ('\0' == *inPtr)
4780 {
4781 return -EINVAL;
4782 }
4783
4784 /*getting the first argument ie the number of channels*/
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004785 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004786 if (1 != v) return -EINVAL;
4787
Srinivas Girigowdade697412013-02-14 16:31:48 -08004788 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004789 if ((v < 0) ||
4790 (tempInt <= 0) ||
4791 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
4792 {
4793 return -EINVAL;
4794 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004795
4796 *pNumChannels = tempInt;
4797
4798 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
4799 "Number of channels are: %d", *pNumChannels);
4800
4801 for (j = 0; j < (*pNumChannels); j++)
4802 {
4803 /*inPtr pointing to the beginning of first space after number of channels*/
4804 inPtr = strpbrk( inPtr, " " );
4805 /*no channel list after the number of channels argument*/
4806 if (NULL == inPtr)
4807 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004808 if (0 != j)
4809 {
4810 *pNumChannels = j;
4811 return VOS_STATUS_SUCCESS;
4812 }
4813 else
4814 {
4815 return -EINVAL;
4816 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004817 }
4818
4819 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004820 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08004821
4822 /*no channel list after the number of channels argument and spaces*/
4823 if ( '\0' == *inPtr )
4824 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004825 if (0 != j)
4826 {
4827 *pNumChannels = j;
4828 return VOS_STATUS_SUCCESS;
4829 }
4830 else
4831 {
4832 return -EINVAL;
4833 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004834 }
4835
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004836 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004837 if (1 != v) return -EINVAL;
4838
Srinivas Girigowdade697412013-02-14 16:31:48 -08004839 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004840 if ((v < 0) ||
4841 (tempInt <= 0) ||
4842 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4843 {
4844 return -EINVAL;
4845 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004846 pChannelList[j] = tempInt;
4847
4848 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
4849 "Channel %d added to preferred channel list",
4850 pChannelList[j] );
4851 }
4852
Srinivas Girigowdade697412013-02-14 16:31:48 -08004853 return VOS_STATUS_SUCCESS;
4854}
4855
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004856
4857/**---------------------------------------------------------------------------
4858
4859 \brief hdd_parse_reassoc_command_data() - HDD Parse reassoc command data
4860
4861 This function parses the reasoc command data passed in the format
4862 REASSOC<space><bssid><space><channel>
4863
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004864 \param - pValue Pointer to input data (its a NUL terminated string)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004865 \param - pTargetApBssid Pointer to target Ap bssid
4866 \param - pChannel Pointer to the Target AP channel
4867
4868 \return - 0 for success non-zero for failure
4869
4870 --------------------------------------------------------------------------*/
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004871VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue,
4872 tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004873{
4874 tANI_U8 *inPtr = pValue;
4875 int tempInt;
4876 int v = 0;
4877 tANI_U8 tempBuf[32];
Kiet Lamaa8e15a2014-02-11 23:30:06 -08004878 /* 12 hexa decimal digits, 5 ':' and '\0' */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004879 tANI_U8 macAddress[18];
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004880
4881 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4882 /*no argument after the command*/
4883 if (NULL == inPtr)
4884 {
4885 return -EINVAL;
4886 }
4887
4888 /*no space after the command*/
4889 else if (SPACE_ASCII_VALUE != *inPtr)
4890 {
4891 return -EINVAL;
4892 }
4893
4894 /*removing empty spaces*/
4895 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4896
4897 /*no argument followed by spaces*/
4898 if ('\0' == *inPtr)
4899 {
4900 return -EINVAL;
4901 }
4902
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004903 v = sscanf(inPtr, "%17s", macAddress);
4904 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004905 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004906 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4907 "Invalid MAC address or All hex inputs are not read (%d)", v);
4908 return -EINVAL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004909 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004910
4911 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
4912 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
4913 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
4914 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
4915 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
4916 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004917
4918 /* point to the next argument */
4919 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4920 /*no argument after the command*/
4921 if (NULL == inPtr) return -EINVAL;
4922
4923 /*removing empty spaces*/
4924 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4925
4926 /*no argument followed by spaces*/
4927 if ('\0' == *inPtr)
4928 {
4929 return -EINVAL;
4930 }
4931
4932 /*getting the next argument ie the channel number */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004933 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004934 if (1 != v) return -EINVAL;
4935
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004936 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004937 if ((v < 0) ||
4938 (tempInt <= 0) ||
4939 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4940 {
4941 return -EINVAL;
4942 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004943
4944 *pChannel = tempInt;
4945 return VOS_STATUS_SUCCESS;
4946}
4947
4948#endif
4949
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004950#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004951/**---------------------------------------------------------------------------
4952
4953 \brief hdd_parse_get_cckm_ie() - HDD Parse and fetch the CCKM IE
4954
4955 This function parses the SETCCKM IE command
4956 SETCCKMIE<space><ie data>
4957
4958 \param - pValue Pointer to input data
4959 \param - pCckmIe Pointer to output cckm Ie
4960 \param - pCckmIeLen Pointer to output cckm ie length
4961
4962 \return - 0 for success non-zero for failure
4963
4964 --------------------------------------------------------------------------*/
4965VOS_STATUS hdd_parse_get_cckm_ie(tANI_U8 *pValue, tANI_U8 **pCckmIe,
4966 tANI_U8 *pCckmIeLen)
4967{
4968 tANI_U8 *inPtr = pValue;
4969 tANI_U8 *dataEnd;
4970 int j = 0;
4971 int i = 0;
4972 tANI_U8 tempByte = 0;
4973
4974 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4975 /*no argument after the command*/
4976 if (NULL == inPtr)
4977 {
4978 return -EINVAL;
4979 }
4980
4981 /*no space after the command*/
4982 else if (SPACE_ASCII_VALUE != *inPtr)
4983 {
4984 return -EINVAL;
4985 }
4986
4987 /*removing empty spaces*/
4988 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4989
4990 /*no argument followed by spaces*/
4991 if ('\0' == *inPtr)
4992 {
4993 return -EINVAL;
4994 }
4995
4996 /* find the length of data */
4997 dataEnd = inPtr;
4998 while(('\0' != *dataEnd) )
4999 {
5000 dataEnd++;
5001 ++(*pCckmIeLen);
5002 }
5003 if ( *pCckmIeLen <= 0) return -EINVAL;
5004
5005 /* Allocate the number of bytes based on the number of input characters
5006 whether it is even or odd.
5007 if the number of input characters are even, then we need N/2 byte.
5008 if the number of input characters are odd, then we need do (N+1)/2 to
5009 compensate rounding off.
5010 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
5011 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
5012 *pCckmIe = vos_mem_malloc((*pCckmIeLen + 1)/2);
5013 if (NULL == *pCckmIe)
5014 {
5015 hddLog(VOS_TRACE_LEVEL_FATAL,
5016 "%s: vos_mem_alloc failed ", __func__);
5017 return -EINVAL;
5018 }
5019 vos_mem_zero(*pCckmIe, (*pCckmIeLen + 1)/2);
5020 /* the buffer received from the upper layer is character buffer,
5021 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
5022 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
5023 and f0 in 3rd location */
5024 for (i = 0, j = 0; j < *pCckmIeLen; j += 2)
5025 {
5026 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
5027 (*pCckmIe)[i++] = tempByte;
5028 }
5029 *pCckmIeLen = i;
5030
5031 return VOS_STATUS_SUCCESS;
5032}
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08005033#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07005034
Jeff Johnson295189b2012-06-20 16:38:30 -07005035/**---------------------------------------------------------------------------
5036
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07005037 \brief hdd_is_valid_mac_address() - Validate MAC address
5038
5039 This function validates whether the given MAC address is valid or not
5040 Expected MAC address is of the format XX:XX:XX:XX:XX:XX
5041 where X is the hexa decimal digit character and separated by ':'
5042 This algorithm works even if MAC address is not separated by ':'
5043
5044 This code checks given input string mac contains exactly 12 hexadecimal digits.
5045 and a separator colon : appears in the input string only after
5046 an even number of hex digits.
5047
5048 \param - pMacAddr pointer to the input MAC address
5049 \return - 1 for valid and 0 for invalid
5050
5051 --------------------------------------------------------------------------*/
5052
5053v_BOOL_t hdd_is_valid_mac_address(const tANI_U8 *pMacAddr)
5054{
5055 int xdigit = 0;
5056 int separator = 0;
5057 while (*pMacAddr)
5058 {
5059 if (isxdigit(*pMacAddr))
5060 {
5061 xdigit++;
5062 }
5063 else if (':' == *pMacAddr)
5064 {
5065 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
5066 break;
5067
5068 ++separator;
5069 }
5070 else
5071 {
5072 separator = -1;
5073 /* Invalid MAC found */
5074 return 0;
5075 }
5076 ++pMacAddr;
5077 }
5078 return (xdigit == 12 && (separator == 5 || separator == 0));
5079}
5080
5081/**---------------------------------------------------------------------------
5082
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305083 \brief __hdd_open() - HDD Open function
Jeff Johnson295189b2012-06-20 16:38:30 -07005084
5085 \param - dev Pointer to net_device structure
5086
5087 \return - 0 for success non-zero for failure
5088
5089 --------------------------------------------------------------------------*/
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305090int __hdd_open(struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07005091{
5092 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5093 hdd_context_t *pHddCtx;
5094 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5095 VOS_STATUS status;
5096 v_BOOL_t in_standby = TRUE;
5097
5098 if (NULL == pAdapter)
5099 {
5100 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Agarwal Ashish971c2882013-10-30 20:11:12 +05305101 "%s: pAdapter is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005102 return -ENODEV;
5103 }
5104
5105 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05305106 MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_OPEN_REQUEST,
5107 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson295189b2012-06-20 16:38:30 -07005108 if (NULL == pHddCtx)
5109 {
5110 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005111 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005112 return -ENODEV;
5113 }
5114
5115 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5116 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
5117 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07005118 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
5119 {
5120 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305121 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07005122 in_standby = FALSE;
5123 break;
5124 }
5125 else
5126 {
5127 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5128 pAdapterNode = pNext;
5129 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005130 }
5131
5132 if (TRUE == in_standby)
5133 {
5134 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
5135 {
5136 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
5137 "wlan out of power save", __func__);
5138 return -EINVAL;
5139 }
5140 }
5141
Jeff Johnson6a81ca42013-04-05 10:37:08 -07005142 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07005143 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
5144 {
5145 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005146 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005147 /* Enable TX queues only when we are connected */
5148 netif_tx_start_all_queues(dev);
5149 }
5150
5151 return 0;
5152}
5153
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305154/**---------------------------------------------------------------------------
5155
5156 \brief hdd_open() - Wrapper function for __hdd_open to protect it from SSR
5157
5158 This is called in response to ifconfig up
5159
5160 \param - dev Pointer to net_device structure
5161
5162 \return - 0 for success non-zero for failure
5163
5164 --------------------------------------------------------------------------*/
5165int hdd_open(struct net_device *dev)
5166{
5167 int ret;
5168
5169 vos_ssr_protect(__func__);
5170 ret = __hdd_open(dev);
5171 vos_ssr_unprotect(__func__);
5172
5173 return ret;
5174}
5175
Jeff Johnson295189b2012-06-20 16:38:30 -07005176int hdd_mon_open (struct net_device *dev)
5177{
5178 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5179
5180 if(pAdapter == NULL) {
5181 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005182 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005183 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005184 }
5185
5186 netif_start_queue(dev);
5187
5188 return 0;
5189}
5190/**---------------------------------------------------------------------------
5191
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305192 \brief __hdd_stop() - HDD stop function
Jeff Johnson295189b2012-06-20 16:38:30 -07005193
5194 \param - dev Pointer to net_device structure
5195
5196 \return - 0 for success non-zero for failure
5197
5198 --------------------------------------------------------------------------*/
5199
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305200int __hdd_stop (struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07005201{
5202 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5203 hdd_context_t *pHddCtx;
5204 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5205 VOS_STATUS status;
5206 v_BOOL_t enter_standby = TRUE;
5207
5208 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005209 if (NULL == pAdapter)
5210 {
5211 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Agarwal Ashish971c2882013-10-30 20:11:12 +05305212 "%s: pAdapter is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005213 return -ENODEV;
5214 }
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05305215 MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_OPEN_REQUEST,
5216 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson295189b2012-06-20 16:38:30 -07005217 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
5218 if (NULL == pHddCtx)
5219 {
5220 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005221 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005222 return -ENODEV;
5223 }
5224
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05305225 /* Nothing to be done if the interface is not opened */
5226 if (VOS_FALSE == test_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags))
5227 {
5228 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5229 "%s: NETDEV Interface is not OPENED", __func__);
5230 return -ENODEV;
5231 }
5232
5233 /* Make sure the interface is marked as closed */
Jeff Johnson6a81ca42013-04-05 10:37:08 -07005234 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07005235 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05305236
5237 /* Disable TX on the interface, after this hard_start_xmit() will not
5238 * be called on that interface
5239 */
Jeff Johnson295189b2012-06-20 16:38:30 -07005240 netif_tx_disable(pAdapter->dev);
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05305241
5242 /* Mark the interface status as "down" for outside world */
Jeff Johnson295189b2012-06-20 16:38:30 -07005243 netif_carrier_off(pAdapter->dev);
5244
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05305245 /* The interface is marked as down for outside world (aka kernel)
5246 * But the driver is pretty much alive inside. The driver needs to
5247 * tear down the existing connection on the netdev (session)
5248 * cleanup the data pipes and wait until the control plane is stabilized
5249 * for this interface. The call also needs to wait until the above
5250 * mentioned actions are completed before returning to the caller.
5251 * Notice that the hdd_stop_adapter is requested not to close the session
5252 * That is intentional to be able to scan if it is a STA/P2P interface
5253 */
5254 hdd_stop_adapter(pHddCtx, pAdapter, VOS_FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -07005255
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05305256 /* DeInit the adapter. This ensures datapath cleanup as well */
5257 hdd_deinit_adapter(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005258 /* SoftAP ifaces should never go in power save mode
5259 making sure same here. */
5260 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
5261 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07005262 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07005263 )
5264 {
5265 /* SoftAP mode, so return from here */
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305266 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5267 "%s: In SAP MODE", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005268 EXIT();
5269 return 0;
5270 }
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05305271 /* Find if any iface is up. If any iface is up then can't put device to
5272 * sleep/power save mode
5273 */
Jeff Johnson295189b2012-06-20 16:38:30 -07005274 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5275 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
5276 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07005277 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
5278 {
5279 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305280 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07005281 enter_standby = FALSE;
5282 break;
5283 }
5284 else
5285 {
5286 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5287 pAdapterNode = pNext;
5288 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005289 }
5290
5291 if (TRUE == enter_standby)
5292 {
5293 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
5294 "entering standby", __func__);
5295 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
5296 {
5297 /*log and return success*/
5298 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
5299 "wlan in power save", __func__);
5300 }
5301 }
5302
5303 EXIT();
5304 return 0;
5305}
5306
5307/**---------------------------------------------------------------------------
5308
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305309 \brief hdd_stop() - wrapper_function for __hdd_stop to protect it from SSR
Jeff Johnson295189b2012-06-20 16:38:30 -07005310
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305311 This is called in response to ifconfig down
5312
5313 \param - dev Pointer to net_device structure
5314
5315 \return - 0 for success non-zero for failure
5316-----------------------------------------------------------------------------*/
5317int hdd_stop (struct net_device *dev)
5318{
5319 int ret;
5320
5321 vos_ssr_protect(__func__);
5322 ret = __hdd_stop(dev);
5323 vos_ssr_unprotect(__func__);
5324
5325 return ret;
5326}
5327
5328/**---------------------------------------------------------------------------
5329
5330 \brief __hdd_uninit() - HDD uninit function
Jeff Johnson295189b2012-06-20 16:38:30 -07005331
5332 \param - dev Pointer to net_device structure
5333
5334 \return - void
5335
5336 --------------------------------------------------------------------------*/
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305337static void __hdd_uninit (struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07005338{
5339 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5340
5341 ENTER();
5342
5343 do
5344 {
5345 if (NULL == pAdapter)
5346 {
5347 hddLog(VOS_TRACE_LEVEL_FATAL,
5348 "%s: NULL pAdapter", __func__);
5349 break;
5350 }
5351
5352 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
5353 {
5354 hddLog(VOS_TRACE_LEVEL_FATAL,
5355 "%s: Invalid magic", __func__);
5356 break;
5357 }
5358
5359 if (NULL == pAdapter->pHddCtx)
5360 {
5361 hddLog(VOS_TRACE_LEVEL_FATAL,
5362 "%s: NULL pHddCtx", __func__);
5363 break;
5364 }
5365
5366 if (dev != pAdapter->dev)
5367 {
5368 hddLog(VOS_TRACE_LEVEL_FATAL,
5369 "%s: Invalid device reference", __func__);
5370 /* we haven't validated all cases so let this go for now */
5371 }
5372
5373 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
5374
5375 /* after uninit our adapter structure will no longer be valid */
5376 pAdapter->dev = NULL;
5377 pAdapter->magic = 0;
5378 } while (0);
5379
5380 EXIT();
5381}
5382
5383/**---------------------------------------------------------------------------
5384
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305385 \brief hdd_uninit() - Wrapper function to protect __hdd_uninit from SSR
5386
5387 This is called during the netdev unregister to uninitialize all data
5388associated with the device
5389
5390 \param - dev Pointer to net_device structure
5391
5392 \return - void
5393
5394 --------------------------------------------------------------------------*/
5395static void hdd_uninit (struct net_device *dev)
5396{
5397 vos_ssr_protect(__func__);
5398 __hdd_uninit(dev);
5399 vos_ssr_unprotect(__func__);
5400}
5401
5402/**---------------------------------------------------------------------------
5403
Jeff Johnson295189b2012-06-20 16:38:30 -07005404 \brief hdd_release_firmware() -
5405
5406 This function calls the release firmware API to free the firmware buffer.
5407
5408 \param - pFileName Pointer to the File Name.
5409 pCtx - Pointer to the adapter .
5410
5411
5412 \return - 0 for success, non zero for failure
5413
5414 --------------------------------------------------------------------------*/
5415
5416VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
5417{
5418 VOS_STATUS status = VOS_STATUS_SUCCESS;
5419 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
5420 ENTER();
5421
5422
5423 if (!strcmp(WLAN_FW_FILE, pFileName)) {
5424
5425 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
5426
5427 if(pHddCtx->fw) {
5428 release_firmware(pHddCtx->fw);
5429 pHddCtx->fw = NULL;
5430 }
5431 else
5432 status = VOS_STATUS_E_FAILURE;
5433 }
5434 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
5435 if(pHddCtx->nv) {
5436 release_firmware(pHddCtx->nv);
5437 pHddCtx->nv = NULL;
5438 }
5439 else
5440 status = VOS_STATUS_E_FAILURE;
5441
5442 }
5443
5444 EXIT();
5445 return status;
5446}
5447
5448/**---------------------------------------------------------------------------
5449
5450 \brief hdd_request_firmware() -
5451
5452 This function reads the firmware file using the request firmware
5453 API and returns the the firmware data and the firmware file size.
5454
5455 \param - pfileName - Pointer to the file name.
5456 - pCtx - Pointer to the adapter .
5457 - ppfw_data - Pointer to the pointer of the firmware data.
5458 - pSize - Pointer to the file size.
5459
5460 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
5461
5462 --------------------------------------------------------------------------*/
5463
5464
5465VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
5466{
5467 int status;
5468 VOS_STATUS retval = VOS_STATUS_SUCCESS;
5469 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
5470 ENTER();
5471
5472 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
5473
5474 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
5475
5476 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
5477 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
5478 __func__, pfileName);
5479 retval = VOS_STATUS_E_FAILURE;
5480 }
5481
5482 else {
5483 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
5484 *pSize = pHddCtx->fw->size;
5485 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
5486 __func__, *pSize);
5487 }
5488 }
5489 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
5490
5491 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
5492
5493 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
5494 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
5495 __func__, pfileName);
5496 retval = VOS_STATUS_E_FAILURE;
5497 }
5498
5499 else {
5500 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
5501 *pSize = pHddCtx->nv->size;
5502 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
5503 __func__, *pSize);
5504 }
5505 }
5506
5507 EXIT();
5508 return retval;
5509}
5510/**---------------------------------------------------------------------------
5511 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
5512
5513 This is the function invoked by SME to inform the result of a full power
5514 request issued by HDD
5515
5516 \param - callbackcontext - Pointer to cookie
5517 status - result of request
5518
5519 \return - None
5520
5521--------------------------------------------------------------------------*/
5522void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
5523{
5524 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
5525
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07005526 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07005527 if(&pHddCtx->full_pwr_comp_var)
5528 {
5529 complete(&pHddCtx->full_pwr_comp_var);
5530 }
5531}
5532
5533/**---------------------------------------------------------------------------
5534
5535 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
5536
5537 This is the function invoked by SME to inform the result of BMPS
5538 request issued by HDD
5539
5540 \param - callbackcontext - Pointer to cookie
5541 status - result of request
5542
5543 \return - None
5544
5545--------------------------------------------------------------------------*/
5546void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
5547{
5548
5549 struct completion *completion_var = (struct completion*) callbackContext;
5550
Arif Hussain6d2a3322013-11-17 19:50:10 -08005551 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07005552 if(completion_var != NULL)
5553 {
5554 complete(completion_var);
5555 }
5556}
5557
5558/**---------------------------------------------------------------------------
5559
5560 \brief hdd_get_cfg_file_size() -
5561
5562 This function reads the configuration file using the request firmware
5563 API and returns the configuration file size.
5564
5565 \param - pCtx - Pointer to the adapter .
5566 - pFileName - Pointer to the file name.
5567 - pBufSize - Pointer to the buffer size.
5568
5569 \return - 0 for success, non zero for failure
5570
5571 --------------------------------------------------------------------------*/
5572
5573VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
5574{
5575 int status;
5576 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
5577
5578 ENTER();
5579
5580 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
5581
5582 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
5583 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
5584 status = VOS_STATUS_E_FAILURE;
5585 }
5586 else {
5587 *pBufSize = pHddCtx->fw->size;
5588 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
5589 release_firmware(pHddCtx->fw);
5590 pHddCtx->fw = NULL;
5591 }
5592
5593 EXIT();
5594 return VOS_STATUS_SUCCESS;
5595}
5596
5597/**---------------------------------------------------------------------------
5598
5599 \brief hdd_read_cfg_file() -
5600
5601 This function reads the configuration file using the request firmware
5602 API and returns the cfg data and the buffer size of the configuration file.
5603
5604 \param - pCtx - Pointer to the adapter .
5605 - pFileName - Pointer to the file name.
5606 - pBuffer - Pointer to the data buffer.
5607 - pBufSize - Pointer to the buffer size.
5608
5609 \return - 0 for success, non zero for failure
5610
5611 --------------------------------------------------------------------------*/
5612
5613VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
5614 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
5615{
5616 int status;
5617 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
5618
5619 ENTER();
5620
5621 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
5622
5623 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
5624 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
5625 return VOS_STATUS_E_FAILURE;
5626 }
5627 else {
5628 if(*pBufSize != pHddCtx->fw->size) {
5629 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
5630 "file size", __func__);
5631 release_firmware(pHddCtx->fw);
5632 pHddCtx->fw = NULL;
5633 return VOS_STATUS_E_FAILURE;
5634 }
5635 else {
5636 if(pBuffer) {
5637 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
5638 }
5639 release_firmware(pHddCtx->fw);
5640 pHddCtx->fw = NULL;
5641 }
5642 }
5643
5644 EXIT();
5645
5646 return VOS_STATUS_SUCCESS;
5647}
5648
5649/**---------------------------------------------------------------------------
5650
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305651 \brief __hdd_set_mac_address() -
Jeff Johnson295189b2012-06-20 16:38:30 -07005652
5653 This function sets the user specified mac address using
5654 the command ifconfig wlanX hw ether <mac adress>.
5655
5656 \param - dev - Pointer to the net device.
5657 - addr - Pointer to the sockaddr.
5658 \return - 0 for success, non zero for failure
5659
5660 --------------------------------------------------------------------------*/
5661
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305662static int __hdd_set_mac_address(struct net_device *dev, void *addr)
Jeff Johnson295189b2012-06-20 16:38:30 -07005663{
5664 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5665 struct sockaddr *psta_mac_addr = addr;
5666 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5667
5668 ENTER();
5669
5670 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
Jeff Johnson295189b2012-06-20 16:38:30 -07005671 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
5672
5673 EXIT();
5674 return halStatus;
5675}
5676
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305677/**---------------------------------------------------------------------------
5678
5679 \brief hdd_set_mac_address() -
5680
5681 Wrapper function to protect __hdd_set_mac_address() function from ssr
5682
5683 \param - dev - Pointer to the net device.
5684 - addr - Pointer to the sockaddr.
5685 \return - 0 for success, non zero for failure
5686
5687 --------------------------------------------------------------------------*/
5688static int hdd_set_mac_address(struct net_device *dev, void *addr)
5689{
5690 int ret;
5691
5692 vos_ssr_protect(__func__);
5693 ret = __hdd_set_mac_address(dev, addr);
5694 vos_ssr_unprotect(__func__);
5695
5696 return ret;
5697}
5698
Jeff Johnson295189b2012-06-20 16:38:30 -07005699tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
5700{
5701 int i;
5702 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5703 {
Abhishek Singheb183782014-02-06 13:37:21 +05305704 if( 0 == ((pHddCtx->cfg_ini->intfAddrMask) & (1 << i)) )
Jeff Johnson295189b2012-06-20 16:38:30 -07005705 break;
5706 }
5707
5708 if( VOS_MAX_CONCURRENCY_PERSONA == i)
5709 return NULL;
5710
5711 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
5712 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
5713}
5714
5715void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
5716{
5717 int i;
5718 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5719 {
5720 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
5721 {
5722 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
5723 break;
5724 }
5725 }
5726 return;
5727}
5728
5729#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
5730 static struct net_device_ops wlan_drv_ops = {
5731 .ndo_open = hdd_open,
5732 .ndo_stop = hdd_stop,
5733 .ndo_uninit = hdd_uninit,
5734 .ndo_start_xmit = hdd_hard_start_xmit,
5735 .ndo_tx_timeout = hdd_tx_timeout,
5736 .ndo_get_stats = hdd_stats,
5737 .ndo_do_ioctl = hdd_ioctl,
5738 .ndo_set_mac_address = hdd_set_mac_address,
5739 .ndo_select_queue = hdd_select_queue,
5740#ifdef WLAN_FEATURE_PACKET_FILTERING
5741#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
5742 .ndo_set_rx_mode = hdd_set_multicast_list,
5743#else
5744 .ndo_set_multicast_list = hdd_set_multicast_list,
5745#endif //LINUX_VERSION_CODE
5746#endif
5747 };
Jeff Johnson295189b2012-06-20 16:38:30 -07005748 static struct net_device_ops wlan_mon_drv_ops = {
5749 .ndo_open = hdd_mon_open,
5750 .ndo_stop = hdd_stop,
5751 .ndo_uninit = hdd_uninit,
5752 .ndo_start_xmit = hdd_mon_hard_start_xmit,
5753 .ndo_tx_timeout = hdd_tx_timeout,
5754 .ndo_get_stats = hdd_stats,
5755 .ndo_do_ioctl = hdd_ioctl,
5756 .ndo_set_mac_address = hdd_set_mac_address,
5757 };
Jeff Johnson295189b2012-06-20 16:38:30 -07005758
5759#endif
5760
5761void hdd_set_station_ops( struct net_device *pWlanDev )
5762{
5763#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
Jeff Johnson295189b2012-06-20 16:38:30 -07005764 pWlanDev->netdev_ops = &wlan_drv_ops;
5765#else
5766 pWlanDev->open = hdd_open;
5767 pWlanDev->stop = hdd_stop;
5768 pWlanDev->uninit = hdd_uninit;
5769 pWlanDev->hard_start_xmit = NULL;
5770 pWlanDev->tx_timeout = hdd_tx_timeout;
5771 pWlanDev->get_stats = hdd_stats;
5772 pWlanDev->do_ioctl = hdd_ioctl;
Jeff Johnson295189b2012-06-20 16:38:30 -07005773 pWlanDev->set_mac_address = hdd_set_mac_address;
5774#endif
5775}
5776
Jeff Johnsoneed415b2013-01-18 16:11:20 -08005777static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07005778{
5779 struct net_device *pWlanDev = NULL;
5780 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005781 /*
5782 * cfg80211 initialization and registration....
5783 */
5784 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
5785
Jeff Johnson295189b2012-06-20 16:38:30 -07005786 if(pWlanDev != NULL)
5787 {
5788
5789 //Save the pointer to the net_device in the HDD adapter
5790 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
5791
Jeff Johnson295189b2012-06-20 16:38:30 -07005792 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
5793
5794 pAdapter->dev = pWlanDev;
5795 pAdapter->pHddCtx = pHddCtx;
5796 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
Agarwal Ashish47d18112014-08-04 19:55:07 +05305797 spin_lock_init(&pAdapter->lock_for_active_session);
Jeff Johnson295189b2012-06-20 16:38:30 -07005798
5799 init_completion(&pAdapter->session_open_comp_var);
5800 init_completion(&pAdapter->session_close_comp_var);
5801 init_completion(&pAdapter->disconnect_comp_var);
5802 init_completion(&pAdapter->linkup_event_var);
5803 init_completion(&pAdapter->cancel_rem_on_chan_var);
5804 init_completion(&pAdapter->rem_on_chan_ready_event);
Vinay Krishna Erannaf0e523b2014-03-01 21:00:16 +05305805 init_completion(&pAdapter->pno_comp_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07005806#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
5807 init_completion(&pAdapter->offchannel_tx_event);
5808#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005809 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005810#ifdef FEATURE_WLAN_TDLS
5811 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07005812 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08005813 init_completion(&pAdapter->tdls_mgmt_comp);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05305814 init_completion(&pAdapter->tdls_link_establish_req_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005815#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005816 init_completion(&pHddCtx->mc_sus_event_var);
5817 init_completion(&pHddCtx->tx_sus_event_var);
Gopichand Nakkala05621412013-06-19 19:37:38 +05305818 init_completion(&pHddCtx->rx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07005819 init_completion(&pAdapter->ula_complete);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07005820 init_completion(&pAdapter->change_country_code);
Jeff Johnson295189b2012-06-20 16:38:30 -07005821
Rajeev79dbe4c2013-10-05 11:03:42 +05305822#ifdef FEATURE_WLAN_BATCH_SCAN
5823 init_completion(&pAdapter->hdd_set_batch_scan_req_var);
5824 init_completion(&pAdapter->hdd_get_batch_scan_req_var);
5825 pAdapter->pBatchScanRsp = NULL;
5826 pAdapter->numScanList = 0;
Rajeev Kumar20140c12013-10-21 19:39:02 -07005827 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
Kiet Lamaa8e15a2014-02-11 23:30:06 -08005828 pAdapter->prev_batch_id = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05305829 mutex_init(&pAdapter->hdd_batch_scan_lock);
5830#endif
5831
Jeff Johnson295189b2012-06-20 16:38:30 -07005832 pAdapter->isLinkUpSvcNeeded = FALSE;
5833 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
5834 //Init the net_device structure
5835 strlcpy(pWlanDev->name, name, IFNAMSIZ);
5836
5837 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
5838 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
5839 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
5840 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
5841
5842 hdd_set_station_ops( pAdapter->dev );
5843
5844 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07005845 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
5846 pAdapter->wdev.wiphy = pHddCtx->wiphy;
5847 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07005848 /* set pWlanDev's parent to underlying device */
5849 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
Kumar Anand82c009f2014-05-29 00:29:42 -07005850
5851 hdd_wmm_init( pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07005852 }
5853
5854 return pAdapter;
5855}
5856
5857VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
5858{
5859 struct net_device *pWlanDev = pAdapter->dev;
5860 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
5861 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
5862 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5863
5864 if( rtnl_lock_held )
5865 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08005866 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07005867 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
5868 {
5869 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
5870 return VOS_STATUS_E_FAILURE;
5871 }
5872 }
5873 if (register_netdevice(pWlanDev))
5874 {
5875 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
5876 return VOS_STATUS_E_FAILURE;
5877 }
5878 }
5879 else
5880 {
5881 if(register_netdev(pWlanDev))
5882 {
5883 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
5884 return VOS_STATUS_E_FAILURE;
5885 }
5886 }
5887 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
5888
5889 return VOS_STATUS_SUCCESS;
5890}
5891
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005892static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07005893{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005894 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07005895
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005896 if (NULL == pAdapter)
5897 {
5898 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
5899 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07005900 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005901
5902 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
5903 {
5904 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
5905 return eHAL_STATUS_NOT_INITIALIZED;
5906 }
5907
5908 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
5909
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005910#ifndef WLAN_OPEN_SOURCE
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005911 /* need to make sure all of our scheduled work has completed.
5912 * This callback is called from MC thread context, so it is safe to
5913 * to call below flush workqueue API from here.
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005914 *
5915 * Even though this is called from MC thread context, if there is a faulty
5916 * work item in the system, that can hang this call forever. So flushing
5917 * this global work queue is not safe; and now we make sure that
5918 * individual work queues are stopped correctly. But the cancel work queue
5919 * is a GPL only API, so the proprietary version of the driver would still
5920 * rely on the global work queue flush.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005921 */
5922 flush_scheduled_work();
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005923#endif
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005924
5925 /* We can be blocked while waiting for scheduled work to be
5926 * flushed, and the adapter structure can potentially be freed, in
5927 * which case the magic will have been reset. So make sure the
5928 * magic is still good, and hence the adapter structure is still
5929 * valid, before signaling completion */
5930 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
5931 {
5932 complete(&pAdapter->session_close_comp_var);
5933 }
5934
Jeff Johnson295189b2012-06-20 16:38:30 -07005935 return eHAL_STATUS_SUCCESS;
5936}
5937
5938VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
5939{
5940 struct net_device *pWlanDev = pAdapter->dev;
5941 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
5942 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
5943 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5944 VOS_STATUS status = VOS_STATUS_E_FAILURE;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305945 long rc = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07005946
5947 INIT_COMPLETION(pAdapter->session_open_comp_var);
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07005948 sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07005949 //Open a SME session for future operation
5950 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07005951 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07005952 if ( !HAL_STATUS_SUCCESS( halStatus ) )
5953 {
5954 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005955 "sme_OpenSession() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005956 halStatus, halStatus );
5957 status = VOS_STATUS_E_FAILURE;
5958 goto error_sme_open;
5959 }
5960
5961 //Block on a completion variable. Can't wait forever though.
Vinay Krishna Eranna0fe2e7c2014-04-09 21:32:08 +05305962 rc = wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07005963 &pAdapter->session_open_comp_var,
5964 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305965 if (rc <= 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07005966 {
5967 hddLog(VOS_TRACE_LEVEL_FATAL,
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305968 "Session is not opened within timeout period code %ld", rc );
Jeff Johnson295189b2012-06-20 16:38:30 -07005969 status = VOS_STATUS_E_FAILURE;
5970 goto error_sme_open;
5971 }
5972
5973 // Register wireless extensions
5974 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
5975 {
5976 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005977 "hdd_register_wext() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005978 halStatus, halStatus );
5979 status = VOS_STATUS_E_FAILURE;
5980 goto error_register_wext;
5981 }
5982 //Safe to register the hard_start_xmit function again
5983#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
5984 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
5985#else
5986 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
5987#endif
5988
5989 //Set the Connection State to Not Connected
Abhishek Singhf4669da2014-05-26 15:07:49 +05305990 hddLog(VOS_TRACE_LEVEL_INFO,
5991 "%s: Set HDD connState to eConnectionState_NotConnected",
5992 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005993 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
5994
5995 //Set the default operation channel
5996 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
5997
5998 /* Make the default Auth Type as OPEN*/
5999 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
6000
6001 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
6002 {
6003 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07006004 "hdd_init_tx_rx() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07006005 status, status );
6006 goto error_init_txrx;
6007 }
6008
6009 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
6010
6011 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
6012 {
6013 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07006014 "hdd_wmm_adapter_init() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07006015 status, status );
6016 goto error_wmm_init;
6017 }
6018
6019 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
6020
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006021#ifdef FEATURE_WLAN_TDLS
Agarwal Ashish4b87f922014-06-18 03:03:21 +05306022 if(0 != wlan_hdd_sta_tdls_init(pAdapter))
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006023 {
6024 status = VOS_STATUS_E_FAILURE;
Agarwal Ashish4b87f922014-06-18 03:03:21 +05306025 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_sta_tdls_init failed",__func__);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006026 goto error_tdls_init;
6027 }
6028 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
6029#endif
6030
Jeff Johnson295189b2012-06-20 16:38:30 -07006031 return VOS_STATUS_SUCCESS;
6032
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006033#ifdef FEATURE_WLAN_TDLS
6034error_tdls_init:
6035 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
6036 hdd_wmm_adapter_close(pAdapter);
6037#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006038error_wmm_init:
6039 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
6040 hdd_deinit_tx_rx(pAdapter);
6041error_init_txrx:
6042 hdd_UnregisterWext(pWlanDev);
6043error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07006044 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07006045 {
6046 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07006047 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07006048 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07006049 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07006050 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306051 unsigned long rc;
6052
Jeff Johnson295189b2012-06-20 16:38:30 -07006053 //Block on a completion variable. Can't wait forever though.
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306054 rc = wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07006055 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07006056 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306057 if (rc <= 0)
6058 hddLog(VOS_TRACE_LEVEL_ERROR,
6059 FL("Session is not opened within timeout period code %ld"), rc);
Jeff Johnson295189b2012-06-20 16:38:30 -07006060 }
6061}
6062error_sme_open:
6063 return status;
6064}
6065
Jeff Johnson295189b2012-06-20 16:38:30 -07006066void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
6067{
6068 hdd_cfg80211_state_t *cfgState;
6069
6070 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
6071
6072 if( NULL != cfgState->buf )
6073 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306074 long rc;
Jeff Johnson295189b2012-06-20 16:38:30 -07006075 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
6076 rc = wait_for_completion_interruptible_timeout(
6077 &pAdapter->tx_action_cnf_event,
6078 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306079 if (rc <= 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07006080 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08006081 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306082 "%s ERROR: HDD Wait for Action Confirmation Failed!! %ld"
6083 , __func__, rc);
Jeff Johnson295189b2012-06-20 16:38:30 -07006084 }
6085 }
6086 return;
6087}
Jeff Johnson295189b2012-06-20 16:38:30 -07006088
6089void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
6090{
6091 ENTER();
6092 switch ( pAdapter->device_mode )
6093 {
6094 case WLAN_HDD_INFRA_STATION:
6095 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006096 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07006097 {
6098 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
6099 {
6100 hdd_deinit_tx_rx( pAdapter );
6101 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
6102 }
6103
6104 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
6105 {
6106 hdd_wmm_adapter_close( pAdapter );
6107 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
6108 }
6109
Jeff Johnson295189b2012-06-20 16:38:30 -07006110 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006111#ifdef FEATURE_WLAN_TDLS
6112 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
6113 {
6114 wlan_hdd_tdls_exit(pAdapter);
6115 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
6116 }
6117#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006118
6119 break;
6120 }
6121
6122 case WLAN_HDD_SOFTAP:
6123 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07006124 {
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05306125
6126 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
6127 {
6128 hdd_wmm_adapter_close( pAdapter );
6129 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
6130 }
6131
Jeff Johnson295189b2012-06-20 16:38:30 -07006132 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07006133
6134 hdd_unregister_hostapd(pAdapter);
6135 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07006136 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07006137 break;
6138 }
6139
6140 case WLAN_HDD_MONITOR:
6141 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006142 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07006143 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
6144 {
6145 hdd_deinit_tx_rx( pAdapter );
6146 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
6147 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006148 if(NULL != pAdapterforTx)
6149 {
6150 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
6151 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006152 break;
6153 }
6154
6155
6156 default:
6157 break;
6158 }
6159
6160 EXIT();
6161}
6162
6163void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
6164{
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -08006165 struct net_device *pWlanDev = NULL;
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05306166
6167 ENTER();
6168 if (NULL == pAdapter)
6169 {
6170 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6171 "%s: HDD adapter is Null", __func__);
6172 return;
6173 }
6174
6175 pWlanDev = pAdapter->dev;
Jeff Johnson295189b2012-06-20 16:38:30 -07006176
Rajeev79dbe4c2013-10-05 11:03:42 +05306177#ifdef FEATURE_WLAN_BATCH_SCAN
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05306178 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
6179 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Rajeev Kumarf999e582014-01-09 17:33:29 -08006180 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05306181 || (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)
6182 )
6183 {
Rajeev Kumarf999e582014-01-09 17:33:29 -08006184 if (pAdapter)
Rajeev79dbe4c2013-10-05 11:03:42 +05306185 {
Rajeev Kumarf999e582014-01-09 17:33:29 -08006186 if (eHDD_BATCH_SCAN_STATE_STARTED == pAdapter->batchScanState)
6187 {
6188 hdd_deinit_batch_scan(pAdapter);
6189 }
Rajeev79dbe4c2013-10-05 11:03:42 +05306190 }
Rajeev Kumarf999e582014-01-09 17:33:29 -08006191 }
Rajeev79dbe4c2013-10-05 11:03:42 +05306192#endif
6193
Jeff Johnson295189b2012-06-20 16:38:30 -07006194 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
6195 if( rtnl_held )
6196 {
6197 unregister_netdevice(pWlanDev);
6198 }
6199 else
6200 {
6201 unregister_netdev(pWlanDev);
6202 }
6203 // note that the pAdapter is no longer valid at this point
6204 // since the memory has been reclaimed
6205 }
6206
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05306207 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07006208}
6209
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006210void hdd_set_pwrparams(hdd_context_t *pHddCtx)
6211{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306212 VOS_STATUS status;
6213 hdd_adapter_t *pAdapter = NULL;
6214 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006215
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306216 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006217
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306218 /*loop through all adapters.*/
6219 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006220 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306221 pAdapter = pAdapterNode->pAdapter;
6222 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
6223 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006224
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306225 { // we skip this registration for modes other than STA and P2P client modes.
6226 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6227 pAdapterNode = pNext;
6228 continue;
6229 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006230
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306231 //Apply Dynamic DTIM For P2P
6232 //Only if ignoreDynamicDtimInP2pMode is not set in ini
6233 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
6234 pHddCtx->cfg_ini->enableModulatedDTIM) &&
6235 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
6236 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
6237 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
6238 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
6239 (eConnectionState_Associated ==
6240 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
6241 (pHddCtx->cfg_ini->fIsBmpsEnabled))
6242 {
6243 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006244
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306245 powerRequest.uIgnoreDTIM = 1;
6246 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
6247
6248 if (pHddCtx->cfg_ini->enableModulatedDTIM)
6249 {
6250 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
6251 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
6252 }
6253 else
6254 {
6255 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
6256 }
6257
6258 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
6259 * specified during Enter/Exit BMPS when LCD off*/
6260 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
6261 NULL, eANI_BOOLEAN_FALSE);
6262 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
6263 NULL, eANI_BOOLEAN_FALSE);
6264
6265 /* switch to the DTIM specified in cfg.ini */
6266 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6267 "Switch to DTIM %d", powerRequest.uListenInterval);
6268 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
6269 break;
6270
6271 }
6272
6273 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6274 pAdapterNode = pNext;
6275 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006276}
6277
6278void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
6279{
6280 /*Switch back to DTIM 1*/
6281 tSirSetPowerParamsReq powerRequest = { 0 };
6282
6283 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
6284 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07006285 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006286
6287 /* Update ignoreDTIM and ListedInterval in CFG with default values */
6288 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
6289 NULL, eANI_BOOLEAN_FALSE);
6290 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
6291 NULL, eANI_BOOLEAN_FALSE);
6292
6293 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6294 "Switch to DTIM%d",powerRequest.uListenInterval);
6295 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
6296
6297}
6298
Jeff Johnson295189b2012-06-20 16:38:30 -07006299VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
6300{
6301 VOS_STATUS status = VOS_STATUS_SUCCESS;
6302
6303 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
6304 {
6305 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
6306 }
6307
6308 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
6309 {
6310 sme_StartAutoBmpsTimer(pHddCtx->hHal);
6311 }
6312
6313 if (pHddCtx->cfg_ini->fIsImpsEnabled)
6314 {
6315 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
6316 }
6317
6318 return status;
6319}
6320
6321VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
6322{
6323 hdd_adapter_t *pAdapter = NULL;
6324 eHalStatus halStatus;
6325 VOS_STATUS status = VOS_STATUS_E_INVAL;
6326 v_BOOL_t disableBmps = FALSE;
6327 v_BOOL_t disableImps = FALSE;
6328
6329 switch(session_type)
6330 {
6331 case WLAN_HDD_INFRA_STATION:
6332 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07006333 case WLAN_HDD_P2P_CLIENT:
6334 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07006335 //Exit BMPS -> Is Sta/P2P Client is already connected
6336 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
6337 if((NULL != pAdapter)&&
6338 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
6339 {
6340 disableBmps = TRUE;
6341 }
6342
6343 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
6344 if((NULL != pAdapter)&&
6345 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
6346 {
6347 disableBmps = TRUE;
6348 }
6349
6350 //Exit both Bmps and Imps incase of Go/SAP Mode
6351 if((WLAN_HDD_SOFTAP == session_type) ||
6352 (WLAN_HDD_P2P_GO == session_type))
6353 {
6354 disableBmps = TRUE;
6355 disableImps = TRUE;
6356 }
6357
6358 if(TRUE == disableImps)
6359 {
6360 if (pHddCtx->cfg_ini->fIsImpsEnabled)
6361 {
6362 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
6363 }
6364 }
6365
6366 if(TRUE == disableBmps)
6367 {
6368 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
6369 {
6370 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
6371
6372 if(eHAL_STATUS_SUCCESS != halStatus)
6373 {
6374 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08006375 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006376 VOS_ASSERT(0);
6377 return status;
6378 }
6379 }
6380
6381 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
6382 {
6383 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
6384
6385 if(eHAL_STATUS_SUCCESS != halStatus)
6386 {
6387 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08006388 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006389 VOS_ASSERT(0);
6390 return status;
6391 }
6392 }
6393 }
6394
6395 if((TRUE == disableBmps) ||
6396 (TRUE == disableImps))
6397 {
6398 /* Now, get the chip into Full Power now */
6399 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
6400 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
6401 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
6402
6403 if(halStatus != eHAL_STATUS_SUCCESS)
6404 {
6405 if(halStatus == eHAL_STATUS_PMC_PENDING)
6406 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306407 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07006408 //Block on a completion variable. Can't wait forever though
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306409 ret = wait_for_completion_interruptible_timeout(
6410 &pHddCtx->full_pwr_comp_var,
6411 msecs_to_jiffies(1000));
6412 if (ret <= 0)
6413 {
6414 hddLog(VOS_TRACE_LEVEL_ERROR,
6415 "%s: wait on full_pwr_comp_var failed %ld",
6416 __func__, ret);
6417 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006418 }
6419 else
6420 {
6421 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08006422 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006423 VOS_ASSERT(0);
6424 return status;
6425 }
6426 }
6427
6428 status = VOS_STATUS_SUCCESS;
6429 }
6430
6431 break;
6432 }
6433 return status;
6434}
6435
6436hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08006437 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07006438 tANI_U8 rtnl_held )
6439{
6440 hdd_adapter_t *pAdapter = NULL;
6441 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
6442 VOS_STATUS status = VOS_STATUS_E_FAILURE;
6443 VOS_STATUS exitbmpsStatus;
6444
Arif Hussain6d2a3322013-11-17 19:50:10 -08006445 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d",__func__,iface_name,session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006446
Nirav Shah436658f2014-02-28 17:05:45 +05306447 if(macAddr == NULL)
6448 {
6449 /* Not received valid macAddr */
6450 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6451 "%s:Unable to add virtual intf: Not able to get"
6452 "valid mac address",__func__);
6453 return NULL;
6454 }
6455
Jeff Johnson295189b2012-06-20 16:38:30 -07006456 //Disable BMPS incase of Concurrency
6457 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
6458
6459 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
6460 {
6461 //Fail to Exit BMPS
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306462 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Exit BMPS", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006463 VOS_ASSERT(0);
6464 return NULL;
6465 }
6466
6467 switch(session_type)
6468 {
6469 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07006470 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006471 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07006472 {
6473 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
6474
6475 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306476 {
6477 hddLog(VOS_TRACE_LEVEL_FATAL,
6478 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006479 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306480 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006481
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306482#ifdef FEATURE_WLAN_TDLS
6483 /* A Mutex Lock is introduced while changing/initializing the mode to
6484 * protect the concurrent access for the Adapters by TDLS module.
6485 */
Rajesh Chauhana34c6e62014-03-25 16:37:58 +05306486 mutex_lock(&pHddCtx->tdls_lock);
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306487#endif
6488
Jeff Johnsone7245742012-09-05 17:12:55 -07006489 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
6490 NL80211_IFTYPE_P2P_CLIENT:
6491 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07006492
Jeff Johnson295189b2012-06-20 16:38:30 -07006493 pAdapter->device_mode = session_type;
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306494#ifdef FEATURE_WLAN_TDLS
6495 mutex_unlock(&pHddCtx->tdls_lock);
6496#endif
Sunil Dutt66485cb2013-12-19 19:05:03 +05306497
6498 status = hdd_init_station_mode( pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07006499 if( VOS_STATUS_SUCCESS != status )
6500 goto err_free_netdev;
6501
6502 status = hdd_register_interface( pAdapter, rtnl_held );
6503 if( VOS_STATUS_SUCCESS != status )
6504 {
6505 hdd_deinit_adapter(pHddCtx, pAdapter);
6506 goto err_free_netdev;
6507 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306508
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05306509 // Workqueue which gets scheduled in IPv4 notification callback.
6510 INIT_WORK(&pAdapter->ipv4NotifierWorkQueue, hdd_ipv4_notifier_work_queue);
6511
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306512#ifdef WLAN_NS_OFFLOAD
6513 // Workqueue which gets scheduled in IPv6 notification callback.
6514 INIT_WORK(&pAdapter->ipv6NotifierWorkQueue, hdd_ipv6_notifier_work_queue);
6515#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006516 //Stop the Interface TX queue.
6517 netif_tx_disable(pAdapter->dev);
6518 //netif_tx_disable(pWlanDev);
6519 netif_carrier_off(pAdapter->dev);
6520
6521 break;
6522 }
6523
Jeff Johnson295189b2012-06-20 16:38:30 -07006524 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07006525 case WLAN_HDD_SOFTAP:
6526 {
6527 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
6528 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306529 {
6530 hddLog(VOS_TRACE_LEVEL_FATAL,
6531 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006532 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306533 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006534
Jeff Johnson295189b2012-06-20 16:38:30 -07006535 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
6536 NL80211_IFTYPE_AP:
6537 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07006538 pAdapter->device_mode = session_type;
6539
6540 status = hdd_init_ap_mode(pAdapter);
6541 if( VOS_STATUS_SUCCESS != status )
6542 goto err_free_netdev;
6543
6544 status = hdd_register_hostapd( pAdapter, rtnl_held );
6545 if( VOS_STATUS_SUCCESS != status )
6546 {
6547 hdd_deinit_adapter(pHddCtx, pAdapter);
6548 goto err_free_netdev;
6549 }
6550
6551 netif_tx_disable(pAdapter->dev);
6552 netif_carrier_off(pAdapter->dev);
6553
6554 hdd_set_conparam( 1 );
6555 break;
6556 }
6557 case WLAN_HDD_MONITOR:
6558 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006559 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
6560 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306561 {
6562 hddLog(VOS_TRACE_LEVEL_FATAL,
6563 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006564 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306565 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006566
6567 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
6568 pAdapter->device_mode = session_type;
6569 status = hdd_register_interface( pAdapter, rtnl_held );
6570#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
6571 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
6572#else
6573 pAdapter->dev->open = hdd_mon_open;
6574 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
6575#endif
6576 hdd_init_tx_rx( pAdapter );
6577 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
6578 //Set adapter to be used for data tx. It will use either GO or softap.
6579 pAdapter->sessionCtx.monitor.pAdapterForTx =
6580 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07006581 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
6582 {
6583 pAdapter->sessionCtx.monitor.pAdapterForTx =
6584 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
6585 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006586 /* This workqueue will be used to transmit management packet over
6587 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07006588 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
6589 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
6590 return NULL;
6591 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07006592
Jeff Johnson295189b2012-06-20 16:38:30 -07006593 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
6594 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07006595 }
6596 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07006597 case WLAN_HDD_FTM:
6598 {
6599 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
6600
6601 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306602 {
6603 hddLog(VOS_TRACE_LEVEL_FATAL,
6604 FL("failed to allocate adapter for session %d"), session_type);
6605 return NULL;
6606 }
6607
Jeff Johnson295189b2012-06-20 16:38:30 -07006608 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
6609 * message while loading driver in FTM mode. */
6610 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
6611 pAdapter->device_mode = session_type;
6612 status = hdd_register_interface( pAdapter, rtnl_held );
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05306613
6614 hdd_init_tx_rx( pAdapter );
6615
6616 //Stop the Interface TX queue.
6617 netif_tx_disable(pAdapter->dev);
6618 netif_carrier_off(pAdapter->dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07006619 }
6620 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07006621 default:
6622 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306623 hddLog(VOS_TRACE_LEVEL_FATAL,"%s Invalid session type %d",
6624 __func__, session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006625 VOS_ASSERT(0);
6626 return NULL;
6627 }
6628 }
6629
Jeff Johnson295189b2012-06-20 16:38:30 -07006630 if( VOS_STATUS_SUCCESS == status )
6631 {
6632 //Add it to the hdd's session list.
6633 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
6634 if( NULL == pHddAdapterNode )
6635 {
6636 status = VOS_STATUS_E_NOMEM;
6637 }
6638 else
6639 {
6640 pHddAdapterNode->pAdapter = pAdapter;
6641 status = hdd_add_adapter_back ( pHddCtx,
6642 pHddAdapterNode );
6643 }
6644 }
6645
6646 if( VOS_STATUS_SUCCESS != status )
6647 {
6648 if( NULL != pAdapter )
6649 {
6650 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
6651 pAdapter = NULL;
6652 }
6653 if( NULL != pHddAdapterNode )
6654 {
6655 vos_mem_free( pHddAdapterNode );
6656 }
6657
6658 goto resume_bmps;
6659 }
6660
6661 if(VOS_STATUS_SUCCESS == status)
6662 {
6663 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
6664
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07006665 //Initialize the WoWL service
6666 if(!hdd_init_wowl(pAdapter))
6667 {
6668 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
6669 goto err_free_netdev;
6670 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006671 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006672 return pAdapter;
6673
6674err_free_netdev:
6675 free_netdev(pAdapter->dev);
6676 wlan_hdd_release_intf_addr( pHddCtx,
6677 pAdapter->macAddressCurrent.bytes );
6678
6679resume_bmps:
6680 //If bmps disabled enable it
6681 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
6682 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306683 if (pHddCtx->hdd_wlan_suspended)
6684 {
6685 hdd_set_pwrparams(pHddCtx);
6686 }
6687 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07006688 }
6689 return NULL;
6690}
6691
6692VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
6693 tANI_U8 rtnl_held )
6694{
6695 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
6696 VOS_STATUS status;
6697
6698 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
6699 if( VOS_STATUS_SUCCESS != status )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306700 {
6701 hddLog(VOS_TRACE_LEVEL_WARN,"%s: adapter list empty %d",
6702 __func__, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07006703 return status;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306704 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006705
6706 while ( pCurrent->pAdapter != pAdapter )
6707 {
6708 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
6709 if( VOS_STATUS_SUCCESS != status )
6710 break;
6711
6712 pCurrent = pNext;
6713 }
6714 pAdapterNode = pCurrent;
6715 if( VOS_STATUS_SUCCESS == status )
6716 {
6717 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
6718 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306719
6720#ifdef FEATURE_WLAN_TDLS
6721
6722 /* A Mutex Lock is introduced while changing/initializing the mode to
6723 * protect the concurrent access for the Adapters by TDLS module.
6724 */
Rajesh Chauhana34c6e62014-03-25 16:37:58 +05306725 mutex_lock(&pHddCtx->tdls_lock);
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306726#endif
6727
Jeff Johnson295189b2012-06-20 16:38:30 -07006728 hdd_remove_adapter( pHddCtx, pAdapterNode );
6729 vos_mem_free( pAdapterNode );
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08006730 pAdapterNode = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006731
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306732#ifdef FEATURE_WLAN_TDLS
6733 mutex_unlock(&pHddCtx->tdls_lock);
6734#endif
6735
Jeff Johnson295189b2012-06-20 16:38:30 -07006736
6737 /* If there is a single session of STA/P2P client, re-enable BMPS */
Agarwal Ashish51325b52014-06-16 16:50:49 +05306738 if ((!vos_concurrent_open_sessions_running()) &&
6739 ((pHddCtx->no_of_open_sessions[VOS_STA_MODE] >= 1) ||
6740 (pHddCtx->no_of_open_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
Jeff Johnson295189b2012-06-20 16:38:30 -07006741 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306742 if (pHddCtx->hdd_wlan_suspended)
6743 {
6744 hdd_set_pwrparams(pHddCtx);
6745 }
6746 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07006747 }
6748
6749 return VOS_STATUS_SUCCESS;
6750 }
6751
6752 return VOS_STATUS_E_FAILURE;
6753}
6754
6755VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
6756{
6757 hdd_adapter_list_node_t *pHddAdapterNode;
6758 VOS_STATUS status;
6759
6760 ENTER();
6761
6762 do
6763 {
6764 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
6765 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
6766 {
6767 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
6768 vos_mem_free( pHddAdapterNode );
6769 }
6770 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
6771
6772 EXIT();
6773
6774 return VOS_STATUS_SUCCESS;
6775}
6776
6777void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
6778{
6779 v_U8_t addIE[1] = {0};
6780
6781 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6782 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
6783 eANI_BOOLEAN_FALSE) )
6784 {
6785 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006786 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006787 }
6788
6789 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6790 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
6791 eANI_BOOLEAN_FALSE) )
6792 {
6793 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006794 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006795 }
6796
6797 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6798 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
6799 eANI_BOOLEAN_FALSE) )
6800 {
6801 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006802 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006803 }
6804}
6805
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05306806VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
6807 const v_BOOL_t bCloseSession )
Jeff Johnson295189b2012-06-20 16:38:30 -07006808{
6809 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
6810 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6811 union iwreq_data wrqu;
Kaushik, Sushant7005e372014-04-08 11:36:54 +05306812 v_U8_t retry = 0;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306813 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07006814
6815 ENTER();
6816
6817 switch(pAdapter->device_mode)
6818 {
6819 case WLAN_HDD_INFRA_STATION:
6820 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006821 case WLAN_HDD_P2P_DEVICE:
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05306822 {
6823 hdd_station_ctx_t *pstation = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6824 if( hdd_connIsConnected(pstation) ||
6825 (pstation->conn_info.connState == eConnectionState_Connecting) )
Jeff Johnson295189b2012-06-20 16:38:30 -07006826 {
6827 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
6828 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
6829 pAdapter->sessionId,
6830 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
6831 else
6832 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
6833 pAdapter->sessionId,
6834 eCSR_DISCONNECT_REASON_UNSPECIFIED);
6835 //success implies disconnect command got queued up successfully
6836 if(halStatus == eHAL_STATUS_SUCCESS)
6837 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306838 ret = wait_for_completion_interruptible_timeout(
6839 &pAdapter->disconnect_comp_var,
6840 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6841 if (ret <= 0)
6842 {
6843 hddLog(VOS_TRACE_LEVEL_ERROR,
6844 "%s: wait on disconnect_comp_var failed %ld",
6845 __func__, ret);
6846 }
6847 }
6848 else
6849 {
6850 hddLog(LOGE, "%s: failed to post disconnect event to SME",
6851 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006852 }
6853 memset(&wrqu, '\0', sizeof(wrqu));
6854 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
6855 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
6856 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
6857 }
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05306858 else if(pstation->conn_info.connState ==
6859 eConnectionState_Disconnecting)
6860 {
6861 ret = wait_for_completion_interruptible_timeout(
6862 &pAdapter->disconnect_comp_var,
6863 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6864 if (ret <= 0)
6865 {
6866 hddLog(VOS_TRACE_LEVEL_ERROR,
6867 FL("wait on disconnect_comp_var failed %ld"), ret);
6868 }
6869 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006870 else
6871 {
Srinivas, Dasari138af4f2014-02-07 11:13:45 +05306872 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
6873 eCSR_SCAN_ABORT_DEFAULT);
Jeff Johnson295189b2012-06-20 16:38:30 -07006874 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +05306875 if (pAdapter->device_mode != WLAN_HDD_INFRA_STATION)
6876 {
6877 while (pAdapter->is_roc_inprogress)
6878 {
6879 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6880 "%s: ROC in progress for session %d!!!",
6881 __func__, pAdapter->sessionId);
6882 // waiting for ROC to expire
6883 msleep(500);
6884 /* In GO present case , if retry exceeds 3,
6885 it means something went wrong. */
6886 if ( retry++ > MAX_WAIT_FOR_ROC_COMPLETION )
6887 {
6888 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6889 "%s: ROC completion is not received.!!!", __func__);
6890 sme_CancelRemainOnChannel(WLAN_HDD_GET_HAL_CTX(pAdapter),
6891 pAdapter->sessionId);
6892 wait_for_completion_interruptible_timeout(
6893 &pAdapter->cancel_rem_on_chan_var,
6894 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
6895 break;
6896 }
6897 }
6898 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306899#ifdef WLAN_NS_OFFLOAD
Vinay Krishna Eranna941360f2014-01-16 15:38:22 +05306900#ifdef WLAN_OPEN_SOURCE
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306901 cancel_work_sync(&pAdapter->ipv6NotifierWorkQueue);
6902#endif
Vinay Krishna Eranna941360f2014-01-16 15:38:22 +05306903 if (pAdapter->ipv6_notifier_registered)
6904 {
6905 hddLog(LOG1, FL("Unregistered IPv6 notifier"));
6906 unregister_inet6addr_notifier(&pAdapter->ipv6_notifier);
6907 pAdapter->ipv6_notifier_registered = false;
6908 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306909#endif
Vinay Krishna Erannad9cbdb32014-01-16 12:59:10 +05306910 if (pAdapter->ipv4_notifier_registered)
6911 {
6912 hddLog(LOG1, FL("Unregistered IPv4 notifier"));
6913 unregister_inetaddr_notifier(&pAdapter->ipv4_notifier);
6914 pAdapter->ipv4_notifier_registered = false;
6915 }
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05306916#ifdef WLAN_OPEN_SOURCE
6917 cancel_work_sync(&pAdapter->ipv4NotifierWorkQueue);
6918#endif
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05306919 /* It is possible that the caller of this function does not
6920 * wish to close the session
6921 */
6922 if (VOS_TRUE == bCloseSession &&
6923 test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07006924 {
6925 INIT_COMPLETION(pAdapter->session_close_comp_var);
6926 if (eHAL_STATUS_SUCCESS ==
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05306927 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
6928 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07006929 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306930 unsigned long ret;
6931
Jeff Johnson295189b2012-06-20 16:38:30 -07006932 //Block on a completion variable. Can't wait forever though.
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306933 ret = wait_for_completion_timeout(
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05306934 &pAdapter->session_close_comp_var,
6935 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306936 if ( 0 >= ret)
6937 {
6938 hddLog(LOGE, "%s: failure waiting for session_close_comp_var %ld",
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05306939 __func__, ret);
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306940 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006941 }
6942 }
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05306943 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006944 break;
6945
6946 case WLAN_HDD_SOFTAP:
6947 case WLAN_HDD_P2P_GO:
6948 //Any softap specific cleanup here...
Kaushik, Sushant7005e372014-04-08 11:36:54 +05306949 if (pAdapter->device_mode == WLAN_HDD_P2P_GO) {
6950 while (pAdapter->is_roc_inprogress) {
6951 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6952 "%s: ROC in progress for session %d!!!",
6953 __func__, pAdapter->sessionId);
6954 msleep(500);
6955 if ( retry++ > MAX_WAIT_FOR_ROC_COMPLETION ) {
6956 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6957 "%s: ROC completion is not received.!!!", __func__);
6958 WLANSAP_CancelRemainOnChannel(
6959 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
6960 wait_for_completion_interruptible_timeout(
6961 &pAdapter->cancel_rem_on_chan_var,
6962 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
6963 break;
6964 }
6965 }
6966 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006967 mutex_lock(&pHddCtx->sap_lock);
6968 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
6969 {
6970 VOS_STATUS status;
6971 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6972
6973 //Stop Bss.
6974 status = WLANSAP_StopBss(pHddCtx->pvosContext);
6975 if (VOS_IS_STATUS_SUCCESS(status))
6976 {
6977 hdd_hostapd_state_t *pHostapdState =
6978 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6979
6980 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
6981
6982 if (!VOS_IS_STATUS_SUCCESS(status))
6983 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306984 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss %d",
6985 __func__, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07006986 }
6987 }
6988 else
6989 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006990 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006991 }
6992 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
Agarwal Ashish51325b52014-06-16 16:50:49 +05306993 wlan_hdd_decr_active_session(pHddCtx, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07006994
6995 if (eHAL_STATUS_FAILURE ==
6996 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
6997 0, NULL, eANI_BOOLEAN_FALSE))
6998 {
6999 hddLog(LOGE,
7000 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007001 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007002 }
7003
7004 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
7005 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
7006 eANI_BOOLEAN_FALSE) )
7007 {
7008 hddLog(LOGE,
7009 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
7010 }
7011
7012 // Reset WNI_CFG_PROBE_RSP Flags
7013 wlan_hdd_reset_prob_rspies(pAdapter);
7014 kfree(pAdapter->sessionCtx.ap.beacon);
7015 pAdapter->sessionCtx.ap.beacon = NULL;
7016 }
7017 mutex_unlock(&pHddCtx->sap_lock);
7018 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07007019
Jeff Johnson295189b2012-06-20 16:38:30 -07007020 case WLAN_HDD_MONITOR:
Sameer Thalappilbee426e2013-10-30 10:30:30 -07007021#ifdef WLAN_OPEN_SOURCE
7022 cancel_work_sync(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue);
7023#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007024 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07007025
Jeff Johnson295189b2012-06-20 16:38:30 -07007026 default:
7027 break;
7028 }
7029
7030 EXIT();
7031 return VOS_STATUS_SUCCESS;
7032}
7033
7034VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
7035{
7036 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7037 VOS_STATUS status;
7038 hdd_adapter_t *pAdapter;
7039
7040 ENTER();
7041
7042 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7043
7044 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7045 {
7046 pAdapter = pAdapterNode->pAdapter;
7047 netif_tx_disable(pAdapter->dev);
7048 netif_carrier_off(pAdapter->dev);
7049
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307050 hdd_stop_adapter( pHddCtx, pAdapter, VOS_TRUE );
Jeff Johnson295189b2012-06-20 16:38:30 -07007051
7052 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7053 pAdapterNode = pNext;
7054 }
7055
7056 EXIT();
7057
7058 return VOS_STATUS_SUCCESS;
7059}
7060
Rajeev Kumarf999e582014-01-09 17:33:29 -08007061
7062#ifdef FEATURE_WLAN_BATCH_SCAN
7063/**---------------------------------------------------------------------------
7064
7065 \brief hdd_deinit_batch_scan () - This function cleans up batch scan data
7066 structures
7067
7068 \param - pAdapter Pointer to HDD adapter
7069
7070 \return - None
7071
7072 --------------------------------------------------------------------------*/
7073void hdd_deinit_batch_scan(hdd_adapter_t *pAdapter)
7074{
7075 tHddBatchScanRsp *pNode;
7076 tHddBatchScanRsp *pPrev;
7077
Siddharth Bhalb3e9b792014-02-24 15:14:16 +05307078 if (NULL == pAdapter)
Rajeev Kumarf999e582014-01-09 17:33:29 -08007079 {
Siddharth Bhalb3e9b792014-02-24 15:14:16 +05307080 hddLog(VOS_TRACE_LEVEL_ERROR,
7081 "%s: Adapter context is Null", __func__);
7082 return;
7083 }
7084
7085 pNode = pAdapter->pBatchScanRsp;
7086 while (pNode)
7087 {
7088 pPrev = pNode;
7089 pNode = pNode->pNext;
7090 vos_mem_free((v_VOID_t * )pPrev);
Rajeev Kumarf999e582014-01-09 17:33:29 -08007091 }
7092
7093 pAdapter->pBatchScanRsp = NULL;
7094 pAdapter->numScanList = 0;
7095 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
7096 pAdapter->prev_batch_id = 0;
7097
7098 return;
7099}
7100#endif
7101
7102
Jeff Johnson295189b2012-06-20 16:38:30 -07007103VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
7104{
7105 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7106 VOS_STATUS status;
7107 hdd_adapter_t *pAdapter;
7108
7109 ENTER();
7110
7111 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7112
7113 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7114 {
7115 pAdapter = pAdapterNode->pAdapter;
7116 netif_tx_disable(pAdapter->dev);
7117 netif_carrier_off(pAdapter->dev);
7118
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07007119 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
7120
Jeff Johnson295189b2012-06-20 16:38:30 -07007121 hdd_deinit_tx_rx(pAdapter);
Agarwal Ashish6267caa2014-08-06 19:16:21 +05307122
7123 wlan_hdd_decr_active_session(pHddCtx, pAdapter->device_mode);
7124
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05307125 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
7126 {
7127 hdd_wmm_adapter_close( pAdapter );
7128 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
7129 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007130
Rajeev Kumarf999e582014-01-09 17:33:29 -08007131#ifdef FEATURE_WLAN_BATCH_SCAN
7132 if (eHDD_BATCH_SCAN_STATE_STARTED == pAdapter->batchScanState)
7133 {
7134 hdd_deinit_batch_scan(pAdapter);
7135 }
7136#endif
7137
Jeff Johnson295189b2012-06-20 16:38:30 -07007138 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7139 pAdapterNode = pNext;
7140 }
7141
7142 EXIT();
7143
7144 return VOS_STATUS_SUCCESS;
7145}
7146
7147VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
7148{
7149 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7150 VOS_STATUS status;
7151 hdd_adapter_t *pAdapter;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05307152 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -07007153
7154 ENTER();
7155
7156 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7157
7158 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7159 {
7160 pAdapter = pAdapterNode->pAdapter;
7161
Kumar Anand82c009f2014-05-29 00:29:42 -07007162 hdd_wmm_init( pAdapter );
7163
Jeff Johnson295189b2012-06-20 16:38:30 -07007164 switch(pAdapter->device_mode)
7165 {
7166 case WLAN_HDD_INFRA_STATION:
7167 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07007168 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05307169
7170 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
7171
Jeff Johnson295189b2012-06-20 16:38:30 -07007172 hdd_init_station_mode(pAdapter);
7173 /* Open the gates for HDD to receive Wext commands */
7174 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07007175 pHddCtx->scan_info.mScanPending = FALSE;
7176 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07007177
7178 //Trigger the initial scan
7179 hdd_wlan_initial_scan(pAdapter);
7180
7181 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05307182 if (eConnectionState_Associated == connState ||
7183 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -07007184 {
7185 union iwreq_data wrqu;
7186 memset(&wrqu, '\0', sizeof(wrqu));
7187 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
7188 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
7189 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07007190 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07007191
Jeff Johnson295189b2012-06-20 16:38:30 -07007192 /* indicate disconnected event to nl80211 */
7193 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
7194 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07007195 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05307196 else if (eConnectionState_Connecting == connState)
7197 {
7198 /*
7199 * Indicate connect failure to supplicant if we were in the
7200 * process of connecting
7201 */
7202 cfg80211_connect_result(pAdapter->dev, NULL,
7203 NULL, 0, NULL, 0,
7204 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
7205 GFP_KERNEL);
7206 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007207 break;
7208
7209 case WLAN_HDD_SOFTAP:
7210 /* softAP can handle SSR */
7211 break;
7212
7213 case WLAN_HDD_P2P_GO:
Sameer Thalappiledf0d792013-08-09 14:31:03 -07007214 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send stop ap to supplicant",
Jeff Johnson295189b2012-06-20 16:38:30 -07007215 __func__);
Sameer Thalappiledf0d792013-08-09 14:31:03 -07007216 cfg80211_ap_stopped(pAdapter->dev, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07007217 break;
7218
7219 case WLAN_HDD_MONITOR:
7220 /* monitor interface start */
7221 break;
7222 default:
7223 break;
7224 }
7225
7226 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7227 pAdapterNode = pNext;
7228 }
7229
7230 EXIT();
7231
7232 return VOS_STATUS_SUCCESS;
7233}
7234
7235VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
7236{
7237 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7238 hdd_adapter_t *pAdapter;
7239 VOS_STATUS status;
7240 v_U32_t roamId;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307241 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07007242
7243 ENTER();
7244
7245 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7246
7247 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7248 {
7249 pAdapter = pAdapterNode->pAdapter;
7250
7251 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
7252 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
7253 {
7254 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7255 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
7256
Abhishek Singhf4669da2014-05-26 15:07:49 +05307257 hddLog(VOS_TRACE_LEVEL_INFO,
7258 "%s: Set HDD connState to eConnectionState_NotConnected",
7259 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007260 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
7261 init_completion(&pAdapter->disconnect_comp_var);
7262 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
7263 eCSR_DISCONNECT_REASON_UNSPECIFIED);
7264
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307265 ret = wait_for_completion_interruptible_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07007266 &pAdapter->disconnect_comp_var,
7267 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307268 if (0 >= ret)
7269 hddLog(LOGE, "%s: failure waiting for disconnect_comp_var %ld",
7270 __func__, ret);
Jeff Johnson295189b2012-06-20 16:38:30 -07007271
7272 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
7273 pHddCtx->isAmpAllowed = VOS_FALSE;
7274 sme_RoamConnect(pHddCtx->hHal,
7275 pAdapter->sessionId, &(pWextState->roamProfile),
7276 &roamId);
7277 }
7278
7279 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7280 pAdapterNode = pNext;
7281 }
7282
7283 EXIT();
7284
7285 return VOS_STATUS_SUCCESS;
7286}
7287
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07007288void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
7289{
7290 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7291 VOS_STATUS status;
7292 hdd_adapter_t *pAdapter;
7293 hdd_station_ctx_t *pHddStaCtx;
7294 hdd_ap_ctx_t *pHddApCtx;
7295 hdd_hostapd_state_t * pHostapdState;
7296 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
7297 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
7298 const char *p2pMode = "DEV";
7299 const char *ccMode = "Standalone";
7300 int n;
7301
7302 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7303 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7304 {
7305 pAdapter = pAdapterNode->pAdapter;
7306 switch (pAdapter->device_mode) {
7307 case WLAN_HDD_INFRA_STATION:
7308 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7309 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
7310 staChannel = pHddStaCtx->conn_info.operationChannel;
7311 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
7312 }
7313 break;
7314 case WLAN_HDD_P2P_CLIENT:
7315 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7316 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
7317 p2pChannel = pHddStaCtx->conn_info.operationChannel;
7318 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
7319 p2pMode = "CLI";
7320 }
7321 break;
7322 case WLAN_HDD_P2P_GO:
7323 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
7324 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
7325 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
7326 p2pChannel = pHddApCtx->operatingChannel;
7327 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
7328 }
7329 p2pMode = "GO";
7330 break;
7331 case WLAN_HDD_SOFTAP:
7332 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
7333 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
7334 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
7335 apChannel = pHddApCtx->operatingChannel;
7336 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
7337 }
7338 break;
7339 default:
7340 break;
7341 }
7342 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7343 pAdapterNode = pNext;
7344 }
7345 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
7346 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
7347 }
7348 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
7349 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
7350 if (p2pChannel > 0) {
7351 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
7352 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
7353 }
7354 if (apChannel > 0) {
7355 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
7356 apChannel, MAC_ADDR_ARRAY(apBssid));
7357 }
7358
7359 if (p2pChannel > 0 && apChannel > 0) {
7360 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
7361 }
7362}
7363
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07007364bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07007365{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07007366 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07007367}
7368
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07007369/* Once SSR is disabled then it cannot be set. */
7370void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07007371{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07007372 if (HDD_SSR_DISABLED == isSsrRequired)
7373 return;
7374
Jeff Johnson295189b2012-06-20 16:38:30 -07007375 isSsrRequired = value;
7376}
7377
7378VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
7379 hdd_adapter_list_node_t** ppAdapterNode)
7380{
7381 VOS_STATUS status;
7382 spin_lock(&pHddCtx->hddAdapters.lock);
7383 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
7384 (hdd_list_node_t**) ppAdapterNode );
7385 spin_unlock(&pHddCtx->hddAdapters.lock);
7386 return status;
7387}
7388
7389VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
7390 hdd_adapter_list_node_t* pAdapterNode,
7391 hdd_adapter_list_node_t** pNextAdapterNode)
7392{
7393 VOS_STATUS status;
7394 spin_lock(&pHddCtx->hddAdapters.lock);
7395 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
7396 (hdd_list_node_t*) pAdapterNode,
7397 (hdd_list_node_t**)pNextAdapterNode );
7398
7399 spin_unlock(&pHddCtx->hddAdapters.lock);
7400 return status;
7401}
7402
7403VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
7404 hdd_adapter_list_node_t* pAdapterNode)
7405{
7406 VOS_STATUS status;
7407 spin_lock(&pHddCtx->hddAdapters.lock);
7408 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
7409 &pAdapterNode->node );
7410 spin_unlock(&pHddCtx->hddAdapters.lock);
7411 return status;
7412}
7413
7414VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
7415 hdd_adapter_list_node_t** ppAdapterNode)
7416{
7417 VOS_STATUS status;
7418 spin_lock(&pHddCtx->hddAdapters.lock);
7419 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
7420 (hdd_list_node_t**) ppAdapterNode );
7421 spin_unlock(&pHddCtx->hddAdapters.lock);
7422 return status;
7423}
7424
7425VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
7426 hdd_adapter_list_node_t* pAdapterNode)
7427{
7428 VOS_STATUS status;
7429 spin_lock(&pHddCtx->hddAdapters.lock);
7430 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
7431 (hdd_list_node_t*) pAdapterNode );
7432 spin_unlock(&pHddCtx->hddAdapters.lock);
7433 return status;
7434}
7435
7436VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
7437 hdd_adapter_list_node_t* pAdapterNode)
7438{
7439 VOS_STATUS status;
7440 spin_lock(&pHddCtx->hddAdapters.lock);
7441 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
7442 (hdd_list_node_t*) pAdapterNode );
7443 spin_unlock(&pHddCtx->hddAdapters.lock);
7444 return status;
7445}
7446
7447hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
7448 tSirMacAddr macAddr )
7449{
7450 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7451 hdd_adapter_t *pAdapter;
7452 VOS_STATUS status;
7453
7454 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7455
7456 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7457 {
7458 pAdapter = pAdapterNode->pAdapter;
7459
7460 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
7461 macAddr, sizeof(tSirMacAddr) ) )
7462 {
7463 return pAdapter;
7464 }
7465 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7466 pAdapterNode = pNext;
7467 }
7468
7469 return NULL;
7470
7471}
7472
7473hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
7474{
7475 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7476 hdd_adapter_t *pAdapter;
7477 VOS_STATUS status;
7478
7479 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7480
7481 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7482 {
7483 pAdapter = pAdapterNode->pAdapter;
7484
7485 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
7486 IFNAMSIZ ) )
7487 {
7488 return pAdapter;
7489 }
7490 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7491 pAdapterNode = pNext;
7492 }
7493
7494 return NULL;
7495
7496}
7497
7498hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
7499{
7500 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7501 hdd_adapter_t *pAdapter;
7502 VOS_STATUS status;
7503
7504 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7505
7506 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7507 {
7508 pAdapter = pAdapterNode->pAdapter;
7509
7510 if( pAdapter && (mode == pAdapter->device_mode) )
7511 {
7512 return pAdapter;
7513 }
7514 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7515 pAdapterNode = pNext;
7516 }
7517
7518 return NULL;
7519
7520}
7521
7522//Remove this function later
7523hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
7524{
7525 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7526 hdd_adapter_t *pAdapter;
7527 VOS_STATUS status;
7528
7529 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7530
7531 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7532 {
7533 pAdapter = pAdapterNode->pAdapter;
7534
7535 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
7536 {
7537 return pAdapter;
7538 }
7539
7540 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7541 pAdapterNode = pNext;
7542 }
7543
7544 return NULL;
7545
7546}
7547
Jeff Johnson295189b2012-06-20 16:38:30 -07007548/**---------------------------------------------------------------------------
7549
7550 \brief hdd_set_monitor_tx_adapter() -
7551
7552 This API initializes the adapter to be used while transmitting on monitor
7553 adapter.
7554
7555 \param - pHddCtx - Pointer to the HDD context.
7556 pAdapter - Adapter that will used for TX. This can be NULL.
7557 \return - None.
7558 --------------------------------------------------------------------------*/
7559void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
7560{
7561 hdd_adapter_t *pMonAdapter;
7562
7563 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
7564
7565 if( NULL != pMonAdapter )
7566 {
7567 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
7568 }
7569}
Jeff Johnson295189b2012-06-20 16:38:30 -07007570/**---------------------------------------------------------------------------
7571
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307572 \brief hdd_get_operating_channel() -
Jeff Johnson295189b2012-06-20 16:38:30 -07007573
7574 This API returns the operating channel of the requested device mode
7575
7576 \param - pHddCtx - Pointer to the HDD context.
7577 - mode - Device mode for which operating channel is required
7578 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
7579 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
7580 \return - channel number. "0" id the requested device is not found OR it is not connected.
7581 --------------------------------------------------------------------------*/
7582v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
7583{
7584 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7585 VOS_STATUS status;
7586 hdd_adapter_t *pAdapter;
7587 v_U8_t operatingChannel = 0;
7588
7589 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7590
7591 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7592 {
7593 pAdapter = pAdapterNode->pAdapter;
7594
7595 if( mode == pAdapter->device_mode )
7596 {
7597 switch(pAdapter->device_mode)
7598 {
7599 case WLAN_HDD_INFRA_STATION:
7600 case WLAN_HDD_P2P_CLIENT:
7601 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
7602 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
7603 break;
7604 case WLAN_HDD_SOFTAP:
7605 case WLAN_HDD_P2P_GO:
7606 /*softap connection info */
7607 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
7608 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
7609 break;
7610 default:
7611 break;
7612 }
7613
7614 break; //Found the device of interest. break the loop
7615 }
7616
7617 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7618 pAdapterNode = pNext;
7619 }
7620 return operatingChannel;
7621}
7622
7623#ifdef WLAN_FEATURE_PACKET_FILTERING
7624/**---------------------------------------------------------------------------
7625
7626 \brief hdd_set_multicast_list() -
7627
7628 This used to set the multicast address list.
7629
7630 \param - dev - Pointer to the WLAN device.
7631 - skb - Pointer to OS packet (sk_buff).
7632 \return - success/fail
7633
7634 --------------------------------------------------------------------------*/
7635static void hdd_set_multicast_list(struct net_device *dev)
7636{
7637 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07007638 int mc_count;
7639 int i = 0;
7640 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307641
7642 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07007643 {
7644 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307645 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007646 return;
7647 }
7648
7649 if (dev->flags & IFF_ALLMULTI)
7650 {
7651 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007652 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307653 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07007654 }
7655 else
7656 {
7657 mc_count = netdev_mc_count(dev);
7658 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007659 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07007660 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
7661 {
7662 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007663 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307664 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07007665 return;
7666 }
7667
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307668 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07007669
7670 netdev_for_each_mc_addr(ha, dev) {
7671 if (i == mc_count)
7672 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307673 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
7674 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
Arif Hussain6d2a3322013-11-17 19:50:10 -08007675 hddLog(VOS_TRACE_LEVEL_INFO, "%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07007676 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307677 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07007678 i++;
7679 }
7680 }
7681 return;
7682}
7683#endif
7684
7685/**---------------------------------------------------------------------------
7686
7687 \brief hdd_select_queue() -
7688
7689 This function is registered with the Linux OS for network
7690 core to decide which queue to use first.
7691
7692 \param - dev - Pointer to the WLAN device.
7693 - skb - Pointer to OS packet (sk_buff).
7694 \return - ac, Queue Index/access category corresponding to UP in IP header
7695
7696 --------------------------------------------------------------------------*/
7697v_U16_t hdd_select_queue(struct net_device *dev,
7698 struct sk_buff *skb)
7699{
7700 return hdd_wmm_select_queue(dev, skb);
7701}
7702
7703
7704/**---------------------------------------------------------------------------
7705
7706 \brief hdd_wlan_initial_scan() -
7707
7708 This function triggers the initial scan
7709
7710 \param - pAdapter - Pointer to the HDD adapter.
7711
7712 --------------------------------------------------------------------------*/
7713void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
7714{
7715 tCsrScanRequest scanReq;
7716 tCsrChannelInfo channelInfo;
7717 eHalStatus halStatus;
Jeff Johnson02797792013-10-26 19:17:13 -07007718 tANI_U32 scanId;
Jeff Johnson295189b2012-06-20 16:38:30 -07007719 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7720
7721 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
7722 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
7723 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
7724
7725 if(sme_Is11dSupported(pHddCtx->hHal))
7726 {
7727 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
7728 if ( HAL_STATUS_SUCCESS( halStatus ) )
7729 {
7730 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
7731 if( !scanReq.ChannelInfo.ChannelList )
7732 {
7733 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
7734 vos_mem_free(channelInfo.ChannelList);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08007735 channelInfo.ChannelList = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007736 return;
7737 }
7738 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
7739 channelInfo.numOfChannels);
7740 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
7741 vos_mem_free(channelInfo.ChannelList);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08007742 channelInfo.ChannelList = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007743 }
7744
7745 scanReq.scanType = eSIR_PASSIVE_SCAN;
7746 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
7747 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
7748 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
7749 }
7750 else
7751 {
7752 scanReq.scanType = eSIR_ACTIVE_SCAN;
7753 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
7754 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
7755 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
7756 }
7757
7758 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
7759 if ( !HAL_STATUS_SUCCESS( halStatus ) )
7760 {
7761 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
7762 __func__, halStatus );
7763 }
7764
7765 if(sme_Is11dSupported(pHddCtx->hHal))
7766 vos_mem_free(scanReq.ChannelInfo.ChannelList);
7767}
7768
Jeff Johnson295189b2012-06-20 16:38:30 -07007769/**---------------------------------------------------------------------------
7770
7771 \brief hdd_full_power_callback() - HDD full power callback function
7772
7773 This is the function invoked by SME to inform the result of a full power
7774 request issued by HDD
7775
7776 \param - callbackcontext - Pointer to cookie
7777 \param - status - result of request
7778
7779 \return - None
7780
7781 --------------------------------------------------------------------------*/
7782static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
7783{
Jeff Johnson72a40512013-12-19 10:14:15 -08007784 struct statsContext *pContext = callbackContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07007785
7786 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307787 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07007788
7789 if (NULL == callbackContext)
7790 {
7791 hddLog(VOS_TRACE_LEVEL_ERROR,
7792 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007793 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07007794 return;
7795 }
7796
Jeff Johnson72a40512013-12-19 10:14:15 -08007797 /* there is a race condition that exists between this callback
7798 function and the caller since the caller could time out either
7799 before or while this code is executing. we use a spinlock to
7800 serialize these actions */
7801 spin_lock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07007802
7803 if (POWER_CONTEXT_MAGIC != pContext->magic)
7804 {
7805 /* the caller presumably timed out so there is nothing we can do */
Jeff Johnson72a40512013-12-19 10:14:15 -08007806 spin_unlock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07007807 hddLog(VOS_TRACE_LEVEL_WARN,
7808 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007809 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07007810 return;
7811 }
7812
Jeff Johnson72a40512013-12-19 10:14:15 -08007813 /* context is valid so caller is still waiting */
7814
7815 /* paranoia: invalidate the magic */
7816 pContext->magic = 0;
7817
7818 /* notify the caller */
Jeff Johnson295189b2012-06-20 16:38:30 -07007819 complete(&pContext->completion);
Jeff Johnson72a40512013-12-19 10:14:15 -08007820
7821 /* serialization is complete */
7822 spin_unlock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07007823}
7824
7825/**---------------------------------------------------------------------------
7826
7827 \brief hdd_wlan_exit() - HDD WLAN exit function
7828
7829 This is the driver exit point (invoked during rmmod)
7830
7831 \param - pHddCtx - Pointer to the HDD Context
7832
7833 \return - None
7834
7835 --------------------------------------------------------------------------*/
7836void hdd_wlan_exit(hdd_context_t *pHddCtx)
7837{
7838 eHalStatus halStatus;
7839 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
7840 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05307841 struct wiphy *wiphy = pHddCtx->wiphy;
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -08007842 hdd_adapter_t* pAdapter = NULL;
Jeff Johnson72a40512013-12-19 10:14:15 -08007843 struct statsContext powerContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07007844 long lrc;
c_hpothu5ab05e92014-06-13 17:34:05 +05307845 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007846
7847 ENTER();
7848
Jeff Johnson88ba7742013-02-27 14:36:02 -08007849 if (VOS_FTM_MODE != hdd_get_conparam())
7850 {
7851 // Unloading, restart logic is no more required.
7852 wlan_hdd_restart_deinit(pHddCtx);
Jeff Johnsone7245742012-09-05 17:12:55 -07007853
c_hpothu5ab05e92014-06-13 17:34:05 +05307854 vosStatus = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7855 while (NULL != pAdapterNode && VOS_STATUS_E_EMPTY != vosStatus)
Jeff Johnson295189b2012-06-20 16:38:30 -07007856 {
c_hpothu5ab05e92014-06-13 17:34:05 +05307857 pAdapter = pAdapterNode->pAdapter;
7858 if (NULL != pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07007859 {
c_hpothu5ab05e92014-06-13 17:34:05 +05307860 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode ||
7861 WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)
7862 {
7863 wlan_hdd_cfg80211_deregister_frames(pAdapter);
7864 hdd_UnregisterWext(pAdapter->dev);
7865 }
7866 // Cancel any outstanding scan requests. We are about to close all
7867 // of our adapters, but an adapter structure is what SME passes back
7868 // to our callback function. Hence if there are any outstanding scan
7869 // requests then there is a race condition between when the adapter
7870 // is closed and when the callback is invoked.We try to resolve that
7871 // race condition here by canceling any outstanding scans before we
7872 // close the adapters.
7873 // Note that the scans may be cancelled in an asynchronous manner,
7874 // so ideally there needs to be some kind of synchronization. Rather
7875 // than introduce a new synchronization here, we will utilize the
7876 // fact that we are about to Request Full Power, and since that is
7877 // synchronized, the expectation is that by the time Request Full
7878 // Power has completed all scans will be cancelled.
7879 if (pHddCtx->scan_info.mScanPending)
7880 {
7881 hddLog(VOS_TRACE_LEVEL_INFO,
7882 FL("abort scan mode: %d sessionId: %d"),
7883 pAdapter->device_mode,
7884 pAdapter->sessionId);
7885 hdd_abort_mac_scan(pHddCtx,
7886 pAdapter->sessionId,
7887 eCSR_SCAN_ABORT_DEFAULT);
7888 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007889 }
c_hpothu5ab05e92014-06-13 17:34:05 +05307890 vosStatus = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7891 pAdapterNode = pNext;
Jeff Johnson295189b2012-06-20 16:38:30 -07007892 }
7893 }
c_hpothu5ab05e92014-06-13 17:34:05 +05307894 else
Jeff Johnson88ba7742013-02-27 14:36:02 -08007895 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307896 hddLog(VOS_TRACE_LEVEL_INFO,"%s: FTM MODE",__func__);
Jeff Johnson88ba7742013-02-27 14:36:02 -08007897 wlan_hdd_ftm_close(pHddCtx);
7898 goto free_hdd_ctx;
7899 }
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307900
Jeff Johnson295189b2012-06-20 16:38:30 -07007901 /* DeRegister with platform driver as client for Suspend/Resume */
7902 vosStatus = hddDeregisterPmOps(pHddCtx);
7903 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
7904 {
7905 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
7906 VOS_ASSERT(0);
7907 }
7908
7909 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
7910 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
7911 {
7912 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
7913 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007914
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07007915 //Stop the traffic monitor timer
7916 if ( VOS_TIMER_STATE_RUNNING ==
7917 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr))
7918 {
7919 vos_timer_stop(&pHddCtx->tx_rx_trafficTmr);
7920 }
7921
7922 // Destroy the traffic monitor timer
7923 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
7924 &pHddCtx->tx_rx_trafficTmr)))
7925 {
7926 hddLog(VOS_TRACE_LEVEL_ERROR,
7927 "%s: Cannot deallocate Traffic monitor timer", __func__);
7928 }
7929
Jeff Johnson295189b2012-06-20 16:38:30 -07007930 //Disable IMPS/BMPS as we do not want the device to enter any power
7931 //save mode during shutdown
7932 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
7933 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
7934 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
7935
7936 //Ensure that device is in full power as we will touch H/W during vos_Stop
7937 init_completion(&powerContext.completion);
7938 powerContext.magic = POWER_CONTEXT_MAGIC;
7939
7940 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
7941 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
7942
7943 if (eHAL_STATUS_SUCCESS != halStatus)
7944 {
7945 if (eHAL_STATUS_PMC_PENDING == halStatus)
7946 {
7947 /* request was sent -- wait for the response */
7948 lrc = wait_for_completion_interruptible_timeout(
7949 &powerContext.completion,
7950 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
Jeff Johnson295189b2012-06-20 16:38:30 -07007951 if (lrc <= 0)
7952 {
7953 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007954 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07007955 }
7956 }
7957 else
7958 {
7959 hddLog(VOS_TRACE_LEVEL_ERROR,
7960 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007961 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07007962 /* continue -- need to clean up as much as possible */
7963 }
7964 }
7965
Jeff Johnson72a40512013-12-19 10:14:15 -08007966 /* either we never sent a request, we sent a request and received a
7967 response or we sent a request and timed out. if we never sent a
7968 request or if we sent a request and got a response, we want to
7969 clear the magic out of paranoia. if we timed out there is a
7970 race condition such that the callback function could be
7971 executing at the same time we are. of primary concern is if the
7972 callback function had already verified the "magic" but had not
7973 yet set the completion variable when a timeout occurred. we
7974 serialize these activities by invalidating the magic while
7975 holding a shared spinlock which will cause us to block if the
7976 callback is currently executing */
7977 spin_lock(&hdd_context_lock);
7978 powerContext.magic = 0;
7979 spin_unlock(&hdd_context_lock);
7980
Yue Ma0d4891e2013-08-06 17:01:45 -07007981 hdd_debugfs_exit(pHddCtx);
7982
Jeff Johnson295189b2012-06-20 16:38:30 -07007983 // Unregister the Net Device Notifier
7984 unregister_netdevice_notifier(&hdd_netdev_notifier);
7985
Jeff Johnson295189b2012-06-20 16:38:30 -07007986 hdd_stop_all_adapters( pHddCtx );
7987
Jeff Johnson295189b2012-06-20 16:38:30 -07007988#ifdef WLAN_BTAMP_FEATURE
7989 vosStatus = WLANBAP_Stop(pVosContext);
7990 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
7991 {
7992 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7993 "%s: Failed to stop BAP",__func__);
7994 }
7995#endif //WLAN_BTAMP_FEATURE
7996
7997 //Stop all the modules
7998 vosStatus = vos_stop( pVosContext );
7999 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
8000 {
8001 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8002 "%s: Failed to stop VOSS",__func__);
8003 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
8004 }
8005
Jeff Johnson295189b2012-06-20 16:38:30 -07008006 //Assert Deep sleep signal now to put Libra HW in lowest power state
8007 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
8008 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
8009
8010 //Vote off any PMIC voltage supplies
8011 vos_chipPowerDown(NULL, NULL, NULL);
8012
8013 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
8014
Leo Chang59cdc7e2013-07-10 10:08:21 -07008015
Jeff Johnson295189b2012-06-20 16:38:30 -07008016 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07008017 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07008018
8019 //Close the scheduler before calling vos_close to make sure no thread is
8020 // scheduled after the each module close is called i.e after all the data
8021 // structures are freed.
8022 vosStatus = vos_sched_close( pVosContext );
8023 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
8024 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
8025 "%s: Failed to close VOSS Scheduler",__func__);
8026 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
8027 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008028#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07008029#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
8030 /* Destroy the wake lock */
8031 wake_lock_destroy(&pHddCtx->rx_wake_lock);
8032#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08008033 /* Destroy the wake lock */
8034 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008035#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008036
Mihir Shete7a24b5f2013-12-21 12:18:31 +05308037#ifdef CONFIG_ENABLE_LINUX_REG
8038 vosStatus = vos_nv_close();
8039 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
8040 {
8041 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8042 "%s: Failed to close NV", __func__);
8043 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
8044 }
8045#endif
8046
Jeff Johnson295189b2012-06-20 16:38:30 -07008047 //Close VOSS
8048 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
8049 vos_close(pVosContext);
8050
Jeff Johnson295189b2012-06-20 16:38:30 -07008051 //Close Watchdog
8052 if(pHddCtx->cfg_ini->fIsLogpEnabled)
8053 vos_watchdog_close(pVosContext);
8054
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05308055 //Clean up HDD Nlink Service
8056 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05308057
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05308058#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05308059 if (pHddCtx->cfg_ini->wlanLoggingEnable)
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05308060 {
8061 wlan_logging_sock_deactivate_svc();
8062 }
8063#endif
8064
Vinay Krishna Erannaef30b522014-08-26 17:48:16 +05308065#ifdef WLAN_KD_READY_NOTIFIER
8066 nl_srv_exit(pHddCtx->ptt_pid);
8067#else
8068 nl_srv_exit();
8069#endif /* WLAN_KD_READY_NOTIFIER */
8070
8071
Jeff Johnson295189b2012-06-20 16:38:30 -07008072 /* Cancel the vote for XO Core ON.
8073 * This is done here to ensure there is no race condition since MC, TX and WD threads have
8074 * exited at this point
8075 */
8076 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
Arif Hussain6d2a3322013-11-17 19:50:10 -08008077 " when WLAN is turned OFF");
Jeff Johnson295189b2012-06-20 16:38:30 -07008078 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
8079 {
8080 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
8081 " Not returning failure."
Arif Hussain6d2a3322013-11-17 19:50:10 -08008082 " Power consumed will be high");
Jeff Johnson295189b2012-06-20 16:38:30 -07008083 }
8084
8085 hdd_close_all_adapters( pHddCtx );
8086
Jeff Johnson295189b2012-06-20 16:38:30 -07008087 /* free the power on lock from platform driver */
8088 if (free_riva_power_on_lock("wlan"))
8089 {
8090 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
8091 __func__);
8092 }
8093
Jeff Johnson88ba7742013-02-27 14:36:02 -08008094free_hdd_ctx:
c_hpothu78c7b602014-05-17 17:35:49 +05308095
8096 //Free up dynamically allocated members inside HDD Adapter
8097 if (pHddCtx->cfg_ini)
8098 {
8099 kfree(pHddCtx->cfg_ini);
8100 pHddCtx->cfg_ini= NULL;
8101 }
8102
Leo Changf04ddad2013-09-18 13:46:38 -07008103 /* FTM mode, WIPHY did not registered
8104 If un-register here, system crash will happen */
8105 if (VOS_FTM_MODE != hdd_get_conparam())
8106 {
8107 wiphy_unregister(wiphy) ;
8108 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008109 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07008110 if (hdd_is_ssr_required())
8111 {
8112 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07008113 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07008114 msleep(5000);
8115 }
8116 hdd_set_ssr_required (VOS_FALSE);
8117}
8118
8119
8120/**---------------------------------------------------------------------------
8121
8122 \brief hdd_update_config_from_nv() - Function to update the contents of
8123 the running configuration with parameters taken from NV storage
8124
8125 \param - pHddCtx - Pointer to the HDD global context
8126
8127 \return - VOS_STATUS_SUCCESS if successful
8128
8129 --------------------------------------------------------------------------*/
8130static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
8131{
Jeff Johnson295189b2012-06-20 16:38:30 -07008132 v_BOOL_t itemIsValid = VOS_FALSE;
8133 VOS_STATUS status;
8134 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
8135 v_U8_t macLoop;
8136
8137 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
8138 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
8139 if(status != VOS_STATUS_SUCCESS)
8140 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08008141 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed");
Jeff Johnson295189b2012-06-20 16:38:30 -07008142 return VOS_STATUS_E_FAILURE;
8143 }
8144
8145 if (itemIsValid == VOS_TRUE)
8146 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08008147 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV");
Jeff Johnson295189b2012-06-20 16:38:30 -07008148 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
8149 VOS_MAX_CONCURRENCY_PERSONA);
8150 if(status != VOS_STATUS_SUCCESS)
8151 {
8152 /* Get MAC from NV fail, not update CFG info
8153 * INI MAC value will be used for MAC setting */
Arif Hussain6d2a3322013-11-17 19:50:10 -08008154 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed");
Jeff Johnson295189b2012-06-20 16:38:30 -07008155 return VOS_STATUS_E_FAILURE;
8156 }
8157
8158 /* If first MAC is not valid, treat all others are not valid
8159 * Then all MACs will be got from ini file */
8160 if(vos_is_macaddr_zero(&macFromNV[0]))
8161 {
8162 /* MAC address in NV file is not configured yet */
8163 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
8164 return VOS_STATUS_E_INVAL;
8165 }
8166
8167 /* Get MAC address from NV, update CFG info */
8168 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
8169 {
8170 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
8171 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308172 hddLog(VOS_TRACE_LEVEL_ERROR,"not valid MAC from NV for %d", macLoop);
Jeff Johnson295189b2012-06-20 16:38:30 -07008173 /* This MAC is not valid, skip it
8174 * This MAC will be got from ini file */
8175 }
8176 else
8177 {
8178 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
8179 (v_U8_t *)&macFromNV[macLoop].bytes[0],
8180 VOS_MAC_ADDR_SIZE);
8181 }
8182 }
8183 }
8184 else
8185 {
8186 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
8187 return VOS_STATUS_E_FAILURE;
8188 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008189
Jeff Johnson295189b2012-06-20 16:38:30 -07008190
8191 return VOS_STATUS_SUCCESS;
8192}
8193
8194/**---------------------------------------------------------------------------
8195
8196 \brief hdd_post_voss_start_config() - HDD post voss start config helper
8197
8198 \param - pAdapter - Pointer to the HDD
8199
8200 \return - None
8201
8202 --------------------------------------------------------------------------*/
8203VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
8204{
8205 eHalStatus halStatus;
8206 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308207 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -07008208
Jeff Johnson295189b2012-06-20 16:38:30 -07008209
8210 // Send ready indication to the HDD. This will kick off the MAC
8211 // into a 'running' state and should kick off an initial scan.
8212 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
8213 if ( !HAL_STATUS_SUCCESS( halStatus ) )
8214 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308215 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07008216 "code %08d [x%08x]",__func__, halStatus, halStatus );
8217 return VOS_STATUS_E_FAILURE;
8218 }
8219
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308220 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -07008221 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
8222 // And RIVA will crash
8223 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
8224 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308225 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
8226 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
8227
8228
Jeff Johnson295189b2012-06-20 16:38:30 -07008229 return VOS_STATUS_SUCCESS;
8230}
8231
Jeff Johnson295189b2012-06-20 16:38:30 -07008232/* wake lock APIs for HDD */
8233void hdd_prevent_suspend(void)
8234{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008235#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008236 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008237#else
8238 wcnss_prevent_suspend();
8239#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008240}
8241
8242void hdd_allow_suspend(void)
8243{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008244#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008245 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008246#else
8247 wcnss_allow_suspend();
8248#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008249}
8250
Mahesh A Saptasagarb9c50402014-01-16 15:49:22 +05308251void hdd_prevent_suspend_timeout(v_U32_t timeout)
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07008252{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008253#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07008254 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07008255#else
8256 /* Do nothing as there is no API in wcnss for timeout*/
8257#endif
8258}
8259
Jeff Johnson295189b2012-06-20 16:38:30 -07008260/**---------------------------------------------------------------------------
8261
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008262 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
8263 information between Host and Riva
8264
8265 This function gets reported version of FW
8266 It also finds the version of Riva headers used to compile the host
8267 It compares the above two and prints a warning if they are different
8268 It gets the SW and HW version string
8269 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
8270 indicating the features they support through a bitmap
8271
8272 \param - pHddCtx - Pointer to HDD context
8273
8274 \return - void
8275
8276 --------------------------------------------------------------------------*/
8277
8278void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
8279{
8280
8281 tSirVersionType versionCompiled;
8282 tSirVersionType versionReported;
8283 tSirVersionString versionString;
8284 tANI_U8 fwFeatCapsMsgSupported = 0;
8285 VOS_STATUS vstatus;
8286
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -08008287 memset(&versionCompiled, 0, sizeof(versionCompiled));
8288 memset(&versionReported, 0, sizeof(versionReported));
8289
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008290 /* retrieve and display WCNSS version information */
8291 do {
8292
8293 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
8294 &versionCompiled);
8295 if (!VOS_IS_STATUS_SUCCESS(vstatus))
8296 {
8297 hddLog(VOS_TRACE_LEVEL_FATAL,
8298 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008299 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008300 break;
8301 }
8302
8303 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
8304 &versionReported);
8305 if (!VOS_IS_STATUS_SUCCESS(vstatus))
8306 {
8307 hddLog(VOS_TRACE_LEVEL_FATAL,
8308 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008309 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008310 break;
8311 }
8312
8313 if ((versionCompiled.major != versionReported.major) ||
8314 (versionCompiled.minor != versionReported.minor) ||
8315 (versionCompiled.version != versionReported.version) ||
8316 (versionCompiled.revision != versionReported.revision))
8317 {
8318 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
8319 "Host expected %u.%u.%u.%u\n",
8320 WLAN_MODULE_NAME,
8321 (int)versionReported.major,
8322 (int)versionReported.minor,
8323 (int)versionReported.version,
8324 (int)versionReported.revision,
8325 (int)versionCompiled.major,
8326 (int)versionCompiled.minor,
8327 (int)versionCompiled.version,
8328 (int)versionCompiled.revision);
8329 }
8330 else
8331 {
8332 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
8333 WLAN_MODULE_NAME,
8334 (int)versionReported.major,
8335 (int)versionReported.minor,
8336 (int)versionReported.version,
8337 (int)versionReported.revision);
8338 }
8339
8340 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
8341 versionString,
8342 sizeof(versionString));
8343 if (!VOS_IS_STATUS_SUCCESS(vstatus))
8344 {
8345 hddLog(VOS_TRACE_LEVEL_FATAL,
8346 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008347 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008348 break;
8349 }
8350
8351 pr_info("%s: WCNSS software version %s\n",
8352 WLAN_MODULE_NAME, versionString);
8353
8354 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
8355 versionString,
8356 sizeof(versionString));
8357 if (!VOS_IS_STATUS_SUCCESS(vstatus))
8358 {
8359 hddLog(VOS_TRACE_LEVEL_FATAL,
8360 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008361 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008362 break;
8363 }
8364
8365 pr_info("%s: WCNSS hardware version %s\n",
8366 WLAN_MODULE_NAME, versionString);
8367
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07008368 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
8369 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008370 send the message only if it the riva is 1.1
8371 minor numbers for different riva branches:
8372 0 -> (1.0)Mainline Build
8373 1 -> (1.1)Mainline Build
8374 2->(1.04) Stability Build
8375 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07008376 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008377 ((versionReported.minor>=1) && (versionReported.version>=1)))
8378 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
8379 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07008380
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008381 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08008382 {
8383#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
8384 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
8385 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
8386#endif
Ravi Joshid2ca7c42013-07-23 08:37:49 -07008387 /* Indicate if IBSS heartbeat monitoring needs to be offloaded */
8388 if (!pHddCtx->cfg_ini->enableIbssHeartBeatOffload)
8389 {
8390 sme_disableFeatureCapablity(IBSS_HEARTBEAT_OFFLOAD);
8391 }
8392
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008393 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08008394 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008395
8396 } while (0);
8397
8398}
Neelansh Mittaledafed22014-09-04 18:54:39 +05308399void wlan_hdd_send_svc_nlink_msg(int type, void *data, int len)
8400{
8401 struct sk_buff *skb;
8402 struct nlmsghdr *nlh;
8403 tAniMsgHdr *ani_hdr;
8404
8405 skb = alloc_skb(NLMSG_SPACE(WLAN_NL_MAX_PAYLOAD), GFP_KERNEL);
8406
8407 if(skb == NULL) {
8408 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8409 "%s: alloc_skb failed", __func__);
8410 return;
8411 }
8412
8413 nlh = (struct nlmsghdr *)skb->data;
8414 nlh->nlmsg_pid = 0; /* from kernel */
8415 nlh->nlmsg_flags = 0;
8416 nlh->nlmsg_seq = 0;
8417 nlh->nlmsg_type = WLAN_NL_MSG_SVC;
8418
8419 ani_hdr = NLMSG_DATA(nlh);
8420 ani_hdr->type = type;
8421
8422 switch(type) {
8423 case WLAN_SVC_SAP_RESTART_IND:
8424 ani_hdr->length = 0;
8425 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr)));
8426 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr)));
8427 break;
8428 default:
8429 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8430 "Attempt to send unknown nlink message %d", type);
8431 kfree_skb(skb);
8432 return;
8433 }
8434
8435 nl_srv_bcast(skb);
8436
8437 return;
8438}
8439
8440
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008441
8442/**---------------------------------------------------------------------------
8443
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308444 \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
8445
8446 \param - pHddCtx - Pointer to the hdd context
8447
8448 \return - true if hardware supports 5GHz
8449
8450 --------------------------------------------------------------------------*/
Vinay Krishna Erannafacf5e22014-02-24 13:16:25 +05308451boolean hdd_is_5g_supported(hdd_context_t * pHddCtx)
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308452{
8453 /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
8454 * then hardware support 5Ghz.
8455 */
8456 if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode())
8457 {
Agarwal Ashish971c2882013-10-30 20:11:12 +05308458 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Hardware supports 5Ghz", __func__);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308459 return true;
8460 }
8461 else
8462 {
Agarwal Ashish971c2882013-10-30 20:11:12 +05308463 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Hardware doesn't supports 5Ghz",
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308464 __func__);
8465 return false;
8466 }
8467}
8468
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308469/**---------------------------------------------------------------------------
8470
8471 \brief hdd_generate_iface_mac_addr_auto() - HDD Mac Interface Auto
8472 generate function
8473
8474 This is generate the random mac address for WLAN interface
8475
8476 \param - pHddCtx - Pointer to HDD context
8477 idx - Start interface index to get auto
8478 generated mac addr.
8479 mac_addr - Mac address
8480
8481 \return - 0 for success, < 0 for failure
8482
8483 --------------------------------------------------------------------------*/
8484
8485static int hdd_generate_iface_mac_addr_auto(hdd_context_t *pHddCtx,
8486 int idx, v_MACADDR_t mac_addr)
8487{
8488 int i;
8489 unsigned int serialno;
8490 serialno = wcnss_get_serial_number();
8491
8492 if (0 != serialno)
8493 {
8494 /* MAC address has 3 bytes of OUI so we have a maximum of 3
8495 bytes of the serial number that can be used to generate
8496 the other 3 bytes of the MAC address. Mask off all but
8497 the lower 3 bytes (this will also make sure we don't
8498 overflow in the next step) */
8499 serialno &= 0x00FFFFFF;
8500
8501 /* we need a unique address for each session */
8502 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
8503
8504 /* autogen other Mac addresses */
8505 for (i = idx; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
8506 {
8507 /* start with the entire default address */
8508 pHddCtx->cfg_ini->intfMacAddr[i] = mac_addr;
8509 /* then replace the lower 3 bytes */
8510 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
8511 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
8512 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
8513
8514 serialno++;
8515 hddLog(VOS_TRACE_LEVEL_ERROR,
8516 "%s: Derived Mac Addr: "
8517 MAC_ADDRESS_STR, __func__,
8518 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[i].bytes));
8519 }
8520
8521 }
8522 else
8523 {
8524 hddLog(LOGE, FL("Failed to Get Serial NO"));
8525 return -1;
8526 }
8527 return 0;
8528}
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308529
8530/**---------------------------------------------------------------------------
8531
Mihir Shetefc7ff5b2014-01-27 11:30:05 +05308532 \brief hdd_11d_scan_done - callback to be executed when 11d scan is
8533 completed to flush out the scan results
8534
8535 11d scan is done during driver load and is a passive scan on all
8536 channels supported by the device, 11d scans may find some APs on
8537 frequencies which are forbidden to be used in the regulatory domain
8538 the device is operating in. If these APs are notified to the supplicant
8539 it may try to connect to these APs, thus flush out all the scan results
8540 which are present in SME after 11d scan is done.
8541
8542 \return - eHalStatus
8543
8544 --------------------------------------------------------------------------*/
8545static eHalStatus hdd_11d_scan_done(tHalHandle halHandle, void *pContext,
8546 tANI_U32 scanId, eCsrScanStatus status)
8547{
8548 ENTER();
8549
8550 sme_ScanFlushResult(halHandle, 0);
8551
8552 EXIT();
8553
8554 return eHAL_STATUS_SUCCESS;
8555}
8556
8557/**---------------------------------------------------------------------------
8558
Jeff Johnson295189b2012-06-20 16:38:30 -07008559 \brief hdd_wlan_startup() - HDD init function
8560
8561 This is the driver startup code executed once a WLAN device has been detected
8562
8563 \param - dev - Pointer to the underlying device
8564
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08008565 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07008566
8567 --------------------------------------------------------------------------*/
8568
8569int hdd_wlan_startup(struct device *dev )
8570{
8571 VOS_STATUS status;
8572 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07008573 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07008574 hdd_context_t *pHddCtx = NULL;
8575 v_CONTEXT_t pVosContext= NULL;
8576#ifdef WLAN_BTAMP_FEATURE
8577 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
8578 WLANBAP_ConfigType btAmpConfig;
8579 hdd_config_t *pConfig;
8580#endif
8581 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07008582 struct wiphy *wiphy;
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308583 v_MACADDR_t mac_addr;
Jeff Johnson295189b2012-06-20 16:38:30 -07008584
8585 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07008586 /*
8587 * cfg80211: wiphy allocation
8588 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308589 wiphy = wlan_hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t)) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07008590
8591 if(wiphy == NULL)
8592 {
8593 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08008594 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07008595 }
8596
8597 pHddCtx = wiphy_priv(wiphy);
8598
Jeff Johnson295189b2012-06-20 16:38:30 -07008599 //Initialize the adapter context to zeros.
8600 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
8601
Jeff Johnson295189b2012-06-20 16:38:30 -07008602 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07008603 hdd_prevent_suspend();
Mihir Shete18156292014-03-11 15:38:30 +05308604 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_LOAD_IN_PROGRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -07008605
8606 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
8607
8608 /*Get vos context here bcoz vos_open requires it*/
8609 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
8610
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08008611 if(pVosContext == NULL)
8612 {
8613 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
8614 goto err_free_hdd_context;
8615 }
8616
Jeff Johnson295189b2012-06-20 16:38:30 -07008617 //Save the Global VOSS context in adapter context for future.
8618 pHddCtx->pvosContext = pVosContext;
8619
8620 //Save the adapter context in global context for future.
8621 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
8622
Jeff Johnson295189b2012-06-20 16:38:30 -07008623 pHddCtx->parent_dev = dev;
8624
8625 init_completion(&pHddCtx->full_pwr_comp_var);
8626 init_completion(&pHddCtx->standby_comp_var);
8627 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07008628 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08008629 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Kiet Lam46b8e4e2013-11-06 21:49:53 +05308630 init_completion(&pHddCtx->wiphy_channel_update_event);
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +05308631 init_completion(&pHddCtx->ssr_comp_var);
Amar Singhala49cbc52013-10-08 18:37:44 -07008632
8633#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhalfddc28c2013-09-05 13:03:40 -07008634 init_completion(&pHddCtx->linux_reg_req);
Amar Singhala49cbc52013-10-08 18:37:44 -07008635#else
8636 init_completion(&pHddCtx->driver_crda_req);
8637#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008638
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05308639 spin_lock_init(&pHddCtx->schedScan_lock);
8640
Jeff Johnson295189b2012-06-20 16:38:30 -07008641 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
8642
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05308643#ifdef FEATURE_WLAN_TDLS
8644 /* tdls_lock is initialized before an hdd_open_adapter ( which is
8645 * invoked by other instances also) to protect the concurrent
8646 * access for the Adapters by TDLS module.
8647 */
8648 mutex_init(&pHddCtx->tdls_lock);
8649#endif
Agarwal Ashish1f422872014-07-22 00:11:55 +05308650 /* By default Strict Regulatory For FCC should be false */
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05308651
Agarwal Ashish1f422872014-07-22 00:11:55 +05308652 pHddCtx->nEnableStrictRegulatoryForFCC = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07008653 // Load all config first as TL config is needed during vos_open
8654 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
8655 if(pHddCtx->cfg_ini == NULL)
8656 {
8657 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
8658 goto err_free_hdd_context;
8659 }
8660
8661 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
8662
8663 // Read and parse the qcom_cfg.ini file
8664 status = hdd_parse_config_ini( pHddCtx );
8665 if ( VOS_STATUS_SUCCESS != status )
8666 {
8667 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
8668 __func__, WLAN_INI_FILE);
8669 goto err_config;
8670 }
Arif Hussaind5218912013-12-05 01:10:55 -08008671#ifdef MEMORY_DEBUG
8672 if (pHddCtx->cfg_ini->IsMemoryDebugSupportEnabled)
8673 vos_mem_init();
8674
8675 hddLog(VOS_TRACE_LEVEL_INFO, "%s: gEnableMemoryDebug=%d",
8676 __func__, pHddCtx->cfg_ini->IsMemoryDebugSupportEnabled);
8677#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008678
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05308679 /* INI has been read, initialise the configuredMcastBcastFilter with
8680 * INI value as this will serve as the default value
8681 */
8682 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
8683 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
8684 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308685
8686 if (false == hdd_is_5g_supported(pHddCtx))
8687 {
8688 //5Ghz is not supported.
8689 if (1 != pHddCtx->cfg_ini->nBandCapability)
8690 {
8691 hddLog(VOS_TRACE_LEVEL_INFO,
8692 "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__);
8693 pHddCtx->cfg_ini->nBandCapability = 1;
8694 }
8695 }
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05308696
8697 /* If SNR Monitoring is enabled, FW has to parse all beacons
8698 * for calcaluting and storing the average SNR, so set Nth beacon
8699 * filter to 1 to enable FW to parse all the beaocons
8700 */
8701 if (1 == pHddCtx->cfg_ini->fEnableSNRMonitoring)
8702 {
8703 /* The log level is deliberately set to WARN as overriding
8704 * nthBeaconFilter to 1 will increase power cosumption and this
8705 * might just prove helpful to detect the power issue.
8706 */
8707 hddLog(VOS_TRACE_LEVEL_WARN,
8708 "%s: Setting pHddCtx->cfg_ini->nthBeaconFilter = 1", __func__);
8709 pHddCtx->cfg_ini->nthBeaconFilter = 1;
8710 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008711 /*
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308712 * cfg80211: Initialization ...
Jeff Johnson295189b2012-06-20 16:38:30 -07008713 */
Manjunathappa Prakasheec4ddf2014-01-13 18:23:51 -08008714 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07008715 {
Manjunathappa Prakasheec4ddf2014-01-13 18:23:51 -08008716 if (0 < wlan_hdd_cfg80211_init(dev, wiphy, pHddCtx->cfg_ini))
8717 {
8718 hddLog(VOS_TRACE_LEVEL_FATAL,
8719 "%s: wlan_hdd_cfg80211_init return failure", __func__);
8720 goto err_config;
8721 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008722 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008723
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08008724 // Update VOS trace levels based upon the cfg.ini
8725 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
8726 pHddCtx->cfg_ini->vosTraceEnableBAP);
8727 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
8728 pHddCtx->cfg_ini->vosTraceEnableTL);
8729 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
8730 pHddCtx->cfg_ini->vosTraceEnableWDI);
8731 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
8732 pHddCtx->cfg_ini->vosTraceEnableHDD);
8733 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
8734 pHddCtx->cfg_ini->vosTraceEnableSME);
8735 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
8736 pHddCtx->cfg_ini->vosTraceEnablePE);
Katya Nigam70d68332013-09-16 16:49:45 +05308737 hdd_vos_trace_enable(VOS_MODULE_ID_PMC,
8738 pHddCtx->cfg_ini->vosTraceEnablePMC);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08008739 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
8740 pHddCtx->cfg_ini->vosTraceEnableWDA);
8741 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
8742 pHddCtx->cfg_ini->vosTraceEnableSYS);
8743 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
8744 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08008745 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
8746 pHddCtx->cfg_ini->vosTraceEnableSAP);
8747 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
8748 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08008749
Jeff Johnson295189b2012-06-20 16:38:30 -07008750 // Update WDI trace levels based upon the cfg.ini
8751 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
8752 pHddCtx->cfg_ini->wdiTraceEnableDAL);
8753 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
8754 pHddCtx->cfg_ini->wdiTraceEnableCTL);
8755 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
8756 pHddCtx->cfg_ini->wdiTraceEnableDAT);
8757 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
8758 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07008759
Jeff Johnson88ba7742013-02-27 14:36:02 -08008760 if (VOS_FTM_MODE == hdd_get_conparam())
8761 {
Jeff Johnson295189b2012-06-20 16:38:30 -07008762 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
8763 {
8764 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
8765 goto err_free_hdd_context;
8766 }
8767 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
c_hpothu2de0ef62014-04-15 16:16:15 +05308768
8769 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -07008770 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08008771 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008772
Jeff Johnson88ba7742013-02-27 14:36:02 -08008773 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07008774 if(pHddCtx->cfg_ini->fIsLogpEnabled)
8775 {
8776 status = vos_watchdog_open(pVosContext,
8777 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
8778
8779 if(!VOS_IS_STATUS_SUCCESS( status ))
8780 {
8781 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308782 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07008783 }
8784 }
8785
8786 pHddCtx->isLogpInProgress = FALSE;
8787 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
8788
Jeff Johnson295189b2012-06-20 16:38:30 -07008789 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
8790 if(!VOS_IS_STATUS_SUCCESS(status))
8791 {
8792 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008793 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07008794 }
8795
Amar Singhala49cbc52013-10-08 18:37:44 -07008796#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -07008797 /* initialize the NV module. This is required so that
8798 we can initialize the channel information in wiphy
8799 from the NV.bin data. The channel information in
8800 wiphy needs to be initialized before wiphy registration */
8801
8802 status = vos_nv_open();
8803 if (!VOS_IS_STATUS_SUCCESS(status))
8804 {
8805 /* NV module cannot be initialized */
8806 hddLog( VOS_TRACE_LEVEL_FATAL,
8807 "%s: vos_nv_open failed", __func__);
8808 goto err_clkvote;
8809 }
8810
8811 status = vos_init_wiphy_from_nv_bin();
8812 if (!VOS_IS_STATUS_SUCCESS(status))
8813 {
8814 /* NV module cannot be initialized */
8815 hddLog( VOS_TRACE_LEVEL_FATAL,
8816 "%s: vos_init_wiphy failed", __func__);
8817 goto err_vos_nv_close;
8818 }
8819
Amar Singhala49cbc52013-10-08 18:37:44 -07008820#endif
8821
Arun Kumar Khandavalliebb19482014-03-25 13:56:53 +05308822 status = vos_open( &pVosContext, pHddCtx->parent_dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07008823 if ( !VOS_IS_STATUS_SUCCESS( status ))
8824 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008825 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
Mihir Shetee1093ba2014-01-21 20:13:32 +05308826 goto err_vos_nv_close;
Jeff Johnson295189b2012-06-20 16:38:30 -07008827 }
8828
Jeff Johnson295189b2012-06-20 16:38:30 -07008829 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
8830
8831 if ( NULL == pHddCtx->hHal )
8832 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008833 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008834 goto err_vosclose;
8835 }
8836
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008837 status = vos_preStart( pHddCtx->pvosContext );
8838 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8839 {
8840 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05308841 goto err_vosclose;
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008842 }
Jeff Johnsone7245742012-09-05 17:12:55 -07008843
Arif Hussaineaf68602013-12-30 23:10:44 -08008844 if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan)
8845 {
8846 pHddCtx->cfg_ini->enableDFSChnlScan = enable_dfs_chan_scan;
8847 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_dfs_chan_scan set to %d",
8848 __func__, enable_dfs_chan_scan);
8849 }
8850 if (0 == enable_11d || 1 == enable_11d)
8851 {
8852 pHddCtx->cfg_ini->Is11dSupportEnabled = enable_11d;
8853 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_11d set to %d",
8854 __func__, enable_11d);
8855 }
8856
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008857 /* Note that the vos_preStart() sequence triggers the cfg download.
8858 The cfg download must occur before we update the SME config
8859 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07008860 status = hdd_set_sme_config( pHddCtx );
8861
8862 if ( VOS_STATUS_SUCCESS != status )
8863 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008864 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05308865 goto err_vosclose;
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008866 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008867
Jeff Johnson295189b2012-06-20 16:38:30 -07008868 /* In the integrated architecture we update the configuration from
8869 the INI file and from NV before vOSS has been started so that
8870 the final contents are available to send down to the cCPU */
8871
8872 // Apply the cfg.ini to cfg.dat
8873 if (FALSE == hdd_update_config_dat(pHddCtx))
8874 {
8875 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05308876 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07008877 }
8878
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308879 // Get mac addr from platform driver
8880 ret = wcnss_get_wlan_mac_address((char*)&mac_addr.bytes);
8881
8882 if ((0 == ret) && (!vos_is_macaddr_zero(&mac_addr)))
Jeff Johnson295189b2012-06-20 16:38:30 -07008883 {
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308884 /* Store the mac addr for first interface */
8885 pHddCtx->cfg_ini->intfMacAddr[0] = mac_addr;
8886
8887 hddLog(VOS_TRACE_LEVEL_ERROR,
8888 "%s: WLAN Mac Addr: "
8889 MAC_ADDRESS_STR, __func__,
8890 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
8891
8892 /* Here, passing Arg2 as 1 because we do not want to change the
8893 last 3 bytes (means non OUI bytes) of first interface mac
8894 addr.
8895 */
8896 if (0 != hdd_generate_iface_mac_addr_auto(pHddCtx, 1, mac_addr))
8897 {
8898 hddLog(VOS_TRACE_LEVEL_ERROR,
8899 "%s: Failed to generate wlan interface mac addr "
8900 "using MAC from ini file ", __func__);
8901 }
8902 }
8903 else if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
8904 {
8905 // Apply the NV to cfg.dat
8906 /* Prima Update MAC address only at here */
Jeff Johnson295189b2012-06-20 16:38:30 -07008907#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
8908 /* There was not a valid set of MAC Addresses in NV. See if the
8909 default addresses were modified by the cfg.ini settings. If so,
8910 we'll use them, but if not, we'll autogenerate a set of MAC
8911 addresses based upon the device serial number */
8912
8913 static const v_MACADDR_t default_address =
8914 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
Jeff Johnson295189b2012-06-20 16:38:30 -07008915
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308916 if (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
8917 sizeof(default_address)))
Jeff Johnson295189b2012-06-20 16:38:30 -07008918 {
8919 /* cfg.ini has the default address, invoke autogen logic */
8920
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308921 /* Here, passing Arg2 as 0 because we want to change the
8922 last 3 bytes (means non OUI bytes) of all the interfaces
8923 mac addr.
8924 */
8925 if (0 != hdd_generate_iface_mac_addr_auto(pHddCtx, 0,
8926 default_address))
Jeff Johnson295189b2012-06-20 16:38:30 -07008927 {
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308928 hddLog(VOS_TRACE_LEVEL_ERROR,
8929 "%s: Failed to generate wlan interface mac addr "
8930 "using MAC from ini file " MAC_ADDRESS_STR, __func__,
8931 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
Jeff Johnson295189b2012-06-20 16:38:30 -07008932 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008933 }
8934 else
8935#endif //WLAN_AUTOGEN_MACADDR_FEATURE
8936 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008937 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07008938 "%s: Invalid MAC address in NV, using MAC from ini file "
8939 MAC_ADDRESS_STR, __func__,
8940 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
8941 }
8942 }
8943 {
8944 eHalStatus halStatus;
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308945
8946 /* Set the MAC Address Currently this is used by HAL to
8947 * add self sta. Remove this once self sta is added as
8948 * part of session open.
8949 */
Jeff Johnson295189b2012-06-20 16:38:30 -07008950 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
8951 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
8952 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308953
Jeff Johnson295189b2012-06-20 16:38:30 -07008954 if (!HAL_STATUS_SUCCESS( halStatus ))
8955 {
8956 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
8957 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05308958 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07008959 }
8960 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008961
8962 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
8963 Note: Firmware image will be read and downloaded inside vos_start API */
8964 status = vos_start( pHddCtx->pvosContext );
8965 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8966 {
8967 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05308968 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07008969 }
8970
Leo Chang6cec3e22014-01-21 15:33:49 -08008971#ifdef FEATURE_WLAN_CH_AVOID
8972 /* Plug in avoid channel notification callback
8973 * This should happen before ADD_SELF_STA
8974 * FW will send first IND with ADD_SELF_STA REQ from host */
Pradeep Reddy POTTETI5c2e16d2014-06-27 16:47:38 +05308975
8976 /* check the Channel Avoidance is enabled */
8977 if (TRUE == pHddCtx->cfg_ini->fenableCHAvoidance)
8978 {
8979 sme_AddChAvoidCallback(pHddCtx->hHal,
8980 hdd_hostapd_ch_avoid_cb);
8981 }
Leo Chang6cec3e22014-01-21 15:33:49 -08008982#endif /* FEATURE_WLAN_CH_AVOID */
8983
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008984 /* Exchange capability info between Host and FW and also get versioning info from FW */
8985 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07008986
Agarwal Ashishad9281b2014-06-10 14:57:30 +05308987#ifdef CONFIG_ENABLE_LINUX_REG
8988 status = wlan_hdd_init_channels(pHddCtx);
8989 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8990 {
8991 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: wlan_hdd_init_channels failed",
8992 __func__);
8993 goto err_vosstop;
8994 }
8995#endif
8996
Jeff Johnson295189b2012-06-20 16:38:30 -07008997 status = hdd_post_voss_start_config( pHddCtx );
8998 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8999 {
9000 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
9001 __func__);
9002 goto err_vosstop;
9003 }
Amar Singhala49cbc52013-10-08 18:37:44 -07009004
9005#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05309006 wlan_hdd_cfg80211_update_reg_info( wiphy );
9007
9008 /* registration of wiphy dev with cfg80211 */
9009 if (0 > wlan_hdd_cfg80211_register(wiphy))
9010 {
9011 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
9012 goto err_vosstop;
9013 }
Amar Singhala49cbc52013-10-08 18:37:44 -07009014#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009015
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05309016#ifdef CONFIG_ENABLE_LINUX_REG
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05309017 /* registration of wiphy dev with cfg80211 */
9018 if (0 > wlan_hdd_cfg80211_register(wiphy))
9019 {
9020 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
9021 goto err_vosstop;
9022 }
9023
9024 status = wlan_hdd_init_channels_for_cc(pHddCtx);
9025 if ( !VOS_IS_STATUS_SUCCESS( status ) )
9026 {
9027 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: wlan_hdd_init_channels_for_cc failed",
9028 __func__);
9029 goto err_unregister_wiphy;
9030 }
9031#endif
9032
Jeff Johnson295189b2012-06-20 16:38:30 -07009033 if (VOS_STA_SAP_MODE == hdd_get_conparam())
9034 {
9035 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
9036 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
9037 }
9038 else
9039 {
Jeff Johnson295189b2012-06-20 16:38:30 -07009040 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
9041 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
9042 if (pAdapter != NULL)
9043 {
kaidde69982014-06-18 13:23:21 +08009044 if (pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated && !(pHddCtx->cfg_ini->intfMacAddr[0].bytes[0] &= 0x02))
Jeff Johnson295189b2012-06-20 16:38:30 -07009045 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05309046 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
9047 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
9048 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07009049
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05309050 /* Generate the P2P Device Address. This consists of the device's
9051 * primary MAC address with the locally administered bit set.
9052 */
9053 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07009054 }
9055 else
9056 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05309057 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
9058 if (p2p_dev_addr != NULL)
9059 {
9060 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
9061 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
9062 }
9063 else
9064 {
9065 hddLog(VOS_TRACE_LEVEL_FATAL,
9066 "%s: Failed to allocate mac_address for p2p_device",
9067 __func__);
9068 goto err_close_adapter;
9069 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009070 }
Jeff Johnsone7245742012-09-05 17:12:55 -07009071
9072 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
9073 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
9074 if ( NULL == pP2pAdapter )
9075 {
9076 hddLog(VOS_TRACE_LEVEL_FATAL,
9077 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07009078 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07009079 goto err_close_adapter;
9080 }
Jeff Johnsone7245742012-09-05 17:12:55 -07009081 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009082 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009083
9084 if( pAdapter == NULL )
9085 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08009086 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
9087 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07009088 }
Jeff Johnsone7245742012-09-05 17:12:55 -07009089
Arif Hussain66559122013-11-21 10:11:40 -08009090 if (country_code)
9091 {
9092 eHalStatus ret;
Arif Hussaincb607082013-12-20 11:57:42 -08009093 INIT_COMPLETION(pAdapter->change_country_code);
Arif Hussain66559122013-11-21 10:11:40 -08009094 hdd_checkandupdate_dfssetting(pAdapter, country_code);
9095#ifndef CONFIG_ENABLE_LINUX_REG
9096 hdd_checkandupdate_phymode(pAdapter, country_code);
9097#endif
Arif Hussaineaf68602013-12-30 23:10:44 -08009098 ret = sme_ChangeCountryCode(pHddCtx->hHal,
9099 (void *)(tSmeChangeCountryCallback)
9100 wlan_hdd_change_country_code_callback,
Arif Hussain66559122013-11-21 10:11:40 -08009101 country_code,
9102 pAdapter, pHddCtx->pvosContext,
Abhishek Singha306a442013-11-07 18:39:01 +05309103 eSIR_TRUE, eSIR_TRUE);
Arif Hussain66559122013-11-21 10:11:40 -08009104 if (eHAL_STATUS_SUCCESS == ret)
9105 {
Arif Hussaincb607082013-12-20 11:57:42 -08009106 ret = wait_for_completion_interruptible_timeout(
9107 &pAdapter->change_country_code,
9108 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
9109
9110 if (0 >= ret)
9111 {
9112 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
9113 "%s: SME while setting country code timed out", __func__);
9114 }
Arif Hussain66559122013-11-21 10:11:40 -08009115 }
9116 else
9117 {
Arif Hussaincb607082013-12-20 11:57:42 -08009118 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
9119 "%s: SME Change Country code from module param fail ret=%d",
9120 __func__, ret);
Arif Hussain66559122013-11-21 10:11:40 -08009121 }
9122 }
9123
Jeff Johnson295189b2012-06-20 16:38:30 -07009124#ifdef WLAN_BTAMP_FEATURE
9125 vStatus = WLANBAP_Open(pVosContext);
9126 if(!VOS_IS_STATUS_SUCCESS(vStatus))
9127 {
9128 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
9129 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07009130 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07009131 }
9132
9133 vStatus = BSL_Init(pVosContext);
9134 if(!VOS_IS_STATUS_SUCCESS(vStatus))
9135 {
9136 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
9137 "%s: Failed to Init BSL",__func__);
9138 goto err_bap_close;
9139 }
9140 vStatus = WLANBAP_Start(pVosContext);
9141 if (!VOS_IS_STATUS_SUCCESS(vStatus))
9142 {
9143 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
9144 "%s: Failed to start TL",__func__);
9145 goto err_bap_close;
9146 }
9147
9148 pConfig = pHddCtx->cfg_ini;
9149 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
9150 status = WLANBAP_SetConfig(&btAmpConfig);
9151
9152#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07009153
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07009154#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
9155 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
9156 {
9157 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
9158 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
9159 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
9160 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
9161 }
9162#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009163
Agarwal Ashish4b87f922014-06-18 03:03:21 +05309164 wlan_hdd_tdls_init(pHddCtx);
9165
Mihir Shetefc7ff5b2014-01-27 11:30:05 +05309166 sme_Register11dScanDoneCallback(pHddCtx->hHal, hdd_11d_scan_done);
9167
Jeff Johnson295189b2012-06-20 16:38:30 -07009168 /* Register with platform driver as client for Suspend/Resume */
9169 status = hddRegisterPmOps(pHddCtx);
9170 if ( !VOS_IS_STATUS_SUCCESS( status ) )
9171 {
9172 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
9173#ifdef WLAN_BTAMP_FEATURE
9174 goto err_bap_stop;
9175#else
Jeff Johnsone7245742012-09-05 17:12:55 -07009176 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07009177#endif //WLAN_BTAMP_FEATURE
9178 }
9179
Yue Ma0d4891e2013-08-06 17:01:45 -07009180 /* Open debugfs interface */
9181 if (VOS_STATUS_SUCCESS != hdd_debugfs_init(pAdapter))
9182 {
9183 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
9184 "%s: hdd_debugfs_init failed!", __func__);
Yue Ma0d4891e2013-08-06 17:01:45 -07009185 }
9186
Jeff Johnson295189b2012-06-20 16:38:30 -07009187 /* Register TM level change handler function to the platform */
9188 status = hddDevTmRegisterNotifyCallback(pHddCtx);
9189 if ( !VOS_IS_STATUS_SUCCESS( status ) )
9190 {
9191 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
9192 goto err_unregister_pmops;
9193 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009194
9195 /* register for riva power on lock to platform driver */
9196 if (req_riva_power_on_lock("wlan"))
9197 {
9198 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
9199 __func__);
9200 goto err_unregister_pmops;
9201 }
9202
Jeff Johnson295189b2012-06-20 16:38:30 -07009203 // register net device notifier for device change notification
9204 ret = register_netdevice_notifier(&hdd_netdev_notifier);
9205
9206 if(ret < 0)
9207 {
9208 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
9209 goto err_free_power_on_lock;
9210 }
9211
9212 //Initialize the nlink service
9213 if(nl_srv_init() != 0)
9214 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05309215 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009216 goto err_reg_netdev;
9217 }
9218
Leo Chang4ce1cc52013-10-21 18:27:15 -07009219#ifdef WLAN_KD_READY_NOTIFIER
9220 pHddCtx->kd_nl_init = 1;
9221#endif /* WLAN_KD_READY_NOTIFIER */
9222
Jeff Johnson295189b2012-06-20 16:38:30 -07009223 //Initialize the BTC service
9224 if(btc_activate_service(pHddCtx) != 0)
9225 {
9226 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
9227 goto err_nl_srv;
9228 }
9229
9230#ifdef PTT_SOCK_SVC_ENABLE
9231 //Initialize the PTT service
9232 if(ptt_sock_activate_svc(pHddCtx) != 0)
9233 {
9234 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
9235 goto err_nl_srv;
9236 }
9237#endif
9238
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05309239#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9240 if(pHddCtx->cfg_ini && pHddCtx->cfg_ini->wlanLoggingEnable)
9241 {
9242 if(wlan_logging_sock_activate_svc(
9243 pHddCtx->cfg_ini->wlanLoggingFEToConsole,
9244 pHddCtx->cfg_ini->wlanLoggingNumBuf))
9245 {
9246 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wlan_logging_sock_activate_svc"
9247 " failed", __func__);
9248 goto err_nl_srv;
9249 }
9250 }
9251#endif
9252
Jeff Johnson295189b2012-06-20 16:38:30 -07009253 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07009254 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07009255 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07009256 /* Action frame registered in one adapter which will
9257 * applicable to all interfaces
9258 */
Agarwal Ashish8fa0e9a2014-05-23 00:40:12 +05309259 wlan_hdd_cfg80211_register_frames(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07009260 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009261
9262 mutex_init(&pHddCtx->sap_lock);
9263
Jeff Johnson295189b2012-06-20 16:38:30 -07009264
Sameer Thalappil50dc0092013-02-19 17:23:33 -08009265#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07009266#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
9267 /* Initialize the wake lcok */
9268 wake_lock_init(&pHddCtx->rx_wake_lock,
9269 WAKE_LOCK_SUSPEND,
9270 "qcom_rx_wakelock");
9271#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08009272 /* Initialize the wake lcok */
9273 wake_lock_init(&pHddCtx->sap_wake_lock,
9274 WAKE_LOCK_SUSPEND,
9275 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08009276#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07009277
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07009278 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
9279 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07009280
Katya Nigam5c306ea2014-06-19 15:39:54 +05309281 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_NO_LOAD_UNLOAD_IN_PROGRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -07009282 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
9283 hdd_allow_suspend();
Katya Nigam5c306ea2014-06-19 15:39:54 +05309284
9285#ifdef FEATURE_WLAN_SCAN_PNO
9286 /*SME must send channel update configuration to RIVA*/
9287 sme_UpdateChannelConfig(pHddCtx->hHal);
9288#endif
Abhishek Singhf644b272014-08-21 02:59:39 +05309289 /* Send the update default channel list to the FW*/
9290 sme_UpdateChannelList(pHddCtx->hHal);
Abhishek Singha306a442013-11-07 18:39:01 +05309291#ifndef CONFIG_ENABLE_LINUX_REG
9292 /*updating wiphy so that regulatory user hints can be processed*/
9293 if (wiphy)
9294 {
9295 regulatory_hint(wiphy, "00");
9296 }
9297#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07009298 // Initialize the restart logic
9299 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05309300
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07009301 //Register the traffic monitor timer now
9302 if ( pHddCtx->cfg_ini->dynSplitscan)
9303 {
9304 vos_timer_init(&pHddCtx->tx_rx_trafficTmr,
9305 VOS_TIMER_TYPE_SW,
9306 hdd_tx_rx_pkt_cnt_stat_timer_handler,
9307 (void *)pHddCtx);
9308 }
Dino Mycle6fb96c12014-06-10 11:52:40 +05309309#ifdef WLAN_FEATURE_EXTSCAN
9310 sme_EXTScanRegisterCallback(pHddCtx->hHal,
9311 wlan_hdd_cfg80211_extscan_callback,
9312 pHddCtx);
9313#endif /* WLAN_FEATURE_EXTSCAN */
Jeff Johnson295189b2012-06-20 16:38:30 -07009314 goto success;
9315
9316err_nl_srv:
Leo Chang59cdc7e2013-07-10 10:08:21 -07009317#ifdef WLAN_KD_READY_NOTIFIER
9318 nl_srv_exit(pHddCtx->ptt_pid);
9319#else
Jeff Johnson295189b2012-06-20 16:38:30 -07009320 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07009321#endif /* WLAN_KD_READY_NOTIFIER */
Jeff Johnson295189b2012-06-20 16:38:30 -07009322err_reg_netdev:
9323 unregister_netdevice_notifier(&hdd_netdev_notifier);
9324
9325err_free_power_on_lock:
9326 free_riva_power_on_lock("wlan");
9327
9328err_unregister_pmops:
9329 hddDevTmUnregisterNotifyCallback(pHddCtx);
9330 hddDeregisterPmOps(pHddCtx);
9331
Yue Ma0d4891e2013-08-06 17:01:45 -07009332 hdd_debugfs_exit(pHddCtx);
9333
Jeff Johnson295189b2012-06-20 16:38:30 -07009334#ifdef WLAN_BTAMP_FEATURE
9335err_bap_stop:
9336 WLANBAP_Stop(pVosContext);
9337#endif
9338
9339#ifdef WLAN_BTAMP_FEATURE
9340err_bap_close:
9341 WLANBAP_Close(pVosContext);
9342#endif
9343
Jeff Johnson295189b2012-06-20 16:38:30 -07009344err_close_adapter:
9345 hdd_close_all_adapters( pHddCtx );
Mahesh A Saptasagar9ecefe42014-07-15 18:43:49 +05309346#ifdef CONFIG_ENABLE_LINUX_REG
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05309347err_unregister_wiphy:
Mahesh A Saptasagar9ecefe42014-07-15 18:43:49 +05309348#endif
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05309349 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07009350err_vosstop:
9351 vos_stop(pVosContext);
9352
Amar Singhala49cbc52013-10-08 18:37:44 -07009353err_vosclose:
Jeff Johnson295189b2012-06-20 16:38:30 -07009354 status = vos_sched_close( pVosContext );
9355 if (!VOS_IS_STATUS_SUCCESS(status)) {
9356 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
9357 "%s: Failed to close VOSS Scheduler", __func__);
9358 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
9359 }
Amar Singhala49cbc52013-10-08 18:37:44 -07009360 vos_close(pVosContext );
9361
Amar Singhal0a402232013-10-11 20:57:16 -07009362err_vos_nv_close:
9363
c_hpothue6a36282014-03-19 12:27:38 +05309364#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -07009365 vos_nv_close();
9366
Jeff Johnson295189b2012-06-20 16:38:30 -07009367err_clkvote:
c_hpothu70f8d812014-03-22 22:59:23 +05309368#endif
Jeff Johnsonbc676b42013-02-14 16:04:08 -08009369 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07009370
9371err_wdclose:
9372 if(pHddCtx->cfg_ini->fIsLogpEnabled)
9373 vos_watchdog_close(pVosContext);
9374
Jeff Johnson295189b2012-06-20 16:38:30 -07009375err_config:
9376 kfree(pHddCtx->cfg_ini);
9377 pHddCtx->cfg_ini= NULL;
9378
9379err_free_hdd_context:
9380 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07009381 wiphy_free(wiphy) ;
9382 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07009383 VOS_BUG(1);
9384
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08009385 if (hdd_is_ssr_required())
9386 {
9387 /* WDI timeout had happened during load, so SSR is needed here */
9388 subsystem_restart("wcnss");
9389 msleep(5000);
9390 }
9391 hdd_set_ssr_required (VOS_FALSE);
9392
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08009393 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07009394
9395success:
9396 EXIT();
9397 return 0;
9398}
9399
9400/**---------------------------------------------------------------------------
9401
Jeff Johnson32d95a32012-09-10 13:15:23 -07009402 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07009403
Jeff Johnson32d95a32012-09-10 13:15:23 -07009404 This is the driver entry point - called in different timeline depending
9405 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07009406
9407 \param - None
9408
9409 \return - 0 for success, non zero for failure
9410
9411 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07009412static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07009413{
9414 VOS_STATUS status;
9415 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07009416 struct device *dev = NULL;
9417 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07009418#ifdef HAVE_WCNSS_CAL_DOWNLOAD
9419 int max_retries = 0;
9420#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009421
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05309422#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9423 wlan_logging_sock_init_svc();
9424#endif
9425
Jeff Johnson295189b2012-06-20 16:38:30 -07009426 ENTER();
9427
Sameer Thalappil50dc0092013-02-19 17:23:33 -08009428#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07009429 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07009430#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009431
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05309432 hddTraceInit();
Jeff Johnson295189b2012-06-20 16:38:30 -07009433 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
9434 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
9435
9436 //Power Up Libra WLAN card first if not already powered up
9437 status = vos_chipPowerUp(NULL,NULL,NULL);
9438 if (!VOS_IS_STATUS_SUCCESS(status))
9439 {
9440 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
9441 "exiting", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05309442#ifdef WLAN_OPEN_SOURCE
9443 wake_lock_destroy(&wlan_wake_lock);
9444#endif
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05309445
9446#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9447 wlan_logging_sock_deinit_svc();
9448#endif
9449
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08009450 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07009451 }
9452
Jeff Johnson295189b2012-06-20 16:38:30 -07009453#ifdef ANI_BUS_TYPE_PCI
9454
9455 dev = wcnss_wlan_get_device();
9456
9457#endif // ANI_BUS_TYPE_PCI
9458
9459#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07009460
9461#ifdef HAVE_WCNSS_CAL_DOWNLOAD
9462 /* wait until WCNSS driver downloads NV */
9463 while (!wcnss_device_ready() && 5 >= ++max_retries) {
9464 msleep(1000);
9465 }
9466 if (max_retries >= 5) {
9467 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05309468#ifdef WLAN_OPEN_SOURCE
9469 wake_lock_destroy(&wlan_wake_lock);
9470#endif
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05309471
9472#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9473 wlan_logging_sock_deinit_svc();
9474#endif
9475
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07009476 return -ENODEV;
9477 }
9478#endif
9479
Jeff Johnson295189b2012-06-20 16:38:30 -07009480 dev = wcnss_wlan_get_device();
9481#endif // ANI_BUS_TYPE_PLATFORM
9482
9483
9484 do {
9485 if (NULL == dev) {
9486 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
9487 ret_status = -1;
9488 break;
9489 }
9490
Jeff Johnson295189b2012-06-20 16:38:30 -07009491#ifdef TIMER_MANAGER
9492 vos_timer_manager_init();
9493#endif
9494
9495 /* Preopen VOSS so that it is ready to start at least SAL */
9496 status = vos_preOpen(&pVosContext);
9497
9498 if (!VOS_IS_STATUS_SUCCESS(status))
9499 {
9500 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
9501 ret_status = -1;
9502 break;
9503 }
9504
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009505#ifndef MODULE
9506 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
9507 */
9508 hdd_set_conparam((v_UINT_t)con_mode);
9509#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009510
9511 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08009512 if (hdd_wlan_startup(dev))
9513 {
Jeff Johnson295189b2012-06-20 16:38:30 -07009514 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08009515 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009516 vos_preClose( &pVosContext );
9517 ret_status = -1;
9518 break;
9519 }
9520
9521 /* Cancel the vote for XO Core ON
9522 * This is done here for safety purposes in case we re-initialize without turning
9523 * it OFF in any error scenario.
9524 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07009525 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07009526 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07009527 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07009528 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
9529 {
9530 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
Arif Hussain6d2a3322013-11-17 19:50:10 -08009531 " Power consumed will be high");
Jeff Johnson295189b2012-06-20 16:38:30 -07009532 }
9533 } while (0);
9534
9535 if (0 != ret_status)
9536 {
9537 //Assert Deep sleep signal now to put Libra HW in lowest power state
9538 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
9539 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
9540
9541 //Vote off any PMIC voltage supplies
9542 vos_chipPowerDown(NULL, NULL, NULL);
9543#ifdef TIMER_MANAGER
9544 vos_timer_exit();
9545#endif
9546#ifdef MEMORY_DEBUG
9547 vos_mem_exit();
9548#endif
9549
Sameer Thalappil50dc0092013-02-19 17:23:33 -08009550#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07009551 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07009552#endif
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05309553
9554#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9555 wlan_logging_sock_deinit_svc();
9556#endif
9557
Jeff Johnson295189b2012-06-20 16:38:30 -07009558 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
9559 }
9560 else
9561 {
9562 //Send WLAN UP indication to Nlink Service
9563 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
9564
9565 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Jeff Johnson295189b2012-06-20 16:38:30 -07009566 }
9567
9568 EXIT();
9569
9570 return ret_status;
9571}
9572
Jeff Johnson32d95a32012-09-10 13:15:23 -07009573/**---------------------------------------------------------------------------
9574
9575 \brief hdd_module_init() - Init Function
9576
9577 This is the driver entry point (invoked when module is loaded using insmod)
9578
9579 \param - None
9580
9581 \return - 0 for success, non zero for failure
9582
9583 --------------------------------------------------------------------------*/
9584#ifdef MODULE
9585static int __init hdd_module_init ( void)
9586{
9587 return hdd_driver_init();
9588}
Jeff Johnson32d95a32012-09-10 13:15:23 -07009589#else /* #ifdef MODULE */
9590static int __init hdd_module_init ( void)
9591{
9592 /* Driver initialization is delayed to fwpath_changed_handler */
9593 return 0;
9594}
Jeff Johnson32d95a32012-09-10 13:15:23 -07009595#endif /* #ifdef MODULE */
9596
Jeff Johnson295189b2012-06-20 16:38:30 -07009597
9598/**---------------------------------------------------------------------------
9599
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009600 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07009601
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009602 This is the driver exit point (invoked when module is unloaded using rmmod
9603 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07009604
9605 \param - None
9606
9607 \return - None
9608
9609 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009610static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07009611{
9612 hdd_context_t *pHddCtx = NULL;
9613 v_CONTEXT_t pVosContext = NULL;
Agarwal Ashish5e414792014-06-08 15:25:23 +05309614 v_REGDOMAIN_t regId;
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +05309615 unsigned long rc = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07009616
9617 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
9618
9619 //Get the global vos context
9620 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
9621
9622 if(!pVosContext)
9623 {
9624 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
9625 goto done;
9626 }
9627
9628 //Get the HDD context.
9629 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
9630
9631 if(!pHddCtx)
9632 {
9633 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
9634 }
9635 else
9636 {
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +05309637 INIT_COMPLETION(pHddCtx->ssr_comp_var);
9638
9639 if (pHddCtx->isLogpInProgress)
9640 {
Sameer Thalappil451ebb92013-06-28 15:49:58 -07009641 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +05309642 "%s:SSR in Progress; block rmmod !!!", __func__);
9643 rc = wait_for_completion_timeout(&pHddCtx->ssr_comp_var,
9644 msecs_to_jiffies(30000));
9645 if(!rc)
9646 {
9647 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
9648 "%s:SSR timedout, fatal error", __func__);
9649 VOS_BUG(0);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07009650 }
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +05309651 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009652
Vinay Krishna Erannae362b452014-09-23 13:09:46 +05309653 rtnl_lock();
Mihir Shete18156292014-03-11 15:38:30 +05309654 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_UNLOAD_IN_PROGRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -07009655 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
Vinay Krishna Erannae362b452014-09-23 13:09:46 +05309656 rtnl_unlock();
Jeff Johnson295189b2012-06-20 16:38:30 -07009657
Agarwal Ashish8db39882014-07-30 21:56:07 +05309658 /* Driver Need to send country code 00 in below condition
9659 * 1) If gCountryCodePriority is set to 1; and last country
9660 * code set is through 11d. This needs to be done in case
9661 * when NV country code is 00.
9662 * This Needs to be done as when kernel store last country
9663 * code and if stored country code is not through 11d,
9664 * in sme_HandleChangeCountryCodeByUser we will disable 11d
9665 * in next load/unload as soon as we get any country through
9666 * 11d. In sme_HandleChangeCountryCodeByUser
9667 * pMsg->countryCode will be last countryCode and
9668 * pMac->scan.countryCode11d will be country through 11d so
9669 * due to mismatch driver will disable 11d.
9670 *
9671 * 2) When NV country Code is non-zero ;
9672 * There are chances that kernel last country and default
9673 * country can be same. In this case if Driver doesn't pass 00 to
9674 * kernel, at the time of driver loading next timer, driver will not
9675 * call any hint to kernel as country is same. This can add 3 sec
9676 * delay in driver loading.
9677 */
9678
9679 if ((eANI_BOOLEAN_TRUE == sme_Is11dCountrycode(pHddCtx->hHal) &&
Agarwal Ashish8dcd2862014-07-25 11:58:52 +05309680 pHddCtx->cfg_ini->fSupplicantCountryCodeHasPriority &&
Agarwal Ashish8db39882014-07-30 21:56:07 +05309681 sme_Is11dSupported(pHddCtx->hHal)) || (vos_is_nv_country_non_zero() ))
Agarwal Ashish5e414792014-06-08 15:25:23 +05309682 {
Agarwal Ashish8dcd2862014-07-25 11:58:52 +05309683 hddLog(VOS_TRACE_LEVEL_INFO,
9684 FL("CountryCode 00 is being set while unloading driver"));
Agarwal Ashish5e414792014-06-08 15:25:23 +05309685 vos_nv_getRegDomainFromCountryCode(&regId , "00", COUNTRY_USER);
9686 }
9687
Jeff Johnson295189b2012-06-20 16:38:30 -07009688 //Do all the cleanup before deregistering the driver
9689 hdd_wlan_exit(pHddCtx);
9690 }
9691
Jeff Johnson295189b2012-06-20 16:38:30 -07009692 vos_preClose( &pVosContext );
9693
9694#ifdef TIMER_MANAGER
9695 vos_timer_exit();
9696#endif
9697#ifdef MEMORY_DEBUG
9698 vos_mem_exit();
9699#endif
9700
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05309701#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9702 wlan_logging_sock_deinit_svc();
9703#endif
9704
Jeff Johnson295189b2012-06-20 16:38:30 -07009705done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08009706#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07009707 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07009708#endif
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05309709
Jeff Johnson295189b2012-06-20 16:38:30 -07009710 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
9711}
9712
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009713/**---------------------------------------------------------------------------
9714
9715 \brief hdd_module_exit() - Exit function
9716
9717 This is the driver exit point (invoked when module is unloaded using rmmod)
9718
9719 \param - None
9720
9721 \return - None
9722
9723 --------------------------------------------------------------------------*/
9724static void __exit hdd_module_exit(void)
9725{
9726 hdd_driver_exit();
9727}
9728
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009729#ifdef MODULE
9730static int fwpath_changed_handler(const char *kmessage,
9731 struct kernel_param *kp)
9732{
Jeff Johnson76052702013-04-16 13:55:05 -07009733 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009734}
9735
9736static int con_mode_handler(const char *kmessage,
9737 struct kernel_param *kp)
9738{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07009739 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009740}
9741#else /* #ifdef MODULE */
9742/**---------------------------------------------------------------------------
9743
Jeff Johnson76052702013-04-16 13:55:05 -07009744 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009745
Jeff Johnson76052702013-04-16 13:55:05 -07009746 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009747 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07009748 - invoked when module parameter fwpath is modified from userspace to signal
9749 initializing the WLAN driver or when con_mode is modified from userspace
9750 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009751
9752 \return - 0 for success, non zero for failure
9753
9754 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07009755static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009756{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07009757 int ret_status;
9758
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009759 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07009760 ret_status = hdd_driver_init();
9761 wlan_hdd_inited = ret_status ? 0 : 1;
9762 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009763 }
9764
9765 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07009766
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009767 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07009768
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07009769 ret_status = hdd_driver_init();
9770 wlan_hdd_inited = ret_status ? 0 : 1;
9771 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009772}
9773
Jeff Johnson295189b2012-06-20 16:38:30 -07009774/**---------------------------------------------------------------------------
9775
Jeff Johnson76052702013-04-16 13:55:05 -07009776 \brief fwpath_changed_handler() - Handler Function
9777
9778 Handle changes to the fwpath parameter
9779
9780 \return - 0 for success, non zero for failure
9781
9782 --------------------------------------------------------------------------*/
9783static int fwpath_changed_handler(const char *kmessage,
9784 struct kernel_param *kp)
9785{
9786 int ret;
9787
9788 ret = param_set_copystring(kmessage, kp);
9789 if (0 == ret)
9790 ret = kickstart_driver();
9791 return ret;
9792}
9793
9794/**---------------------------------------------------------------------------
9795
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009796 \brief con_mode_handler() -
9797
9798 Handler function for module param con_mode when it is changed by userspace
9799 Dynamically linked - do nothing
9800 Statically linked - exit and init driver, as in rmmod and insmod
9801
Jeff Johnson76052702013-04-16 13:55:05 -07009802 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009803
Jeff Johnson76052702013-04-16 13:55:05 -07009804 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009805
9806 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07009807static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009808{
Jeff Johnson76052702013-04-16 13:55:05 -07009809 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009810
Jeff Johnson76052702013-04-16 13:55:05 -07009811 ret = param_set_int(kmessage, kp);
9812 if (0 == ret)
9813 ret = kickstart_driver();
9814 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009815}
9816#endif /* #ifdef MODULE */
9817
9818/**---------------------------------------------------------------------------
9819
Jeff Johnson295189b2012-06-20 16:38:30 -07009820 \brief hdd_get_conparam() -
9821
9822 This is the driver exit point (invoked when module is unloaded using rmmod)
9823
9824 \param - None
9825
9826 \return - tVOS_CON_MODE
9827
9828 --------------------------------------------------------------------------*/
9829tVOS_CON_MODE hdd_get_conparam ( void )
9830{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009831#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07009832 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009833#else
9834 return (tVOS_CON_MODE)curr_con_mode;
9835#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009836}
9837void hdd_set_conparam ( v_UINT_t newParam )
9838{
9839 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009840#ifndef MODULE
9841 curr_con_mode = con_mode;
9842#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009843}
9844/**---------------------------------------------------------------------------
9845
9846 \brief hdd_softap_sta_deauth() - function
9847
9848 This to take counter measure to handle deauth req from HDD
9849
9850 \param - pAdapter - Pointer to the HDD
9851
9852 \param - enable - boolean value
9853
9854 \return - None
9855
9856 --------------------------------------------------------------------------*/
9857
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009858VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07009859{
Jeff Johnson295189b2012-06-20 16:38:30 -07009860 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009861 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07009862
9863 ENTER();
9864
Rajesh Chauhan18488fc2013-08-22 10:15:03 -07009865 hddLog(LOG1, "hdd_softap_sta_deauth:(%p, false)",
9866 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07009867
9868 //Ignore request to deauth bcmc station
9869 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009870 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07009871
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009872 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07009873
9874 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009875 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07009876}
9877
9878/**---------------------------------------------------------------------------
9879
Rashmi Ramanna1f0948d2014-08-28 15:33:48 +05309880 \brief hdd_del_all_sta() - function
9881
9882 This function removes all the stations associated on stopping AP/P2P GO.
9883
9884 \param - pAdapter - Pointer to the HDD
9885
9886 \return - None
9887
9888 --------------------------------------------------------------------------*/
9889
9890int hdd_del_all_sta(hdd_adapter_t *pAdapter)
9891{
9892 v_U16_t i;
9893 VOS_STATUS vos_status;
9894
9895 ENTER();
9896
9897 hddLog(VOS_TRACE_LEVEL_INFO,
9898 "%s: Delete all STAs associated.",__func__);
9899 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
9900 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
9901 )
9902 {
9903 for(i = 0; i < WLAN_MAX_STA_COUNT; i++)
9904 {
9905 if ((pAdapter->aStaInfo[i].isUsed) &&
9906 (!pAdapter->aStaInfo[i].isDeauthInProgress))
9907 {
9908 u8 *macAddr = pAdapter->aStaInfo[i].macAddrSTA.bytes;
9909 hddLog(VOS_TRACE_LEVEL_ERROR,
9910 "%s: Delete STA with staid = %d and MAC::"
9911 MAC_ADDRESS_STR,
9912 __func__, i, MAC_ADDR_ARRAY(macAddr));
9913 vos_status = hdd_softap_sta_deauth(pAdapter, macAddr);
9914 if (VOS_IS_STATUS_SUCCESS(vos_status))
9915 pAdapter->aStaInfo[i].isDeauthInProgress = TRUE;
9916 }
9917 }
9918 }
9919
9920 EXIT();
9921 return 0;
9922}
9923
9924/**---------------------------------------------------------------------------
9925
Jeff Johnson295189b2012-06-20 16:38:30 -07009926 \brief hdd_softap_sta_disassoc() - function
9927
9928 This to take counter measure to handle deauth req from HDD
9929
9930 \param - pAdapter - Pointer to the HDD
9931
9932 \param - enable - boolean value
9933
9934 \return - None
9935
9936 --------------------------------------------------------------------------*/
9937
9938void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
9939{
9940 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
9941
9942 ENTER();
9943
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05309944 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07009945
9946 //Ignore request to disassoc bcmc station
9947 if( pDestMacAddress[0] & 0x1 )
9948 return;
9949
9950 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
9951}
9952
9953void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
9954{
9955 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
9956
9957 ENTER();
9958
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05309959 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07009960
9961 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
9962}
9963
Jeff Johnson295189b2012-06-20 16:38:30 -07009964/**---------------------------------------------------------------------------
9965 *
9966 * \brief hdd_get__concurrency_mode() -
9967 *
9968 *
9969 * \param - None
9970 *
9971 * \return - CONCURRENCY MODE
9972 *
9973 * --------------------------------------------------------------------------*/
9974tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
9975{
9976 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
9977 hdd_context_t *pHddCtx;
9978
9979 if (NULL != pVosContext)
9980 {
9981 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
9982 if (NULL != pHddCtx)
9983 {
9984 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
9985 }
9986 }
9987
9988 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07009989 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009990 return VOS_STA;
9991}
Sushant Kaushikabb7ee62014-07-18 16:20:12 +05309992v_BOOL_t
9993wlan_hdd_is_GO_power_collapse_allowed (hdd_context_t* pHddCtx)
9994{
9995 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07009996
Sushant Kaushikabb7ee62014-07-18 16:20:12 +05309997 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_GO);
9998 if (pAdapter == NULL)
9999 {
10000 hddLog(VOS_TRACE_LEVEL_INFO,
10001 FL("GO doesn't exist"));
10002 return TRUE;
10003 }
10004 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
10005 {
10006 hddLog(VOS_TRACE_LEVEL_INFO,
10007 FL("GO started"));
10008 return TRUE;
10009 }
10010 else
10011 /* wait till GO changes its interface to p2p device */
10012 hddLog(VOS_TRACE_LEVEL_INFO,
10013 FL("Del_bss called, avoid apps suspend"));
10014 return FALSE;
10015
10016}
Jeff Johnson295189b2012-06-20 16:38:30 -070010017/* Decide whether to allow/not the apps power collapse.
10018 * Allow apps power collapse if we are in connected state.
10019 * if not, allow only if we are in IMPS */
10020v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
10021{
10022 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -080010023 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -080010024 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -070010025 hdd_config_t *pConfig = pHddCtx->cfg_ini;
10026 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
10027 hdd_adapter_t *pAdapter = NULL;
10028 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -080010029 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -070010030
Jeff Johnson295189b2012-06-20 16:38:30 -070010031 if (VOS_STA_SAP_MODE == hdd_get_conparam())
10032 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -070010033
Yathish9f22e662012-12-10 14:21:35 -080010034 concurrent_state = hdd_get_concurrency_mode();
10035
Sushant Kaushikabb7ee62014-07-18 16:20:12 +053010036 if ((concurrent_state == (VOS_STA | VOS_P2P_GO)) &&
10037 !(wlan_hdd_is_GO_power_collapse_allowed(pHddCtx)))
10038 return FALSE;
Yathish9f22e662012-12-10 14:21:35 -080010039#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
Sushant Kaushikabb7ee62014-07-18 16:20:12 +053010040
Yathish9f22e662012-12-10 14:21:35 -080010041 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
Sushant Kaushikabb7ee62014-07-18 16:20:12 +053010042 (concurrent_state == (VOS_STA | VOS_P2P_GO)))&&
Yathish9f22e662012-12-10 14:21:35 -080010043 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
10044 return TRUE;
10045#endif
10046
Jeff Johnson295189b2012-06-20 16:38:30 -070010047 /*loop through all adapters. TBD fix for Concurrency */
10048 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10049 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
10050 {
10051 pAdapter = pAdapterNode->pAdapter;
10052 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
10053 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
10054 {
Srikant Kuppafef66a72013-01-30 17:32:44 -080010055 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
c_hpothu4e8faac2014-05-16 17:38:44 +053010056 && (pmcState != IMPS && pmcState != BMPS && pmcState != UAPSD
Srikant Kuppafef66a72013-01-30 17:32:44 -080010057 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -080010058 (eANI_BOOLEAN_TRUE == scanRspPending) ||
10059 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -070010060 {
Srikant Kuppafef66a72013-01-30 17:32:44 -080010061 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -080010062 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
10063 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -070010064 return FALSE;
10065 }
10066 }
10067 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10068 pAdapterNode = pNext;
10069 }
10070 return TRUE;
10071}
10072
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -080010073/* Decides whether to send suspend notification to Riva
10074 * if any adapter is in BMPS; then it is required */
10075v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
10076{
10077 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
10078 hdd_config_t *pConfig = pHddCtx->cfg_ini;
10079
10080 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
10081 {
10082 return TRUE;
10083 }
10084 return FALSE;
10085}
10086
Jeff Johnson295189b2012-06-20 16:38:30 -070010087void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
10088{
10089 switch(mode)
10090 {
Chilam Ngc4244af2013-04-01 15:37:32 -070010091 case VOS_STA_MODE:
10092 case VOS_P2P_CLIENT_MODE:
10093 case VOS_P2P_GO_MODE:
10094 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -070010095 pHddCtx->concurrency_mode |= (1 << mode);
Agarwal Ashish51325b52014-06-16 16:50:49 +053010096 pHddCtx->no_of_open_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -070010097 break;
10098 default:
10099 break;
Jeff Johnson295189b2012-06-20 16:38:30 -070010100 }
Agarwal Ashish51325b52014-06-16 16:50:49 +053010101 hddLog(VOS_TRACE_LEVEL_INFO, FL("concurrency_mode = 0x%x "
10102 "Number of open sessions for mode %d = %d"),
10103 pHddCtx->concurrency_mode, mode,
10104 pHddCtx->no_of_open_sessions[mode]);
Jeff Johnson295189b2012-06-20 16:38:30 -070010105}
10106
10107
10108void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
10109{
10110 switch(mode)
10111 {
Chilam Ngc4244af2013-04-01 15:37:32 -070010112 case VOS_STA_MODE:
10113 case VOS_P2P_CLIENT_MODE:
10114 case VOS_P2P_GO_MODE:
10115 case VOS_STA_SAP_MODE:
Agarwal Ashish51325b52014-06-16 16:50:49 +053010116 pHddCtx->no_of_open_sessions[mode]--;
10117 if (!(pHddCtx->no_of_open_sessions[mode]))
10118 pHddCtx->concurrency_mode &= (~(1 << mode));
Jeff Johnson295189b2012-06-20 16:38:30 -070010119 break;
10120 default:
10121 break;
10122 }
Agarwal Ashish51325b52014-06-16 16:50:49 +053010123 hddLog(VOS_TRACE_LEVEL_INFO, FL("concurrency_mode = 0x%x "
10124 "Number of open sessions for mode %d = %d"),
10125 pHddCtx->concurrency_mode, mode, pHddCtx->no_of_open_sessions[mode]);
10126
10127}
10128/**---------------------------------------------------------------------------
10129 *
10130 * \brief wlan_hdd_incr_active_session()
10131 *
10132 * This function increments the number of active sessions
10133 * maintained per device mode
10134 * Incase of STA/P2P CLI/IBSS upon connection indication it is incremented
10135 * Incase of SAP/P2P GO upon bss start it is incremented
10136 *
10137 * \param pHddCtx - HDD Context
10138 * \param mode - device mode
10139 *
10140 * \return - None
10141 *
10142 * --------------------------------------------------------------------------*/
10143void wlan_hdd_incr_active_session(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
10144{
10145 switch (mode) {
10146 case VOS_STA_MODE:
10147 case VOS_P2P_CLIENT_MODE:
10148 case VOS_P2P_GO_MODE:
10149 case VOS_STA_SAP_MODE:
10150 pHddCtx->no_of_active_sessions[mode]++;
10151 break;
10152 default:
10153 hddLog(VOS_TRACE_LEVEL_INFO, FL("Not Expected Mode %d"), mode);
10154 break;
10155 }
10156 hddLog(VOS_TRACE_LEVEL_INFO, FL("No.# of active sessions for mode %d = %d"),
10157 mode,
10158 pHddCtx->no_of_active_sessions[mode]);
10159}
10160
10161/**---------------------------------------------------------------------------
10162 *
10163 * \brief wlan_hdd_decr_active_session()
10164 *
10165 * This function decrements the number of active sessions
10166 * maintained per device mode
10167 * Incase of STA/P2P CLI/IBSS upon disconnection it is decremented
10168 * Incase of SAP/P2P GO upon bss stop it is decremented
10169 *
10170 * \param pHddCtx - HDD Context
10171 * \param mode - device mode
10172 *
10173 * \return - None
10174 *
10175 * --------------------------------------------------------------------------*/
10176void wlan_hdd_decr_active_session(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
10177{
10178 switch (mode) {
10179 case VOS_STA_MODE:
10180 case VOS_P2P_CLIENT_MODE:
10181 case VOS_P2P_GO_MODE:
10182 case VOS_STA_SAP_MODE:
Agarwal Ashish5325f522014-08-06 00:58:44 +053010183 if (pHddCtx->no_of_active_sessions[mode] > 0)
10184 pHddCtx->no_of_active_sessions[mode]--;
10185 else
10186 hddLog(VOS_TRACE_LEVEL_INFO, FL(" No.# of Active sessions"
10187 "is already Zero"));
Agarwal Ashish51325b52014-06-16 16:50:49 +053010188 break;
10189 default:
10190 hddLog(VOS_TRACE_LEVEL_INFO, FL("Not Expected Mode %d"), mode);
10191 break;
10192 }
10193 hddLog(VOS_TRACE_LEVEL_INFO, FL("No.# of active sessions for mode %d = %d"),
10194 mode,
10195 pHddCtx->no_of_active_sessions[mode]);
Jeff Johnson295189b2012-06-20 16:38:30 -070010196}
10197
Jeff Johnsone7245742012-09-05 17:12:55 -070010198/**---------------------------------------------------------------------------
10199 *
10200 * \brief wlan_hdd_restart_init
10201 *
10202 * This function initalizes restart timer/flag. An internal function.
10203 *
10204 * \param - pHddCtx
10205 *
10206 * \return - None
10207 *
10208 * --------------------------------------------------------------------------*/
10209
10210static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
10211{
10212 /* Initialize */
10213 pHddCtx->hdd_restart_retries = 0;
10214 atomic_set(&pHddCtx->isRestartInProgress, 0);
10215 vos_timer_init(&pHddCtx->hdd_restart_timer,
10216 VOS_TIMER_TYPE_SW,
10217 wlan_hdd_restart_timer_cb,
10218 pHddCtx);
10219}
10220/**---------------------------------------------------------------------------
10221 *
10222 * \brief wlan_hdd_restart_deinit
10223 *
10224 * This function cleans up the resources used. An internal function.
10225 *
10226 * \param - pHddCtx
10227 *
10228 * \return - None
10229 *
10230 * --------------------------------------------------------------------------*/
10231
10232static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
10233{
10234
10235 VOS_STATUS vos_status;
10236 /* Block any further calls */
10237 atomic_set(&pHddCtx->isRestartInProgress, 1);
10238 /* Cleanup */
10239 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
10240 if (!VOS_IS_STATUS_SUCCESS(vos_status))
c_hpothu6ff1c3c2013-10-01 19:01:57 +053010241 hddLog(LOGE, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -070010242 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
10243 if (!VOS_IS_STATUS_SUCCESS(vos_status))
c_hpothu6ff1c3c2013-10-01 19:01:57 +053010244 hddLog(LOGE, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -070010245
10246}
10247
10248/**---------------------------------------------------------------------------
10249 *
10250 * \brief wlan_hdd_framework_restart
10251 *
10252 * This function uses a cfg80211 API to start a framework initiated WLAN
10253 * driver module unload/load.
10254 *
10255 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
10256 *
10257 *
10258 * \param - pHddCtx
10259 *
10260 * \return - VOS_STATUS_SUCCESS: Success
10261 * VOS_STATUS_E_EMPTY: Adapter is Empty
10262 * VOS_STATUS_E_NOMEM: No memory
10263
10264 * --------------------------------------------------------------------------*/
10265
10266static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
10267{
10268 VOS_STATUS status = VOS_STATUS_SUCCESS;
10269 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -070010270 int len = (sizeof (struct ieee80211_mgmt));
10271 struct ieee80211_mgmt *mgmt = NULL;
10272
10273 /* Prepare the DEAUTH managment frame with reason code */
10274 mgmt = kzalloc(len, GFP_KERNEL);
10275 if(mgmt == NULL)
10276 {
10277 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
10278 "%s: memory allocation failed (%d bytes)", __func__, len);
10279 return VOS_STATUS_E_NOMEM;
10280 }
10281 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -070010282
10283 /* Iterate over all adapters/devices */
10284 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10285 do
10286 {
10287 if( (status == VOS_STATUS_SUCCESS) &&
10288 pAdapterNode &&
10289 pAdapterNode->pAdapter)
10290 {
10291 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
10292 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
10293 pAdapterNode->pAdapter->dev->name,
10294 pAdapterNode->pAdapter->device_mode,
10295 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -070010296 /*
10297 * CFG80211 event to restart the driver
10298 *
10299 * 'cfg80211_send_unprot_deauth' sends a
10300 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
10301 * of SME(Linux Kernel) state machine.
10302 *
10303 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
10304 * the driver.
10305 *
10306 */
10307
10308 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -070010309 }
10310 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10311 pAdapterNode = pNext;
10312 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
10313
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -070010314
10315 /* Free the allocated management frame */
10316 kfree(mgmt);
10317
Jeff Johnsone7245742012-09-05 17:12:55 -070010318 /* Retry until we unload or reach max count */
10319 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
10320 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
10321
10322 return status;
10323
10324}
10325/**---------------------------------------------------------------------------
10326 *
10327 * \brief wlan_hdd_restart_timer_cb
10328 *
10329 * Restart timer callback. An internal function.
10330 *
10331 * \param - User data:
10332 *
10333 * \return - None
10334 *
10335 * --------------------------------------------------------------------------*/
10336
10337void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
10338{
10339 hdd_context_t *pHddCtx = usrDataForCallback;
10340 wlan_hdd_framework_restart(pHddCtx);
10341 return;
10342
10343}
10344
10345
10346/**---------------------------------------------------------------------------
10347 *
10348 * \brief wlan_hdd_restart_driver
10349 *
10350 * This function sends an event to supplicant to restart the WLAN driver.
10351 *
10352 * This function is called from vos_wlanRestart.
10353 *
10354 * \param - pHddCtx
10355 *
10356 * \return - VOS_STATUS_SUCCESS: Success
10357 * VOS_STATUS_E_EMPTY: Adapter is Empty
10358 * VOS_STATUS_E_ALREADY: Request already in progress
10359
10360 * --------------------------------------------------------------------------*/
10361VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
10362{
10363 VOS_STATUS status = VOS_STATUS_SUCCESS;
10364
10365 /* A tight check to make sure reentrancy */
10366 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
10367 {
Mihir Shetefd528652014-06-23 19:07:50 +053010368 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnsone7245742012-09-05 17:12:55 -070010369 "%s: WLAN restart is already in progress", __func__);
10370
10371 return VOS_STATUS_E_ALREADY;
10372 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -070010373 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -080010374#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -070010375 wcnss_reset_intr();
10376#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -070010377
Jeff Johnsone7245742012-09-05 17:12:55 -070010378 return status;
10379}
10380
Mihir Shetee1093ba2014-01-21 20:13:32 +053010381/**---------------------------------------------------------------------------
10382 *
10383 * \brief wlan_hdd_init_channels
10384 *
10385 * This function is used to initialize the channel list in CSR
10386 *
10387 * This function is called from hdd_wlan_startup
10388 *
10389 * \param - pHddCtx: HDD context
10390 *
10391 * \return - VOS_STATUS_SUCCESS: Success
10392 * VOS_STATUS_E_FAULT: Failure reported by SME
10393
10394 * --------------------------------------------------------------------------*/
10395static VOS_STATUS wlan_hdd_init_channels(hdd_context_t *pHddCtx)
10396{
10397 eHalStatus status;
10398
10399 status = sme_InitChannels(pHddCtx->hHal);
10400 if (HAL_STATUS_SUCCESS(status))
10401 {
10402 return VOS_STATUS_SUCCESS;
10403 }
10404 else
10405 {
10406 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Channel initialization failed(%d)",
10407 __func__, status);
10408 return VOS_STATUS_E_FAULT;
10409 }
10410}
10411
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053010412static VOS_STATUS wlan_hdd_init_channels_for_cc(hdd_context_t *pHddCtx)
10413{
10414 eHalStatus status;
10415
10416 status = sme_InitChannelsForCC(pHddCtx->hHal);
10417 if (HAL_STATUS_SUCCESS(status))
10418 {
10419 return VOS_STATUS_SUCCESS;
10420 }
10421 else
10422 {
10423 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Issue reg hint failed(%d)",
10424 __func__, status);
10425 return VOS_STATUS_E_FAULT;
10426 }
10427}
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -070010428/*
10429 * API to find if there is any STA or P2P-Client is connected
10430 */
10431VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
10432{
10433 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
10434}
Jeff Johnsone7245742012-09-05 17:12:55 -070010435
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053010436int wlan_hdd_scan_abort(hdd_adapter_t *pAdapter)
10437{
10438 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10439 hdd_scaninfo_t *pScanInfo = NULL;
Girish Gowli4bf7a632014-06-12 13:42:11 +053010440 long status = 0;
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053010441
10442 pScanInfo = &pHddCtx->scan_info;
10443 if (pScanInfo->mScanPending)
10444 {
10445 INIT_COMPLETION(pScanInfo->abortscan_event_var);
10446 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
10447 eCSR_SCAN_ABORT_DEFAULT);
10448
10449 status = wait_for_completion_interruptible_timeout(
10450 &pScanInfo->abortscan_event_var,
10451 msecs_to_jiffies(5000));
Girish Gowli4bf7a632014-06-12 13:42:11 +053010452 if (0 >= status)
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053010453 {
10454 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Girish Gowli4bf7a632014-06-12 13:42:11 +053010455 "%s: Timeout or Interrupt occurred while waiting for abort"
10456 "scan, status- %ld", __func__, status);
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053010457 return -ETIMEDOUT;
10458 }
10459 }
Girish Gowli4bf7a632014-06-12 13:42:11 +053010460 return 0;
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053010461}
10462
Jeff Johnson295189b2012-06-20 16:38:30 -070010463//Register the module init/exit functions
10464module_init(hdd_module_init);
10465module_exit(hdd_module_exit);
10466
10467MODULE_LICENSE("Dual BSD/GPL");
10468MODULE_AUTHOR("Qualcomm Atheros, Inc.");
10469MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
10470
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070010471module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
10472 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -070010473
Jeff Johnson76052702013-04-16 13:55:05 -070010474module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -070010475 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Arif Hussain66559122013-11-21 10:11:40 -080010476
10477module_param(enable_dfs_chan_scan, int,
10478 S_IRUSR | S_IRGRP | S_IROTH);
10479
10480module_param(enable_11d, int,
10481 S_IRUSR | S_IRGRP | S_IROTH);
10482
10483module_param(country_code, charp,
10484 S_IRUSR | S_IRGRP | S_IROTH);