blob: acd0c7de15fef48d51870f08a168b40dcde41813 [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Kiet Lam842dad02014-02-18 18:44:02 -08002 * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved.
3 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
Kiet Lamaa8e15a2014-02-11 23:30:06 -080023 * Copyright (c) 2012-2014 Qualcomm Atheros, Inc.
24 * All Rights Reserved.
25 * Qualcomm Atheros Confidential and Proprietary.
Kiet Lam842dad02014-02-18 18:44:02 -080026 *
Gopichand Nakkala92f07d82013-01-08 21:16:34 -080027 */
Kiet Lam842dad02014-02-18 18:44:02 -080028
29
Jeff Johnson295189b2012-06-20 16:38:30 -070030/*========================================================================
31
32 \file wlan_hdd_main.c
33
34 \brief WLAN Host Device Driver implementation
35
36 Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved.
37
38 Qualcomm Confidential and Proprietary.
39
40 ========================================================================*/
41
42/**=========================================================================
43
44 EDIT HISTORY FOR FILE
45
46
47 This section contains comments describing changes made to the module.
48 Notice that changes are listed in reverse chronological order.
49
50
51 $Header:$ $DateTime: $ $Author: $
52
53
54 when who what, where, why
55 -------- --- --------------------------------------------------------
56 04/5/09 Shailender Created module.
57 02/24/10 Sudhir.S.Kohalli Added to support param for SoftAP module
58 06/03/10 js - Added support to hostapd driven deauth/disassoc/mic failure
59 ==========================================================================*/
60
61/*--------------------------------------------------------------------------
62 Include Files
63 ------------------------------------------------------------------------*/
64//#include <wlan_qct_driver.h>
65#include <wlan_hdd_includes.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070066#include <vos_api.h>
67#include <vos_sched.h>
68#include <vos_power.h>
69#include <linux/etherdevice.h>
70#include <linux/firmware.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070071#ifdef ANI_BUS_TYPE_PLATFORM
72#include <linux/wcnss_wlan.h>
73#endif //ANI_BUS_TYPE_PLATFORM
74#ifdef ANI_BUS_TYPE_PCI
75#include "wcnss_wlan.h"
76#endif /* ANI_BUS_TYPE_PCI */
77#include <wlan_hdd_tx_rx.h>
78#include <palTimer.h>
79#include <wniApi.h>
80#include <wlan_nlink_srv.h>
81#include <wlan_btc_svc.h>
82#include <wlan_hdd_cfg.h>
83#include <wlan_ptt_sock_svc.h>
Vinay Krishna Erannad938c422014-03-10 17:14:21 +053084#include <wlan_logging_sock_svc.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070085#include <wlan_hdd_wowl.h>
86#include <wlan_hdd_misc.h>
87#include <wlan_hdd_wext.h>
88#ifdef WLAN_BTAMP_FEATURE
89#include <bap_hdd_main.h>
90#include <bapInternal.h>
91#endif // WLAN_BTAMP_FEATURE
Sushant Kaushik4b7cb302014-01-06 17:45:01 +053092#include "wlan_hdd_trace.h"
93#include "vos_types.h"
94#include "vos_trace.h"
Jeff Johnson295189b2012-06-20 16:38:30 -070095#include <linux/wireless.h>
96#include <net/cfg80211.h>
Vinay Krishna Erannad9cbdb32014-01-16 12:59:10 +053097#include <linux/inetdevice.h>
98#include <net/addrconf.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070099#include "wlan_hdd_cfg80211.h"
100#include "wlan_hdd_p2p.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700101#include <linux/rtnetlink.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700102int wlan_hdd_ftm_start(hdd_context_t *pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700103#include "sapApi.h"
104#include <linux/semaphore.h>
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -0700105#include <linux/ctype.h>
Arun Kumar Khandavalli74fe3032014-03-17 20:35:34 +0530106#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0))
107#include <soc/qcom/subsystem_restart.h>
108#else
Jeff Johnson295189b2012-06-20 16:38:30 -0700109#include <mach/subsystem_restart.h>
Arun Kumar Khandavalli74fe3032014-03-17 20:35:34 +0530110#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700111#include <wlan_hdd_hostapd.h>
112#include <wlan_hdd_softap_tx_rx.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700113#include "cfgApi.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700114#include "wlan_hdd_dev_pwr.h"
115#ifdef WLAN_BTAMP_FEATURE
116#include "bap_hdd_misc.h"
117#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700118#include "wlan_qct_pal_trace.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700119#include "qwlan_version.h"
Yathish9f22e662012-12-10 14:21:35 -0800120#include "wlan_qct_wda.h"
Chilam NG571c65a2013-01-19 12:27:36 +0530121#ifdef FEATURE_WLAN_TDLS
122#include "wlan_hdd_tdls.h"
123#endif
Yue Ma0d4891e2013-08-06 17:01:45 -0700124#include "wlan_hdd_debugfs.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700125
126#ifdef MODULE
127#define WLAN_MODULE_NAME module_name(THIS_MODULE)
128#else
129#define WLAN_MODULE_NAME "wlan"
130#endif
131
132#ifdef TIMER_MANAGER
133#define TIMER_MANAGER_STR " +TIMER_MANAGER"
134#else
135#define TIMER_MANAGER_STR ""
136#endif
137
138#ifdef MEMORY_DEBUG
139#define MEMORY_DEBUG_STR " +MEMORY_DEBUG"
140#else
141#define MEMORY_DEBUG_STR ""
142#endif
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530143#define MAX_WAIT_FOR_ROC_COMPLETION 3
Jeff Johnson295189b2012-06-20 16:38:30 -0700144/* the Android framework expects this param even though we don't use it */
145#define BUF_LEN 20
Jeff Johnson76052702013-04-16 13:55:05 -0700146static char fwpath_buffer[BUF_LEN];
147static struct kparam_string fwpath = {
148 .string = fwpath_buffer,
149 .maxlen = BUF_LEN,
150};
Arif Hussain66559122013-11-21 10:11:40 -0800151
152static char *country_code;
153static int enable_11d = -1;
154static int enable_dfs_chan_scan = -1;
c_hpothu92367912014-05-01 15:18:17 +0530155static int gbcnMissRate = -1;
Arif Hussain66559122013-11-21 10:11:40 -0800156
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700157#ifndef MODULE
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700158static int wlan_hdd_inited;
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700159#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700160
Jeff Johnsone7245742012-09-05 17:12:55 -0700161/*
Jeff Johnson72a40512013-12-19 10:14:15 -0800162 * spinlock for synchronizing asynchronous request/response
163 * (full description of use in wlan_hdd_main.h)
164 */
165DEFINE_SPINLOCK(hdd_context_lock);
166
167/*
Jeff Johnsone7245742012-09-05 17:12:55 -0700168 * The rate at which the driver sends RESTART event to supplicant
169 * once the function 'vos_wlanRestart()' is called
170 *
171 */
172#define WLAN_HDD_RESTART_RETRY_DELAY_MS 5000 /* 5 second */
173#define WLAN_HDD_RESTART_RETRY_MAX_CNT 5 /* 5 retries */
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -0700174
175/*
176 * Size of Driver command strings from upper layer
177 */
178#define SIZE_OF_SETROAMMODE 11 /* size of SETROAMMODE */
179#define SIZE_OF_GETROAMMODE 11 /* size of GETROAMMODE */
180
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -0800181#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda5cecb202013-10-08 09:13:25 -0700182#define TID_MIN_VALUE 0
183#define TID_MAX_VALUE 15
184static VOS_STATUS hdd_get_tsm_stats(hdd_adapter_t *pAdapter, const tANI_U8 tid,
185 tAniTrafStrmMetrics* pTsmMetrics);
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -0800186static VOS_STATUS hdd_parse_ese_beacon_req(tANI_U8 *pValue,
187 tCsrEseBeaconReq *pEseBcnReq);
188#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -0700189
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +0530190static VOS_STATUS wlan_hdd_init_channels_for_cc(hdd_context_t *pHddCtx);
Atul Mittal1d722422014-03-19 11:15:07 +0530191/*
192 * Maximum buffer size used for returning the data back to user space
193 */
194#define WLAN_MAX_BUF_SIZE 1024
195#define WLAN_PRIV_DATA_MAX_LEN 8192
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -0700196/*
197 * Driver miracast parameters 0-Disabled
198 * 1-Source, 2-Sink
199 */
200#define WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL 0
201#define WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL 2
202
c_hpothu92367912014-05-01 15:18:17 +0530203//wait time for beacon miss rate.
204#define BCN_MISS_RATE_TIME 500
205
Sameer Thalappil50dc0092013-02-19 17:23:33 -0800206#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -0700207static struct wake_lock wlan_wake_lock;
Jeff Johnsone7245742012-09-05 17:12:55 -0700208#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700209/* set when SSR is needed after unload */
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -0700210static e_hdd_ssr_required isSsrRequired = HDD_SSR_NOT_REQUIRED;
Jeff Johnson295189b2012-06-20 16:38:30 -0700211
212//internal function declaration
Jeff Johnsone7245742012-09-05 17:12:55 -0700213static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx);
214static void wlan_hdd_restart_init(hdd_context_t *pHddCtx);
215static void wlan_hdd_restart_deinit(hdd_context_t *pHddCtx);
216void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback);
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800217void hdd_set_wlan_suspend_mode(bool suspend);
Jeff Johnsone7245742012-09-05 17:12:55 -0700218
Jeff Johnson295189b2012-06-20 16:38:30 -0700219v_U16_t hdd_select_queue(struct net_device *dev,
220 struct sk_buff *skb);
221
222#ifdef WLAN_FEATURE_PACKET_FILTERING
223static void hdd_set_multicast_list(struct net_device *dev);
224#endif
225
226void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter);
227
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -0800228#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -0800229void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand);
230static VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels);
Srinivas Girigowda100eb322013-03-15 16:48:20 -0700231static VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid,
232 tANI_U8 *pChannel, tANI_U8 *pDwellTime,
233 tANI_U8 **pBuf, tANI_U8 *pBufLen);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -0700234static VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue,
235 tANI_U8 *pTargetApBssid,
236 tANI_U8 *pChannel);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800237#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -0800238#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda5cecb202013-10-08 09:13:25 -0700239VOS_STATUS hdd_parse_get_cckm_ie(tANI_U8 *pValue, tANI_U8 **pCckmIe, tANI_U8 *pCckmIeLen);
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -0800240#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -0700241
Mihir Shetee1093ba2014-01-21 20:13:32 +0530242static VOS_STATUS wlan_hdd_init_channels(hdd_context_t *pHddCtx);
Sushant Kaushik8bc7df22014-04-09 17:55:29 +0530243const char * hdd_device_modetoString(v_U8_t device_mode)
244{
245 switch(device_mode)
246 {
247 CASE_RETURN_STRING( WLAN_HDD_INFRA_STATION );
248 CASE_RETURN_STRING( WLAN_HDD_SOFTAP );
249 CASE_RETURN_STRING( WLAN_HDD_P2P_CLIENT );
250 CASE_RETURN_STRING( WLAN_HDD_P2P_GO );
251 CASE_RETURN_STRING( WLAN_HDD_MONITOR);
252 CASE_RETURN_STRING( WLAN_HDD_FTM );
253 CASE_RETURN_STRING( WLAN_HDD_IBSS );
254 CASE_RETURN_STRING( WLAN_HDD_P2P_DEVICE );
255 default:
256 return "device_mode Unknown";
257 }
258}
Mihir Shetee1093ba2014-01-21 20:13:32 +0530259
Jeff Johnson295189b2012-06-20 16:38:30 -0700260static int hdd_netdev_notifier_call(struct notifier_block * nb,
261 unsigned long state,
262 void *ndev)
263{
264 struct net_device *dev = ndev;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700265 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson27cee452013-03-27 11:10:24 -0700266 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700267#ifdef WLAN_BTAMP_FEATURE
268 VOS_STATUS status;
Jeff Johnson295189b2012-06-20 16:38:30 -0700269#endif
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +0530270 long result;
Jeff Johnson295189b2012-06-20 16:38:30 -0700271
272 //Make sure that this callback corresponds to our device.
Jeff Johnson27cee452013-03-27 11:10:24 -0700273 if ((strncmp(dev->name, "wlan", 4)) &&
Amar Singhal4c723bd2013-03-25 18:14:15 -0700274 (strncmp(dev->name, "p2p", 3)))
275 return NOTIFY_DONE;
276
Jeff Johnson295189b2012-06-20 16:38:30 -0700277 if (!dev->ieee80211_ptr)
Jeff Johnson27cee452013-03-27 11:10:24 -0700278 return NOTIFY_DONE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700279
Jeff Johnson27cee452013-03-27 11:10:24 -0700280 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -0700281 {
Jeff Johnsona8a1a482012-12-12 16:49:33 -0800282 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Adapter Null Pointer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700283 VOS_ASSERT(0);
284 return NOTIFY_DONE;
285 }
286
Jeff Johnson27cee452013-03-27 11:10:24 -0700287 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
288 if (NULL == pHddCtx)
289 {
290 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Context Null Pointer", __func__);
291 VOS_ASSERT(0);
292 return NOTIFY_DONE;
293 }
Sameer Thalappil14067972014-01-23 14:54:54 -0800294 if (pHddCtx->isLogpInProgress)
295 return NOTIFY_DONE;
296
Jeff Johnson27cee452013-03-27 11:10:24 -0700297
298 hddLog(VOS_TRACE_LEVEL_INFO, "%s: %s New Net Device State = %lu",
299 __func__, dev->name, state);
Jeff Johnson295189b2012-06-20 16:38:30 -0700300
301 switch (state) {
302 case NETDEV_REGISTER:
303 break;
304
305 case NETDEV_UNREGISTER:
306 break;
307
308 case NETDEV_UP:
309 break;
310
311 case NETDEV_DOWN:
312 break;
313
314 case NETDEV_CHANGE:
Jeff Johnsone7245742012-09-05 17:12:55 -0700315 if(TRUE == pAdapter->isLinkUpSvcNeeded)
316 complete(&pAdapter->linkup_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700317 break;
318
319 case NETDEV_GOING_DOWN:
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +0530320 result = wlan_hdd_scan_abort(pAdapter);
Girish Gowli4bf7a632014-06-12 13:42:11 +0530321 if (result < 0)
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +0530322 {
323 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
324 "%s: Timeout occurred while waiting for abortscan %ld",
325 __func__, result);
Jeff Johnson295189b2012-06-20 16:38:30 -0700326 }
327 else
328 {
329 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +0530330 "%s: Scan Abort Successful" , __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700331 }
332#ifdef WLAN_BTAMP_FEATURE
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700333 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: disabling AMP", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700334 status = WLANBAP_StopAmp();
335 if(VOS_STATUS_SUCCESS != status )
336 {
337 pHddCtx->isAmpAllowed = VOS_TRUE;
338 hddLog(VOS_TRACE_LEVEL_FATAL,
339 "%s: Failed to stop AMP", __func__);
340 }
341 else
342 {
343 //a state m/c implementation in PAL is TBD to avoid this delay
344 msleep(500);
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700345 if ( pHddCtx->isAmpAllowed )
346 {
347 WLANBAP_DeregisterFromHCI();
348 pHddCtx->isAmpAllowed = VOS_FALSE;
349 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700350 }
351#endif //WLAN_BTAMP_FEATURE
352 break;
353
354 default:
355 break;
356 }
357
358 return NOTIFY_DONE;
359}
360
361struct notifier_block hdd_netdev_notifier = {
362 .notifier_call = hdd_netdev_notifier_call,
363};
364
365/*---------------------------------------------------------------------------
366 * Function definitions
367 *-------------------------------------------------------------------------*/
Jeff Johnson295189b2012-06-20 16:38:30 -0700368void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx);
369void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -0700370//variable to hold the insmod parameters
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700371static int con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -0700372#ifndef MODULE
373/* current con_mode - used only for statically linked driver
374 * con_mode is changed by userspace to indicate a mode change which will
375 * result in calling the module exit and init functions. The module
376 * exit function will clean up based on the value of con_mode prior to it
377 * being changed by userspace. So curr_con_mode records the current con_mode
378 * for exit when con_mode becomes the next mode for init
379 */
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700380static int curr_con_mode;
Jeff Johnson295189b2012-06-20 16:38:30 -0700381#endif
382
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -0800383/**---------------------------------------------------------------------------
384
385 \brief hdd_vos_trace_enable() - Configure initial VOS Trace enable
386
387 Called immediately after the cfg.ini is read in order to configure
388 the desired trace levels.
389
390 \param - moduleId - module whose trace level is being configured
391 \param - bitmask - bitmask of log levels to be enabled
392
393 \return - void
394
395 --------------------------------------------------------------------------*/
396static void hdd_vos_trace_enable(VOS_MODULE_ID moduleId, v_U32_t bitmask)
397{
398 wpt_tracelevel level;
399
400 /* if the bitmask is the default value, then a bitmask was not
401 specified in cfg.ini, so leave the logging level alone (it
402 will remain at the "compiled in" default value) */
403 if (CFG_VOS_TRACE_ENABLE_DEFAULT == bitmask)
404 {
405 return;
406 }
407
408 /* a mask was specified. start by disabling all logging */
409 vos_trace_setValue(moduleId, VOS_TRACE_LEVEL_NONE, 0);
410
411 /* now cycle through the bitmask until all "set" bits are serviced */
412 level = VOS_TRACE_LEVEL_FATAL;
413 while (0 != bitmask)
414 {
415 if (bitmask & 1)
416 {
417 vos_trace_setValue(moduleId, level, 1);
418 }
419 level++;
420 bitmask >>= 1;
421 }
422}
423
424
Jeff Johnson295189b2012-06-20 16:38:30 -0700425/**---------------------------------------------------------------------------
426
427 \brief hdd_wdi_trace_enable() - Configure initial WDI Trace enable
428
429 Called immediately after the cfg.ini is read in order to configure
430 the desired trace levels in the WDI.
431
432 \param - moduleId - module whose trace level is being configured
433 \param - bitmask - bitmask of log levels to be enabled
434
435 \return - void
436
437 --------------------------------------------------------------------------*/
438static void hdd_wdi_trace_enable(wpt_moduleid moduleId, v_U32_t bitmask)
439{
440 wpt_tracelevel level;
441
442 /* if the bitmask is the default value, then a bitmask was not
443 specified in cfg.ini, so leave the logging level alone (it
444 will remain at the "compiled in" default value) */
445 if (CFG_WDI_TRACE_ENABLE_DEFAULT == bitmask)
446 {
447 return;
448 }
449
450 /* a mask was specified. start by disabling all logging */
451 wpalTraceSetLevel(moduleId, eWLAN_PAL_TRACE_LEVEL_NONE, 0);
452
453 /* now cycle through the bitmask until all "set" bits are serviced */
454 level = eWLAN_PAL_TRACE_LEVEL_FATAL;
455 while (0 != bitmask)
456 {
457 if (bitmask & 1)
458 {
459 wpalTraceSetLevel(moduleId, level, 1);
460 }
461 level++;
462 bitmask >>= 1;
463 }
464}
Jeff Johnson295189b2012-06-20 16:38:30 -0700465
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530466/*
467 * FUNCTION: wlan_hdd_validate_context
468 * This function is used to check the HDD context
469 */
470int wlan_hdd_validate_context(hdd_context_t *pHddCtx)
471{
472 ENTER();
473
474 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
475 {
476 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
477 "%s: HDD context is Null", __func__);
478 return -ENODEV;
479 }
480
481 if (pHddCtx->isLogpInProgress)
482 {
483 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
484 "%s: LOGP in Progress. Ignore!!!", __func__);
485 return -EAGAIN;
486 }
487
Mihir Shete18156292014-03-11 15:38:30 +0530488 if (WLAN_HDD_IS_LOAD_UNLOAD_IN_PROGRESS(pHddCtx))
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530489 {
490 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
491 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
492 return -EAGAIN;
493 }
494 return 0;
495}
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700496#ifdef CONFIG_ENABLE_LINUX_REG
497void hdd_checkandupdate_phymode( hdd_context_t *pHddCtx)
498{
499 hdd_adapter_t *pAdapter = NULL;
500 hdd_station_ctx_t *pHddStaCtx = NULL;
501 eCsrPhyMode phyMode;
502 hdd_config_t *cfg_param = NULL;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530503
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700504 if (NULL == pHddCtx)
505 {
506 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
507 "HDD Context is null !!");
508 return ;
509 }
510
511 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
512 if (NULL == pAdapter)
513 {
514 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
515 "pAdapter is null !!");
516 return ;
517 }
518
519 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
520 if (NULL == pHddStaCtx)
521 {
522 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
523 "pHddStaCtx is null !!");
524 return ;
525 }
526
527 cfg_param = pHddCtx->cfg_ini;
528 if (NULL == cfg_param)
529 {
530 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
531 "cfg_params not available !!");
532 return ;
533 }
534
535 phyMode = sme_GetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter));
536
537 if (!pHddCtx->isVHT80Allowed)
538 {
539 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
540 (eCSR_DOT11_MODE_11ac == phyMode) ||
541 (eCSR_DOT11_MODE_11ac_ONLY == phyMode))
542 {
543 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
544 "Setting phymode to 11n!!");
545 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter), eCSR_DOT11_MODE_11n);
546 }
547 }
548 else
549 {
550 /*New country Supports 11ac as well resetting value back from .ini*/
551 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter),
552 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->dot11Mode));
553 return ;
554 }
555
556 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
557 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode) ||
558 (eCSR_CFG_DOT11_MODE_11AC == pHddStaCtx->conn_info.dot11Mode)))
559 {
560 VOS_STATUS vosStatus;
561
562 // need to issue a disconnect to CSR.
563 INIT_COMPLETION(pAdapter->disconnect_comp_var);
564 vosStatus = sme_RoamDisconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
565 pAdapter->sessionId,
566 eCSR_DISCONNECT_REASON_UNSPECIFIED );
567
568 if (VOS_STATUS_SUCCESS == vosStatus)
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530569 {
570 long ret;
571
572 ret = wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700573 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530574 if (0 >= ret)
575 hddLog(LOGE, FL("failure waiting for disconnect_comp_var %ld"),
576 ret);
577 }
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700578
579 }
580}
581#else
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530582void hdd_checkandupdate_phymode( hdd_adapter_t *pAdapter, char *country_code)
583{
584 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
585 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
586 hdd_config_t *cfg_param;
587 eCsrPhyMode phyMode;
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530588 long ret;
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530589
590 if (NULL == pHddCtx)
591 {
592 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
593 "HDD Context is null !!");
594 return ;
595 }
596
597 cfg_param = pHddCtx->cfg_ini;
598
599 if (NULL == cfg_param)
600 {
601 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
602 "cfg_params not available !!");
603 return ;
604 }
605
606 phyMode = sme_GetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter));
607
608 if (NULL != strstr(cfg_param->listOfNon11acCountryCode, country_code))
609 {
610 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
611 (eCSR_DOT11_MODE_11ac == phyMode) ||
612 (eCSR_DOT11_MODE_11ac_ONLY == phyMode))
613 {
614 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
615 "Setting phymode to 11n!!");
616 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter), eCSR_DOT11_MODE_11n);
617 }
618 }
619 else
620 {
621 /*New country Supports 11ac as well resetting value back from .ini*/
622 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter),
623 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->dot11Mode));
624 return ;
625 }
626
627 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
628 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode) ||
629 (eCSR_CFG_DOT11_MODE_11AC == pHddStaCtx->conn_info.dot11Mode)))
630 {
631 VOS_STATUS vosStatus;
632
633 // need to issue a disconnect to CSR.
634 INIT_COMPLETION(pAdapter->disconnect_comp_var);
635 vosStatus = sme_RoamDisconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
636 pAdapter->sessionId,
637 eCSR_DISCONNECT_REASON_UNSPECIFIED );
638
639 if (VOS_STATUS_SUCCESS == vosStatus)
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530640 {
641 ret = wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530642 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530643 if (ret <= 0)
644 {
645 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
646 "wait on disconnect_comp_var is failed %ld", ret);
647 }
648 }
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530649
650 }
651}
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700652#endif //CONFIG_ENABLE_LINUX_REG
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530653
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700654void hdd_checkandupdate_dfssetting( hdd_adapter_t *pAdapter, char *country_code)
655{
656 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
657 hdd_config_t *cfg_param;
658
659 if (NULL == pHddCtx)
660 {
661 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
662 "HDD Context is null !!");
663 return ;
664 }
665
666 cfg_param = pHddCtx->cfg_ini;
667
668 if (NULL == cfg_param)
669 {
670 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
671 "cfg_params not available !!");
672 return ;
673 }
674
675 if (NULL != strstr(cfg_param->listOfNonDfsCountryCode, country_code))
676 {
677 /*New country doesn't support DFS */
678 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), 0);
679 }
680 else
681 {
682 /*New country Supports DFS as well resetting value back from .ini*/
683 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), cfg_param->enableDFSChnlScan);
684 }
685
686}
687
Rajeev79dbe4c2013-10-05 11:03:42 +0530688#ifdef FEATURE_WLAN_BATCH_SCAN
689
690/**---------------------------------------------------------------------------
691
692 \brief hdd_extract_assigned_int_from_str() - Extracts assigned integer from
693 input string
694
695 This function extracts assigned integer from string in below format:
696 "STRING=10" : extracts integer 10 from this string
697
698 \param - pInPtr Pointer to input string
699 \param - base Base for string to int conversion(10 for decimal 16 for hex)
700 \param - pOutPtr Pointer to variable in which extracted integer needs to be
701 assigned
702 \param - pLastArg to tell whether it is last arguement in input string or
703 not
704
705 \return - NULL for failure cases
706 pointer to next arguement in input string for success cases
707 --------------------------------------------------------------------------*/
708static tANI_U8 *
709hdd_extract_assigned_int_from_str
710(
711 tANI_U8 *pInPtr,
712 tANI_U8 base,
713 tANI_U32 *pOutPtr,
714 tANI_U8 *pLastArg
715)
716{
717 int tempInt;
718 int v = 0;
719 char buf[32];
720 int val = 0;
721 *pLastArg = FALSE;
722
723 pInPtr = strnchr(pInPtr, strlen(pInPtr), EQUALS_TO_ASCII_VALUE);
724 if (NULL == pInPtr)
725 {
726 return NULL;
727 }
728
729 pInPtr++;
730
731 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
732
733 val = sscanf(pInPtr, "%32s ", buf);
734 if (val < 0 && val > strlen(pInPtr))
735 {
736 return NULL;
737 }
738 pInPtr += val;
739 v = kstrtos32(buf, base, &tempInt);
740 if (v < 0)
741 {
742 return NULL;
743 }
Rajeev Kumar4d93d842014-01-02 18:31:21 -0800744 if (tempInt < 0)
745 {
746 tempInt = 0;
747 }
Rajeev79dbe4c2013-10-05 11:03:42 +0530748 *pOutPtr = tempInt;
749
750 pInPtr = strnchr(pInPtr, strlen(pInPtr), SPACE_ASCII_VALUE);
751 if (NULL == pInPtr)
752 {
753 *pLastArg = TRUE;
754 return NULL;
755 }
756 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
757
758 return pInPtr;
759}
760
761/**---------------------------------------------------------------------------
762
763 \brief hdd_extract_assigned_char_from_str() - Extracts assigned char from
764 input string
765
766 This function extracts assigned character from string in below format:
767 "STRING=A" : extracts char 'A' from this string
768
769 \param - pInPtr Pointer to input string
770 \param - pOutPtr Pointer to variable in which extracted char needs to be
771 assigned
772 \param - pLastArg to tell whether it is last arguement in input string or
773 not
774
775 \return - NULL for failure cases
776 pointer to next arguement in input string for success cases
777 --------------------------------------------------------------------------*/
778static tANI_U8 *
779hdd_extract_assigned_char_from_str
780(
781 tANI_U8 *pInPtr,
782 tANI_U8 *pOutPtr,
783 tANI_U8 *pLastArg
784)
785{
786 *pLastArg = FALSE;
787
788 pInPtr = strnchr(pInPtr, strlen(pInPtr), EQUALS_TO_ASCII_VALUE);
789 if (NULL == pInPtr)
790 {
791 return NULL;
792 }
793
794 pInPtr++;
795
796 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
797
798 *pOutPtr = *pInPtr;
799
800 pInPtr = strnchr(pInPtr, strlen(pInPtr), SPACE_ASCII_VALUE);
801 if (NULL == pInPtr)
802 {
803 *pLastArg = TRUE;
804 return NULL;
805 }
806 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
807
808 return pInPtr;
809}
810
811
812/**---------------------------------------------------------------------------
813
814 \brief hdd_parse_set_batchscan_command () - HDD parse set batch scan command
815
816 This function parses set batch scan command in below format:
817 WLS_BATCHING_SET <space> followed by below arguements
818 "SCANFREQ=XX" : Optional defaults to 30 sec
819 "MSCAN=XX" : Required number of scans to attempt to batch
820 "BESTN=XX" : Best Network (RSSI) defaults to 16
821 "CHANNEL=<X,Y>" : optional defaults to all channels, can list 'A'or` B.
822 A. implies only 5 GHz , B. implies only 2.4GHz
823 "RTT=X" : optional defaults to 0
824 returns the MIN of MSCAN or the max # of scans firmware can cache or -1 on
825 error
826
827 For example input commands:
828 1) WLS_BATCHING_SET SCANFREQ=60 MSCAN=10 BESTN=20 CHANNEL=A RTT=0 -> This is
829 translated into set batch scan with following parameters:
830 a) Frequence 60 seconds
831 b) Batch 10 scans together
832 c) Best RSSI to be 20
833 d) 5GHz band only
834 e) RTT is equal to 0
835
836 \param - pValue Pointer to input channel list
837 \param - pHddSetBatchScanReq Pointer to HDD batch scan request structure
838
839 \return - 0 for success non-zero for failure
840
841 --------------------------------------------------------------------------*/
842static int
843hdd_parse_set_batchscan_command
844(
845 tANI_U8 *pValue,
846 tSirSetBatchScanReq *pHddSetBatchScanReq
847)
848{
849 tANI_U8 *inPtr = pValue;
850 tANI_U8 val = 0;
851 tANI_U8 lastArg = 0;
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800852 tANI_U32 nScanFreq;
853 tANI_U32 nMscan;
854 tANI_U32 nBestN;
855 tANI_U8 ucRfBand;
856 tANI_U32 nRtt;
Rajeev Kumarc933d982013-11-18 20:04:20 -0800857 tANI_U32 temp;
Rajeev79dbe4c2013-10-05 11:03:42 +0530858
859 /*initialize default values*/
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800860 nScanFreq = HDD_SET_BATCH_SCAN_DEFAULT_FREQ;
861 ucRfBand = HDD_SET_BATCH_SCAN_DEFAULT_BAND;
862 nRtt = 0;
863 nBestN = HDD_SET_BATCH_SCAN_BEST_NETWORK;
Rajeev79dbe4c2013-10-05 11:03:42 +0530864
865 /*go to space after WLS_BATCHING_SET command*/
866 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
867 /*no argument after the command*/
868 if (NULL == inPtr)
869 {
870 return -EINVAL;
871 }
872
873 /*no space after the command*/
874 else if (SPACE_ASCII_VALUE != *inPtr)
875 {
876 return -EINVAL;
877 }
878
879 /*removing empty spaces*/
880 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
881
882 /*no argument followed by spaces*/
883 if ('\0' == *inPtr)
884 {
885 return -EINVAL;
886 }
887
888 /*check and parse SCANFREQ*/
889 if ((strncmp(inPtr, "SCANFREQ", 8) == 0))
890 {
891 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumarc933d982013-11-18 20:04:20 -0800892 &temp, &lastArg);
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800893
Rajeev Kumarc933d982013-11-18 20:04:20 -0800894 if (0 != temp)
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800895 {
Rajeev Kumarc933d982013-11-18 20:04:20 -0800896 nScanFreq = temp;
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800897 }
898
Rajeev79dbe4c2013-10-05 11:03:42 +0530899 if ( (NULL == inPtr) || (TRUE == lastArg))
900 {
901 return -EINVAL;
902 }
903 }
904
905 /*check and parse MSCAN*/
906 if ((strncmp(inPtr, "MSCAN", 5) == 0))
907 {
908 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800909 &nMscan, &lastArg);
910
911 if (0 == nMscan)
912 {
913 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
914 "invalid MSCAN=%d", nMscan);
915 return -EINVAL;
916 }
917
Rajeev79dbe4c2013-10-05 11:03:42 +0530918 if (TRUE == lastArg)
919 {
920 goto done;
921 }
922 else if (NULL == inPtr)
923 {
924 return -EINVAL;
925 }
926 }
927 else
928 {
929 return -EINVAL;
930 }
931
932 /*check and parse BESTN*/
933 if ((strncmp(inPtr, "BESTN", 5) == 0))
934 {
935 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumarc933d982013-11-18 20:04:20 -0800936 &temp, &lastArg);
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800937
Rajeev Kumarc933d982013-11-18 20:04:20 -0800938 if (0 != temp)
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800939 {
Rajeev Kumarc933d982013-11-18 20:04:20 -0800940 nBestN = temp;
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800941 }
942
Rajeev79dbe4c2013-10-05 11:03:42 +0530943 if (TRUE == lastArg)
944 {
945 goto done;
946 }
947 else if (NULL == inPtr)
948 {
949 return -EINVAL;
950 }
951 }
952
953 /*check and parse CHANNEL*/
954 if ((strncmp(inPtr, "CHANNEL", 7) == 0))
955 {
956 inPtr = hdd_extract_assigned_char_from_str(inPtr, &val, &lastArg);
Rajeev Kumarc933d982013-11-18 20:04:20 -0800957
Rajeev79dbe4c2013-10-05 11:03:42 +0530958 if (('A' == val) || ('a' == val))
959 {
c_hpothuebf89732014-02-25 13:00:24 +0530960 ucRfBand = HDD_SET_BATCH_SCAN_5GHz_BAND_ONLY;
Rajeev79dbe4c2013-10-05 11:03:42 +0530961 }
962 else if (('B' == val) || ('b' == val))
963 {
c_hpothuebf89732014-02-25 13:00:24 +0530964 ucRfBand = HDD_SET_BATCH_SCAN_24GHz_BAND_ONLY;
Rajeev79dbe4c2013-10-05 11:03:42 +0530965 }
966 else
967 {
Rajeev Kumarc933d982013-11-18 20:04:20 -0800968 ucRfBand = HDD_SET_BATCH_SCAN_DEFAULT_BAND;
969 }
970
971 if (TRUE == lastArg)
972 {
973 goto done;
974 }
975 else if (NULL == inPtr)
976 {
Rajeev79dbe4c2013-10-05 11:03:42 +0530977 return -EINVAL;
978 }
979 }
980
981 /*check and parse RTT*/
982 if ((strncmp(inPtr, "RTT", 3) == 0))
983 {
984 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800985 &nRtt, &lastArg);
Rajeev79dbe4c2013-10-05 11:03:42 +0530986 if (TRUE == lastArg)
987 {
988 goto done;
989 }
990 if (NULL == inPtr)
991 {
992 return -EINVAL;
993 }
994 }
995
996
997done:
998
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800999 pHddSetBatchScanReq->scanFrequency = nScanFreq;
1000 pHddSetBatchScanReq->numberOfScansToBatch = nMscan;
1001 pHddSetBatchScanReq->bestNetwork = nBestN;
1002 pHddSetBatchScanReq->rfBand = ucRfBand;
1003 pHddSetBatchScanReq->rtt = nRtt;
1004
Rajeev79dbe4c2013-10-05 11:03:42 +05301005 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1006 "Received WLS_BATCHING_SET with SCANFREQ=%d "
1007 "MSCAN=%d BESTN=%d CHANNEL=%d RTT=%d",
1008 pHddSetBatchScanReq->scanFrequency,
1009 pHddSetBatchScanReq->numberOfScansToBatch,
1010 pHddSetBatchScanReq->bestNetwork,
1011 pHddSetBatchScanReq->rfBand,
1012 pHddSetBatchScanReq->rtt);
1013
1014 return 0;
1015}/*End of hdd_parse_set_batchscan_command*/
1016
1017/**---------------------------------------------------------------------------
1018
1019 \brief hdd_set_batch_scan_req_callback () - This function is called after
1020 receiving set batch scan response from FW and it saves set batch scan
1021 response data FW to HDD context and sets the completion event on
1022 which hdd_ioctl is waiting
1023
1024 \param - callbackContext Pointer to HDD adapter
1025 \param - pRsp Pointer to set batch scan response data received from FW
1026
1027 \return - nothing
1028
1029 --------------------------------------------------------------------------*/
1030static void hdd_set_batch_scan_req_callback
1031(
1032 void *callbackContext,
1033 tSirSetBatchScanRsp *pRsp
1034)
1035{
1036 hdd_adapter_t* pAdapter = (hdd_adapter_t*)callbackContext;
1037 tSirSetBatchScanRsp *pHddSetBatchScanRsp;
1038
1039 /*sanity check*/
1040 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
1041 {
1042 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1043 "%s: Invalid pAdapter magic", __func__);
1044 VOS_ASSERT(0);
1045 return;
1046 }
1047 pHddSetBatchScanRsp = &pAdapter->hddSetBatchScanRsp;
1048
1049 /*save set batch scan response*/
1050 pHddSetBatchScanRsp->nScansToBatch = pRsp->nScansToBatch;
1051
1052 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1053 "Received set batch scan rsp from FW with nScansToBatch=%d",
1054 pHddSetBatchScanRsp->nScansToBatch);
1055
1056 pAdapter->hdd_wait_for_set_batch_scan_rsp = FALSE;
1057 complete(&pAdapter->hdd_set_batch_scan_req_var);
1058
1059 return;
1060}/*End of hdd_set_batch_scan_req_callback*/
1061
1062
1063/**---------------------------------------------------------------------------
1064
1065 \brief hdd_populate_batch_scan_rsp_queue () - This function stores AP meta
1066 info in hdd batch scan response queue
1067
1068 \param - pAdapter Pointer to hdd adapter
1069 \param - pAPMetaInfo Pointer to access point meta info
1070 \param - scanId scan ID of batch scan response
1071 \param - isLastAp tells whether AP is last AP in batch scan response or not
1072
1073 \return - nothing
1074
1075 --------------------------------------------------------------------------*/
1076static void hdd_populate_batch_scan_rsp_queue( hdd_adapter_t* pAdapter,
1077 tpSirBatchScanNetworkInfo pApMetaInfo, tANI_U32 scanId, v_BOOL_t isLastAp)
1078{
1079 tHddBatchScanRsp *pHead;
1080 tHddBatchScanRsp *pNode;
1081 tHddBatchScanRsp *pPrev;
1082 tHddBatchScanRsp *pTemp;
1083 tANI_U8 ssidLen;
1084
1085 /*head of hdd batch scan response queue*/
1086 pHead = pAdapter->pBatchScanRsp;
1087
1088 pNode = (tHddBatchScanRsp *)vos_mem_malloc(sizeof(tHddBatchScanRsp));
1089 if (NULL == pNode)
1090 {
1091 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1092 "%s: Could not allocate memory", __func__);
1093 VOS_ASSERT(0);
1094 return;
1095 }
1096
1097 vos_mem_copy(pNode->ApInfo.bssid, pApMetaInfo->bssid,
1098 sizeof(pNode->ApInfo.bssid));
1099 ssidLen = strlen(pApMetaInfo->ssid);
1100 if (SIR_MAX_SSID_SIZE < ssidLen)
1101 {
1102 /*invalid scan result*/
1103 vos_mem_free(pNode);
1104 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1105 "%s: Invalid AP meta info ssidlen %d", __func__, ssidLen);
1106 return;
1107 }
1108 vos_mem_copy(pNode->ApInfo.ssid, pApMetaInfo->ssid, ssidLen);
1109 /*null terminate ssid*/
1110 pNode->ApInfo.ssid[ssidLen] = '\0';
1111 pNode->ApInfo.ch = pApMetaInfo->ch;
1112 pNode->ApInfo.rssi = pApMetaInfo->rssi;
1113 pNode->ApInfo.age = pApMetaInfo->timestamp;
1114 pNode->ApInfo.batchId = scanId;
1115 pNode->ApInfo.isLastAp = isLastAp;
1116
1117 pNode->pNext = NULL;
1118 if (NULL == pHead)
1119 {
1120 pAdapter->pBatchScanRsp = pNode;
1121 }
1122 else
1123 {
1124 pTemp = pHead;
1125 while (NULL != pTemp)
1126 {
1127 pPrev = pTemp;
1128 pTemp = pTemp->pNext;
1129 }
1130 pPrev->pNext = pNode;
1131 }
1132
1133 return;
1134}/*End of hdd_populate_batch_scan_rsp_queue*/
1135
1136/**---------------------------------------------------------------------------
1137
1138 \brief hdd_batch_scan_result_ind_callback () - This function is called after
1139 receiving batch scan response indication from FW. It saves get batch scan
1140 response data in HDD batch scan response queue. This callback sets the
1141 completion event on which hdd_ioctl is waiting only after getting complete
1142 batch scan response data from FW
1143
1144 \param - callbackContext Pointer to HDD adapter
1145 \param - pRsp Pointer to get batch scan response data received from FW
1146
1147 \return - nothing
1148
1149 --------------------------------------------------------------------------*/
1150static void hdd_batch_scan_result_ind_callback
1151(
1152 void *callbackContext,
1153 void *pRsp
1154)
1155{
1156 v_BOOL_t isLastAp;
1157 tANI_U32 numApMetaInfo;
Rajeev Kumarce651e42013-10-21 18:57:15 -07001158 tANI_U32 numNetworkInScanList;
Rajeev79dbe4c2013-10-05 11:03:42 +05301159 tANI_U32 numberScanList;
1160 tANI_U32 nextScanListOffset;
1161 tANI_U32 nextApMetaInfoOffset;
1162 hdd_adapter_t* pAdapter;
1163 tpSirBatchScanList pScanList;
1164 tpSirBatchScanNetworkInfo pApMetaInfo;
1165 tpSirBatchScanResultIndParam pBatchScanRsp;/*batch scan rsp data from FW*/
1166 tSirSetBatchScanReq *pReq;
1167
1168 pAdapter = (hdd_adapter_t *)callbackContext;
1169 /*sanity check*/
Rajeev Kumar5286bb92013-12-05 11:52:10 -08001170 if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
Rajeev79dbe4c2013-10-05 11:03:42 +05301171 {
1172 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1173 "%s: Invalid pAdapter magic", __func__);
1174 VOS_ASSERT(0);
1175 return;
1176 }
1177
1178 /*initialize locals*/
1179 pReq = &pAdapter->hddSetBatchScanReq;
1180 pBatchScanRsp = (tpSirBatchScanResultIndParam)pRsp;
1181 isLastAp = FALSE;
1182 numApMetaInfo = 0;
Rajeev Kumarce651e42013-10-21 18:57:15 -07001183 numNetworkInScanList = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05301184 numberScanList = 0;
1185 nextScanListOffset = 0;
1186 nextApMetaInfoOffset = 0;
1187 pScanList = NULL;
1188 pApMetaInfo = NULL;
1189
1190 if ((NULL == pBatchScanRsp) || (NULL == pReq))
1191 {
1192 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1193 "%s: pBatchScanRsp is %p pReq %p", __func__, pBatchScanRsp, pReq);
1194 isLastAp = TRUE;
1195 goto done;
1196 }
1197
1198 pAdapter->numScanList = numberScanList = pBatchScanRsp->numScanLists;
1199 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1200 "Batch scan rsp: numberScalList %d", numberScanList);
1201
1202 if ((!numberScanList) || (numberScanList > pReq->numberOfScansToBatch))
1203 {
1204 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1205 "%s: numberScanList %d", __func__, numberScanList);
1206 isLastAp = TRUE;
1207 goto done;
1208 }
1209
1210 while (numberScanList)
1211 {
Rajeev Kumarce651e42013-10-21 18:57:15 -07001212 pScanList = (tpSirBatchScanList)((tANI_U8 *)pBatchScanRsp->scanResults +
Rajeev79dbe4c2013-10-05 11:03:42 +05301213 nextScanListOffset);
1214 if (NULL == pScanList)
1215 {
1216 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1217 "%s: pScanList is %p", __func__, pScanList);
1218 isLastAp = TRUE;
1219 goto done;
1220 }
Rajeev Kumarce651e42013-10-21 18:57:15 -07001221 numNetworkInScanList = numApMetaInfo = pScanList->numNetworksInScanList;
Rajeev79dbe4c2013-10-05 11:03:42 +05301222 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumarce651e42013-10-21 18:57:15 -07001223 "Batch scan rsp: numApMetaInfo %d scanId %d",
1224 numApMetaInfo, pScanList->scanId);
Rajeev79dbe4c2013-10-05 11:03:42 +05301225
1226 if ((!numApMetaInfo) || (numApMetaInfo > pReq->bestNetwork))
1227 {
1228 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1229 "%s: numApMetaInfo %d", __func__, numApMetaInfo);
1230 isLastAp = TRUE;
1231 goto done;
1232 }
1233
Rajeev Kumarce651e42013-10-21 18:57:15 -07001234 /*Initialize next AP meta info offset for next scan list*/
1235 nextApMetaInfoOffset = 0;
1236
Rajeev79dbe4c2013-10-05 11:03:42 +05301237 while (numApMetaInfo)
1238 {
1239 pApMetaInfo = (tpSirBatchScanNetworkInfo)(pScanList->scanList +
1240 nextApMetaInfoOffset);
1241 if (NULL == pApMetaInfo)
1242 {
1243 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1244 "%s: pApMetaInfo is %p", __func__, pApMetaInfo);
1245 isLastAp = TRUE;
1246 goto done;
1247 }
1248 /*calculate AP age*/
1249 pApMetaInfo->timestamp =
1250 pBatchScanRsp->timestamp - pApMetaInfo->timestamp;
1251
1252 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
Arif Hussaina7c8e412013-11-20 11:06:42 -08001253 "%s: bssId "MAC_ADDRESS_STR
1254 " ch %d rssi %d timestamp %d", __func__,
1255 MAC_ADDR_ARRAY(pApMetaInfo->bssid),
1256 pApMetaInfo->ch, pApMetaInfo->rssi,
1257 pApMetaInfo->timestamp);
Rajeev79dbe4c2013-10-05 11:03:42 +05301258
1259 /*mark last AP in batch scan response*/
1260 if ((TRUE == pBatchScanRsp->isLastResult) &&
1261 (1 == numberScanList) && (1 == numApMetaInfo))
1262 {
1263 isLastAp = TRUE;
1264 }
1265
1266 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1267 /*store batch scan repsonse in hdd queue*/
1268 hdd_populate_batch_scan_rsp_queue(pAdapter, pApMetaInfo,
1269 pScanList->scanId, isLastAp);
1270 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1271
1272 nextApMetaInfoOffset += sizeof(tSirBatchScanNetworkInfo);
1273 numApMetaInfo--;
1274 }
1275
Rajeev Kumarce651e42013-10-21 18:57:15 -07001276 nextScanListOffset += ((sizeof(tSirBatchScanList) - sizeof(tANI_U8))
1277 + (sizeof(tSirBatchScanNetworkInfo)
1278 * numNetworkInScanList));
Rajeev79dbe4c2013-10-05 11:03:42 +05301279 numberScanList--;
1280 }
1281
1282done:
1283
1284 /*notify hdd_ioctl only if complete batch scan rsp is received and it was
1285 requested from hdd_ioctl*/
1286 if ((TRUE == pAdapter->hdd_wait_for_get_batch_scan_rsp) &&
1287 (TRUE == isLastAp))
1288 {
1289 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
1290 complete(&pAdapter->hdd_get_batch_scan_req_var);
1291 }
1292
1293 return;
1294}/*End of hdd_batch_scan_result_ind_callback*/
1295
1296/**---------------------------------------------------------------------------
1297
1298 \brief hdd_format_batch_scan_rsp () - This function formats batch scan
1299 response as per batch scan FR request format by putting proper markers
1300
1301 \param - pDest pointer to destination buffer
1302 \param - cur_len current length
1303 \param - tot_len total remaining size which can be written to user space
1304 \param - pApMetaInfo Pointer to get batch scan response AP meta info
1305 \param - pAdapter Pointer to HDD adapter
1306
1307 \return - ret no of characters written
1308
1309 --------------------------------------------------------------------------*/
1310static tANI_U32
1311hdd_format_batch_scan_rsp
1312(
1313 tANI_U8 *pDest,
1314 tANI_U32 cur_len,
1315 tANI_U32 tot_len,
1316 tHddBatchScanRsp *pApMetaInfo,
1317 hdd_adapter_t* pAdapter
1318)
1319{
1320 tANI_U32 ret = 0;
1321 tANI_U32 rem_len = 0;
1322 tANI_U8 temp_len = 0;
1323 tANI_U8 temp_total_len = 0;
1324 tANI_U8 temp[HDD_BATCH_SCAN_AP_META_INFO_SIZE];
1325 tANI_U8 *pTemp = temp;
1326
1327 /*Batch scan reponse needs to be returned to user space in
1328 following format:
1329 "scancount=X\n" where X is the number of scans in current batch
1330 batch
1331 "trunc\n" optional present if current scan truncated
1332 "bssid=XX:XX:XX:XX:XX:XX\n"
1333 "ssid=XXXX\n"
1334 "freq=X\n" frequency in Mhz
1335 "level=XX\n"
1336 "age=X\n" ms
1337 "dist=X\n" cm (-1 if not available)
1338 "errror=X\n" (-1if not available)
1339 "====\n" (end of ap marker)
1340 "####\n" (end of scan marker)
1341 "----\n" (end of results)*/
1342 /*send scan result in above format to user space based on
1343 available length*/
1344 /*The GET response may have more data than the driver can return in its
1345 buffer. In that case the buffer should be filled to the nearest complete
1346 scan, ending with "%%%%".Subsequent callsshould return the remaining data
1347 starting with the next scan (optional .trunc\n., .apcount=X\n., etc).
1348 The final buffer should end with "----\n"*/
1349
1350 /*sanity*/
1351 if (cur_len > tot_len)
1352 {
1353 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1354 "%s: invaid cur_len %d tot_len %d", __func__, cur_len, tot_len);
1355 return 0;
1356 }
1357 else
1358 {
1359 rem_len = (tot_len - cur_len);
1360 }
1361
1362 /*end scan marker*/
1363 if (pApMetaInfo->ApInfo.batchId != pAdapter->prev_batch_id)
1364 {
1365 temp_len = snprintf(pTemp, sizeof(temp), "####\n");
1366 pTemp += temp_len;
1367 temp_total_len += temp_len;
1368 }
1369
1370 /*bssid*/
1371 temp_len = snprintf(pTemp, sizeof(temp),
1372 "bssid=0x%x:0x%x:0x%x:0x%x:0x%x:0x%x\n",
1373 pApMetaInfo->ApInfo.bssid[0], pApMetaInfo->ApInfo.bssid[1],
1374 pApMetaInfo->ApInfo.bssid[2], pApMetaInfo->ApInfo.bssid[3],
1375 pApMetaInfo->ApInfo.bssid[4], pApMetaInfo->ApInfo.bssid[5]);
1376 pTemp += temp_len;
1377 temp_total_len += temp_len;
1378
1379 /*ssid*/
1380 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "ssid=%s\n",
1381 pApMetaInfo->ApInfo.ssid);
1382 pTemp += temp_len;
1383 temp_total_len += temp_len;
1384
1385 /*freq*/
1386 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "freq=%d\n",
Rajeev Kumarc40f7512013-11-04 14:13:23 -08001387 sme_ChnToFreq(pApMetaInfo->ApInfo.ch));
Rajeev79dbe4c2013-10-05 11:03:42 +05301388 pTemp += temp_len;
1389 temp_total_len += temp_len;
1390
1391 /*level*/
1392 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "level=%d\n",
1393 pApMetaInfo->ApInfo.rssi);
1394 pTemp += temp_len;
1395 temp_total_len += temp_len;
1396
1397 /*age*/
Jeff Johnson02797792013-10-26 19:17:13 -07001398 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "age=%d\n",
Rajeev79dbe4c2013-10-05 11:03:42 +05301399 pApMetaInfo->ApInfo.age);
1400 pTemp += temp_len;
1401 temp_total_len += temp_len;
1402
1403 /*dist*/
1404 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "dist=-1\n");
1405 pTemp += temp_len;
1406 temp_total_len += temp_len;
1407
1408 /*error*/
1409 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "error=-1\n");
1410 pTemp += temp_len;
1411 temp_total_len += temp_len;
1412
1413 /*end AP marker*/
1414 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "====\n");
1415 pTemp += temp_len;
1416 temp_total_len += temp_len;
1417
1418 /*last AP in batch scan response*/
1419 if(TRUE == pApMetaInfo->ApInfo.isLastAp)
1420 {
1421 /*end scan marker*/
1422 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "####\n");
1423 pTemp += temp_len;
1424 temp_total_len += temp_len;
1425
1426 /*end batch scan result marker*/
1427 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "----\n");
1428 pTemp += temp_len;
1429 temp_total_len += temp_len;
Kiet Lamaa8e15a2014-02-11 23:30:06 -08001430
Rajeev79dbe4c2013-10-05 11:03:42 +05301431 }
1432
1433 if (temp_total_len < rem_len)
1434 {
1435 ret = temp_total_len + 1;
1436 strlcpy(pDest, temp, ret);
1437 pAdapter->isTruncated = FALSE;
1438 }
1439 else
1440 {
1441 pAdapter->isTruncated = TRUE;
1442 if (rem_len >= strlen("%%%%"))
1443 {
Rajeev Kumarc933d982013-11-18 20:04:20 -08001444 ret = snprintf(pDest, sizeof(temp), "%%%%");
Rajeev79dbe4c2013-10-05 11:03:42 +05301445 }
Rajeev Kumarc933d982013-11-18 20:04:20 -08001446 else
Rajeev79dbe4c2013-10-05 11:03:42 +05301447 {
1448 ret = 0;
1449 }
1450 }
1451
1452 return ret;
1453
1454}/*End of hdd_format_batch_scan_rsp*/
1455
1456/**---------------------------------------------------------------------------
1457
1458 \brief hdd_populate_user_batch_scan_rsp() - This function populates user data
1459 buffer starting with head of hdd batch scan response queue
1460
1461 \param - pAdapter Pointer to HDD adapter
1462 \param - pDest Pointer to user data buffer
1463 \param - cur_len current offset in user buffer
1464 \param - rem_len remaining no of bytes in user buffer
1465
1466 \return - number of bytes written in user buffer
1467
1468 --------------------------------------------------------------------------*/
1469
1470tANI_U32 hdd_populate_user_batch_scan_rsp
1471(
1472 hdd_adapter_t* pAdapter,
1473 tANI_U8 *pDest,
1474 tANI_U32 cur_len,
1475 tANI_U32 rem_len
1476)
1477{
1478 tHddBatchScanRsp *pHead;
1479 tHddBatchScanRsp *pPrev;
1480 tANI_U32 len;
1481
Rajeev79dbe4c2013-10-05 11:03:42 +05301482 pAdapter->isTruncated = FALSE;
1483
1484 /*head of hdd batch scan response queue*/
1485 pHead = pAdapter->pBatchScanRsp;
1486 while (pHead)
1487 {
1488 len = hdd_format_batch_scan_rsp(pDest, cur_len, rem_len, pHead,
1489 pAdapter);
1490 pDest += len;
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07001491 pDest--;
Rajeev79dbe4c2013-10-05 11:03:42 +05301492 cur_len += len;
1493 if(TRUE == pAdapter->isTruncated)
1494 {
1495 /*result is truncated return rest of scan rsp in next req*/
1496 cur_len = rem_len;
1497 break;
1498 }
1499 pPrev = pHead;
1500 pHead = pHead->pNext;
1501 pAdapter->pBatchScanRsp = pHead;
Rajeev Kumarbe17d8b2014-01-10 15:39:45 -08001502 if (TRUE == pPrev->ApInfo.isLastAp)
1503 {
1504 pAdapter->prev_batch_id = 0;
1505 }
1506 else
1507 {
1508 pAdapter->prev_batch_id = pPrev->ApInfo.batchId;
1509 }
Rajeev79dbe4c2013-10-05 11:03:42 +05301510 vos_mem_free(pPrev);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08001511 pPrev = NULL;
Rajeev79dbe4c2013-10-05 11:03:42 +05301512 }
1513
1514 return cur_len;
1515}/*End of hdd_populate_user_batch_scan_rsp*/
1516
1517/**---------------------------------------------------------------------------
1518
1519 \brief hdd_return_batch_scan_rsp_to_user () - This function returns batch
1520 scan response data from HDD queue to user space
1521 It does following in detail:
1522 a) if HDD has enough data in its queue then it 1st copies data to user
1523 space and then send get batch scan indication message to FW. In this
1524 case it does not wait on any event and batch scan response data will
1525 be populated in HDD response queue in MC thread context after receiving
1526 indication from FW
1527 b) else send get batch scan indication message to FW and wait on an event
1528 which will be set once HDD receives complete batch scan response from
1529 FW and then this function returns batch scan response to user space
1530
1531 \param - pAdapter Pointer to HDD adapter
1532 \param - pPrivData Pointer to priv_data
1533
1534 \return - 0 for success -EFAULT for failure
1535
1536 --------------------------------------------------------------------------*/
1537
1538int hdd_return_batch_scan_rsp_to_user
1539(
1540 hdd_adapter_t* pAdapter,
1541 hdd_priv_data_t *pPrivData,
1542 tANI_U8 *command
1543)
1544{
1545 tANI_U8 *pDest;
1546 tANI_U32 count = 0;
1547 tANI_U32 len = 0;
1548 tANI_U32 cur_len = 0;
1549 tANI_U32 rem_len = 0;
1550 eHalStatus halStatus;
1551 unsigned long rc;
1552 tSirTriggerBatchScanResultInd *pReq;
1553
1554 pReq = &pAdapter->hddTriggerBatchScanResultInd;
1555 pReq->param = 0;/*batch scan client*/
1556 pDest = (tANI_U8 *)(command + pPrivData->used_len);
1557 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
1558
1559 cur_len = pPrivData->used_len;
1560 if (pPrivData->total_len > pPrivData->used_len)
1561 {
1562 rem_len = pPrivData->total_len - pPrivData->used_len;
1563 }
1564 else
1565 {
1566 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1567 "%s: Invalid user data buffer total_len %d used_len %d",
1568 __func__, pPrivData->total_len, pPrivData->used_len);
1569 return -EFAULT;
1570 }
1571
1572 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1573 len = hdd_populate_user_batch_scan_rsp(pAdapter, pDest,
1574 cur_len, rem_len);
1575 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1576
1577 /*enough scan result available in cache to return to user space or
1578 scan result needs to be fetched 1st from fw and then return*/
Rajeev Kumar99db6262013-11-11 15:23:36 -08001579 if (len == cur_len)
Rajeev79dbe4c2013-10-05 11:03:42 +05301580 {
1581 pAdapter->hdd_wait_for_get_batch_scan_rsp = TRUE;
1582 halStatus = sme_TriggerBatchScanResultInd(
1583 WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
1584 pAdapter->sessionId, hdd_batch_scan_result_ind_callback,
1585 pAdapter);
1586 if ( eHAL_STATUS_SUCCESS == halStatus )
1587 {
1588 if (TRUE == pAdapter->hdd_wait_for_get_batch_scan_rsp)
1589 {
1590 INIT_COMPLETION(pAdapter->hdd_get_batch_scan_req_var);
1591 rc = wait_for_completion_timeout(
1592 &pAdapter->hdd_get_batch_scan_req_var,
1593 msecs_to_jiffies(HDD_GET_BATCH_SCAN_RSP_TIME_OUT));
1594 if (0 == rc)
1595 {
1596 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1597 "%s: Timeout waiting to fetch batch scan rsp from fw",
1598 __func__);
1599 return -EFAULT;
1600 }
1601 }
1602
1603 len = snprintf(pDest, HDD_BATCH_SCAN_AP_META_INFO_SIZE,
Jeff Johnson02797792013-10-26 19:17:13 -07001604 "scancount=%u\n", pAdapter->numScanList);
Rajeev79dbe4c2013-10-05 11:03:42 +05301605 pDest += len;
1606 cur_len += len;
1607
1608 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1609 len = hdd_populate_user_batch_scan_rsp(pAdapter, pDest,
1610 cur_len, rem_len);
1611 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1612
1613 count = 0;
1614 len = (len - pPrivData->used_len);
1615 pDest = (command + pPrivData->used_len);
1616 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar99db6262013-11-11 15:23:36 -08001617 "NEW BATCH SCAN RESULT:");
Rajeev79dbe4c2013-10-05 11:03:42 +05301618 while(count < len)
1619 {
1620 printk("%c", *(pDest + count));
1621 count++;
1622 }
1623 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1624 "%s: copy %d data to user buffer", __func__, len);
1625 if (copy_to_user(pPrivData->buf, pDest, len))
1626 {
1627 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1628 "%s: failed to copy data to user buffer", __func__);
1629 return -EFAULT;
1630 }
1631 }
1632 else
1633 {
1634 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1635 "sme_GetBatchScanScan returned failure halStatus %d",
1636 halStatus);
1637 return -EINVAL;
1638 }
1639 }
1640 else
1641 {
Rajeev79dbe4c2013-10-05 11:03:42 +05301642 count = 0;
1643 len = (len - pPrivData->used_len);
1644 pDest = (command + pPrivData->used_len);
1645 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar99db6262013-11-11 15:23:36 -08001646 "REMAINING TRUNCATED BATCH SCAN RESULT:");
Rajeev79dbe4c2013-10-05 11:03:42 +05301647 while(count < len)
1648 {
1649 printk("%c", *(pDest + count));
1650 count++;
1651 }
Rajeev Kumar99db6262013-11-11 15:23:36 -08001652 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1653 "%s: copy %d data to user buffer", __func__, len);
Rajeev79dbe4c2013-10-05 11:03:42 +05301654 if (copy_to_user(pPrivData->buf, pDest, len))
1655 {
1656 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1657 "%s: failed to copy data to user buffer", __func__);
1658 return -EFAULT;
1659 }
Rajeev79dbe4c2013-10-05 11:03:42 +05301660 }
1661
1662 return 0;
1663} /*End of hdd_return_batch_scan_rsp_to_user*/
1664
Rajeev Kumar8b373292014-01-08 20:36:55 -08001665
1666/**---------------------------------------------------------------------------
1667
1668 \brief hdd_handle_batch_scan_ioctl () - This function handles WLS_BATCHING
1669 IOCTLs from user space. Following BATCH SCAN DEV IOCTs are handled:
1670 WLS_BATCHING VERSION
1671 WLS_BATCHING SET
1672 WLS_BATCHING GET
1673 WLS_BATCHING STOP
1674
1675 \param - pAdapter Pointer to HDD adapter
1676 \param - pPrivdata Pointer to priv_data
1677 \param - command Pointer to command
1678
1679 \return - 0 for success -EFAULT for failure
1680
1681 --------------------------------------------------------------------------*/
1682
1683int hdd_handle_batch_scan_ioctl
1684(
1685 hdd_adapter_t *pAdapter,
1686 hdd_priv_data_t *pPrivdata,
1687 tANI_U8 *command
1688)
1689{
1690 int ret = 0;
Yue Mae36e3552014-03-05 17:06:20 -08001691 hdd_context_t *pHddCtx;
1692
1693 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
1694 ret = wlan_hdd_validate_context(pHddCtx);
1695 if (ret)
1696 {
1697 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1698 "%s: HDD context is not valid!", __func__);
1699 goto exit;
1700 }
Rajeev Kumar8b373292014-01-08 20:36:55 -08001701
1702 if (strncmp(command, "WLS_BATCHING VERSION", 20) == 0)
1703 {
1704 char extra[32];
1705 tANI_U8 len = 0;
1706 tANI_U8 version = HDD_BATCH_SCAN_VERSION;
1707
1708 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
1709 {
1710 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1711 "%s: Batch scan feature is not supported by FW", __func__);
1712 ret = -EINVAL;
1713 goto exit;
1714 }
1715
1716 len = scnprintf(extra, sizeof(extra), "WLS_BATCHING_VERSION %d",
1717 version);
1718 if (copy_to_user(pPrivdata->buf, &extra, len + 1))
1719 {
1720 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1721 "%s: failed to copy data to user buffer", __func__);
1722 ret = -EFAULT;
1723 goto exit;
1724 }
1725 ret = HDD_BATCH_SCAN_VERSION;
1726 }
1727 else if (strncmp(command, "WLS_BATCHING SET", 16) == 0)
1728 {
1729 int status;
1730 tANI_U8 *value = (command + 16);
1731 eHalStatus halStatus;
1732 unsigned long rc;
1733 tSirSetBatchScanReq *pReq = &pAdapter->hddSetBatchScanReq;
1734 tSirSetBatchScanRsp *pRsp = &pAdapter->hddSetBatchScanRsp;
1735
1736 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
1737 {
1738 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1739 "%s: Batch scan feature is not supported by FW", __func__);
1740 ret = -EINVAL;
1741 goto exit;
1742 }
1743
1744 if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) &&
1745 (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) &&
1746 (WLAN_HDD_P2P_GO != pAdapter->device_mode) &&
1747 (WLAN_HDD_P2P_DEVICE != pAdapter->device_mode))
1748 {
1749 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Sushant Kaushik8bc7df22014-04-09 17:55:29 +05301750 "Received WLS_BATCHING SET command in invalid mode %s (%d) "
Rajeev Kumar8b373292014-01-08 20:36:55 -08001751 "WLS_BATCHING_SET is only allowed in infra STA/P2P client mode",
Sushant Kaushik8bc7df22014-04-09 17:55:29 +05301752 hdd_device_modetoString(pAdapter->device_mode),
1753 pAdapter->device_mode);
Rajeev Kumar8b373292014-01-08 20:36:55 -08001754 ret = -EINVAL;
1755 goto exit;
1756 }
1757
1758 status = hdd_parse_set_batchscan_command(value, pReq);
1759 if (status)
1760 {
1761 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1762 "Invalid WLS_BATCHING SET command");
1763 ret = -EINVAL;
1764 goto exit;
1765 }
1766
1767
1768 pAdapter->hdd_wait_for_set_batch_scan_rsp = TRUE;
1769 halStatus = sme_SetBatchScanReq(WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
1770 pAdapter->sessionId, hdd_set_batch_scan_req_callback,
1771 pAdapter);
1772
1773 if ( eHAL_STATUS_SUCCESS == halStatus )
1774 {
Mahesh A Saptasagar5f568172014-05-14 17:02:33 +05301775 char extra[32];
1776 tANI_U8 len = 0;
1777 tANI_U8 mScan = 0;
1778
Rajeev Kumar8b373292014-01-08 20:36:55 -08001779 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1780 "sme_SetBatchScanReq returned success halStatus %d",
1781 halStatus);
1782 if (TRUE == pAdapter->hdd_wait_for_set_batch_scan_rsp)
1783 {
1784 INIT_COMPLETION(pAdapter->hdd_set_batch_scan_req_var);
1785 rc = wait_for_completion_timeout(
1786 &pAdapter->hdd_set_batch_scan_req_var,
1787 msecs_to_jiffies(HDD_SET_BATCH_SCAN_REQ_TIME_OUT));
1788 if (0 == rc)
1789 {
1790 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1791 "%s: Timeout waiting for set batch scan to complete",
1792 __func__);
1793 ret = -EINVAL;
1794 goto exit;
1795 }
1796 }
1797 if ( !pRsp->nScansToBatch )
1798 {
1799 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1800 "%s: Received set batch scan failure response from FW",
1801 __func__);
1802 ret = -EINVAL;
1803 goto exit;
1804 }
1805 /*As per the Batch Scan Framework API we should return the MIN of
1806 either MSCAN or the max # of scans firmware can cache*/
Mahesh A Saptasagar5f568172014-05-14 17:02:33 +05301807 mScan = MIN(pReq->numberOfScansToBatch , pRsp->nScansToBatch);
Rajeev Kumar8b373292014-01-08 20:36:55 -08001808
1809 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STARTED;
1810
1811 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1812 "%s: request MSCAN %d response MSCAN %d ret %d",
Mahesh A Saptasagar5f568172014-05-14 17:02:33 +05301813 __func__, pReq->numberOfScansToBatch, pRsp->nScansToBatch, mScan);
1814 len = scnprintf(extra, sizeof(extra), "%d", mScan);
1815 if (copy_to_user(pPrivdata->buf, &extra, len + 1))
1816 {
1817 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1818 "%s: failed to copy MSCAN value to user buffer", __func__);
1819 ret = -EFAULT;
1820 goto exit;
1821 }
Rajeev Kumar8b373292014-01-08 20:36:55 -08001822 }
1823 else
1824 {
1825 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1826 "sme_SetBatchScanReq returned failure halStatus %d",
1827 halStatus);
1828 ret = -EINVAL;
1829 goto exit;
1830 }
1831 }
1832 else if (strncmp(command, "WLS_BATCHING STOP", 17) == 0)
1833 {
1834 eHalStatus halStatus;
1835 tSirStopBatchScanInd *pInd = &pAdapter->hddStopBatchScanInd;
1836 pInd->param = 0;
1837
1838 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
1839 {
1840 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1841 "%s: Batch scan feature is not supported by FW", __func__);
1842 ret = -EINVAL;
1843 goto exit;
1844 }
1845
1846 if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState)
1847 {
1848 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1849 "Batch scan is not yet enabled batch scan state %d",
1850 pAdapter->batchScanState);
1851 ret = -EINVAL;
1852 goto exit;
1853 }
1854
Kiet Lamaa8e15a2014-02-11 23:30:06 -08001855 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1856 hdd_deinit_batch_scan(pAdapter);
1857 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1858
Rajeev Kumar8b373292014-01-08 20:36:55 -08001859 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
1860
1861 halStatus = sme_StopBatchScanInd(WLAN_HDD_GET_HAL_CTX(pAdapter), pInd,
1862 pAdapter->sessionId);
1863 if ( eHAL_STATUS_SUCCESS == halStatus )
1864 {
1865 ret = 0;
1866 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1867 "sme_StopBatchScanInd returned success halStatus %d",
1868 halStatus);
1869 }
1870 else
1871 {
1872 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1873 "sme_StopBatchScanInd returned failure halStatus %d",
1874 halStatus);
1875 ret = -EINVAL;
1876 goto exit;
1877 }
1878 }
1879 else if (strncmp(command, "WLS_BATCHING GET", 16) == 0)
1880 {
1881 tANI_U32 remain_len;
1882
1883 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
1884 {
1885 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1886 "%s: Batch scan feature is not supported by FW", __func__);
1887 ret = -EINVAL;
1888 goto exit;
1889 }
1890
1891 if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState)
1892 {
1893 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1894 "Batch scan is not yet enabled could not return results"
1895 "Batch Scan state %d",
1896 pAdapter->batchScanState);
1897 ret = -EINVAL;
1898 goto exit;
1899 }
1900
1901 pPrivdata->used_len = 16;
1902 remain_len = pPrivdata->total_len - pPrivdata->used_len;
1903 if (remain_len < pPrivdata->total_len)
1904 {
1905 /*Clear previous batch scan response data if any*/
1906 vos_mem_zero((tANI_U8 *)(command + pPrivdata->used_len), remain_len);
1907 }
1908 else
1909 {
1910 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1911 "Invalid total length from user space can't fetch batch"
1912 " scan response total_len %d used_len %d remain len %d",
1913 pPrivdata->total_len, pPrivdata->used_len, remain_len);
1914 ret = -EINVAL;
1915 goto exit;
1916 }
1917 ret = hdd_return_batch_scan_rsp_to_user(pAdapter, pPrivdata, command);
1918 }
1919
1920exit:
1921
1922 return ret;
1923}
1924
1925
Rajeev79dbe4c2013-10-05 11:03:42 +05301926#endif/*End of FEATURE_WLAN_BATCH_SCAN*/
1927
c_hpothu92367912014-05-01 15:18:17 +05301928static void getBcnMissRateCB(VOS_STATUS status, int bcnMissRate, void *data)
1929{
1930 bcnMissRateContext_t *pCBCtx = (bcnMissRateContext_t *)data;
1931
1932 /* there is a race condition that exists between this callback
1933 function and the caller since the caller could time out either
1934 before or while this code is executing. we use a spinlock to
1935 serialize these actions */
1936 spin_lock(&hdd_context_lock);
1937
1938 gbcnMissRate = -1;
1939
1940 if(pCBCtx->magic != BCN_MISS_RATE_CONTEXT_MAGIC || NULL == data)
1941 {
1942 hddLog(VOS_TRACE_LEVEL_ERROR,
1943 FL("invalid context magic: %08x data: %p"), pCBCtx->magic, data );
1944 spin_unlock(&hdd_context_lock);
1945 return ;
1946 }
1947
1948 if (VOS_STATUS_SUCCESS == status)
1949 {
1950 gbcnMissRate = bcnMissRate;
1951 }
1952 complete(&(pCBCtx->completion));
1953 spin_unlock(&hdd_context_lock);
1954
1955 return;
1956}
1957
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05301958static int hdd_get_dwell_time(hdd_config_t *pCfg, tANI_U8 *command, char *extra, tANI_U8 n, tANI_U8 *len)
1959{
1960 int ret = 0;
1961
1962 if (!pCfg || !command || !extra || !len)
1963 {
1964 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1965 "%s: argument passsed for GETDWELLTIME is incorrect", __func__);
1966 ret = -EINVAL;
1967 return ret;
1968 }
1969
1970 if (strncmp(command, "GETDWELLTIME ACTIVE MAX", 23) == 0)
1971 {
1972 *len = scnprintf(extra, n, "GETDWELLTIME ACTIVE MAX %u\n",
1973 (int)pCfg->nActiveMaxChnTime);
1974 return ret;
1975 }
1976 else if (strncmp(command, "GETDWELLTIME ACTIVE MIN", 23) == 0)
1977 {
1978 *len = scnprintf(extra, n, "GETDWELLTIME ACTIVE MIN %u\n",
1979 (int)pCfg->nActiveMinChnTime);
1980 return ret;
1981 }
1982 else if (strncmp(command, "GETDWELLTIME PASSIVE MAX", 24) == 0)
1983 {
1984 *len = scnprintf(extra, n, "GETDWELLTIME PASSIVE MAX %u\n",
1985 (int)pCfg->nPassiveMaxChnTime);
1986 return ret;
1987 }
1988 else if (strncmp(command, "GETDWELLTIME PASSIVE MIN", 24) == 0)
1989 {
1990 *len = scnprintf(extra, n, "GETDWELLTIME PASSIVE MIN %u\n",
1991 (int)pCfg->nPassiveMinChnTime);
1992 return ret;
1993 }
1994 else
1995 {
1996 ret = -EINVAL;
1997 }
1998
1999 return ret;
2000}
2001
2002static int hdd_set_dwell_time(hdd_adapter_t *pAdapter, tANI_U8 *command)
2003{
2004 hdd_config_t *pCfg;
2005 tANI_U8 *value = command;
2006 int val = 0, ret = 0, temp = 0;
2007
2008 if (!pAdapter || !command || !(pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini))
2009 {
2010 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2011 "%s: argument passed for SETDWELLTIME is incorrect", __func__);
2012 ret = -EINVAL;
2013 return ret;
2014 }
2015
2016 if (strncmp(command, "SETDWELLTIME ACTIVE MAX", 23) == 0 )
2017 {
2018 value = value + 24;
2019 temp = kstrtou32(value, 10, &val);
2020 if (temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_MIN ||
2021 val > CFG_ACTIVE_MAX_CHANNEL_TIME_MAX )
2022 {
2023 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2024 "%s: argument passed for SETDWELLTIME ACTIVE MAX is incorrect", __func__);
2025 ret = -EFAULT;
2026 return ret;
2027 }
2028 pCfg->nActiveMaxChnTime = val;
2029 }
2030 else if (strncmp(command, "SETDWELLTIME ACTIVE MIN", 23) == 0)
2031 {
2032 value = value + 24;
2033 temp = kstrtou32(value, 10, &val);
2034 if (temp !=0 || val < CFG_ACTIVE_MIN_CHANNEL_TIME_MIN ||
2035 val > CFG_ACTIVE_MIN_CHANNEL_TIME_MAX )
2036 {
2037 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2038 "%s: argument passsed for SETDWELLTIME ACTIVE MIN is incorrect", __func__);
2039 ret = -EFAULT;
2040 return ret;
2041 }
2042 pCfg->nActiveMinChnTime = val;
2043 }
2044 else if (strncmp(command, "SETDWELLTIME PASSIVE MAX", 24) == 0)
2045 {
2046 value = value + 25;
2047 temp = kstrtou32(value, 10, &val);
2048 if (temp != 0 || val < CFG_PASSIVE_MAX_CHANNEL_TIME_MIN ||
2049 val > CFG_PASSIVE_MAX_CHANNEL_TIME_MAX )
2050 {
2051 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2052 "%s: argument passed for SETDWELLTIME PASSIVE MAX is incorrect", __func__);
2053 ret = -EFAULT;
2054 return ret;
2055 }
2056 pCfg->nPassiveMaxChnTime = val;
2057 }
2058 else if (strncmp(command, "SETDWELLTIME PASSIVE MIN", 24) == 0)
2059 {
2060 value = value + 25;
2061 temp = kstrtou32(value, 10, &val);
2062 if (temp != 0 || val < CFG_PASSIVE_MIN_CHANNEL_TIME_MIN ||
2063 val > CFG_PASSIVE_MIN_CHANNEL_TIME_MAX )
2064 {
2065 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2066 "%s: argument passed for SETDWELLTIME PASSIVE MIN is incorrect", __func__);
2067 ret = -EFAULT;
2068 return ret;
2069 }
2070 pCfg->nPassiveMinChnTime = val;
2071 }
2072 else
2073 {
2074 ret = -EINVAL;
2075 }
2076
2077 return ret;
2078}
2079
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002080static int hdd_driver_command(hdd_adapter_t *pAdapter,
2081 hdd_priv_data_t *ppriv_data)
Jeff Johnson295189b2012-06-20 16:38:30 -07002082{
Jeff Johnson295189b2012-06-20 16:38:30 -07002083 hdd_priv_data_t priv_data;
2084 tANI_U8 *command = NULL;
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002085 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07002086
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002087 /*
2088 * Note that valid pointers are provided by caller
2089 */
Jeff Johnson295189b2012-06-20 16:38:30 -07002090
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002091 /* copy to local struct to avoid numerous changes to legacy code */
2092 priv_data = *ppriv_data;
Jeff Johnson295189b2012-06-20 16:38:30 -07002093
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002094 if (priv_data.total_len <= 0 ||
2095 priv_data.total_len > WLAN_PRIV_DATA_MAX_LEN)
Sameer Thalappil8ef3a0e2013-04-05 14:36:04 -07002096 {
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002097 hddLog(VOS_TRACE_LEVEL_WARN,
2098 "%s:invalid priv_data.total_len(%d)!!!", __func__,
2099 priv_data.total_len);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07002100 ret = -EINVAL;
2101 goto exit;
2102 }
2103
2104 /* Allocate +1 for '\0' */
2105 command = kmalloc(priv_data.total_len + 1, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07002106 if (!command)
2107 {
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002108 hddLog(VOS_TRACE_LEVEL_ERROR,
2109 "%s: failed to allocate memory", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002110 ret = -ENOMEM;
2111 goto exit;
2112 }
2113
2114 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
2115 {
2116 ret = -EFAULT;
2117 goto exit;
2118 }
2119
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002120 /* Make sure the command is NUL-terminated */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07002121 command[priv_data.total_len] = '\0';
2122
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002123 /* at one time the following block of code was conditional. braces
2124 * have been retained to avoid re-indenting the legacy code
2125 */
Jeff Johnson295189b2012-06-20 16:38:30 -07002126 {
2127 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2128
2129 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07002130 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -07002131
2132 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
2133 {
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302134 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2135 TRACE_CODE_HDD_P2P_DEV_ADDR_IOCTL,
2136 pAdapter->sessionId, (unsigned)
2137 (*(pHddCtx->p2pDeviceAddress.bytes+2)<<24 |
2138 *(pHddCtx->p2pDeviceAddress.bytes+3)<<16 |
2139 *(pHddCtx->p2pDeviceAddress.bytes+4)<<8 |
2140 *(pHddCtx->p2pDeviceAddress.bytes+5))));
Jeff Johnson295189b2012-06-20 16:38:30 -07002141 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
2142 sizeof(tSirMacAddr)))
2143 {
2144 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Arif Hussain6d2a3322013-11-17 19:50:10 -08002145 "%s: failed to copy data to user buffer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002146 ret = -EFAULT;
2147 }
2148 }
Amar Singhal0974e402013-02-12 14:27:46 -08002149 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07002150 {
Amar Singhal0974e402013-02-12 14:27:46 -08002151 tANI_U8 *ptr = command ;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002152
Jeff Johnson295189b2012-06-20 16:38:30 -07002153 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -08002154
2155 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -07002156 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07002157 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -08002158 "%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 -07002159 /* Change band request received */
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002160 ret = hdd_setBand_helper(pAdapter->dev, ptr);
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302161 if(ret != 0)
2162 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002163 "%s: failed to set band ret=%d", __func__, ret);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002164 }
Kiet Lamf040f472013-11-20 21:15:23 +05302165 else if(strncmp(command, "SETWMMPS", 8) == 0)
2166 {
2167 tANI_U8 *ptr = command;
2168 ret = hdd_wmmps_helper(pAdapter, ptr);
2169 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07002170 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
2171 {
2172 char *country_code;
2173
2174 country_code = command + 8;
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07002175
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002176 INIT_COMPLETION(pAdapter->change_country_code);
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07002177 hdd_checkandupdate_dfssetting(pAdapter, country_code);
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -07002178#ifndef CONFIG_ENABLE_LINUX_REG
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +05302179 hdd_checkandupdate_phymode(pAdapter, country_code);
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -07002180#endif
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002181 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal,
2182 (void *)(tSmeChangeCountryCallback)
2183 wlan_hdd_change_country_code_callback,
Abhishek Singha306a442013-11-07 18:39:01 +05302184 country_code, pAdapter, pHddCtx->pvosContext, eSIR_TRUE, eSIR_TRUE);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002185 if (eHAL_STATUS_SUCCESS == ret)
2186 {
2187 ret = wait_for_completion_interruptible_timeout(
2188 &pAdapter->change_country_code,
2189 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
2190 if (0 >= ret)
2191 {
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002192 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: SME while setting country code timed out %d",
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302193 __func__, ret);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002194 }
2195 }
2196 else
Jeff Johnson32d95a32012-09-10 13:15:23 -07002197 {
2198 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002199 "%s: SME Change Country code fail ret=%d", __func__, ret);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002200 ret = -EINVAL;
Jeff Johnson32d95a32012-09-10 13:15:23 -07002201 }
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002202
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07002203 }
2204 /*
2205 command should be a string having format
2206 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
2207 */
Amar Singhal0974e402013-02-12 14:27:46 -08002208 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07002209 {
Amar Singhal0974e402013-02-12 14:27:46 -08002210 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07002211
2212 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002213 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07002214
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -08002215 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -07002216 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -08002217 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
2218 {
2219 int suspend = 0;
2220 tANI_U8 *ptr = (tANI_U8*)command + 15;
2221
2222 suspend = *ptr - '0';
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302223 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2224 TRACE_CODE_HDD_SETSUSPENDMODE_IOCTL,
2225 pAdapter->sessionId, suspend));
Sameer Thalappil45931fb2013-02-01 11:18:05 -08002226 hdd_set_wlan_suspend_mode(suspend);
2227 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002228#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
2229 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
2230 {
2231 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002232 tANI_S8 rssi = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002233 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
2234 eHalStatus status = eHAL_STATUS_SUCCESS;
2235
2236 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
2237 value = value + 15;
2238
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002239 /* Convert the value from ascii to integer */
2240 ret = kstrtos8(value, 10, &rssi);
2241 if (ret < 0)
2242 {
2243 /* If the input value is greater than max value of datatype, then also
2244 kstrtou8 fails */
2245 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2246 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdafa7157d2013-10-31 10:14:22 -07002247 __func__,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002248 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
2249 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
2250 ret = -EINVAL;
2251 goto exit;
2252 }
2253
Srinivas Girigowdade697412013-02-14 16:31:48 -08002254 lookUpThreshold = abs(rssi);
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002255
Srinivas Girigowdade697412013-02-14 16:31:48 -08002256 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
2257 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
2258 {
2259 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2260 "Neighbor lookup threshold value %d is out of range"
2261 " (Min: %d Max: %d)", lookUpThreshold,
2262 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
2263 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
2264 ret = -EINVAL;
2265 goto exit;
2266 }
2267
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302268 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2269 TRACE_CODE_HDD_SETROAMTRIGGER_IOCTL,
2270 pAdapter->sessionId, lookUpThreshold));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002271 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2272 "%s: Received Command to Set Roam trigger"
2273 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
2274
2275 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
2276 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
2277 if (eHAL_STATUS_SUCCESS != status)
2278 {
2279 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2280 "%s: Failed to set roam trigger, try again", __func__);
2281 ret = -EPERM;
2282 goto exit;
2283 }
2284
2285 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
mukul sharmad6e1fdd2014-06-23 19:19:09 +05302286 pHddCtx->cfg_ini->nNeighborReassocRssiThreshold = lookUpThreshold + 5;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002287 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
2288 }
2289 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
2290 {
2291 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
2292 int rssi = (-1) * lookUpThreshold;
2293 char extra[32];
2294 tANI_U8 len = 0;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302295 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2296 TRACE_CODE_HDD_GETROAMTRIGGER_IOCTL,
2297 pAdapter->sessionId, lookUpThreshold));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002298 len = scnprintf(extra, sizeof(extra), "%s %d", command, rssi);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002299 if (copy_to_user(priv_data.buf, &extra, len + 1))
2300 {
2301 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2302 "%s: failed to copy data to user buffer", __func__);
2303 ret = -EFAULT;
2304 goto exit;
2305 }
2306 }
2307 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
2308 {
2309 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002310 tANI_U8 roamScanPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002311 tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002312
Srinivas Girigowdade697412013-02-14 16:31:48 -08002313 /* input refresh period is in terms of seconds */
2314 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
2315 value = value + 18;
2316 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002317 ret = kstrtou8(value, 10, &roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002318 if (ret < 0)
2319 {
2320 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002321 kstrtou8 fails */
Srinivas Girigowdade697412013-02-14 16:31:48 -08002322 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002323 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdade697412013-02-14 16:31:48 -08002324 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07002325 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
2326 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002327 ret = -EINVAL;
2328 goto exit;
2329 }
2330
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002331 if ((roamScanPeriod < (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000)) ||
2332 (roamScanPeriod > (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000)))
Srinivas Girigowdade697412013-02-14 16:31:48 -08002333 {
2334 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002335 "Roam scan period value %d is out of range"
2336 " (Min: %d Max: %d)", roamScanPeriod,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07002337 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
2338 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002339 ret = -EINVAL;
2340 goto exit;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302341 }
2342 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2343 TRACE_CODE_HDD_SETROAMSCANPERIOD_IOCTL,
2344 pAdapter->sessionId, roamScanPeriod));
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002345 neighborEmptyScanRefreshPeriod = roamScanPeriod * 1000;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002346
2347 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2348 "%s: Received Command to Set roam scan period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002349 " (Empty Scan refresh period) = %d", __func__, roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002350
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002351 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod;
2352 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002353 }
2354 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
2355 {
2356 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
2357 char extra[32];
2358 tANI_U8 len = 0;
2359
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302360 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2361 TRACE_CODE_HDD_GETROAMSCANPERIOD_IOCTL,
2362 pAdapter->sessionId, nEmptyScanRefreshPeriod));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002363 len = scnprintf(extra, sizeof(extra), "%s %d",
2364 "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002365 /* Returned value is in units of seconds */
2366 if (copy_to_user(priv_data.buf, &extra, len + 1))
2367 {
2368 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2369 "%s: failed to copy data to user buffer", __func__);
2370 ret = -EFAULT;
2371 goto exit;
2372 }
2373 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002374 else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0)
2375 {
2376 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002377 tANI_U8 roamScanRefreshPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002378 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002379
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002380 /* input refresh period is in terms of seconds */
2381 /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */
2382 value = value + 25;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002383
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002384 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002385 ret = kstrtou8(value, 10, &roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002386 if (ret < 0)
2387 {
2388 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002389 kstrtou8 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002390 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002391 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002392 __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002393 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
2394 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
2395 ret = -EINVAL;
2396 goto exit;
2397 }
2398
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002399 if ((roamScanRefreshPeriod < (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000)) ||
2400 (roamScanRefreshPeriod > (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000)))
2401 {
2402 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2403 "Neighbor scan results refresh period value %d is out of range"
2404 " (Min: %d Max: %d)", roamScanRefreshPeriod,
2405 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
2406 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
2407 ret = -EINVAL;
2408 goto exit;
2409 }
2410 neighborScanRefreshPeriod = roamScanRefreshPeriod * 1000;
2411
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002412 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2413 "%s: Received Command to Set roam scan refresh period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002414 " (Scan refresh period) = %d", __func__, roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002415
2416 pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod;
2417 sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
2418 }
2419 else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0)
2420 {
2421 tANI_U16 value = sme_getNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
2422 char extra[32];
2423 tANI_U8 len = 0;
2424
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002425 len = scnprintf(extra, sizeof(extra), "%s %d",
2426 "GETROAMSCANREFRESHPERIOD", (value/1000));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002427 /* Returned value is in units of seconds */
2428 if (copy_to_user(priv_data.buf, &extra, len + 1))
2429 {
2430 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2431 "%s: failed to copy data to user buffer", __func__);
2432 ret = -EFAULT;
2433 goto exit;
2434 }
2435 }
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07002436#ifdef FEATURE_WLAN_LFR
2437 /* SETROAMMODE */
2438 else if (strncmp(command, "SETROAMMODE", SIZE_OF_SETROAMMODE) == 0)
2439 {
2440 tANI_U8 *value = command;
2441 tANI_BOOLEAN roamMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
2442
2443 /* Move pointer to ahead of SETROAMMODE<delimiter> */
2444 value = value + SIZE_OF_SETROAMMODE + 1;
2445
2446 /* Convert the value from ascii to integer */
2447 ret = kstrtou8(value, SIZE_OF_SETROAMMODE, &roamMode);
2448 if (ret < 0)
2449 {
2450 /* If the input value is greater than max value of datatype, then also
2451 kstrtou8 fails */
2452 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2453 "%s: kstrtou8 failed range [%d - %d]", __func__,
2454 CFG_LFR_FEATURE_ENABLED_MIN,
2455 CFG_LFR_FEATURE_ENABLED_MAX);
2456 ret = -EINVAL;
2457 goto exit;
2458 }
2459 if ((roamMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
2460 (roamMode > CFG_LFR_FEATURE_ENABLED_MAX))
2461 {
2462 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2463 "Roam Mode value %d is out of range"
2464 " (Min: %d Max: %d)", roamMode,
2465 CFG_LFR_FEATURE_ENABLED_MIN,
2466 CFG_LFR_FEATURE_ENABLED_MAX);
2467 ret = -EINVAL;
2468 goto exit;
2469 }
2470
2471 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2472 "%s: Received Command to Set Roam Mode = %d", __func__, roamMode);
2473 /*
2474 * Note that
2475 * SETROAMMODE 0 is to enable LFR while
2476 * SETROAMMODE 1 is to disable LFR, but
2477 * NotifyIsFastRoamIniFeatureEnabled 0/1 is to enable/disable.
2478 * So, we have to invert the value to call sme_UpdateIsFastRoamIniFeatureEnabled.
2479 */
2480 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
2481 roamMode = CFG_LFR_FEATURE_ENABLED_MAX; /* Roam enable */
2482 else
2483 roamMode = CFG_LFR_FEATURE_ENABLED_MIN; /* Roam disable */
2484
2485 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = roamMode;
2486 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), roamMode);
2487 }
2488 /* GETROAMMODE */
2489 else if (strncmp(priv_data.buf, "GETROAMMODE", SIZE_OF_GETROAMMODE) == 0)
2490 {
2491 tANI_BOOLEAN roamMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2492 char extra[32];
2493 tANI_U8 len = 0;
2494
2495 /*
2496 * roamMode value shall be inverted because the sementics is different.
2497 */
2498 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
2499 roamMode = CFG_LFR_FEATURE_ENABLED_MAX;
2500 else
2501 roamMode = CFG_LFR_FEATURE_ENABLED_MIN;
2502
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002503 len = scnprintf(extra, sizeof(extra), "%s %d", command, roamMode);
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07002504 if (copy_to_user(priv_data.buf, &extra, len + 1))
2505 {
2506 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2507 "%s: failed to copy data to user buffer", __func__);
2508 ret = -EFAULT;
2509 goto exit;
2510 }
2511 }
2512#endif
Srinivas Girigowdade697412013-02-14 16:31:48 -08002513#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002514#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -08002515 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
2516 {
2517 tANI_U8 *value = command;
2518 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
2519
2520 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
2521 value = value + 13;
2522 /* Convert the value from ascii to integer */
2523 ret = kstrtou8(value, 10, &roamRssiDiff);
2524 if (ret < 0)
2525 {
2526 /* If the input value is greater than max value of datatype, then also
2527 kstrtou8 fails */
2528 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2529 "%s: kstrtou8 failed range [%d - %d]", __func__,
2530 CFG_ROAM_RSSI_DIFF_MIN,
2531 CFG_ROAM_RSSI_DIFF_MAX);
2532 ret = -EINVAL;
2533 goto exit;
2534 }
2535
2536 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
2537 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
2538 {
2539 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2540 "Roam rssi diff value %d is out of range"
2541 " (Min: %d Max: %d)", roamRssiDiff,
2542 CFG_ROAM_RSSI_DIFF_MIN,
2543 CFG_ROAM_RSSI_DIFF_MAX);
2544 ret = -EINVAL;
2545 goto exit;
2546 }
2547
2548 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2549 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
2550
2551 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
2552 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
2553 }
2554 else if (strncmp(priv_data.buf, "GETROAMDELTA", 12) == 0)
2555 {
2556 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
2557 char extra[32];
2558 tANI_U8 len = 0;
2559
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302560 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2561 TRACE_CODE_HDD_GETROAMDELTA_IOCTL,
2562 pAdapter->sessionId, roamRssiDiff));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002563 len = scnprintf(extra, sizeof(extra), "%s %d",
2564 command, roamRssiDiff);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002565 if (copy_to_user(priv_data.buf, &extra, len + 1))
2566 {
2567 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2568 "%s: failed to copy data to user buffer", __func__);
2569 ret = -EFAULT;
2570 goto exit;
2571 }
2572 }
2573#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002574#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -08002575 else if (strncmp(command, "GETBAND", 7) == 0)
2576 {
2577 int band = -1;
2578 char extra[32];
2579 tANI_U8 len = 0;
2580 hdd_getBand_helper(pHddCtx, &band);
2581
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302582 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2583 TRACE_CODE_HDD_GETBAND_IOCTL,
2584 pAdapter->sessionId, band));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002585 len = scnprintf(extra, sizeof(extra), "%s %d", command, band);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002586 if (copy_to_user(priv_data.buf, &extra, len + 1))
2587 {
2588 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2589 "%s: failed to copy data to user buffer", __func__);
2590 ret = -EFAULT;
2591 goto exit;
2592 }
2593 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002594 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
2595 {
2596 tANI_U8 *value = command;
2597 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2598 tANI_U8 numChannels = 0;
2599 eHalStatus status = eHAL_STATUS_SUCCESS;
2600
2601 status = hdd_parse_channellist(value, ChannelList, &numChannels);
2602 if (eHAL_STATUS_SUCCESS != status)
2603 {
2604 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2605 "%s: Failed to parse channel list information", __func__);
2606 ret = -EINVAL;
2607 goto exit;
2608 }
2609
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302610 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2611 TRACE_CODE_HDD_SETROAMSCANCHANNELS_IOCTL,
2612 pAdapter->sessionId, numChannels));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002613 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
2614 {
2615 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2616 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
2617 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
2618 ret = -EINVAL;
2619 goto exit;
2620 }
2621 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
2622 numChannels);
2623 if (eHAL_STATUS_SUCCESS != status)
2624 {
2625 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2626 "%s: Failed to update channel list information", __func__);
2627 ret = -EINVAL;
2628 goto exit;
2629 }
2630 }
2631 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
2632 {
2633 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2634 tANI_U8 numChannels = 0;
Jeff Johnson51b67782013-04-05 12:35:41 -07002635 tANI_U8 j = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002636 char extra[128] = {0};
Jeff Johnson51b67782013-04-05 12:35:41 -07002637 int len;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002638
2639 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
2640 ChannelList, &numChannels ))
2641 {
2642 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2643 "%s: failed to get roam scan channel list", __func__);
2644 ret = -EFAULT;
2645 goto exit;
2646 }
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302647 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2648 TRACE_CODE_HDD_GETROAMSCANCHANNELS_IOCTL,
2649 pAdapter->sessionId, numChannels));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002650 /* output channel list is of the format
2651 [Number of roam scan channels][Channel1][Channel2]... */
2652 /* copy the number of channels in the 0th index */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002653 len = scnprintf(extra, sizeof(extra), "%s %d", command, numChannels);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002654 for (j = 0; (j < numChannels); j++)
2655 {
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002656 len += scnprintf(extra + len, sizeof(extra) - len, " %d",
2657 ChannelList[j]);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002658 }
2659
2660 if (copy_to_user(priv_data.buf, &extra, len + 1))
2661 {
2662 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2663 "%s: failed to copy data to user buffer", __func__);
2664 ret = -EFAULT;
2665 goto exit;
2666 }
2667 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002668 else if (strncmp(command, "GETCCXMODE", 10) == 0)
2669 {
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002670 tANI_BOOLEAN eseMode = sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002671 char extra[32];
2672 tANI_U8 len = 0;
2673
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002674 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002675 then this operation is not permitted (return FAILURE) */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002676 if (eseMode &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002677 hdd_is_okc_mode_enabled(pHddCtx) &&
2678 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2679 {
2680 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002681 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002682 " hence this operation is not permitted!", __func__);
2683 ret = -EPERM;
2684 goto exit;
2685 }
2686
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002687 len = scnprintf(extra, sizeof(extra), "%s %d",
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002688 "GETCCXMODE", eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002689 if (copy_to_user(priv_data.buf, &extra, len + 1))
2690 {
2691 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2692 "%s: failed to copy data to user buffer", __func__);
2693 ret = -EFAULT;
2694 goto exit;
2695 }
2696 }
2697 else if (strncmp(command, "GETOKCMODE", 10) == 0)
2698 {
2699 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
2700 char extra[32];
2701 tANI_U8 len = 0;
2702
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002703 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002704 then this operation is not permitted (return FAILURE) */
2705 if (okcMode &&
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002706 sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002707 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2708 {
2709 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002710 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002711 " hence this operation is not permitted!", __func__);
2712 ret = -EPERM;
2713 goto exit;
2714 }
2715
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002716 len = scnprintf(extra, sizeof(extra), "%s %d",
2717 "GETOKCMODE", okcMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002718 if (copy_to_user(priv_data.buf, &extra, len + 1))
2719 {
2720 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2721 "%s: failed to copy data to user buffer", __func__);
2722 ret = -EFAULT;
2723 goto exit;
2724 }
2725 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002726 else if (strncmp(command, "GETFASTROAM", 11) == 0)
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002727 {
2728 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2729 char extra[32];
2730 tANI_U8 len = 0;
2731
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002732 len = scnprintf(extra, sizeof(extra), "%s %d",
2733 "GETFASTROAM", lfrMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002734 if (copy_to_user(priv_data.buf, &extra, len + 1))
2735 {
2736 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2737 "%s: failed to copy data to user buffer", __func__);
2738 ret = -EFAULT;
2739 goto exit;
2740 }
2741 }
2742 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
2743 {
2744 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2745 char extra[32];
2746 tANI_U8 len = 0;
2747
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002748 len = scnprintf(extra, sizeof(extra), "%s %d",
2749 "GETFASTTRANSITION", ft);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002750 if (copy_to_user(priv_data.buf, &extra, len + 1))
2751 {
2752 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2753 "%s: failed to copy data to user buffer", __func__);
2754 ret = -EFAULT;
2755 goto exit;
2756 }
2757 }
2758 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
2759 {
2760 tANI_U8 *value = command;
2761 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
2762
2763 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
2764 value = value + 26;
2765 /* Convert the value from ascii to integer */
2766 ret = kstrtou8(value, 10, &minTime);
2767 if (ret < 0)
2768 {
2769 /* If the input value is greater than max value of datatype, then also
2770 kstrtou8 fails */
2771 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2772 "%s: kstrtou8 failed range [%d - %d]", __func__,
2773 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
2774 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
2775 ret = -EINVAL;
2776 goto exit;
2777 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002778 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
2779 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
2780 {
2781 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2782 "scan min channel time value %d is out of range"
2783 " (Min: %d Max: %d)", minTime,
2784 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
2785 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
2786 ret = -EINVAL;
2787 goto exit;
2788 }
2789
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302790 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2791 TRACE_CODE_HDD_SETROAMSCANCHANNELMINTIME_IOCTL,
2792 pAdapter->sessionId, minTime));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002793 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2794 "%s: Received Command to change channel min time = %d", __func__, minTime);
2795
2796 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
2797 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
2798 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002799 else if (strncmp(command, "SENDACTIONFRAME", 15) == 0)
2800 {
2801 tANI_U8 *value = command;
2802 tANI_U8 channel = 0;
2803 tANI_U8 dwellTime = 0;
2804 tANI_U8 bufLen = 0;
2805 tANI_U8 *buf = NULL;
2806 tSirMacAddr targetApBssid;
2807 eHalStatus status = eHAL_STATUS_SUCCESS;
2808 struct ieee80211_channel chan;
2809 tANI_U8 finalLen = 0;
2810 tANI_U8 *finalBuf = NULL;
2811 tANI_U8 temp = 0;
2812 u64 cookie;
2813 hdd_station_ctx_t *pHddStaCtx = NULL;
2814 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2815
2816 /* if not associated, no need to send action frame */
2817 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2818 {
2819 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2820 ret = -EINVAL;
2821 goto exit;
2822 }
2823
2824 status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel,
2825 &dwellTime, &buf, &bufLen);
2826 if (eHAL_STATUS_SUCCESS != status)
2827 {
2828 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2829 "%s: Failed to parse send action frame data", __func__);
2830 ret = -EINVAL;
2831 goto exit;
2832 }
2833
2834 /* if the target bssid is different from currently associated AP,
2835 then no need to send action frame */
2836 if (VOS_TRUE != vos_mem_compare(targetApBssid,
2837 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2838 {
2839 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__);
2840 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002841 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002842 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002843 goto exit;
2844 }
2845
2846 /* if the channel number is different from operating channel then
2847 no need to send action frame */
2848 if (channel != pHddStaCtx->conn_info.operationChannel)
2849 {
2850 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2851 "%s: channel(%d) is different from operating channel(%d)",
2852 __func__, channel, pHddStaCtx->conn_info.operationChannel);
2853 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002854 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002855 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002856 goto exit;
2857 }
2858 chan.center_freq = sme_ChnToFreq(channel);
2859
2860 finalLen = bufLen + 24;
2861 finalBuf = vos_mem_malloc(finalLen);
2862 if (NULL == finalBuf)
2863 {
2864 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__);
2865 ret = -ENOMEM;
Jeff Johnson11c33152013-04-16 17:52:40 -07002866 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002867 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002868 goto exit;
2869 }
2870 vos_mem_zero(finalBuf, finalLen);
2871
2872 /* Fill subtype */
2873 temp = SIR_MAC_MGMT_ACTION << 4;
2874 vos_mem_copy(finalBuf + 0, &temp, sizeof(temp));
2875
2876 /* Fill type */
2877 temp = SIR_MAC_MGMT_FRAME;
2878 vos_mem_copy(finalBuf + 2, &temp, sizeof(temp));
2879
2880 /* Fill destination address (bssid of the AP) */
2881 vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid));
2882
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07002883 /* Fill source address (STA mac address) */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002884 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
2885
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07002886 /* Fill BSSID (AP mac address) */
2887 vos_mem_copy(finalBuf + 16, targetApBssid, sizeof(targetApBssid));
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002888
2889 /* Fill received buffer from 24th address */
2890 vos_mem_copy(finalBuf + 24, buf, bufLen);
2891
Jeff Johnson11c33152013-04-16 17:52:40 -07002892 /* done with the parsed buffer */
2893 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002894 buf = NULL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002895
DARAM SUDHA39eede62014-02-12 11:16:40 +05302896 wlan_hdd_mgmt_tx( NULL,
Yue Maf49ba872013-08-19 12:04:25 -07002897#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2898 &(pAdapter->wdev),
2899#else
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002900 pAdapter->dev,
Yue Maf49ba872013-08-19 12:04:25 -07002901#endif
2902 &chan, 0,
2903#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
2904 NL80211_CHAN_HT20, 1,
2905#endif
2906 dwellTime, finalBuf, finalLen, 1,
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002907 1, &cookie );
2908 vos_mem_free(finalBuf);
2909 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002910 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
2911 {
2912 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
2913 char extra[32];
2914 tANI_U8 len = 0;
2915
2916 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002917 len = scnprintf(extra, sizeof(extra), "%s %d",
2918 "GETROAMSCANCHANNELMINTIME", val);
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302919 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2920 TRACE_CODE_HDD_GETROAMSCANCHANNELMINTIME_IOCTL,
2921 pAdapter->sessionId, val));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002922 if (copy_to_user(priv_data.buf, &extra, len + 1))
2923 {
2924 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2925 "%s: failed to copy data to user buffer", __func__);
2926 ret = -EFAULT;
2927 goto exit;
2928 }
2929 }
2930 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
2931 {
2932 tANI_U8 *value = command;
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002933 tANI_U16 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002934
2935 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
2936 value = value + 19;
2937 /* Convert the value from ascii to integer */
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002938 ret = kstrtou16(value, 10, &maxTime);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002939 if (ret < 0)
2940 {
2941 /* If the input value is greater than max value of datatype, then also
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002942 kstrtou16 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002943 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002944 "%s: kstrtou16 failed range [%d - %d]", __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002945 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
2946 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
2947 ret = -EINVAL;
2948 goto exit;
2949 }
2950
2951 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
2952 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
2953 {
2954 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2955 "lfr mode value %d is out of range"
2956 " (Min: %d Max: %d)", maxTime,
2957 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
2958 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
2959 ret = -EINVAL;
2960 goto exit;
2961 }
2962
2963 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2964 "%s: Received Command to change channel max time = %d", __func__, maxTime);
2965
2966 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
2967 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
2968 }
2969 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
2970 {
2971 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
2972 char extra[32];
2973 tANI_U8 len = 0;
2974
2975 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002976 len = scnprintf(extra, sizeof(extra), "%s %d",
2977 "GETSCANCHANNELTIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002978 if (copy_to_user(priv_data.buf, &extra, len + 1))
2979 {
2980 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2981 "%s: failed to copy data to user buffer", __func__);
2982 ret = -EFAULT;
2983 goto exit;
2984 }
2985 }
2986 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
2987 {
2988 tANI_U8 *value = command;
2989 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
2990
2991 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
2992 value = value + 16;
2993 /* Convert the value from ascii to integer */
2994 ret = kstrtou16(value, 10, &val);
2995 if (ret < 0)
2996 {
2997 /* If the input value is greater than max value of datatype, then also
2998 kstrtou16 fails */
2999 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3000 "%s: kstrtou16 failed range [%d - %d]", __func__,
3001 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
3002 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
3003 ret = -EINVAL;
3004 goto exit;
3005 }
3006
3007 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
3008 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
3009 {
3010 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3011 "scan home time value %d is out of range"
3012 " (Min: %d Max: %d)", val,
3013 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
3014 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
3015 ret = -EINVAL;
3016 goto exit;
3017 }
3018
3019 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3020 "%s: Received Command to change scan home time = %d", __func__, val);
3021
3022 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
3023 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
3024 }
3025 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
3026 {
3027 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
3028 char extra[32];
3029 tANI_U8 len = 0;
3030
3031 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003032 len = scnprintf(extra, sizeof(extra), "%s %d",
3033 "GETSCANHOMETIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003034 if (copy_to_user(priv_data.buf, &extra, len + 1))
3035 {
3036 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3037 "%s: failed to copy data to user buffer", __func__);
3038 ret = -EFAULT;
3039 goto exit;
3040 }
3041 }
3042 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
3043 {
3044 tANI_U8 *value = command;
3045 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
3046
3047 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
3048 value = value + 17;
3049 /* Convert the value from ascii to integer */
3050 ret = kstrtou8(value, 10, &val);
3051 if (ret < 0)
3052 {
3053 /* If the input value is greater than max value of datatype, then also
3054 kstrtou8 fails */
3055 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3056 "%s: kstrtou8 failed range [%d - %d]", __func__,
3057 CFG_ROAM_INTRA_BAND_MIN,
3058 CFG_ROAM_INTRA_BAND_MAX);
3059 ret = -EINVAL;
3060 goto exit;
3061 }
3062
3063 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
3064 (val > CFG_ROAM_INTRA_BAND_MAX))
3065 {
3066 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3067 "intra band mode value %d is out of range"
3068 " (Min: %d Max: %d)", val,
3069 CFG_ROAM_INTRA_BAND_MIN,
3070 CFG_ROAM_INTRA_BAND_MAX);
3071 ret = -EINVAL;
3072 goto exit;
3073 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003074 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3075 "%s: Received Command to change intra band = %d", __func__, val);
3076
3077 pHddCtx->cfg_ini->nRoamIntraBand = val;
3078 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
3079 }
3080 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
3081 {
3082 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
3083 char extra[32];
3084 tANI_U8 len = 0;
3085
3086 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003087 len = scnprintf(extra, sizeof(extra), "%s %d",
3088 "GETROAMINTRABAND", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003089 if (copy_to_user(priv_data.buf, &extra, len + 1))
3090 {
3091 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3092 "%s: failed to copy data to user buffer", __func__);
3093 ret = -EFAULT;
3094 goto exit;
3095 }
3096 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003097 else if (strncmp(command, "SETSCANNPROBES", 14) == 0)
3098 {
3099 tANI_U8 *value = command;
3100 tANI_U8 nProbes = CFG_ROAM_SCAN_N_PROBES_DEFAULT;
3101
3102 /* Move pointer to ahead of SETSCANNPROBES<delimiter> */
3103 value = value + 15;
3104 /* Convert the value from ascii to integer */
3105 ret = kstrtou8(value, 10, &nProbes);
3106 if (ret < 0)
3107 {
3108 /* If the input value is greater than max value of datatype, then also
3109 kstrtou8 fails */
3110 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3111 "%s: kstrtou8 failed range [%d - %d]", __func__,
3112 CFG_ROAM_SCAN_N_PROBES_MIN,
3113 CFG_ROAM_SCAN_N_PROBES_MAX);
3114 ret = -EINVAL;
3115 goto exit;
3116 }
3117
3118 if ((nProbes < CFG_ROAM_SCAN_N_PROBES_MIN) ||
3119 (nProbes > CFG_ROAM_SCAN_N_PROBES_MAX))
3120 {
3121 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3122 "NProbes value %d is out of range"
3123 " (Min: %d Max: %d)", nProbes,
3124 CFG_ROAM_SCAN_N_PROBES_MIN,
3125 CFG_ROAM_SCAN_N_PROBES_MAX);
3126 ret = -EINVAL;
3127 goto exit;
3128 }
3129
3130 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3131 "%s: Received Command to Set nProbes = %d", __func__, nProbes);
3132
3133 pHddCtx->cfg_ini->nProbes = nProbes;
3134 sme_UpdateRoamScanNProbes((tHalHandle)(pHddCtx->hHal), nProbes);
3135 }
3136 else if (strncmp(priv_data.buf, "GETSCANNPROBES", 14) == 0)
3137 {
3138 tANI_U8 val = sme_getRoamScanNProbes((tHalHandle)(pHddCtx->hHal));
3139 char extra[32];
3140 tANI_U8 len = 0;
3141
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003142 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003143 if (copy_to_user(priv_data.buf, &extra, len + 1))
3144 {
3145 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3146 "%s: failed to copy data to user buffer", __func__);
3147 ret = -EFAULT;
3148 goto exit;
3149 }
3150 }
3151 else if (strncmp(command, "SETSCANHOMEAWAYTIME", 19) == 0)
3152 {
3153 tANI_U8 *value = command;
3154 tANI_U16 homeAwayTime = CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT;
3155
3156 /* Move pointer to ahead of SETSCANHOMEAWAYTIME<delimiter> */
3157 /* input value is in units of msec */
3158 value = value + 20;
3159 /* Convert the value from ascii to integer */
3160 ret = kstrtou16(value, 10, &homeAwayTime);
3161 if (ret < 0)
3162 {
3163 /* If the input value is greater than max value of datatype, then also
3164 kstrtou8 fails */
3165 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3166 "%s: kstrtou8 failed range [%d - %d]", __func__,
3167 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
3168 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
3169 ret = -EINVAL;
3170 goto exit;
3171 }
3172
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003173 if ((homeAwayTime < CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN) ||
3174 (homeAwayTime > CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX))
3175 {
3176 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3177 "homeAwayTime value %d is out of range"
3178 " (Min: %d Max: %d)", homeAwayTime,
3179 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
3180 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
3181 ret = -EINVAL;
3182 goto exit;
3183 }
3184
3185 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3186 "%s: Received Command to Set scan away time = %d", __func__, homeAwayTime);
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07003187 if (pHddCtx->cfg_ini->nRoamScanHomeAwayTime != homeAwayTime)
3188 {
3189 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
3190 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_TRUE);
3191 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003192 }
3193 else if (strncmp(priv_data.buf, "GETSCANHOMEAWAYTIME", 19) == 0)
3194 {
3195 tANI_U16 val = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
3196 char extra[32];
3197 tANI_U8 len = 0;
3198
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003199 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003200 if (copy_to_user(priv_data.buf, &extra, len + 1))
3201 {
3202 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3203 "%s: failed to copy data to user buffer", __func__);
3204 ret = -EFAULT;
3205 goto exit;
3206 }
3207 }
3208 else if (strncmp(command, "REASSOC", 7) == 0)
3209 {
3210 tANI_U8 *value = command;
3211 tANI_U8 channel = 0;
3212 tSirMacAddr targetApBssid;
3213 eHalStatus status = eHAL_STATUS_SUCCESS;
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07003214#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
3215 tCsrHandoffRequest handoffInfo;
3216#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003217 hdd_station_ctx_t *pHddStaCtx = NULL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003218 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3219
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003220 /* if not associated, no need to proceed with reassoc */
3221 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3222 {
3223 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
3224 ret = -EINVAL;
3225 goto exit;
3226 }
3227
3228 status = hdd_parse_reassoc_command_data(value, targetApBssid, &channel);
3229 if (eHAL_STATUS_SUCCESS != status)
3230 {
3231 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3232 "%s: Failed to parse reassoc command data", __func__);
3233 ret = -EINVAL;
3234 goto exit;
3235 }
3236
3237 /* if the target bssid is same as currently associated AP,
3238 then no need to proceed with reassoc */
3239 if (VOS_TRUE == vos_mem_compare(targetApBssid,
3240 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
3241 {
3242 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Reassoc BSSID is same as currently associated AP bssid",__func__);
3243 ret = -EINVAL;
3244 goto exit;
3245 }
3246
3247 /* Check channel number is a valid channel number */
3248 if(VOS_STATUS_SUCCESS !=
3249 wlan_hdd_validate_operation_channel(pAdapter, channel))
3250 {
3251 hddLog(VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08003252 "%s: Invalid Channel [%d]", __func__, channel);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003253 return -EINVAL;
3254 }
3255
3256 /* Proceed with reassoc */
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07003257#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
3258 handoffInfo.channel = channel;
3259 vos_mem_copy(handoffInfo.bssid, targetApBssid, sizeof(tSirMacAddr));
3260 sme_HandoffRequest(pHddCtx->hHal, &handoffInfo);
3261#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003262 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07003263 else if (strncmp(command, "SETWESMODE", 10) == 0)
3264 {
3265 tANI_U8 *value = command;
3266 tANI_BOOLEAN wesMode = CFG_ENABLE_WES_MODE_NAME_DEFAULT;
3267
3268 /* Move pointer to ahead of SETWESMODE<delimiter> */
3269 value = value + 11;
3270 /* Convert the value from ascii to integer */
3271 ret = kstrtou8(value, 10, &wesMode);
3272 if (ret < 0)
3273 {
3274 /* If the input value is greater than max value of datatype, then also
3275 kstrtou8 fails */
3276 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3277 "%s: kstrtou8 failed range [%d - %d]", __func__,
3278 CFG_ENABLE_WES_MODE_NAME_MIN,
3279 CFG_ENABLE_WES_MODE_NAME_MAX);
3280 ret = -EINVAL;
3281 goto exit;
3282 }
3283
3284 if ((wesMode < CFG_ENABLE_WES_MODE_NAME_MIN) ||
3285 (wesMode > CFG_ENABLE_WES_MODE_NAME_MAX))
3286 {
3287 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3288 "WES Mode value %d is out of range"
3289 " (Min: %d Max: %d)", wesMode,
3290 CFG_ENABLE_WES_MODE_NAME_MIN,
3291 CFG_ENABLE_WES_MODE_NAME_MAX);
3292 ret = -EINVAL;
3293 goto exit;
3294 }
3295 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3296 "%s: Received Command to Set WES Mode rssi diff = %d", __func__, wesMode);
3297
3298 pHddCtx->cfg_ini->isWESModeEnabled = wesMode;
3299 sme_UpdateWESMode((tHalHandle)(pHddCtx->hHal), wesMode);
3300 }
3301 else if (strncmp(priv_data.buf, "GETWESMODE", 10) == 0)
3302 {
3303 tANI_BOOLEAN wesMode = sme_GetWESMode((tHalHandle)(pHddCtx->hHal));
3304 char extra[32];
3305 tANI_U8 len = 0;
3306
Arif Hussain826d9412013-11-12 16:44:54 -08003307 len = scnprintf(extra, sizeof(extra), "%s %d", command, wesMode);
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07003308 if (copy_to_user(priv_data.buf, &extra, len + 1))
3309 {
3310 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3311 "%s: failed to copy data to user buffer", __func__);
3312 ret = -EFAULT;
3313 goto exit;
3314 }
3315 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003316#endif /* WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_ESE || FEATURE_WLAN_LFR */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003317#ifdef FEATURE_WLAN_LFR
3318 else if (strncmp(command, "SETFASTROAM", 11) == 0)
3319 {
3320 tANI_U8 *value = command;
3321 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
3322
3323 /* Move pointer to ahead of SETFASTROAM<delimiter> */
3324 value = value + 12;
3325 /* Convert the value from ascii to integer */
3326 ret = kstrtou8(value, 10, &lfrMode);
3327 if (ret < 0)
3328 {
3329 /* If the input value is greater than max value of datatype, then also
3330 kstrtou8 fails */
3331 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3332 "%s: kstrtou8 failed range [%d - %d]", __func__,
3333 CFG_LFR_FEATURE_ENABLED_MIN,
3334 CFG_LFR_FEATURE_ENABLED_MAX);
3335 ret = -EINVAL;
3336 goto exit;
3337 }
3338
3339 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
3340 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
3341 {
3342 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3343 "lfr mode value %d is out of range"
3344 " (Min: %d Max: %d)", lfrMode,
3345 CFG_LFR_FEATURE_ENABLED_MIN,
3346 CFG_LFR_FEATURE_ENABLED_MAX);
3347 ret = -EINVAL;
3348 goto exit;
3349 }
3350
3351 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3352 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
3353
3354 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
3355 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
3356 }
3357#endif
3358#ifdef WLAN_FEATURE_VOWIFI_11R
3359 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
3360 {
3361 tANI_U8 *value = command;
3362 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
3363
3364 /* Move pointer to ahead of SETFASTROAM<delimiter> */
3365 value = value + 18;
3366 /* Convert the value from ascii to integer */
3367 ret = kstrtou8(value, 10, &ft);
3368 if (ret < 0)
3369 {
3370 /* If the input value is greater than max value of datatype, then also
3371 kstrtou8 fails */
3372 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3373 "%s: kstrtou8 failed range [%d - %d]", __func__,
3374 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
3375 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
3376 ret = -EINVAL;
3377 goto exit;
3378 }
3379
3380 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
3381 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
3382 {
3383 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3384 "ft mode value %d is out of range"
3385 " (Min: %d Max: %d)", ft,
3386 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
3387 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
3388 ret = -EINVAL;
3389 goto exit;
3390 }
3391
3392 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3393 "%s: Received Command to change ft mode = %d", __func__, ft);
3394
3395 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
3396 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
3397 }
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05303398
3399 else if (strncmp(command, "FASTREASSOC", 11) == 0)
3400 {
3401 tANI_U8 *value = command;
3402 tSirMacAddr targetApBssid;
3403 tANI_U8 trigger = 0;
3404 eHalStatus status = eHAL_STATUS_SUCCESS;
3405 hdd_station_ctx_t *pHddStaCtx = NULL;
3406 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3407
3408 /* if not associated, no need to proceed with reassoc */
3409 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3410 {
3411 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
3412 ret = -EINVAL;
3413 goto exit;
3414 }
3415
3416 status = hdd_parse_reassoc_command_data(value, targetApBssid, &trigger);
3417 if (eHAL_STATUS_SUCCESS != status)
3418 {
3419 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3420 "%s: Failed to parse reassoc command data", __func__);
3421 ret = -EINVAL;
3422 goto exit;
3423 }
3424
3425 /* if the target bssid is same as currently associated AP,
3426 then no need to proceed with reassoc */
3427 if (VOS_TRUE == vos_mem_compare(targetApBssid,
3428 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
3429 {
3430 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3431 "%s:11r Reassoc BSSID is same as currently associated AP bssid",
3432 __func__);
3433 ret = -EINVAL;
3434 goto exit;
3435 }
3436
3437 /* Proceed with scan/roam */
3438 smeIssueFastRoamNeighborAPEvent(WLAN_HDD_GET_HAL_CTX(pAdapter),
3439 &targetApBssid[0],
3440 (tSmeFastRoamTrigger)(trigger));
3441 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003442#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003443#ifdef FEATURE_WLAN_ESE
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003444 else if (strncmp(command, "SETCCXMODE", 10) == 0)
3445 {
3446 tANI_U8 *value = command;
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003447 tANI_U8 eseMode = CFG_ESE_FEATURE_ENABLED_DEFAULT;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003448
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003449 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003450 then this operation is not permitted (return FAILURE) */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003451 if (sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003452 hdd_is_okc_mode_enabled(pHddCtx) &&
3453 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
3454 {
3455 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003456 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003457 " hence this operation is not permitted!", __func__);
3458 ret = -EPERM;
3459 goto exit;
3460 }
3461
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003462 /* Move pointer to ahead of SETCCXMODE<delimiter> */
3463 value = value + 11;
3464 /* Convert the value from ascii to integer */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003465 ret = kstrtou8(value, 10, &eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003466 if (ret < 0)
3467 {
3468 /* If the input value is greater than max value of datatype, then also
3469 kstrtou8 fails */
3470 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3471 "%s: kstrtou8 failed range [%d - %d]", __func__,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003472 CFG_ESE_FEATURE_ENABLED_MIN,
3473 CFG_ESE_FEATURE_ENABLED_MAX);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003474 ret = -EINVAL;
3475 goto exit;
3476 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003477 if ((eseMode < CFG_ESE_FEATURE_ENABLED_MIN) ||
3478 (eseMode > CFG_ESE_FEATURE_ENABLED_MAX))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003479 {
3480 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003481 "Ese mode value %d is out of range"
3482 " (Min: %d Max: %d)", eseMode,
3483 CFG_ESE_FEATURE_ENABLED_MIN,
3484 CFG_ESE_FEATURE_ENABLED_MAX);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003485 ret = -EINVAL;
3486 goto exit;
3487 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003488 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003489 "%s: Received Command to change ese mode = %d", __func__, eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003490
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003491 pHddCtx->cfg_ini->isEseIniFeatureEnabled = eseMode;
3492 sme_UpdateIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal), eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003493 }
3494#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003495 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
3496 {
3497 tANI_U8 *value = command;
3498 tANI_BOOLEAN roamScanControl = 0;
3499
3500 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
3501 value = value + 19;
3502 /* Convert the value from ascii to integer */
3503 ret = kstrtou8(value, 10, &roamScanControl);
3504 if (ret < 0)
3505 {
3506 /* If the input value is greater than max value of datatype, then also
3507 kstrtou8 fails */
3508 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3509 "%s: kstrtou8 failed ", __func__);
3510 ret = -EINVAL;
3511 goto exit;
3512 }
3513
3514 if (0 != roamScanControl)
3515 {
3516 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3517 "roam scan control invalid value = %d",
3518 roamScanControl);
3519 ret = -EINVAL;
3520 goto exit;
3521 }
3522 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3523 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
3524
3525 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
3526 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003527#ifdef FEATURE_WLAN_OKC
3528 else if (strncmp(command, "SETOKCMODE", 10) == 0)
3529 {
3530 tANI_U8 *value = command;
3531 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
3532
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003533 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003534 then this operation is not permitted (return FAILURE) */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003535 if (sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003536 hdd_is_okc_mode_enabled(pHddCtx) &&
3537 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
3538 {
3539 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003540 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003541 " hence this operation is not permitted!", __func__);
3542 ret = -EPERM;
3543 goto exit;
3544 }
3545
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003546 /* Move pointer to ahead of SETOKCMODE<delimiter> */
3547 value = value + 11;
3548 /* Convert the value from ascii to integer */
3549 ret = kstrtou8(value, 10, &okcMode);
3550 if (ret < 0)
3551 {
3552 /* If the input value is greater than max value of datatype, then also
3553 kstrtou8 fails */
3554 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3555 "%s: kstrtou8 failed range [%d - %d]", __func__,
3556 CFG_OKC_FEATURE_ENABLED_MIN,
3557 CFG_OKC_FEATURE_ENABLED_MAX);
3558 ret = -EINVAL;
3559 goto exit;
3560 }
3561
3562 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
3563 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
3564 {
3565 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3566 "Okc mode value %d is out of range"
3567 " (Min: %d Max: %d)", okcMode,
3568 CFG_OKC_FEATURE_ENABLED_MIN,
3569 CFG_OKC_FEATURE_ENABLED_MAX);
3570 ret = -EINVAL;
3571 goto exit;
3572 }
3573
3574 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3575 "%s: Received Command to change okc mode = %d", __func__, okcMode);
3576
3577 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
3578 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07003579#endif /* FEATURE_WLAN_OKC */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003580 else if (strncmp(priv_data.buf, "GETROAMSCANCONTROL", 18) == 0)
3581 {
3582 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
3583 char extra[32];
3584 tANI_U8 len = 0;
3585
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003586 len = scnprintf(extra, sizeof(extra), "%s %d",
3587 command, roamScanControl);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003588 if (copy_to_user(priv_data.buf, &extra, len + 1))
3589 {
3590 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3591 "%s: failed to copy data to user buffer", __func__);
3592 ret = -EFAULT;
3593 goto exit;
3594 }
3595 }
Gopichand Nakkala227c7f32013-06-26 22:44:57 +05303596#ifdef WLAN_FEATURE_PACKET_FILTERING
3597 else if (strncmp(command, "ENABLE_PKTFILTER_IPV6", 21) == 0)
3598 {
3599 tANI_U8 filterType = 0;
3600 tANI_U8 *value = command;
3601
3602 /* Move pointer to ahead of ENABLE_PKTFILTER_IPV6<delimiter> */
3603 value = value + 22;
3604
3605 /* Convert the value from ascii to integer */
3606 ret = kstrtou8(value, 10, &filterType);
3607 if (ret < 0)
3608 {
3609 /* If the input value is greater than max value of datatype,
3610 * then also kstrtou8 fails
3611 */
3612 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3613 "%s: kstrtou8 failed range ", __func__);
3614 ret = -EINVAL;
3615 goto exit;
3616 }
3617
3618 if (filterType != 0 && filterType != 1)
3619 {
3620 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3621 "%s: Accepted Values are 0 and 1 ", __func__);
3622 ret = -EINVAL;
3623 goto exit;
3624 }
3625 wlan_hdd_setIPv6Filter(WLAN_HDD_GET_CTX(pAdapter), filterType,
3626 pAdapter->sessionId);
3627 }
3628#endif
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303629 else if (strncmp(command, "BTCOEXMODE", 10) == 0 )
3630 {
Kiet Lam94fd2922014-06-18 19:12:43 -07003631 char *bcMode;
3632 bcMode = command + 11;
3633 if ('1' == *bcMode)
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303634 {
c_hpothu9b781ba2013-12-30 20:57:45 +05303635 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Kiet Lam94fd2922014-06-18 19:12:43 -07003636 FL("BTCOEXMODE %d"), *bcMode);
c_hpothu9b781ba2013-12-30 20:57:45 +05303637
3638 pHddCtx->btCoexModeSet = TRUE;
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303639 }
Kiet Lam94fd2922014-06-18 19:12:43 -07003640 else if ('2' == *bcMode)
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303641 {
c_hpothu9b781ba2013-12-30 20:57:45 +05303642 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Kiet Lam94fd2922014-06-18 19:12:43 -07003643 FL("BTCOEXMODE %d"), *bcMode);
c_hpothu9b781ba2013-12-30 20:57:45 +05303644
3645 pHddCtx->btCoexModeSet = FALSE;
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303646 }
3647 }
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07003648 else if (strncmp(command, "SCAN-ACTIVE", 11) == 0)
3649 {
c_hpothudbefd3e2014-04-28 15:59:47 +05303650 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3651 FL("making default scan to ACTIVE"));
3652 pHddCtx->scan_info.scan_mode = eSIR_ACTIVE_SCAN;
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07003653 }
3654 else if (strncmp(command, "SCAN-PASSIVE", 12) == 0)
3655 {
c_hpothudbefd3e2014-04-28 15:59:47 +05303656 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3657 FL("making default scan to PASSIVE"));
3658 pHddCtx->scan_info.scan_mode = eSIR_PASSIVE_SCAN;
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07003659 }
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303660 else if (strncmp(command, "GETDWELLTIME", 12) == 0)
3661 {
3662 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3663 char extra[32];
3664 tANI_U8 len = 0;
3665
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05303666 memset(extra, 0, sizeof(extra));
3667 ret = hdd_get_dwell_time(pCfg, command, extra, sizeof(extra), &len);
3668 if (ret != 0 || copy_to_user(priv_data.buf, &extra, len + 1))
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303669 {
3670 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3671 "%s: failed to copy data to user buffer", __func__);
3672 ret = -EFAULT;
3673 goto exit;
3674 }
3675 ret = len;
3676 }
3677 else if (strncmp(command, "SETDWELLTIME", 12) == 0)
3678 {
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05303679 ret = hdd_set_dwell_time(pAdapter, command);
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303680 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07003681 else if ( strncasecmp(command, "MIRACAST", 8) == 0 )
3682 {
3683 tANI_U8 filterType = 0;
3684 tANI_U8 *value;
3685 value = command + 9;
3686
3687 /* Convert the value from ascii to integer */
3688 ret = kstrtou8(value, 10, &filterType);
3689 if (ret < 0)
3690 {
3691 /* If the input value is greater than max value of datatype,
3692 * then also kstrtou8 fails
3693 */
3694 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3695 "%s: kstrtou8 failed range ", __func__);
3696 ret = -EINVAL;
3697 goto exit;
3698 }
3699 if ((filterType < WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL ) ||
3700 (filterType > WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL))
3701 {
3702 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3703 "%s: Accepted Values are 0 to 2. 0-Disabled, 1-Source,"
3704 " 2-Sink ", __func__);
3705 ret = -EINVAL;
3706 goto exit;
3707 }
3708 //Filtertype value should be either 0-Disabled, 1-Source, 2-sink
3709 pHddCtx->drvr_miracast = filterType;
3710 hdd_tx_rx_pkt_cnt_stat_timer_handler(pHddCtx);
3711 }
Leo Chang614d2072013-08-22 14:59:44 -07003712 else if (strncmp(command, "SETMCRATE", 9) == 0)
3713 {
Leo Chang614d2072013-08-22 14:59:44 -07003714 tANI_U8 *value = command;
3715 int targetRate;
Leo Chang1f98cbd2013-10-17 15:03:52 -07003716 tSirRateUpdateInd *rateUpdate;
3717 eHalStatus status;
Leo Chang614d2072013-08-22 14:59:44 -07003718
3719 /* Only valid for SAP mode */
3720 if (WLAN_HDD_SOFTAP != pAdapter->device_mode)
3721 {
3722 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3723 "%s: SAP mode is not running", __func__);
3724 ret = -EFAULT;
3725 goto exit;
3726 }
3727
3728 /* Move pointer to ahead of SETMCRATE<delimiter> */
3729 /* input value is in units of hundred kbps */
3730 value = value + 10;
3731 /* Convert the value from ascii to integer, decimal base */
3732 ret = kstrtouint(value, 10, &targetRate);
3733
Leo Chang1f98cbd2013-10-17 15:03:52 -07003734 rateUpdate = (tSirRateUpdateInd *)vos_mem_malloc(sizeof(tSirRateUpdateInd));
3735 if (NULL == rateUpdate)
Leo Chang614d2072013-08-22 14:59:44 -07003736 {
Leo Chang1f98cbd2013-10-17 15:03:52 -07003737 hddLog(VOS_TRACE_LEVEL_ERROR,
3738 "%s: SETMCRATE indication alloc fail", __func__);
3739 ret = -EFAULT;
3740 goto exit;
3741 }
3742 vos_mem_zero(rateUpdate, sizeof(tSirRateUpdateInd ));
3743
3744 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3745 "MC Target rate %d", targetRate);
3746 /* Ignore unicast */
3747 rateUpdate->ucastDataRate = -1;
3748 rateUpdate->mcastDataRate24GHz = targetRate;
3749 rateUpdate->mcastDataRate5GHz = targetRate;
3750 rateUpdate->mcastDataRate24GHzTxFlag = 0;
3751 rateUpdate->mcastDataRate5GHzTxFlag = 0;
3752 status = sme_SendRateUpdateInd(pHddCtx->hHal, rateUpdate);
3753 if (eHAL_STATUS_SUCCESS != status)
3754 {
3755 hddLog(VOS_TRACE_LEVEL_ERROR,
3756 "%s: SET_MC_RATE failed", __func__);
3757 vos_mem_free(rateUpdate);
3758 ret = -EFAULT;
3759 goto exit;
Leo Chang614d2072013-08-22 14:59:44 -07003760 }
3761 }
Rajeev79dbe4c2013-10-05 11:03:42 +05303762#ifdef FEATURE_WLAN_BATCH_SCAN
Rajeev Kumar8b373292014-01-08 20:36:55 -08003763 else if (strncmp(command, "WLS_BATCHING", 12) == 0)
Rajeev79dbe4c2013-10-05 11:03:42 +05303764 {
Rajeev Kumar8b373292014-01-08 20:36:55 -08003765 ret = hdd_handle_batch_scan_ioctl(pAdapter, &priv_data, command);
Rajeev79dbe4c2013-10-05 11:03:42 +05303766 }
3767#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003768#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003769 else if (strncmp(command, "SETCCXROAMSCANCHANNELS", 22) == 0)
3770 {
3771 tANI_U8 *value = command;
3772 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
3773 tANI_U8 numChannels = 0;
3774 eHalStatus status = eHAL_STATUS_SUCCESS;
3775
3776 status = hdd_parse_channellist(value, ChannelList, &numChannels);
3777 if (eHAL_STATUS_SUCCESS != status)
3778 {
3779 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3780 "%s: Failed to parse channel list information", __func__);
3781 ret = -EINVAL;
3782 goto exit;
3783 }
3784
3785 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
3786 {
3787 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3788 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
3789 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
3790 ret = -EINVAL;
3791 goto exit;
3792 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003793 status = sme_SetEseRoamScanChannelList((tHalHandle)(pHddCtx->hHal),
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003794 ChannelList,
3795 numChannels);
3796 if (eHAL_STATUS_SUCCESS != status)
3797 {
3798 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3799 "%s: Failed to update channel list information", __func__);
3800 ret = -EINVAL;
3801 goto exit;
3802 }
3803 }
3804 else if (strncmp(command, "GETTSMSTATS", 11) == 0)
3805 {
3806 tANI_U8 *value = command;
3807 char extra[128] = {0};
3808 int len = 0;
3809 tANI_U8 tid = 0;
3810 hdd_station_ctx_t *pHddStaCtx = NULL;
3811 tAniTrafStrmMetrics tsmMetrics;
3812 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3813
3814 /* if not associated, return error */
3815 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3816 {
3817 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:Not associated!",__func__);
3818 ret = -EINVAL;
3819 goto exit;
3820 }
3821
3822 /* Move pointer to ahead of GETTSMSTATS<delimiter> */
3823 value = value + 12;
3824 /* Convert the value from ascii to integer */
3825 ret = kstrtou8(value, 10, &tid);
3826 if (ret < 0)
3827 {
3828 /* If the input value is greater than max value of datatype, then also
3829 kstrtou8 fails */
3830 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3831 "%s: kstrtou8 failed range [%d - %d]", __func__,
3832 TID_MIN_VALUE,
3833 TID_MAX_VALUE);
3834 ret = -EINVAL;
3835 goto exit;
3836 }
3837
3838 if ((tid < TID_MIN_VALUE) || (tid > TID_MAX_VALUE))
3839 {
3840 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3841 "tid value %d is out of range"
3842 " (Min: %d Max: %d)", tid,
3843 TID_MIN_VALUE,
3844 TID_MAX_VALUE);
3845 ret = -EINVAL;
3846 goto exit;
3847 }
3848
3849 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3850 "%s: Received Command to get tsm stats tid = %d", __func__, tid);
3851
3852 if (VOS_STATUS_SUCCESS != hdd_get_tsm_stats(pAdapter, tid, &tsmMetrics))
3853 {
3854 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3855 "%s: failed to get tsm stats", __func__);
3856 ret = -EFAULT;
3857 goto exit;
3858 }
3859
3860 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3861 "UplinkPktQueueDly(%d)\n"
3862 "UplinkPktQueueDlyHist[0](%d)\n"
3863 "UplinkPktQueueDlyHist[1](%d)\n"
3864 "UplinkPktQueueDlyHist[2](%d)\n"
3865 "UplinkPktQueueDlyHist[3](%d)\n"
Arun Kumar Khandavallie8768212014-02-17 16:43:34 +05303866 "UplinkPktTxDly(%u)\n"
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003867 "UplinkPktLoss(%d)\n"
3868 "UplinkPktCount(%d)\n"
3869 "RoamingCount(%d)\n"
3870 "RoamingDly(%d)", tsmMetrics.UplinkPktQueueDly,
3871 tsmMetrics.UplinkPktQueueDlyHist[0],
3872 tsmMetrics.UplinkPktQueueDlyHist[1],
3873 tsmMetrics.UplinkPktQueueDlyHist[2],
3874 tsmMetrics.UplinkPktQueueDlyHist[3],
3875 tsmMetrics.UplinkPktTxDly, tsmMetrics.UplinkPktLoss,
3876 tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount, tsmMetrics.RoamingDly);
3877
3878 /* Output TSM stats is of the format
3879 GETTSMSTATS [PktQueueDly] [PktQueueDlyHist[0]]:[PktQueueDlyHist[1]] ...[RoamingDly]
3880 eg., GETTSMSTATS 10 1:0:0:161 20 1 17 8 39800 */
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003881 len = scnprintf(extra, sizeof(extra), "%s %d %d:%d:%d:%d %u %d %d %d %d", command,
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003882 tsmMetrics.UplinkPktQueueDly, tsmMetrics.UplinkPktQueueDlyHist[0],
3883 tsmMetrics.UplinkPktQueueDlyHist[1], tsmMetrics.UplinkPktQueueDlyHist[2],
3884 tsmMetrics.UplinkPktQueueDlyHist[3], tsmMetrics.UplinkPktTxDly,
3885 tsmMetrics.UplinkPktLoss, tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount,
3886 tsmMetrics.RoamingDly);
3887
3888 if (copy_to_user(priv_data.buf, &extra, len + 1))
3889 {
3890 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3891 "%s: failed to copy data to user buffer", __func__);
3892 ret = -EFAULT;
3893 goto exit;
3894 }
3895 }
3896 else if (strncmp(command, "SETCCKMIE", 9) == 0)
3897 {
3898 tANI_U8 *value = command;
3899 tANI_U8 *cckmIe = NULL;
3900 tANI_U8 cckmIeLen = 0;
3901 eHalStatus status = eHAL_STATUS_SUCCESS;
3902
3903 status = hdd_parse_get_cckm_ie(value, &cckmIe, &cckmIeLen);
3904 if (eHAL_STATUS_SUCCESS != status)
3905 {
3906 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3907 "%s: Failed to parse cckm ie data", __func__);
3908 ret = -EINVAL;
3909 goto exit;
3910 }
3911
3912 if (cckmIeLen > DOT11F_IE_RSN_MAX_LEN)
3913 {
3914 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3915 "%s: CCKM Ie input length is more than max[%d]", __func__,
3916 DOT11F_IE_RSN_MAX_LEN);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08003917 vos_mem_free(cckmIe);
3918 cckmIe = NULL;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003919 ret = -EINVAL;
3920 goto exit;
3921 }
3922 sme_SetCCKMIe((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, cckmIe, cckmIeLen);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08003923 vos_mem_free(cckmIe);
3924 cckmIe = NULL;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003925 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003926 else if (strncmp(command, "CCXBEACONREQ", 12) == 0)
3927 {
3928 tANI_U8 *value = command;
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003929 tCsrEseBeaconReq eseBcnReq;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003930 eHalStatus status = eHAL_STATUS_SUCCESS;
Srinivas Girigowda0c6d7fe2014-05-28 18:18:10 -07003931
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003932 status = hdd_parse_ese_beacon_req(value, &eseBcnReq);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003933 if (eHAL_STATUS_SUCCESS != status)
3934 {
3935 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003936 "%s: Failed to parse ese beacon req", __func__);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003937 ret = -EINVAL;
3938 goto exit;
3939 }
Srinivas Girigowda0c6d7fe2014-05-28 18:18:10 -07003940 if (!hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))) {
3941 hddLog(VOS_TRACE_LEVEL_INFO, FL("Not associated"));
3942 hdd_indicateEseBcnReportNoResults (pAdapter,
3943 eseBcnReq.bcnReq[0].measurementToken,
3944 0x02, //BIT(1) set for measurement done
3945 0); // no BSS
3946 goto exit;
3947 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003948
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003949 status = sme_SetEseBeaconRequest((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, &eseBcnReq);
3950 if (eHAL_STATUS_SUCCESS != status)
3951 {
3952 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3953 "%s: sme_SetEseBeaconRequest failed (%d)", __func__, status);
3954 ret = -EINVAL;
3955 goto exit;
3956 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003957 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003958#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
c_hpothu92367912014-05-01 15:18:17 +05303959 else if (strncmp(command, "GETBCNMISSRATE", 14) == 0)
3960 {
3961 eHalStatus status;
3962 char buf[32], len;
3963 long waitRet;
3964 bcnMissRateContext_t getBcnMissRateCtx;
3965
3966 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3967
3968 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3969 {
3970 hddLog(VOS_TRACE_LEVEL_WARN,
3971 FL("GETBCNMISSRATE: STA is not in connected state"));
3972 ret = -1;
3973 goto exit;
3974 }
3975
3976 init_completion(&(getBcnMissRateCtx.completion));
3977 getBcnMissRateCtx.magic = BCN_MISS_RATE_CONTEXT_MAGIC;
3978
3979 status = sme_getBcnMissRate((tHalHandle)(pHddCtx->hHal),
3980 pAdapter->sessionId,
3981 (void *)getBcnMissRateCB,
3982 (void *)(&getBcnMissRateCtx));
3983 if( eHAL_STATUS_SUCCESS != status)
3984 {
3985 hddLog(VOS_TRACE_LEVEL_INFO,
3986 FL("GETBCNMISSRATE: fail to post WDA cmd"));
3987 ret = -EINVAL;
3988 goto exit;
3989 }
3990
3991 waitRet = wait_for_completion_interruptible_timeout
3992 (&getBcnMissRateCtx.completion, BCN_MISS_RATE_TIME);
3993 if(waitRet <= 0)
3994 {
3995 hddLog(VOS_TRACE_LEVEL_ERROR,
3996 FL("failed to wait on bcnMissRateComp %d"), ret);
3997
3998 //Make magic number to zero so that callback is not called.
3999 spin_lock(&hdd_context_lock);
4000 getBcnMissRateCtx.magic = 0x0;
4001 spin_unlock(&hdd_context_lock);
4002 ret = -EINVAL;
4003 goto exit;
4004 }
4005
4006 hddLog(VOS_TRACE_LEVEL_INFO,
4007 FL("GETBCNMISSRATE: bcnMissRate: %d"), gbcnMissRate);
4008
4009 len = snprintf(buf, sizeof(buf), "GETBCNMISSRATE %d", gbcnMissRate);
4010 if (copy_to_user(priv_data.buf, &buf, len + 1))
4011 {
4012 hddLog(VOS_TRACE_LEVEL_ERROR,
4013 "%s: failed to copy data to user buffer", __func__);
4014 ret = -EFAULT;
4015 goto exit;
4016 }
4017 ret = len;
4018 }
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07004019 else {
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05304020 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
4021 TRACE_CODE_HDD_UNSUPPORTED_IOCTL,
4022 pAdapter->sessionId, 0));
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07004023 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
4024 __func__, command);
4025 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004026 }
4027exit:
4028 if (command)
4029 {
4030 kfree(command);
4031 }
4032 return ret;
4033}
4034
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07004035#ifdef CONFIG_COMPAT
4036static int hdd_driver_compat_ioctl(hdd_adapter_t *pAdapter, struct ifreq *ifr)
4037{
4038 struct {
4039 compat_uptr_t buf;
4040 int used_len;
4041 int total_len;
4042 } compat_priv_data;
4043 hdd_priv_data_t priv_data;
4044 int ret = 0;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004045
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07004046 /*
4047 * Note that pAdapter and ifr have already been verified by caller,
4048 * and HDD context has also been validated
4049 */
4050 if (copy_from_user(&compat_priv_data, ifr->ifr_data,
4051 sizeof(compat_priv_data))) {
4052 ret = -EFAULT;
4053 goto exit;
4054 }
4055 priv_data.buf = compat_ptr(compat_priv_data.buf);
4056 priv_data.used_len = compat_priv_data.used_len;
4057 priv_data.total_len = compat_priv_data.total_len;
4058 ret = hdd_driver_command(pAdapter, &priv_data);
4059 exit:
4060 return ret;
4061}
4062#else /* CONFIG_COMPAT */
4063static int hdd_driver_compat_ioctl(hdd_adapter_t *pAdapter, struct ifreq *ifr)
4064{
4065 /* will never be invoked */
4066 return 0;
4067}
4068#endif /* CONFIG_COMPAT */
4069
4070static int hdd_driver_ioctl(hdd_adapter_t *pAdapter, struct ifreq *ifr)
4071{
4072 hdd_priv_data_t priv_data;
4073 int ret = 0;
4074
4075 /*
4076 * Note that pAdapter and ifr have already been verified by caller,
4077 * and HDD context has also been validated
4078 */
4079 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(priv_data))) {
4080 ret = -EFAULT;
4081 } else {
4082 ret = hdd_driver_command(pAdapter, &priv_data);
4083 }
4084 return ret;
4085}
4086
4087int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
4088{
4089 hdd_adapter_t *pAdapter;
4090 hdd_context_t *pHddCtx;
4091 int ret;
4092
4093 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4094 if (NULL == pAdapter) {
4095 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4096 "%s: HDD adapter context is Null", __func__);
4097 ret = -ENODEV;
4098 goto exit;
4099 }
4100 if (dev != pAdapter->dev) {
4101 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4102 "%s: HDD adapter/dev inconsistency", __func__);
4103 ret = -ENODEV;
4104 goto exit;
4105 }
4106
4107 if ((!ifr) || (!ifr->ifr_data)) {
4108 ret = -EINVAL;
4109 goto exit;
4110 }
4111
4112 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4113 ret = wlan_hdd_validate_context(pHddCtx);
4114 if (ret) {
4115 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4116 "%s: invalid context", __func__);
4117 ret = -EBUSY;
4118 goto exit;
4119 }
4120
4121 switch (cmd) {
4122 case (SIOCDEVPRIVATE + 1):
4123 if (is_compat_task())
4124 ret = hdd_driver_compat_ioctl(pAdapter, ifr);
4125 else
4126 ret = hdd_driver_ioctl(pAdapter, ifr);
4127 break;
4128 default:
4129 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unknown ioctl %d",
4130 __func__, cmd);
4131 ret = -EINVAL;
4132 break;
4133 }
4134 exit:
4135 return ret;
4136}
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004137
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004138#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004139/**---------------------------------------------------------------------------
4140
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004141 \brief hdd_parse_ese_beacon_req() - Parse ese beacon request
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004142
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004143 This function parses the ese beacon request passed in the format
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004144 CCXBEACONREQ<space><Number of fields><space><Measurement token>
4145 <space>Channel 1<space>Scan Mode <space>Meas Duration<space>Channel N
4146 <space>Scan Mode N<space>Meas Duration N
4147 if the Number of bcn req fields (N) does not match with the actual number of fields passed
4148 then take N.
4149 <Meas Token><Channel><Scan Mode> and <Meas Duration> are treated as one pair
4150 For example, CCXBEACONREQ 2 1 1 1 30 2 44 0 40.
4151 This function does not take care of removing duplicate channels from the list
4152
4153 \param - pValue Pointer to data
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004154 \param - pEseBcnReq output pointer to store parsed ie information
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004155
4156 \return - 0 for success non-zero for failure
4157
4158 --------------------------------------------------------------------------*/
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004159static VOS_STATUS hdd_parse_ese_beacon_req(tANI_U8 *pValue,
4160 tCsrEseBeaconReq *pEseBcnReq)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004161{
4162 tANI_U8 *inPtr = pValue;
4163 int tempInt = 0;
4164 int j = 0, i = 0, v = 0;
4165 char buf[32];
4166
4167 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4168 /*no argument after the command*/
4169 if (NULL == inPtr)
4170 {
4171 return -EINVAL;
4172 }
4173 /*no space after the command*/
4174 else if (SPACE_ASCII_VALUE != *inPtr)
4175 {
4176 return -EINVAL;
4177 }
4178
4179 /*removing empty spaces*/
4180 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
4181
4182 /*no argument followed by spaces*/
4183 if ('\0' == *inPtr) return -EINVAL;
4184
4185 /*getting the first argument ie measurement token*/
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004186 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004187 if (1 != v) return -EINVAL;
4188
4189 v = kstrtos32(buf, 10, &tempInt);
4190 if ( v < 0) return -EINVAL;
4191
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004192 pEseBcnReq->numBcnReqIe = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004193
4194 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004195 "Number of Bcn Req Ie fields(%d)", pEseBcnReq->numBcnReqIe);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004196
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004197 for (j = 0; j < (pEseBcnReq->numBcnReqIe); j++)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004198 {
4199 for (i = 0; i < 4; i++)
4200 {
4201 /*inPtr pointing to the beginning of first space after number of ie fields*/
4202 inPtr = strpbrk( inPtr, " " );
4203 /*no ie data after the number of ie fields argument*/
4204 if (NULL == inPtr) return -EINVAL;
4205
4206 /*removing empty space*/
4207 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
4208
4209 /*no ie data after the number of ie fields argument and spaces*/
4210 if ( '\0' == *inPtr ) return -EINVAL;
4211
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004212 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004213 if (1 != v) return -EINVAL;
4214
4215 v = kstrtos32(buf, 10, &tempInt);
4216 if (v < 0) return -EINVAL;
4217
4218 switch (i)
4219 {
4220 case 0: /* Measurement token */
4221 if (tempInt <= 0)
4222 {
4223 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4224 "Invalid Measurement Token(%d)", tempInt);
4225 return -EINVAL;
4226 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004227 pEseBcnReq->bcnReq[j].measurementToken = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004228 break;
4229
4230 case 1: /* Channel number */
4231 if ((tempInt <= 0) ||
4232 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4233 {
4234 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4235 "Invalid Channel Number(%d)", tempInt);
4236 return -EINVAL;
4237 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004238 pEseBcnReq->bcnReq[j].channel = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004239 break;
4240
4241 case 2: /* Scan mode */
Varun Reddy Yeturu0b18d5a2013-12-04 11:42:23 -08004242 if ((tempInt < eSIR_PASSIVE_SCAN) || (tempInt > eSIR_BEACON_TABLE))
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004243 {
4244 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4245 "Invalid Scan Mode(%d) Expected{0|1|2}", tempInt);
4246 return -EINVAL;
4247 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004248 pEseBcnReq->bcnReq[j].scanMode= tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004249 break;
4250
4251 case 3: /* Measurement duration */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004252 if (((tempInt <= 0) && (pEseBcnReq->bcnReq[j].scanMode != eSIR_BEACON_TABLE)) ||
4253 ((tempInt < 0) && (pEseBcnReq->bcnReq[j].scanMode == eSIR_BEACON_TABLE)))
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004254 {
4255 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4256 "Invalid Measurement Duration(%d)", tempInt);
4257 return -EINVAL;
4258 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004259 pEseBcnReq->bcnReq[j].measurementDuration = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004260 break;
4261 }
4262 }
4263 }
4264
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004265 for (j = 0; j < pEseBcnReq->numBcnReqIe; j++)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004266 {
4267 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arun Kumar Khandavallie8768212014-02-17 16:43:34 +05304268 "Index(%d) Measurement Token(%u)Channel(%u) Scan Mode(%u) Measurement Duration(%u)\n",
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004269 j,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004270 pEseBcnReq->bcnReq[j].measurementToken,
4271 pEseBcnReq->bcnReq[j].channel,
4272 pEseBcnReq->bcnReq[j].scanMode,
4273 pEseBcnReq->bcnReq[j].measurementDuration);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004274 }
4275
4276 return VOS_STATUS_SUCCESS;
4277}
4278
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004279static void hdd_GetTsmStatsCB( tAniTrafStrmMetrics tsmMetrics, const tANI_U32 staId, void *pContext )
4280{
4281 struct statsContext *pStatsContext = NULL;
4282 hdd_adapter_t *pAdapter = NULL;
4283
4284 if (NULL == pContext)
4285 {
4286 hddLog(VOS_TRACE_LEVEL_ERROR,
4287 "%s: Bad param, pContext [%p]",
4288 __func__, pContext);
4289 return;
4290 }
4291
Jeff Johnson72a40512013-12-19 10:14:15 -08004292 /* there is a race condition that exists between this callback
4293 function and the caller since the caller could time out either
4294 before or while this code is executing. we use a spinlock to
4295 serialize these actions */
4296 spin_lock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004297
4298 pStatsContext = pContext;
4299 pAdapter = pStatsContext->pAdapter;
4300 if ((NULL == pAdapter) || (STATS_CONTEXT_MAGIC != pStatsContext->magic))
4301 {
4302 /* the caller presumably timed out so there is nothing we can do */
Jeff Johnson72a40512013-12-19 10:14:15 -08004303 spin_unlock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004304 hddLog(VOS_TRACE_LEVEL_WARN,
4305 "%s: Invalid context, pAdapter [%p] magic [%08x]",
4306 __func__, pAdapter, pStatsContext->magic);
4307 return;
4308 }
4309
Jeff Johnson72a40512013-12-19 10:14:15 -08004310 /* context is valid so caller is still waiting */
4311
4312 /* paranoia: invalidate the magic */
4313 pStatsContext->magic = 0;
4314
4315 /* copy over the tsm stats */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004316 pAdapter->tsmStats.UplinkPktQueueDly = tsmMetrics.UplinkPktQueueDly;
4317 vos_mem_copy(pAdapter->tsmStats.UplinkPktQueueDlyHist,
4318 tsmMetrics.UplinkPktQueueDlyHist,
4319 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
4320 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
4321 pAdapter->tsmStats.UplinkPktTxDly = tsmMetrics.UplinkPktTxDly;
4322 pAdapter->tsmStats.UplinkPktLoss = tsmMetrics.UplinkPktLoss;
4323 pAdapter->tsmStats.UplinkPktCount = tsmMetrics.UplinkPktCount;
4324 pAdapter->tsmStats.RoamingCount = tsmMetrics.RoamingCount;
4325 pAdapter->tsmStats.RoamingDly = tsmMetrics.RoamingDly;
4326
Jeff Johnson72a40512013-12-19 10:14:15 -08004327 /* notify the caller */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004328 complete(&pStatsContext->completion);
Jeff Johnson72a40512013-12-19 10:14:15 -08004329
4330 /* serialization is complete */
4331 spin_unlock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004332}
4333
4334
4335
4336static VOS_STATUS hdd_get_tsm_stats(hdd_adapter_t *pAdapter, const tANI_U8 tid,
4337 tAniTrafStrmMetrics* pTsmMetrics)
4338{
4339 hdd_station_ctx_t *pHddStaCtx = NULL;
4340 eHalStatus hstatus;
Jeff Johnson72a40512013-12-19 10:14:15 -08004341 VOS_STATUS vstatus = VOS_STATUS_SUCCESS;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004342 long lrc;
4343 struct statsContext context;
4344 hdd_context_t *pHddCtx = NULL;
4345
4346 if (NULL == pAdapter)
4347 {
4348 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: pAdapter is NULL", __func__);
4349 return VOS_STATUS_E_FAULT;
4350 }
4351
4352 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4353 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4354
4355 /* we are connected prepare our callback context */
4356 init_completion(&context.completion);
4357 context.pAdapter = pAdapter;
4358 context.magic = STATS_CONTEXT_MAGIC;
4359
4360 /* query tsm stats */
4361 hstatus = sme_GetTsmStats(pHddCtx->hHal, hdd_GetTsmStatsCB,
4362 pHddStaCtx->conn_info.staId[ 0 ],
4363 pHddStaCtx->conn_info.bssId,
4364 &context, pHddCtx->pvosContext, tid);
4365
4366 if (eHAL_STATUS_SUCCESS != hstatus)
4367 {
Jeff Johnson72a40512013-12-19 10:14:15 -08004368 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unable to retrieve statistics",
4369 __func__);
4370 vstatus = VOS_STATUS_E_FAULT;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004371 }
4372 else
4373 {
4374 /* request was sent -- wait for the response */
4375 lrc = wait_for_completion_interruptible_timeout(&context.completion,
4376 msecs_to_jiffies(WLAN_WAIT_TIME_STATS));
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004377 if (lrc <= 0)
4378 {
4379 hddLog(VOS_TRACE_LEVEL_ERROR,
4380 "%s: SME %s while retrieving statistics",
4381 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson72a40512013-12-19 10:14:15 -08004382 vstatus = VOS_STATUS_E_TIMEOUT;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004383 }
4384 }
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004385
Jeff Johnson72a40512013-12-19 10:14:15 -08004386 /* either we never sent a request, we sent a request and received a
4387 response or we sent a request and timed out. if we never sent a
4388 request or if we sent a request and got a response, we want to
4389 clear the magic out of paranoia. if we timed out there is a
4390 race condition such that the callback function could be
4391 executing at the same time we are. of primary concern is if the
4392 callback function had already verified the "magic" but had not
4393 yet set the completion variable when a timeout occurred. we
4394 serialize these activities by invalidating the magic while
4395 holding a shared spinlock which will cause us to block if the
4396 callback is currently executing */
4397 spin_lock(&hdd_context_lock);
4398 context.magic = 0;
4399 spin_unlock(&hdd_context_lock);
4400
4401 if (VOS_STATUS_SUCCESS == vstatus)
4402 {
4403 pTsmMetrics->UplinkPktQueueDly = pAdapter->tsmStats.UplinkPktQueueDly;
4404 vos_mem_copy(pTsmMetrics->UplinkPktQueueDlyHist,
4405 pAdapter->tsmStats.UplinkPktQueueDlyHist,
4406 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
4407 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
4408 pTsmMetrics->UplinkPktTxDly = pAdapter->tsmStats.UplinkPktTxDly;
4409 pTsmMetrics->UplinkPktLoss = pAdapter->tsmStats.UplinkPktLoss;
4410 pTsmMetrics->UplinkPktCount = pAdapter->tsmStats.UplinkPktCount;
4411 pTsmMetrics->RoamingCount = pAdapter->tsmStats.RoamingCount;
4412 pTsmMetrics->RoamingDly = pAdapter->tsmStats.RoamingDly;
4413 }
4414 return vstatus;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004415}
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004416#endif /*FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004417
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004418#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -08004419void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
4420{
4421 eCsrBand band = -1;
4422 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
4423 switch (band)
4424 {
4425 case eCSR_BAND_ALL:
4426 *pBand = WLAN_HDD_UI_BAND_AUTO;
4427 break;
4428
4429 case eCSR_BAND_24:
4430 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
4431 break;
4432
4433 case eCSR_BAND_5G:
4434 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
4435 break;
4436
4437 default:
4438 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
4439 *pBand = -1;
4440 break;
4441 }
4442}
4443
4444/**---------------------------------------------------------------------------
4445
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004446 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
4447
4448 This function parses the send action frame data passed in the format
4449 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
4450
Srinivas Girigowda56076852013-08-20 14:00:50 -07004451 \param - pValue Pointer to input data
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004452 \param - pTargetApBssid Pointer to target Ap bssid
4453 \param - pChannel Pointer to the Target AP channel
4454 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
4455 \param - pBuf Pointer to data
4456 \param - pBufLen Pointer to data length
4457
4458 \return - 0 for success non-zero for failure
4459
4460 --------------------------------------------------------------------------*/
4461VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
4462 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
4463{
4464 tANI_U8 *inPtr = pValue;
4465 tANI_U8 *dataEnd;
4466 int tempInt;
4467 int j = 0;
4468 int i = 0;
4469 int v = 0;
4470 tANI_U8 tempBuf[32];
4471 tANI_U8 tempByte = 0;
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004472 /* 12 hexa decimal digits, 5 ':' and '\0' */
4473 tANI_U8 macAddress[18];
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004474
4475 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4476 /*no argument after the command*/
4477 if (NULL == inPtr)
4478 {
4479 return -EINVAL;
4480 }
4481
4482 /*no space after the command*/
4483 else if (SPACE_ASCII_VALUE != *inPtr)
4484 {
4485 return -EINVAL;
4486 }
4487
4488 /*removing empty spaces*/
4489 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4490
4491 /*no argument followed by spaces*/
4492 if ('\0' == *inPtr)
4493 {
4494 return -EINVAL;
4495 }
4496
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004497 v = sscanf(inPtr, "%17s", macAddress);
4498 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004499 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004500 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4501 "Invalid MAC address or All hex inputs are not read (%d)", v);
4502 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004503 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004504
4505 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
4506 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
4507 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
4508 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
4509 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
4510 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004511
4512 /* point to the next argument */
4513 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4514 /*no argument after the command*/
4515 if (NULL == inPtr) return -EINVAL;
4516
4517 /*removing empty spaces*/
4518 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4519
4520 /*no argument followed by spaces*/
4521 if ('\0' == *inPtr)
4522 {
4523 return -EINVAL;
4524 }
4525
4526 /*getting the next argument ie the channel number */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004527 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004528 if (1 != v) return -EINVAL;
4529
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004530 v = kstrtos32(tempBuf, 10, &tempInt);
Agarwal Ashish353b3a82014-04-08 14:55:11 +05304531 if ( v < 0 || tempInt <= 0 || tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX )
Kiet Lambe150c22013-11-21 16:30:32 +05304532 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004533
4534 *pChannel = tempInt;
4535
4536 /* point to the next argument */
4537 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4538 /*no argument after the command*/
4539 if (NULL == inPtr) return -EINVAL;
4540 /*removing empty spaces*/
4541 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4542
4543 /*no argument followed by spaces*/
4544 if ('\0' == *inPtr)
4545 {
4546 return -EINVAL;
4547 }
4548
4549 /*getting the next argument ie the dwell time */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004550 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004551 if (1 != v) return -EINVAL;
4552
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004553 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda5a6e0672014-01-09 14:42:57 -08004554 if ( v < 0 || tempInt < 0) return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004555
4556 *pDwellTime = tempInt;
4557
4558 /* point to the next argument */
4559 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4560 /*no argument after the command*/
4561 if (NULL == inPtr) return -EINVAL;
4562 /*removing empty spaces*/
4563 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4564
4565 /*no argument followed by spaces*/
4566 if ('\0' == *inPtr)
4567 {
4568 return -EINVAL;
4569 }
4570
4571 /* find the length of data */
4572 dataEnd = inPtr;
4573 while(('\0' != *dataEnd) )
4574 {
4575 dataEnd++;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004576 }
Kiet Lambe150c22013-11-21 16:30:32 +05304577 *pBufLen = dataEnd - inPtr ;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004578 if ( *pBufLen <= 0) return -EINVAL;
4579
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07004580 /* Allocate the number of bytes based on the number of input characters
4581 whether it is even or odd.
4582 if the number of input characters are even, then we need N/2 byte.
4583 if the number of input characters are odd, then we need do (N+1)/2 to
4584 compensate rounding off.
4585 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
4586 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
4587 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004588 if (NULL == *pBuf)
4589 {
4590 hddLog(VOS_TRACE_LEVEL_FATAL,
4591 "%s: vos_mem_alloc failed ", __func__);
4592 return -EINVAL;
4593 }
4594
4595 /* the buffer received from the upper layer is character buffer,
4596 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
4597 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
4598 and f0 in 3rd location */
4599 for (i = 0, j = 0; j < *pBufLen; j += 2)
4600 {
Kiet Lambe150c22013-11-21 16:30:32 +05304601 if( j+1 == *pBufLen)
4602 {
4603 tempByte = hdd_parse_hex(inPtr[j]);
4604 }
4605 else
4606 {
4607 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
4608 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004609 (*pBuf)[i++] = tempByte;
4610 }
4611 *pBufLen = i;
4612 return VOS_STATUS_SUCCESS;
4613}
4614
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004615/**---------------------------------------------------------------------------
4616
Srinivas Girigowdade697412013-02-14 16:31:48 -08004617 \brief hdd_parse_channellist() - HDD Parse channel list
4618
4619 This function parses the channel list passed in the format
4620 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004621 if the Number of channels (N) does not match with the actual number of channels passed
4622 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
4623 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
4624 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
4625 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08004626
4627 \param - pValue Pointer to input channel list
4628 \param - ChannelList Pointer to local output array to record channel list
4629 \param - pNumChannels Pointer to number of roam scan channels
4630
4631 \return - 0 for success non-zero for failure
4632
4633 --------------------------------------------------------------------------*/
4634VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
4635{
4636 tANI_U8 *inPtr = pValue;
4637 int tempInt;
4638 int j = 0;
4639 int v = 0;
4640 char buf[32];
4641
4642 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4643 /*no argument after the command*/
4644 if (NULL == inPtr)
4645 {
4646 return -EINVAL;
4647 }
4648
4649 /*no space after the command*/
4650 else if (SPACE_ASCII_VALUE != *inPtr)
4651 {
4652 return -EINVAL;
4653 }
4654
4655 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004656 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08004657
4658 /*no argument followed by spaces*/
4659 if ('\0' == *inPtr)
4660 {
4661 return -EINVAL;
4662 }
4663
4664 /*getting the first argument ie the number of channels*/
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004665 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004666 if (1 != v) return -EINVAL;
4667
Srinivas Girigowdade697412013-02-14 16:31:48 -08004668 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004669 if ((v < 0) ||
4670 (tempInt <= 0) ||
4671 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
4672 {
4673 return -EINVAL;
4674 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004675
4676 *pNumChannels = tempInt;
4677
4678 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
4679 "Number of channels are: %d", *pNumChannels);
4680
4681 for (j = 0; j < (*pNumChannels); j++)
4682 {
4683 /*inPtr pointing to the beginning of first space after number of channels*/
4684 inPtr = strpbrk( inPtr, " " );
4685 /*no channel list after the number of channels argument*/
4686 if (NULL == inPtr)
4687 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004688 if (0 != j)
4689 {
4690 *pNumChannels = j;
4691 return VOS_STATUS_SUCCESS;
4692 }
4693 else
4694 {
4695 return -EINVAL;
4696 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004697 }
4698
4699 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004700 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08004701
4702 /*no channel list after the number of channels argument and spaces*/
4703 if ( '\0' == *inPtr )
4704 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004705 if (0 != j)
4706 {
4707 *pNumChannels = j;
4708 return VOS_STATUS_SUCCESS;
4709 }
4710 else
4711 {
4712 return -EINVAL;
4713 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004714 }
4715
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004716 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004717 if (1 != v) return -EINVAL;
4718
Srinivas Girigowdade697412013-02-14 16:31:48 -08004719 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004720 if ((v < 0) ||
4721 (tempInt <= 0) ||
4722 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4723 {
4724 return -EINVAL;
4725 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004726 pChannelList[j] = tempInt;
4727
4728 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
4729 "Channel %d added to preferred channel list",
4730 pChannelList[j] );
4731 }
4732
Srinivas Girigowdade697412013-02-14 16:31:48 -08004733 return VOS_STATUS_SUCCESS;
4734}
4735
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004736
4737/**---------------------------------------------------------------------------
4738
4739 \brief hdd_parse_reassoc_command_data() - HDD Parse reassoc command data
4740
4741 This function parses the reasoc command data passed in the format
4742 REASSOC<space><bssid><space><channel>
4743
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004744 \param - pValue Pointer to input data (its a NUL terminated string)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004745 \param - pTargetApBssid Pointer to target Ap bssid
4746 \param - pChannel Pointer to the Target AP channel
4747
4748 \return - 0 for success non-zero for failure
4749
4750 --------------------------------------------------------------------------*/
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004751VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue,
4752 tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004753{
4754 tANI_U8 *inPtr = pValue;
4755 int tempInt;
4756 int v = 0;
4757 tANI_U8 tempBuf[32];
Kiet Lamaa8e15a2014-02-11 23:30:06 -08004758 /* 12 hexa decimal digits, 5 ':' and '\0' */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004759 tANI_U8 macAddress[18];
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004760
4761 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4762 /*no argument after the command*/
4763 if (NULL == inPtr)
4764 {
4765 return -EINVAL;
4766 }
4767
4768 /*no space after the command*/
4769 else if (SPACE_ASCII_VALUE != *inPtr)
4770 {
4771 return -EINVAL;
4772 }
4773
4774 /*removing empty spaces*/
4775 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4776
4777 /*no argument followed by spaces*/
4778 if ('\0' == *inPtr)
4779 {
4780 return -EINVAL;
4781 }
4782
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004783 v = sscanf(inPtr, "%17s", macAddress);
4784 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004785 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004786 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4787 "Invalid MAC address or All hex inputs are not read (%d)", v);
4788 return -EINVAL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004789 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004790
4791 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
4792 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
4793 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
4794 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
4795 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
4796 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004797
4798 /* point to the next argument */
4799 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4800 /*no argument after the command*/
4801 if (NULL == inPtr) return -EINVAL;
4802
4803 /*removing empty spaces*/
4804 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4805
4806 /*no argument followed by spaces*/
4807 if ('\0' == *inPtr)
4808 {
4809 return -EINVAL;
4810 }
4811
4812 /*getting the next argument ie the channel number */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004813 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004814 if (1 != v) return -EINVAL;
4815
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004816 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004817 if ((v < 0) ||
4818 (tempInt <= 0) ||
4819 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4820 {
4821 return -EINVAL;
4822 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004823
4824 *pChannel = tempInt;
4825 return VOS_STATUS_SUCCESS;
4826}
4827
4828#endif
4829
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004830#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004831/**---------------------------------------------------------------------------
4832
4833 \brief hdd_parse_get_cckm_ie() - HDD Parse and fetch the CCKM IE
4834
4835 This function parses the SETCCKM IE command
4836 SETCCKMIE<space><ie data>
4837
4838 \param - pValue Pointer to input data
4839 \param - pCckmIe Pointer to output cckm Ie
4840 \param - pCckmIeLen Pointer to output cckm ie length
4841
4842 \return - 0 for success non-zero for failure
4843
4844 --------------------------------------------------------------------------*/
4845VOS_STATUS hdd_parse_get_cckm_ie(tANI_U8 *pValue, tANI_U8 **pCckmIe,
4846 tANI_U8 *pCckmIeLen)
4847{
4848 tANI_U8 *inPtr = pValue;
4849 tANI_U8 *dataEnd;
4850 int j = 0;
4851 int i = 0;
4852 tANI_U8 tempByte = 0;
4853
4854 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4855 /*no argument after the command*/
4856 if (NULL == inPtr)
4857 {
4858 return -EINVAL;
4859 }
4860
4861 /*no space after the command*/
4862 else if (SPACE_ASCII_VALUE != *inPtr)
4863 {
4864 return -EINVAL;
4865 }
4866
4867 /*removing empty spaces*/
4868 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4869
4870 /*no argument followed by spaces*/
4871 if ('\0' == *inPtr)
4872 {
4873 return -EINVAL;
4874 }
4875
4876 /* find the length of data */
4877 dataEnd = inPtr;
4878 while(('\0' != *dataEnd) )
4879 {
4880 dataEnd++;
4881 ++(*pCckmIeLen);
4882 }
4883 if ( *pCckmIeLen <= 0) return -EINVAL;
4884
4885 /* Allocate the number of bytes based on the number of input characters
4886 whether it is even or odd.
4887 if the number of input characters are even, then we need N/2 byte.
4888 if the number of input characters are odd, then we need do (N+1)/2 to
4889 compensate rounding off.
4890 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
4891 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
4892 *pCckmIe = vos_mem_malloc((*pCckmIeLen + 1)/2);
4893 if (NULL == *pCckmIe)
4894 {
4895 hddLog(VOS_TRACE_LEVEL_FATAL,
4896 "%s: vos_mem_alloc failed ", __func__);
4897 return -EINVAL;
4898 }
4899 vos_mem_zero(*pCckmIe, (*pCckmIeLen + 1)/2);
4900 /* the buffer received from the upper layer is character buffer,
4901 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
4902 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
4903 and f0 in 3rd location */
4904 for (i = 0, j = 0; j < *pCckmIeLen; j += 2)
4905 {
4906 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
4907 (*pCckmIe)[i++] = tempByte;
4908 }
4909 *pCckmIeLen = i;
4910
4911 return VOS_STATUS_SUCCESS;
4912}
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004913#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004914
Jeff Johnson295189b2012-06-20 16:38:30 -07004915/**---------------------------------------------------------------------------
4916
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004917 \brief hdd_is_valid_mac_address() - Validate MAC address
4918
4919 This function validates whether the given MAC address is valid or not
4920 Expected MAC address is of the format XX:XX:XX:XX:XX:XX
4921 where X is the hexa decimal digit character and separated by ':'
4922 This algorithm works even if MAC address is not separated by ':'
4923
4924 This code checks given input string mac contains exactly 12 hexadecimal digits.
4925 and a separator colon : appears in the input string only after
4926 an even number of hex digits.
4927
4928 \param - pMacAddr pointer to the input MAC address
4929 \return - 1 for valid and 0 for invalid
4930
4931 --------------------------------------------------------------------------*/
4932
4933v_BOOL_t hdd_is_valid_mac_address(const tANI_U8 *pMacAddr)
4934{
4935 int xdigit = 0;
4936 int separator = 0;
4937 while (*pMacAddr)
4938 {
4939 if (isxdigit(*pMacAddr))
4940 {
4941 xdigit++;
4942 }
4943 else if (':' == *pMacAddr)
4944 {
4945 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
4946 break;
4947
4948 ++separator;
4949 }
4950 else
4951 {
4952 separator = -1;
4953 /* Invalid MAC found */
4954 return 0;
4955 }
4956 ++pMacAddr;
4957 }
4958 return (xdigit == 12 && (separator == 5 || separator == 0));
4959}
4960
4961/**---------------------------------------------------------------------------
4962
Jeff Johnson295189b2012-06-20 16:38:30 -07004963 \brief hdd_open() - HDD Open function
4964
4965 This is called in response to ifconfig up
4966
4967 \param - dev Pointer to net_device structure
4968
4969 \return - 0 for success non-zero for failure
4970
4971 --------------------------------------------------------------------------*/
4972int hdd_open (struct net_device *dev)
4973{
4974 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4975 hdd_context_t *pHddCtx;
4976 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4977 VOS_STATUS status;
4978 v_BOOL_t in_standby = TRUE;
4979
4980 if (NULL == pAdapter)
4981 {
4982 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Agarwal Ashish971c2882013-10-30 20:11:12 +05304983 "%s: pAdapter is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004984 return -ENODEV;
4985 }
4986
4987 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05304988 MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_OPEN_REQUEST,
4989 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson295189b2012-06-20 16:38:30 -07004990 if (NULL == pHddCtx)
4991 {
4992 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004993 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004994 return -ENODEV;
4995 }
4996
4997 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4998 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
4999 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07005000 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
5001 {
5002 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305003 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07005004 in_standby = FALSE;
5005 break;
5006 }
5007 else
5008 {
5009 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5010 pAdapterNode = pNext;
5011 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005012 }
5013
5014 if (TRUE == in_standby)
5015 {
5016 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
5017 {
5018 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
5019 "wlan out of power save", __func__);
5020 return -EINVAL;
5021 }
5022 }
5023
Jeff Johnson6a81ca42013-04-05 10:37:08 -07005024 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07005025 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
5026 {
5027 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005028 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005029 /* Enable TX queues only when we are connected */
5030 netif_tx_start_all_queues(dev);
5031 }
5032
5033 return 0;
5034}
5035
5036int hdd_mon_open (struct net_device *dev)
5037{
5038 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5039
5040 if(pAdapter == NULL) {
5041 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005042 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005043 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005044 }
5045
5046 netif_start_queue(dev);
5047
5048 return 0;
5049}
5050/**---------------------------------------------------------------------------
5051
5052 \brief hdd_stop() - HDD stop function
5053
5054 This is called in response to ifconfig down
5055
5056 \param - dev Pointer to net_device structure
5057
5058 \return - 0 for success non-zero for failure
5059
5060 --------------------------------------------------------------------------*/
5061
5062int hdd_stop (struct net_device *dev)
5063{
5064 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5065 hdd_context_t *pHddCtx;
5066 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5067 VOS_STATUS status;
5068 v_BOOL_t enter_standby = TRUE;
5069
5070 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005071 if (NULL == pAdapter)
5072 {
5073 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Agarwal Ashish971c2882013-10-30 20:11:12 +05305074 "%s: pAdapter is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005075 return -ENODEV;
5076 }
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05305077 MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_OPEN_REQUEST,
5078 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson295189b2012-06-20 16:38:30 -07005079 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
5080 if (NULL == pHddCtx)
5081 {
5082 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005083 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005084 return -ENODEV;
5085 }
5086
Jeff Johnson6a81ca42013-04-05 10:37:08 -07005087 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07005088 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
5089 netif_tx_disable(pAdapter->dev);
5090 netif_carrier_off(pAdapter->dev);
5091
5092
5093 /* SoftAP ifaces should never go in power save mode
5094 making sure same here. */
5095 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
5096 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07005097 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07005098 )
5099 {
5100 /* SoftAP mode, so return from here */
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305101 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5102 "%s: In SAP MODE", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005103 EXIT();
5104 return 0;
5105 }
5106
5107 /* Find if any iface is up then
5108 if any iface is up then can't put device to sleep/ power save mode. */
5109 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5110 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
5111 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07005112 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
5113 {
5114 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305115 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07005116 enter_standby = FALSE;
5117 break;
5118 }
5119 else
5120 {
5121 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5122 pAdapterNode = pNext;
5123 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005124 }
5125
5126 if (TRUE == enter_standby)
5127 {
5128 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
5129 "entering standby", __func__);
5130 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
5131 {
5132 /*log and return success*/
5133 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
5134 "wlan in power save", __func__);
5135 }
5136 }
5137
5138 EXIT();
5139 return 0;
5140}
5141
5142/**---------------------------------------------------------------------------
5143
5144 \brief hdd_uninit() - HDD uninit function
5145
5146 This is called during the netdev unregister to uninitialize all data
5147associated with the device
5148
5149 \param - dev Pointer to net_device structure
5150
5151 \return - void
5152
5153 --------------------------------------------------------------------------*/
5154static void hdd_uninit (struct net_device *dev)
5155{
5156 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5157
5158 ENTER();
5159
5160 do
5161 {
5162 if (NULL == pAdapter)
5163 {
5164 hddLog(VOS_TRACE_LEVEL_FATAL,
5165 "%s: NULL pAdapter", __func__);
5166 break;
5167 }
5168
5169 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
5170 {
5171 hddLog(VOS_TRACE_LEVEL_FATAL,
5172 "%s: Invalid magic", __func__);
5173 break;
5174 }
5175
5176 if (NULL == pAdapter->pHddCtx)
5177 {
5178 hddLog(VOS_TRACE_LEVEL_FATAL,
5179 "%s: NULL pHddCtx", __func__);
5180 break;
5181 }
5182
5183 if (dev != pAdapter->dev)
5184 {
5185 hddLog(VOS_TRACE_LEVEL_FATAL,
5186 "%s: Invalid device reference", __func__);
5187 /* we haven't validated all cases so let this go for now */
5188 }
5189
5190 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
5191
5192 /* after uninit our adapter structure will no longer be valid */
5193 pAdapter->dev = NULL;
5194 pAdapter->magic = 0;
5195 } while (0);
5196
5197 EXIT();
5198}
5199
5200/**---------------------------------------------------------------------------
5201
5202 \brief hdd_release_firmware() -
5203
5204 This function calls the release firmware API to free the firmware buffer.
5205
5206 \param - pFileName Pointer to the File Name.
5207 pCtx - Pointer to the adapter .
5208
5209
5210 \return - 0 for success, non zero for failure
5211
5212 --------------------------------------------------------------------------*/
5213
5214VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
5215{
5216 VOS_STATUS status = VOS_STATUS_SUCCESS;
5217 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
5218 ENTER();
5219
5220
5221 if (!strcmp(WLAN_FW_FILE, pFileName)) {
5222
5223 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
5224
5225 if(pHddCtx->fw) {
5226 release_firmware(pHddCtx->fw);
5227 pHddCtx->fw = NULL;
5228 }
5229 else
5230 status = VOS_STATUS_E_FAILURE;
5231 }
5232 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
5233 if(pHddCtx->nv) {
5234 release_firmware(pHddCtx->nv);
5235 pHddCtx->nv = NULL;
5236 }
5237 else
5238 status = VOS_STATUS_E_FAILURE;
5239
5240 }
5241
5242 EXIT();
5243 return status;
5244}
5245
5246/**---------------------------------------------------------------------------
5247
5248 \brief hdd_request_firmware() -
5249
5250 This function reads the firmware file using the request firmware
5251 API and returns the the firmware data and the firmware file size.
5252
5253 \param - pfileName - Pointer to the file name.
5254 - pCtx - Pointer to the adapter .
5255 - ppfw_data - Pointer to the pointer of the firmware data.
5256 - pSize - Pointer to the file size.
5257
5258 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
5259
5260 --------------------------------------------------------------------------*/
5261
5262
5263VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
5264{
5265 int status;
5266 VOS_STATUS retval = VOS_STATUS_SUCCESS;
5267 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
5268 ENTER();
5269
5270 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
5271
5272 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
5273
5274 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
5275 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
5276 __func__, pfileName);
5277 retval = VOS_STATUS_E_FAILURE;
5278 }
5279
5280 else {
5281 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
5282 *pSize = pHddCtx->fw->size;
5283 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
5284 __func__, *pSize);
5285 }
5286 }
5287 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
5288
5289 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
5290
5291 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
5292 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
5293 __func__, pfileName);
5294 retval = VOS_STATUS_E_FAILURE;
5295 }
5296
5297 else {
5298 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
5299 *pSize = pHddCtx->nv->size;
5300 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
5301 __func__, *pSize);
5302 }
5303 }
5304
5305 EXIT();
5306 return retval;
5307}
5308/**---------------------------------------------------------------------------
5309 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
5310
5311 This is the function invoked by SME to inform the result of a full power
5312 request issued by HDD
5313
5314 \param - callbackcontext - Pointer to cookie
5315 status - result of request
5316
5317 \return - None
5318
5319--------------------------------------------------------------------------*/
5320void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
5321{
5322 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
5323
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07005324 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07005325 if(&pHddCtx->full_pwr_comp_var)
5326 {
5327 complete(&pHddCtx->full_pwr_comp_var);
5328 }
5329}
5330
5331/**---------------------------------------------------------------------------
5332
5333 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
5334
5335 This is the function invoked by SME to inform the result of BMPS
5336 request issued by HDD
5337
5338 \param - callbackcontext - Pointer to cookie
5339 status - result of request
5340
5341 \return - None
5342
5343--------------------------------------------------------------------------*/
5344void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
5345{
5346
5347 struct completion *completion_var = (struct completion*) callbackContext;
5348
Arif Hussain6d2a3322013-11-17 19:50:10 -08005349 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07005350 if(completion_var != NULL)
5351 {
5352 complete(completion_var);
5353 }
5354}
5355
5356/**---------------------------------------------------------------------------
5357
5358 \brief hdd_get_cfg_file_size() -
5359
5360 This function reads the configuration file using the request firmware
5361 API and returns the configuration file size.
5362
5363 \param - pCtx - Pointer to the adapter .
5364 - pFileName - Pointer to the file name.
5365 - pBufSize - Pointer to the buffer size.
5366
5367 \return - 0 for success, non zero for failure
5368
5369 --------------------------------------------------------------------------*/
5370
5371VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
5372{
5373 int status;
5374 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
5375
5376 ENTER();
5377
5378 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
5379
5380 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
5381 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
5382 status = VOS_STATUS_E_FAILURE;
5383 }
5384 else {
5385 *pBufSize = pHddCtx->fw->size;
5386 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
5387 release_firmware(pHddCtx->fw);
5388 pHddCtx->fw = NULL;
5389 }
5390
5391 EXIT();
5392 return VOS_STATUS_SUCCESS;
5393}
5394
5395/**---------------------------------------------------------------------------
5396
5397 \brief hdd_read_cfg_file() -
5398
5399 This function reads the configuration file using the request firmware
5400 API and returns the cfg data and the buffer size of the configuration file.
5401
5402 \param - pCtx - Pointer to the adapter .
5403 - pFileName - Pointer to the file name.
5404 - pBuffer - Pointer to the data buffer.
5405 - pBufSize - Pointer to the buffer size.
5406
5407 \return - 0 for success, non zero for failure
5408
5409 --------------------------------------------------------------------------*/
5410
5411VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
5412 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
5413{
5414 int status;
5415 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
5416
5417 ENTER();
5418
5419 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
5420
5421 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
5422 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
5423 return VOS_STATUS_E_FAILURE;
5424 }
5425 else {
5426 if(*pBufSize != pHddCtx->fw->size) {
5427 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
5428 "file size", __func__);
5429 release_firmware(pHddCtx->fw);
5430 pHddCtx->fw = NULL;
5431 return VOS_STATUS_E_FAILURE;
5432 }
5433 else {
5434 if(pBuffer) {
5435 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
5436 }
5437 release_firmware(pHddCtx->fw);
5438 pHddCtx->fw = NULL;
5439 }
5440 }
5441
5442 EXIT();
5443
5444 return VOS_STATUS_SUCCESS;
5445}
5446
5447/**---------------------------------------------------------------------------
5448
Jeff Johnson295189b2012-06-20 16:38:30 -07005449 \brief hdd_set_mac_address() -
5450
5451 This function sets the user specified mac address using
5452 the command ifconfig wlanX hw ether <mac adress>.
5453
5454 \param - dev - Pointer to the net device.
5455 - addr - Pointer to the sockaddr.
5456 \return - 0 for success, non zero for failure
5457
5458 --------------------------------------------------------------------------*/
5459
5460static int hdd_set_mac_address(struct net_device *dev, void *addr)
5461{
5462 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5463 struct sockaddr *psta_mac_addr = addr;
5464 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5465
5466 ENTER();
5467
5468 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
Jeff Johnson295189b2012-06-20 16:38:30 -07005469 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
5470
5471 EXIT();
5472 return halStatus;
5473}
5474
5475tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
5476{
5477 int i;
5478 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5479 {
Abhishek Singheb183782014-02-06 13:37:21 +05305480 if( 0 == ((pHddCtx->cfg_ini->intfAddrMask) & (1 << i)) )
Jeff Johnson295189b2012-06-20 16:38:30 -07005481 break;
5482 }
5483
5484 if( VOS_MAX_CONCURRENCY_PERSONA == i)
5485 return NULL;
5486
5487 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
5488 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
5489}
5490
5491void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
5492{
5493 int i;
5494 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5495 {
5496 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
5497 {
5498 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
5499 break;
5500 }
5501 }
5502 return;
5503}
5504
5505#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
5506 static struct net_device_ops wlan_drv_ops = {
5507 .ndo_open = hdd_open,
5508 .ndo_stop = hdd_stop,
5509 .ndo_uninit = hdd_uninit,
5510 .ndo_start_xmit = hdd_hard_start_xmit,
5511 .ndo_tx_timeout = hdd_tx_timeout,
5512 .ndo_get_stats = hdd_stats,
5513 .ndo_do_ioctl = hdd_ioctl,
5514 .ndo_set_mac_address = hdd_set_mac_address,
5515 .ndo_select_queue = hdd_select_queue,
5516#ifdef WLAN_FEATURE_PACKET_FILTERING
5517#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
5518 .ndo_set_rx_mode = hdd_set_multicast_list,
5519#else
5520 .ndo_set_multicast_list = hdd_set_multicast_list,
5521#endif //LINUX_VERSION_CODE
5522#endif
5523 };
Jeff Johnson295189b2012-06-20 16:38:30 -07005524 static struct net_device_ops wlan_mon_drv_ops = {
5525 .ndo_open = hdd_mon_open,
5526 .ndo_stop = hdd_stop,
5527 .ndo_uninit = hdd_uninit,
5528 .ndo_start_xmit = hdd_mon_hard_start_xmit,
5529 .ndo_tx_timeout = hdd_tx_timeout,
5530 .ndo_get_stats = hdd_stats,
5531 .ndo_do_ioctl = hdd_ioctl,
5532 .ndo_set_mac_address = hdd_set_mac_address,
5533 };
Jeff Johnson295189b2012-06-20 16:38:30 -07005534
5535#endif
5536
5537void hdd_set_station_ops( struct net_device *pWlanDev )
5538{
5539#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
Jeff Johnson295189b2012-06-20 16:38:30 -07005540 pWlanDev->netdev_ops = &wlan_drv_ops;
5541#else
5542 pWlanDev->open = hdd_open;
5543 pWlanDev->stop = hdd_stop;
5544 pWlanDev->uninit = hdd_uninit;
5545 pWlanDev->hard_start_xmit = NULL;
5546 pWlanDev->tx_timeout = hdd_tx_timeout;
5547 pWlanDev->get_stats = hdd_stats;
5548 pWlanDev->do_ioctl = hdd_ioctl;
Jeff Johnson295189b2012-06-20 16:38:30 -07005549 pWlanDev->set_mac_address = hdd_set_mac_address;
5550#endif
5551}
5552
Jeff Johnsoneed415b2013-01-18 16:11:20 -08005553static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07005554{
5555 struct net_device *pWlanDev = NULL;
5556 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005557 /*
5558 * cfg80211 initialization and registration....
5559 */
5560 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
5561
Jeff Johnson295189b2012-06-20 16:38:30 -07005562 if(pWlanDev != NULL)
5563 {
5564
5565 //Save the pointer to the net_device in the HDD adapter
5566 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
5567
Jeff Johnson295189b2012-06-20 16:38:30 -07005568 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
5569
5570 pAdapter->dev = pWlanDev;
5571 pAdapter->pHddCtx = pHddCtx;
5572 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
5573
5574 init_completion(&pAdapter->session_open_comp_var);
5575 init_completion(&pAdapter->session_close_comp_var);
5576 init_completion(&pAdapter->disconnect_comp_var);
5577 init_completion(&pAdapter->linkup_event_var);
5578 init_completion(&pAdapter->cancel_rem_on_chan_var);
5579 init_completion(&pAdapter->rem_on_chan_ready_event);
Vinay Krishna Erannaf0e523b2014-03-01 21:00:16 +05305580 init_completion(&pAdapter->pno_comp_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07005581#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
5582 init_completion(&pAdapter->offchannel_tx_event);
5583#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005584 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005585#ifdef FEATURE_WLAN_TDLS
5586 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07005587 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08005588 init_completion(&pAdapter->tdls_mgmt_comp);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05305589 init_completion(&pAdapter->tdls_link_establish_req_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005590#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005591 init_completion(&pHddCtx->mc_sus_event_var);
5592 init_completion(&pHddCtx->tx_sus_event_var);
Gopichand Nakkala05621412013-06-19 19:37:38 +05305593 init_completion(&pHddCtx->rx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07005594 init_completion(&pAdapter->ula_complete);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07005595 init_completion(&pAdapter->change_country_code);
Jeff Johnson295189b2012-06-20 16:38:30 -07005596
Rajeev79dbe4c2013-10-05 11:03:42 +05305597#ifdef FEATURE_WLAN_BATCH_SCAN
5598 init_completion(&pAdapter->hdd_set_batch_scan_req_var);
5599 init_completion(&pAdapter->hdd_get_batch_scan_req_var);
5600 pAdapter->pBatchScanRsp = NULL;
5601 pAdapter->numScanList = 0;
Rajeev Kumar20140c12013-10-21 19:39:02 -07005602 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
Kiet Lamaa8e15a2014-02-11 23:30:06 -08005603 pAdapter->prev_batch_id = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05305604 mutex_init(&pAdapter->hdd_batch_scan_lock);
5605#endif
5606
Jeff Johnson295189b2012-06-20 16:38:30 -07005607 pAdapter->isLinkUpSvcNeeded = FALSE;
5608 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
5609 //Init the net_device structure
5610 strlcpy(pWlanDev->name, name, IFNAMSIZ);
5611
5612 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
5613 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
5614 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
5615 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
5616
5617 hdd_set_station_ops( pAdapter->dev );
5618
5619 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07005620 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
5621 pAdapter->wdev.wiphy = pHddCtx->wiphy;
5622 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07005623 /* set pWlanDev's parent to underlying device */
5624 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
5625 }
5626
5627 return pAdapter;
5628}
5629
5630VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
5631{
5632 struct net_device *pWlanDev = pAdapter->dev;
5633 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
5634 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
5635 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5636
5637 if( rtnl_lock_held )
5638 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08005639 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07005640 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
5641 {
5642 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
5643 return VOS_STATUS_E_FAILURE;
5644 }
5645 }
5646 if (register_netdevice(pWlanDev))
5647 {
5648 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
5649 return VOS_STATUS_E_FAILURE;
5650 }
5651 }
5652 else
5653 {
5654 if(register_netdev(pWlanDev))
5655 {
5656 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
5657 return VOS_STATUS_E_FAILURE;
5658 }
5659 }
5660 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
5661
5662 return VOS_STATUS_SUCCESS;
5663}
5664
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005665static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07005666{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005667 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07005668
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005669 if (NULL == pAdapter)
5670 {
5671 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
5672 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07005673 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005674
5675 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
5676 {
5677 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
5678 return eHAL_STATUS_NOT_INITIALIZED;
5679 }
5680
5681 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
5682
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005683#ifndef WLAN_OPEN_SOURCE
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005684 /* need to make sure all of our scheduled work has completed.
5685 * This callback is called from MC thread context, so it is safe to
5686 * to call below flush workqueue API from here.
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005687 *
5688 * Even though this is called from MC thread context, if there is a faulty
5689 * work item in the system, that can hang this call forever. So flushing
5690 * this global work queue is not safe; and now we make sure that
5691 * individual work queues are stopped correctly. But the cancel work queue
5692 * is a GPL only API, so the proprietary version of the driver would still
5693 * rely on the global work queue flush.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005694 */
5695 flush_scheduled_work();
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005696#endif
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005697
5698 /* We can be blocked while waiting for scheduled work to be
5699 * flushed, and the adapter structure can potentially be freed, in
5700 * which case the magic will have been reset. So make sure the
5701 * magic is still good, and hence the adapter structure is still
5702 * valid, before signaling completion */
5703 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
5704 {
5705 complete(&pAdapter->session_close_comp_var);
5706 }
5707
Jeff Johnson295189b2012-06-20 16:38:30 -07005708 return eHAL_STATUS_SUCCESS;
5709}
5710
5711VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
5712{
5713 struct net_device *pWlanDev = pAdapter->dev;
5714 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
5715 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
5716 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5717 VOS_STATUS status = VOS_STATUS_E_FAILURE;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305718 long rc = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07005719
5720 INIT_COMPLETION(pAdapter->session_open_comp_var);
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07005721 sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07005722 //Open a SME session for future operation
5723 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07005724 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07005725 if ( !HAL_STATUS_SUCCESS( halStatus ) )
5726 {
5727 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005728 "sme_OpenSession() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005729 halStatus, halStatus );
5730 status = VOS_STATUS_E_FAILURE;
5731 goto error_sme_open;
5732 }
5733
5734 //Block on a completion variable. Can't wait forever though.
Vinay Krishna Eranna0fe2e7c2014-04-09 21:32:08 +05305735 rc = wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07005736 &pAdapter->session_open_comp_var,
5737 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305738 if (rc <= 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07005739 {
5740 hddLog(VOS_TRACE_LEVEL_FATAL,
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305741 "Session is not opened within timeout period code %ld", rc );
Jeff Johnson295189b2012-06-20 16:38:30 -07005742 status = VOS_STATUS_E_FAILURE;
5743 goto error_sme_open;
5744 }
5745
5746 // Register wireless extensions
5747 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
5748 {
5749 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005750 "hdd_register_wext() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005751 halStatus, halStatus );
5752 status = VOS_STATUS_E_FAILURE;
5753 goto error_register_wext;
5754 }
5755 //Safe to register the hard_start_xmit function again
5756#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
5757 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
5758#else
5759 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
5760#endif
5761
5762 //Set the Connection State to Not Connected
Abhishek Singhf4669da2014-05-26 15:07:49 +05305763 hddLog(VOS_TRACE_LEVEL_INFO,
5764 "%s: Set HDD connState to eConnectionState_NotConnected",
5765 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005766 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
5767
5768 //Set the default operation channel
5769 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
5770
5771 /* Make the default Auth Type as OPEN*/
5772 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
5773
5774 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
5775 {
5776 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005777 "hdd_init_tx_rx() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005778 status, status );
5779 goto error_init_txrx;
5780 }
5781
5782 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5783
5784 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
5785 {
5786 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005787 "hdd_wmm_adapter_init() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005788 status, status );
5789 goto error_wmm_init;
5790 }
5791
5792 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5793
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005794#ifdef FEATURE_WLAN_TDLS
5795 if(0 != wlan_hdd_tdls_init(pAdapter))
5796 {
5797 status = VOS_STATUS_E_FAILURE;
5798 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
5799 goto error_tdls_init;
5800 }
5801 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
5802#endif
5803
Jeff Johnson295189b2012-06-20 16:38:30 -07005804 return VOS_STATUS_SUCCESS;
5805
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005806#ifdef FEATURE_WLAN_TDLS
5807error_tdls_init:
5808 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5809 hdd_wmm_adapter_close(pAdapter);
5810#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005811error_wmm_init:
5812 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5813 hdd_deinit_tx_rx(pAdapter);
5814error_init_txrx:
5815 hdd_UnregisterWext(pWlanDev);
5816error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005817 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07005818 {
5819 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005820 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07005821 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005822 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07005823 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305824 unsigned long rc;
5825
Jeff Johnson295189b2012-06-20 16:38:30 -07005826 //Block on a completion variable. Can't wait forever though.
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305827 rc = wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07005828 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005829 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305830 if (rc <= 0)
5831 hddLog(VOS_TRACE_LEVEL_ERROR,
5832 FL("Session is not opened within timeout period code %ld"), rc);
Jeff Johnson295189b2012-06-20 16:38:30 -07005833 }
5834}
5835error_sme_open:
5836 return status;
5837}
5838
Jeff Johnson295189b2012-06-20 16:38:30 -07005839void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5840{
5841 hdd_cfg80211_state_t *cfgState;
5842
5843 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
5844
5845 if( NULL != cfgState->buf )
5846 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305847 long rc;
Jeff Johnson295189b2012-06-20 16:38:30 -07005848 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
5849 rc = wait_for_completion_interruptible_timeout(
5850 &pAdapter->tx_action_cnf_event,
5851 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305852 if (rc <= 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07005853 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08005854 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305855 "%s ERROR: HDD Wait for Action Confirmation Failed!! %ld"
5856 , __func__, rc);
Jeff Johnson295189b2012-06-20 16:38:30 -07005857 }
5858 }
5859 return;
5860}
Jeff Johnson295189b2012-06-20 16:38:30 -07005861
5862void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5863{
5864 ENTER();
5865 switch ( pAdapter->device_mode )
5866 {
5867 case WLAN_HDD_INFRA_STATION:
5868 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005869 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005870 {
5871 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
5872 {
5873 hdd_deinit_tx_rx( pAdapter );
5874 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5875 }
5876
5877 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
5878 {
5879 hdd_wmm_adapter_close( pAdapter );
5880 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5881 }
5882
Jeff Johnson295189b2012-06-20 16:38:30 -07005883 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005884#ifdef FEATURE_WLAN_TDLS
5885 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
5886 {
5887 wlan_hdd_tdls_exit(pAdapter);
5888 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
5889 }
5890#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005891
5892 break;
5893 }
5894
5895 case WLAN_HDD_SOFTAP:
5896 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005897 {
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05305898
5899 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
5900 {
5901 hdd_wmm_adapter_close( pAdapter );
5902 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5903 }
5904
Jeff Johnson295189b2012-06-20 16:38:30 -07005905 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005906
5907 hdd_unregister_hostapd(pAdapter);
5908 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07005909 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07005910 break;
5911 }
5912
5913 case WLAN_HDD_MONITOR:
5914 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005915 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07005916 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
5917 {
5918 hdd_deinit_tx_rx( pAdapter );
5919 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5920 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005921 if(NULL != pAdapterforTx)
5922 {
5923 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
5924 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005925 break;
5926 }
5927
5928
5929 default:
5930 break;
5931 }
5932
5933 EXIT();
5934}
5935
5936void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
5937{
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -08005938 struct net_device *pWlanDev = NULL;
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05305939
5940 ENTER();
5941 if (NULL == pAdapter)
5942 {
5943 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5944 "%s: HDD adapter is Null", __func__);
5945 return;
5946 }
5947
5948 pWlanDev = pAdapter->dev;
Jeff Johnson295189b2012-06-20 16:38:30 -07005949
Rajeev79dbe4c2013-10-05 11:03:42 +05305950#ifdef FEATURE_WLAN_BATCH_SCAN
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05305951 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
5952 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Rajeev Kumarf999e582014-01-09 17:33:29 -08005953 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05305954 || (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)
5955 )
5956 {
Rajeev Kumarf999e582014-01-09 17:33:29 -08005957 if (pAdapter)
Rajeev79dbe4c2013-10-05 11:03:42 +05305958 {
Rajeev Kumarf999e582014-01-09 17:33:29 -08005959 if (eHDD_BATCH_SCAN_STATE_STARTED == pAdapter->batchScanState)
5960 {
5961 hdd_deinit_batch_scan(pAdapter);
5962 }
Rajeev79dbe4c2013-10-05 11:03:42 +05305963 }
Rajeev Kumarf999e582014-01-09 17:33:29 -08005964 }
Rajeev79dbe4c2013-10-05 11:03:42 +05305965#endif
5966
Jeff Johnson295189b2012-06-20 16:38:30 -07005967 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
5968 if( rtnl_held )
5969 {
5970 unregister_netdevice(pWlanDev);
5971 }
5972 else
5973 {
5974 unregister_netdev(pWlanDev);
5975 }
5976 // note that the pAdapter is no longer valid at this point
5977 // since the memory has been reclaimed
5978 }
5979
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05305980 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07005981}
5982
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005983void hdd_set_pwrparams(hdd_context_t *pHddCtx)
5984{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305985 VOS_STATUS status;
5986 hdd_adapter_t *pAdapter = NULL;
5987 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005988
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305989 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005990
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305991 /*loop through all adapters.*/
5992 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005993 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305994 pAdapter = pAdapterNode->pAdapter;
5995 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
5996 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005997
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305998 { // we skip this registration for modes other than STA and P2P client modes.
5999 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6000 pAdapterNode = pNext;
6001 continue;
6002 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006003
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306004 //Apply Dynamic DTIM For P2P
6005 //Only if ignoreDynamicDtimInP2pMode is not set in ini
6006 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
6007 pHddCtx->cfg_ini->enableModulatedDTIM) &&
6008 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
6009 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
6010 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
6011 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
6012 (eConnectionState_Associated ==
6013 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
6014 (pHddCtx->cfg_ini->fIsBmpsEnabled))
6015 {
6016 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006017
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306018 powerRequest.uIgnoreDTIM = 1;
6019 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
6020
6021 if (pHddCtx->cfg_ini->enableModulatedDTIM)
6022 {
6023 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
6024 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
6025 }
6026 else
6027 {
6028 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
6029 }
6030
6031 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
6032 * specified during Enter/Exit BMPS when LCD off*/
6033 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
6034 NULL, eANI_BOOLEAN_FALSE);
6035 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
6036 NULL, eANI_BOOLEAN_FALSE);
6037
6038 /* switch to the DTIM specified in cfg.ini */
6039 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6040 "Switch to DTIM %d", powerRequest.uListenInterval);
6041 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
6042 break;
6043
6044 }
6045
6046 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6047 pAdapterNode = pNext;
6048 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006049}
6050
6051void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
6052{
6053 /*Switch back to DTIM 1*/
6054 tSirSetPowerParamsReq powerRequest = { 0 };
6055
6056 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
6057 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07006058 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006059
6060 /* Update ignoreDTIM and ListedInterval in CFG with default values */
6061 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
6062 NULL, eANI_BOOLEAN_FALSE);
6063 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
6064 NULL, eANI_BOOLEAN_FALSE);
6065
6066 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6067 "Switch to DTIM%d",powerRequest.uListenInterval);
6068 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
6069
6070}
6071
Jeff Johnson295189b2012-06-20 16:38:30 -07006072VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
6073{
6074 VOS_STATUS status = VOS_STATUS_SUCCESS;
6075
6076 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
6077 {
6078 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
6079 }
6080
6081 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
6082 {
6083 sme_StartAutoBmpsTimer(pHddCtx->hHal);
6084 }
6085
6086 if (pHddCtx->cfg_ini->fIsImpsEnabled)
6087 {
6088 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
6089 }
6090
6091 return status;
6092}
6093
6094VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
6095{
6096 hdd_adapter_t *pAdapter = NULL;
6097 eHalStatus halStatus;
6098 VOS_STATUS status = VOS_STATUS_E_INVAL;
6099 v_BOOL_t disableBmps = FALSE;
6100 v_BOOL_t disableImps = FALSE;
6101
6102 switch(session_type)
6103 {
6104 case WLAN_HDD_INFRA_STATION:
6105 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07006106 case WLAN_HDD_P2P_CLIENT:
6107 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07006108 //Exit BMPS -> Is Sta/P2P Client is already connected
6109 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
6110 if((NULL != pAdapter)&&
6111 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
6112 {
6113 disableBmps = TRUE;
6114 }
6115
6116 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
6117 if((NULL != pAdapter)&&
6118 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
6119 {
6120 disableBmps = TRUE;
6121 }
6122
6123 //Exit both Bmps and Imps incase of Go/SAP Mode
6124 if((WLAN_HDD_SOFTAP == session_type) ||
6125 (WLAN_HDD_P2P_GO == session_type))
6126 {
6127 disableBmps = TRUE;
6128 disableImps = TRUE;
6129 }
6130
6131 if(TRUE == disableImps)
6132 {
6133 if (pHddCtx->cfg_ini->fIsImpsEnabled)
6134 {
6135 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
6136 }
6137 }
6138
6139 if(TRUE == disableBmps)
6140 {
6141 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
6142 {
6143 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
6144
6145 if(eHAL_STATUS_SUCCESS != halStatus)
6146 {
6147 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08006148 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006149 VOS_ASSERT(0);
6150 return status;
6151 }
6152 }
6153
6154 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
6155 {
6156 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
6157
6158 if(eHAL_STATUS_SUCCESS != halStatus)
6159 {
6160 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08006161 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006162 VOS_ASSERT(0);
6163 return status;
6164 }
6165 }
6166 }
6167
6168 if((TRUE == disableBmps) ||
6169 (TRUE == disableImps))
6170 {
6171 /* Now, get the chip into Full Power now */
6172 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
6173 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
6174 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
6175
6176 if(halStatus != eHAL_STATUS_SUCCESS)
6177 {
6178 if(halStatus == eHAL_STATUS_PMC_PENDING)
6179 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306180 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07006181 //Block on a completion variable. Can't wait forever though
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306182 ret = wait_for_completion_interruptible_timeout(
6183 &pHddCtx->full_pwr_comp_var,
6184 msecs_to_jiffies(1000));
6185 if (ret <= 0)
6186 {
6187 hddLog(VOS_TRACE_LEVEL_ERROR,
6188 "%s: wait on full_pwr_comp_var failed %ld",
6189 __func__, ret);
6190 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006191 }
6192 else
6193 {
6194 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08006195 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006196 VOS_ASSERT(0);
6197 return status;
6198 }
6199 }
6200
6201 status = VOS_STATUS_SUCCESS;
6202 }
6203
6204 break;
6205 }
6206 return status;
6207}
6208
6209hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08006210 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07006211 tANI_U8 rtnl_held )
6212{
6213 hdd_adapter_t *pAdapter = NULL;
6214 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
6215 VOS_STATUS status = VOS_STATUS_E_FAILURE;
6216 VOS_STATUS exitbmpsStatus;
6217
Arif Hussain6d2a3322013-11-17 19:50:10 -08006218 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d",__func__,iface_name,session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006219
Nirav Shah436658f2014-02-28 17:05:45 +05306220 if(macAddr == NULL)
6221 {
6222 /* Not received valid macAddr */
6223 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6224 "%s:Unable to add virtual intf: Not able to get"
6225 "valid mac address",__func__);
6226 return NULL;
6227 }
6228
Jeff Johnson295189b2012-06-20 16:38:30 -07006229 //Disable BMPS incase of Concurrency
6230 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
6231
6232 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
6233 {
6234 //Fail to Exit BMPS
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306235 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Exit BMPS", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006236 VOS_ASSERT(0);
6237 return NULL;
6238 }
6239
6240 switch(session_type)
6241 {
6242 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07006243 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006244 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07006245 {
6246 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
6247
6248 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306249 {
6250 hddLog(VOS_TRACE_LEVEL_FATAL,
6251 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006252 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306253 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006254
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306255#ifdef FEATURE_WLAN_TDLS
6256 /* A Mutex Lock is introduced while changing/initializing the mode to
6257 * protect the concurrent access for the Adapters by TDLS module.
6258 */
Rajesh Chauhana34c6e62014-03-25 16:37:58 +05306259 mutex_lock(&pHddCtx->tdls_lock);
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306260#endif
6261
Jeff Johnsone7245742012-09-05 17:12:55 -07006262 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
6263 NL80211_IFTYPE_P2P_CLIENT:
6264 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07006265
Jeff Johnson295189b2012-06-20 16:38:30 -07006266 pAdapter->device_mode = session_type;
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306267#ifdef FEATURE_WLAN_TDLS
6268 mutex_unlock(&pHddCtx->tdls_lock);
6269#endif
Sunil Dutt66485cb2013-12-19 19:05:03 +05306270
6271 status = hdd_init_station_mode( pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07006272 if( VOS_STATUS_SUCCESS != status )
6273 goto err_free_netdev;
6274
6275 status = hdd_register_interface( pAdapter, rtnl_held );
6276 if( VOS_STATUS_SUCCESS != status )
6277 {
6278 hdd_deinit_adapter(pHddCtx, pAdapter);
6279 goto err_free_netdev;
6280 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306281
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05306282 // Workqueue which gets scheduled in IPv4 notification callback.
6283 INIT_WORK(&pAdapter->ipv4NotifierWorkQueue, hdd_ipv4_notifier_work_queue);
6284
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306285#ifdef WLAN_NS_OFFLOAD
6286 // Workqueue which gets scheduled in IPv6 notification callback.
6287 INIT_WORK(&pAdapter->ipv6NotifierWorkQueue, hdd_ipv6_notifier_work_queue);
6288#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006289 //Stop the Interface TX queue.
6290 netif_tx_disable(pAdapter->dev);
6291 //netif_tx_disable(pWlanDev);
6292 netif_carrier_off(pAdapter->dev);
6293
6294 break;
6295 }
6296
Jeff Johnson295189b2012-06-20 16:38:30 -07006297 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07006298 case WLAN_HDD_SOFTAP:
6299 {
6300 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
6301 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306302 {
6303 hddLog(VOS_TRACE_LEVEL_FATAL,
6304 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006305 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306306 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006307
Jeff Johnson295189b2012-06-20 16:38:30 -07006308 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
6309 NL80211_IFTYPE_AP:
6310 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07006311 pAdapter->device_mode = session_type;
6312
6313 status = hdd_init_ap_mode(pAdapter);
6314 if( VOS_STATUS_SUCCESS != status )
6315 goto err_free_netdev;
6316
6317 status = hdd_register_hostapd( pAdapter, rtnl_held );
6318 if( VOS_STATUS_SUCCESS != status )
6319 {
6320 hdd_deinit_adapter(pHddCtx, pAdapter);
6321 goto err_free_netdev;
6322 }
6323
6324 netif_tx_disable(pAdapter->dev);
6325 netif_carrier_off(pAdapter->dev);
6326
6327 hdd_set_conparam( 1 );
6328 break;
6329 }
6330 case WLAN_HDD_MONITOR:
6331 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006332 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
6333 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306334 {
6335 hddLog(VOS_TRACE_LEVEL_FATAL,
6336 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006337 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306338 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006339
6340 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
6341 pAdapter->device_mode = session_type;
6342 status = hdd_register_interface( pAdapter, rtnl_held );
6343#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
6344 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
6345#else
6346 pAdapter->dev->open = hdd_mon_open;
6347 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
6348#endif
6349 hdd_init_tx_rx( pAdapter );
6350 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
6351 //Set adapter to be used for data tx. It will use either GO or softap.
6352 pAdapter->sessionCtx.monitor.pAdapterForTx =
6353 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07006354 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
6355 {
6356 pAdapter->sessionCtx.monitor.pAdapterForTx =
6357 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
6358 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006359 /* This workqueue will be used to transmit management packet over
6360 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07006361 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
6362 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
6363 return NULL;
6364 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07006365
Jeff Johnson295189b2012-06-20 16:38:30 -07006366 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
6367 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07006368 }
6369 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07006370 case WLAN_HDD_FTM:
6371 {
6372 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
6373
6374 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306375 {
6376 hddLog(VOS_TRACE_LEVEL_FATAL,
6377 FL("failed to allocate adapter for session %d"), session_type);
6378 return NULL;
6379 }
6380
Jeff Johnson295189b2012-06-20 16:38:30 -07006381 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
6382 * message while loading driver in FTM mode. */
6383 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
6384 pAdapter->device_mode = session_type;
6385 status = hdd_register_interface( pAdapter, rtnl_held );
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05306386
6387 hdd_init_tx_rx( pAdapter );
6388
6389 //Stop the Interface TX queue.
6390 netif_tx_disable(pAdapter->dev);
6391 netif_carrier_off(pAdapter->dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07006392 }
6393 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07006394 default:
6395 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306396 hddLog(VOS_TRACE_LEVEL_FATAL,"%s Invalid session type %d",
6397 __func__, session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006398 VOS_ASSERT(0);
6399 return NULL;
6400 }
6401 }
6402
Jeff Johnson295189b2012-06-20 16:38:30 -07006403 if( VOS_STATUS_SUCCESS == status )
6404 {
6405 //Add it to the hdd's session list.
6406 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
6407 if( NULL == pHddAdapterNode )
6408 {
6409 status = VOS_STATUS_E_NOMEM;
6410 }
6411 else
6412 {
6413 pHddAdapterNode->pAdapter = pAdapter;
6414 status = hdd_add_adapter_back ( pHddCtx,
6415 pHddAdapterNode );
6416 }
6417 }
6418
6419 if( VOS_STATUS_SUCCESS != status )
6420 {
6421 if( NULL != pAdapter )
6422 {
6423 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
6424 pAdapter = NULL;
6425 }
6426 if( NULL != pHddAdapterNode )
6427 {
6428 vos_mem_free( pHddAdapterNode );
6429 }
6430
6431 goto resume_bmps;
6432 }
6433
6434 if(VOS_STATUS_SUCCESS == status)
6435 {
6436 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
6437
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07006438 //Initialize the WoWL service
6439 if(!hdd_init_wowl(pAdapter))
6440 {
6441 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
6442 goto err_free_netdev;
6443 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006444 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006445 return pAdapter;
6446
6447err_free_netdev:
6448 free_netdev(pAdapter->dev);
6449 wlan_hdd_release_intf_addr( pHddCtx,
6450 pAdapter->macAddressCurrent.bytes );
6451
6452resume_bmps:
6453 //If bmps disabled enable it
6454 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
6455 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306456 if (pHddCtx->hdd_wlan_suspended)
6457 {
6458 hdd_set_pwrparams(pHddCtx);
6459 }
6460 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07006461 }
6462 return NULL;
6463}
6464
6465VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
6466 tANI_U8 rtnl_held )
6467{
6468 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
6469 VOS_STATUS status;
6470
6471 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
6472 if( VOS_STATUS_SUCCESS != status )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306473 {
6474 hddLog(VOS_TRACE_LEVEL_WARN,"%s: adapter list empty %d",
6475 __func__, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07006476 return status;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306477 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006478
6479 while ( pCurrent->pAdapter != pAdapter )
6480 {
6481 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
6482 if( VOS_STATUS_SUCCESS != status )
6483 break;
6484
6485 pCurrent = pNext;
6486 }
6487 pAdapterNode = pCurrent;
6488 if( VOS_STATUS_SUCCESS == status )
6489 {
6490 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
6491 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306492
6493#ifdef FEATURE_WLAN_TDLS
6494
6495 /* A Mutex Lock is introduced while changing/initializing the mode to
6496 * protect the concurrent access for the Adapters by TDLS module.
6497 */
Rajesh Chauhana34c6e62014-03-25 16:37:58 +05306498 mutex_lock(&pHddCtx->tdls_lock);
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306499#endif
6500
Jeff Johnson295189b2012-06-20 16:38:30 -07006501 hdd_remove_adapter( pHddCtx, pAdapterNode );
6502 vos_mem_free( pAdapterNode );
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08006503 pAdapterNode = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006504
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306505#ifdef FEATURE_WLAN_TDLS
6506 mutex_unlock(&pHddCtx->tdls_lock);
6507#endif
6508
Jeff Johnson295189b2012-06-20 16:38:30 -07006509
6510 /* If there is a single session of STA/P2P client, re-enable BMPS */
6511 if ((!vos_concurrent_sessions_running()) &&
6512 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
6513 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
6514 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306515 if (pHddCtx->hdd_wlan_suspended)
6516 {
6517 hdd_set_pwrparams(pHddCtx);
6518 }
6519 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07006520 }
6521
6522 return VOS_STATUS_SUCCESS;
6523 }
6524
6525 return VOS_STATUS_E_FAILURE;
6526}
6527
6528VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
6529{
6530 hdd_adapter_list_node_t *pHddAdapterNode;
6531 VOS_STATUS status;
6532
6533 ENTER();
6534
6535 do
6536 {
6537 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
6538 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
6539 {
6540 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
6541 vos_mem_free( pHddAdapterNode );
6542 }
6543 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
6544
6545 EXIT();
6546
6547 return VOS_STATUS_SUCCESS;
6548}
6549
6550void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
6551{
6552 v_U8_t addIE[1] = {0};
6553
6554 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6555 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
6556 eANI_BOOLEAN_FALSE) )
6557 {
6558 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006559 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006560 }
6561
6562 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6563 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
6564 eANI_BOOLEAN_FALSE) )
6565 {
6566 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006567 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006568 }
6569
6570 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6571 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
6572 eANI_BOOLEAN_FALSE) )
6573 {
6574 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006575 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006576 }
6577}
6578
6579VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
6580{
6581 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
6582 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6583 union iwreq_data wrqu;
Kaushik, Sushant7005e372014-04-08 11:36:54 +05306584 v_U8_t retry = 0;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306585 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07006586
6587 ENTER();
6588
6589 switch(pAdapter->device_mode)
6590 {
6591 case WLAN_HDD_INFRA_STATION:
6592 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006593 case WLAN_HDD_P2P_DEVICE:
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05306594 {
6595 hdd_station_ctx_t *pstation = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6596 if( hdd_connIsConnected(pstation) ||
6597 (pstation->conn_info.connState == eConnectionState_Connecting) )
Jeff Johnson295189b2012-06-20 16:38:30 -07006598 {
6599 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
6600 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
6601 pAdapter->sessionId,
6602 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
6603 else
6604 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
6605 pAdapter->sessionId,
6606 eCSR_DISCONNECT_REASON_UNSPECIFIED);
6607 //success implies disconnect command got queued up successfully
6608 if(halStatus == eHAL_STATUS_SUCCESS)
6609 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306610 ret = wait_for_completion_interruptible_timeout(
6611 &pAdapter->disconnect_comp_var,
6612 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6613 if (ret <= 0)
6614 {
6615 hddLog(VOS_TRACE_LEVEL_ERROR,
6616 "%s: wait on disconnect_comp_var failed %ld",
6617 __func__, ret);
6618 }
6619 }
6620 else
6621 {
6622 hddLog(LOGE, "%s: failed to post disconnect event to SME",
6623 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006624 }
6625 memset(&wrqu, '\0', sizeof(wrqu));
6626 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
6627 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
6628 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
6629 }
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05306630 else if(pstation->conn_info.connState ==
6631 eConnectionState_Disconnecting)
6632 {
6633 ret = wait_for_completion_interruptible_timeout(
6634 &pAdapter->disconnect_comp_var,
6635 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6636 if (ret <= 0)
6637 {
6638 hddLog(VOS_TRACE_LEVEL_ERROR,
6639 FL("wait on disconnect_comp_var failed %ld"), ret);
6640 }
6641 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006642 else
6643 {
Srinivas, Dasari138af4f2014-02-07 11:13:45 +05306644 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
6645 eCSR_SCAN_ABORT_DEFAULT);
Jeff Johnson295189b2012-06-20 16:38:30 -07006646 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +05306647 if (pAdapter->device_mode != WLAN_HDD_INFRA_STATION)
6648 {
6649 while (pAdapter->is_roc_inprogress)
6650 {
6651 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6652 "%s: ROC in progress for session %d!!!",
6653 __func__, pAdapter->sessionId);
6654 // waiting for ROC to expire
6655 msleep(500);
6656 /* In GO present case , if retry exceeds 3,
6657 it means something went wrong. */
6658 if ( retry++ > MAX_WAIT_FOR_ROC_COMPLETION )
6659 {
6660 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6661 "%s: ROC completion is not received.!!!", __func__);
6662 sme_CancelRemainOnChannel(WLAN_HDD_GET_HAL_CTX(pAdapter),
6663 pAdapter->sessionId);
6664 wait_for_completion_interruptible_timeout(
6665 &pAdapter->cancel_rem_on_chan_var,
6666 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
6667 break;
6668 }
6669 }
6670 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306671#ifdef WLAN_NS_OFFLOAD
Vinay Krishna Eranna941360f2014-01-16 15:38:22 +05306672#ifdef WLAN_OPEN_SOURCE
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306673 cancel_work_sync(&pAdapter->ipv6NotifierWorkQueue);
6674#endif
Vinay Krishna Eranna941360f2014-01-16 15:38:22 +05306675 if (pAdapter->ipv6_notifier_registered)
6676 {
6677 hddLog(LOG1, FL("Unregistered IPv6 notifier"));
6678 unregister_inet6addr_notifier(&pAdapter->ipv6_notifier);
6679 pAdapter->ipv6_notifier_registered = false;
6680 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306681#endif
Vinay Krishna Erannad9cbdb32014-01-16 12:59:10 +05306682 if (pAdapter->ipv4_notifier_registered)
6683 {
6684 hddLog(LOG1, FL("Unregistered IPv4 notifier"));
6685 unregister_inetaddr_notifier(&pAdapter->ipv4_notifier);
6686 pAdapter->ipv4_notifier_registered = false;
6687 }
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05306688#ifdef WLAN_OPEN_SOURCE
6689 cancel_work_sync(&pAdapter->ipv4NotifierWorkQueue);
6690#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006691 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
6692 {
6693 INIT_COMPLETION(pAdapter->session_close_comp_var);
6694 if (eHAL_STATUS_SUCCESS ==
6695 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
6696 hdd_smeCloseSessionCallback, pAdapter))
6697 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306698 unsigned long ret;
6699
Jeff Johnson295189b2012-06-20 16:38:30 -07006700 //Block on a completion variable. Can't wait forever though.
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306701 ret = wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07006702 &pAdapter->session_close_comp_var,
6703 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306704 if ( 0 >= ret)
6705 {
6706 hddLog(LOGE, "%s: failure waiting for session_close_comp_var %ld",
6707 __func__, ret);
6708 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006709 }
6710 }
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05306711 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006712 break;
6713
6714 case WLAN_HDD_SOFTAP:
6715 case WLAN_HDD_P2P_GO:
6716 //Any softap specific cleanup here...
Kaushik, Sushant7005e372014-04-08 11:36:54 +05306717 if (pAdapter->device_mode == WLAN_HDD_P2P_GO) {
6718 while (pAdapter->is_roc_inprogress) {
6719 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6720 "%s: ROC in progress for session %d!!!",
6721 __func__, pAdapter->sessionId);
6722 msleep(500);
6723 if ( retry++ > MAX_WAIT_FOR_ROC_COMPLETION ) {
6724 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6725 "%s: ROC completion is not received.!!!", __func__);
6726 WLANSAP_CancelRemainOnChannel(
6727 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
6728 wait_for_completion_interruptible_timeout(
6729 &pAdapter->cancel_rem_on_chan_var,
6730 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
6731 break;
6732 }
6733 }
6734 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006735 mutex_lock(&pHddCtx->sap_lock);
6736 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
6737 {
6738 VOS_STATUS status;
6739 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6740
6741 //Stop Bss.
6742 status = WLANSAP_StopBss(pHddCtx->pvosContext);
6743 if (VOS_IS_STATUS_SUCCESS(status))
6744 {
6745 hdd_hostapd_state_t *pHostapdState =
6746 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6747
6748 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
6749
6750 if (!VOS_IS_STATUS_SUCCESS(status))
6751 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306752 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss %d",
6753 __func__, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07006754 }
6755 }
6756 else
6757 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006758 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006759 }
6760 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
6761
6762 if (eHAL_STATUS_FAILURE ==
6763 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
6764 0, NULL, eANI_BOOLEAN_FALSE))
6765 {
6766 hddLog(LOGE,
6767 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006768 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006769 }
6770
6771 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
6772 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
6773 eANI_BOOLEAN_FALSE) )
6774 {
6775 hddLog(LOGE,
6776 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
6777 }
6778
6779 // Reset WNI_CFG_PROBE_RSP Flags
6780 wlan_hdd_reset_prob_rspies(pAdapter);
6781 kfree(pAdapter->sessionCtx.ap.beacon);
6782 pAdapter->sessionCtx.ap.beacon = NULL;
6783 }
6784 mutex_unlock(&pHddCtx->sap_lock);
6785 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006786
Jeff Johnson295189b2012-06-20 16:38:30 -07006787 case WLAN_HDD_MONITOR:
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006788#ifdef WLAN_OPEN_SOURCE
6789 cancel_work_sync(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue);
6790#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006791 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006792
Jeff Johnson295189b2012-06-20 16:38:30 -07006793 default:
6794 break;
6795 }
6796
6797 EXIT();
6798 return VOS_STATUS_SUCCESS;
6799}
6800
6801VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
6802{
6803 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6804 VOS_STATUS status;
6805 hdd_adapter_t *pAdapter;
6806
6807 ENTER();
6808
6809 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6810
6811 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6812 {
6813 pAdapter = pAdapterNode->pAdapter;
6814 netif_tx_disable(pAdapter->dev);
6815 netif_carrier_off(pAdapter->dev);
6816
6817 hdd_stop_adapter( pHddCtx, pAdapter );
6818
6819 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6820 pAdapterNode = pNext;
6821 }
6822
6823 EXIT();
6824
6825 return VOS_STATUS_SUCCESS;
6826}
6827
Rajeev Kumarf999e582014-01-09 17:33:29 -08006828
6829#ifdef FEATURE_WLAN_BATCH_SCAN
6830/**---------------------------------------------------------------------------
6831
6832 \brief hdd_deinit_batch_scan () - This function cleans up batch scan data
6833 structures
6834
6835 \param - pAdapter Pointer to HDD adapter
6836
6837 \return - None
6838
6839 --------------------------------------------------------------------------*/
6840void hdd_deinit_batch_scan(hdd_adapter_t *pAdapter)
6841{
6842 tHddBatchScanRsp *pNode;
6843 tHddBatchScanRsp *pPrev;
6844
Siddharth Bhalb3e9b792014-02-24 15:14:16 +05306845 if (NULL == pAdapter)
Rajeev Kumarf999e582014-01-09 17:33:29 -08006846 {
Siddharth Bhalb3e9b792014-02-24 15:14:16 +05306847 hddLog(VOS_TRACE_LEVEL_ERROR,
6848 "%s: Adapter context is Null", __func__);
6849 return;
6850 }
6851
6852 pNode = pAdapter->pBatchScanRsp;
6853 while (pNode)
6854 {
6855 pPrev = pNode;
6856 pNode = pNode->pNext;
6857 vos_mem_free((v_VOID_t * )pPrev);
Rajeev Kumarf999e582014-01-09 17:33:29 -08006858 }
6859
6860 pAdapter->pBatchScanRsp = NULL;
6861 pAdapter->numScanList = 0;
6862 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
6863 pAdapter->prev_batch_id = 0;
6864
6865 return;
6866}
6867#endif
6868
6869
Jeff Johnson295189b2012-06-20 16:38:30 -07006870VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
6871{
6872 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6873 VOS_STATUS status;
6874 hdd_adapter_t *pAdapter;
6875
6876 ENTER();
6877
6878 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6879
6880 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6881 {
6882 pAdapter = pAdapterNode->pAdapter;
6883 netif_tx_disable(pAdapter->dev);
6884 netif_carrier_off(pAdapter->dev);
6885
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07006886 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
6887
Jeff Johnson295189b2012-06-20 16:38:30 -07006888 hdd_deinit_tx_rx(pAdapter);
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05306889 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
6890 {
6891 hdd_wmm_adapter_close( pAdapter );
6892 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
6893 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006894
Rajeev Kumarf999e582014-01-09 17:33:29 -08006895#ifdef FEATURE_WLAN_BATCH_SCAN
6896 if (eHDD_BATCH_SCAN_STATE_STARTED == pAdapter->batchScanState)
6897 {
6898 hdd_deinit_batch_scan(pAdapter);
6899 }
6900#endif
6901
Jeff Johnson295189b2012-06-20 16:38:30 -07006902 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6903 pAdapterNode = pNext;
6904 }
6905
6906 EXIT();
6907
6908 return VOS_STATUS_SUCCESS;
6909}
6910
6911VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
6912{
6913 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6914 VOS_STATUS status;
6915 hdd_adapter_t *pAdapter;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306916 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -07006917
6918 ENTER();
6919
6920 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6921
6922 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6923 {
6924 pAdapter = pAdapterNode->pAdapter;
6925
6926 switch(pAdapter->device_mode)
6927 {
6928 case WLAN_HDD_INFRA_STATION:
6929 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006930 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306931
6932 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
6933
Jeff Johnson295189b2012-06-20 16:38:30 -07006934 hdd_init_station_mode(pAdapter);
6935 /* Open the gates for HDD to receive Wext commands */
6936 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07006937 pHddCtx->scan_info.mScanPending = FALSE;
6938 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006939
6940 //Trigger the initial scan
6941 hdd_wlan_initial_scan(pAdapter);
6942
6943 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306944 if (eConnectionState_Associated == connState ||
6945 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -07006946 {
6947 union iwreq_data wrqu;
6948 memset(&wrqu, '\0', sizeof(wrqu));
6949 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
6950 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
6951 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07006952 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006953
Jeff Johnson295189b2012-06-20 16:38:30 -07006954 /* indicate disconnected event to nl80211 */
6955 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
6956 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07006957 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306958 else if (eConnectionState_Connecting == connState)
6959 {
6960 /*
6961 * Indicate connect failure to supplicant if we were in the
6962 * process of connecting
6963 */
6964 cfg80211_connect_result(pAdapter->dev, NULL,
6965 NULL, 0, NULL, 0,
6966 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
6967 GFP_KERNEL);
6968 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006969 break;
6970
6971 case WLAN_HDD_SOFTAP:
6972 /* softAP can handle SSR */
6973 break;
6974
6975 case WLAN_HDD_P2P_GO:
Sameer Thalappiledf0d792013-08-09 14:31:03 -07006976 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send stop ap to supplicant",
Jeff Johnson295189b2012-06-20 16:38:30 -07006977 __func__);
Sameer Thalappiledf0d792013-08-09 14:31:03 -07006978 cfg80211_ap_stopped(pAdapter->dev, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07006979 break;
6980
6981 case WLAN_HDD_MONITOR:
6982 /* monitor interface start */
6983 break;
6984 default:
6985 break;
6986 }
6987
6988 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6989 pAdapterNode = pNext;
6990 }
6991
6992 EXIT();
6993
6994 return VOS_STATUS_SUCCESS;
6995}
6996
6997VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
6998{
6999 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7000 hdd_adapter_t *pAdapter;
7001 VOS_STATUS status;
7002 v_U32_t roamId;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307003 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07007004
7005 ENTER();
7006
7007 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7008
7009 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7010 {
7011 pAdapter = pAdapterNode->pAdapter;
7012
7013 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
7014 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
7015 {
7016 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7017 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
7018
Abhishek Singhf4669da2014-05-26 15:07:49 +05307019 hddLog(VOS_TRACE_LEVEL_INFO,
7020 "%s: Set HDD connState to eConnectionState_NotConnected",
7021 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007022 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
7023 init_completion(&pAdapter->disconnect_comp_var);
7024 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
7025 eCSR_DISCONNECT_REASON_UNSPECIFIED);
7026
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307027 ret = wait_for_completion_interruptible_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07007028 &pAdapter->disconnect_comp_var,
7029 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307030 if (0 >= ret)
7031 hddLog(LOGE, "%s: failure waiting for disconnect_comp_var %ld",
7032 __func__, ret);
Jeff Johnson295189b2012-06-20 16:38:30 -07007033
7034 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
7035 pHddCtx->isAmpAllowed = VOS_FALSE;
7036 sme_RoamConnect(pHddCtx->hHal,
7037 pAdapter->sessionId, &(pWextState->roamProfile),
7038 &roamId);
7039 }
7040
7041 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7042 pAdapterNode = pNext;
7043 }
7044
7045 EXIT();
7046
7047 return VOS_STATUS_SUCCESS;
7048}
7049
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07007050void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
7051{
7052 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7053 VOS_STATUS status;
7054 hdd_adapter_t *pAdapter;
7055 hdd_station_ctx_t *pHddStaCtx;
7056 hdd_ap_ctx_t *pHddApCtx;
7057 hdd_hostapd_state_t * pHostapdState;
7058 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
7059 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
7060 const char *p2pMode = "DEV";
7061 const char *ccMode = "Standalone";
7062 int n;
7063
7064 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7065 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7066 {
7067 pAdapter = pAdapterNode->pAdapter;
7068 switch (pAdapter->device_mode) {
7069 case WLAN_HDD_INFRA_STATION:
7070 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7071 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
7072 staChannel = pHddStaCtx->conn_info.operationChannel;
7073 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
7074 }
7075 break;
7076 case WLAN_HDD_P2P_CLIENT:
7077 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7078 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
7079 p2pChannel = pHddStaCtx->conn_info.operationChannel;
7080 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
7081 p2pMode = "CLI";
7082 }
7083 break;
7084 case WLAN_HDD_P2P_GO:
7085 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
7086 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
7087 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
7088 p2pChannel = pHddApCtx->operatingChannel;
7089 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
7090 }
7091 p2pMode = "GO";
7092 break;
7093 case WLAN_HDD_SOFTAP:
7094 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
7095 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
7096 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
7097 apChannel = pHddApCtx->operatingChannel;
7098 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
7099 }
7100 break;
7101 default:
7102 break;
7103 }
7104 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7105 pAdapterNode = pNext;
7106 }
7107 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
7108 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
7109 }
7110 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
7111 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
7112 if (p2pChannel > 0) {
7113 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
7114 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
7115 }
7116 if (apChannel > 0) {
7117 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
7118 apChannel, MAC_ADDR_ARRAY(apBssid));
7119 }
7120
7121 if (p2pChannel > 0 && apChannel > 0) {
7122 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
7123 }
7124}
7125
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07007126bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07007127{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07007128 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07007129}
7130
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07007131/* Once SSR is disabled then it cannot be set. */
7132void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07007133{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07007134 if (HDD_SSR_DISABLED == isSsrRequired)
7135 return;
7136
Jeff Johnson295189b2012-06-20 16:38:30 -07007137 isSsrRequired = value;
7138}
7139
7140VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
7141 hdd_adapter_list_node_t** ppAdapterNode)
7142{
7143 VOS_STATUS status;
7144 spin_lock(&pHddCtx->hddAdapters.lock);
7145 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
7146 (hdd_list_node_t**) ppAdapterNode );
7147 spin_unlock(&pHddCtx->hddAdapters.lock);
7148 return status;
7149}
7150
7151VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
7152 hdd_adapter_list_node_t* pAdapterNode,
7153 hdd_adapter_list_node_t** pNextAdapterNode)
7154{
7155 VOS_STATUS status;
7156 spin_lock(&pHddCtx->hddAdapters.lock);
7157 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
7158 (hdd_list_node_t*) pAdapterNode,
7159 (hdd_list_node_t**)pNextAdapterNode );
7160
7161 spin_unlock(&pHddCtx->hddAdapters.lock);
7162 return status;
7163}
7164
7165VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
7166 hdd_adapter_list_node_t* pAdapterNode)
7167{
7168 VOS_STATUS status;
7169 spin_lock(&pHddCtx->hddAdapters.lock);
7170 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
7171 &pAdapterNode->node );
7172 spin_unlock(&pHddCtx->hddAdapters.lock);
7173 return status;
7174}
7175
7176VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
7177 hdd_adapter_list_node_t** ppAdapterNode)
7178{
7179 VOS_STATUS status;
7180 spin_lock(&pHddCtx->hddAdapters.lock);
7181 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
7182 (hdd_list_node_t**) ppAdapterNode );
7183 spin_unlock(&pHddCtx->hddAdapters.lock);
7184 return status;
7185}
7186
7187VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
7188 hdd_adapter_list_node_t* pAdapterNode)
7189{
7190 VOS_STATUS status;
7191 spin_lock(&pHddCtx->hddAdapters.lock);
7192 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
7193 (hdd_list_node_t*) pAdapterNode );
7194 spin_unlock(&pHddCtx->hddAdapters.lock);
7195 return status;
7196}
7197
7198VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
7199 hdd_adapter_list_node_t* pAdapterNode)
7200{
7201 VOS_STATUS status;
7202 spin_lock(&pHddCtx->hddAdapters.lock);
7203 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
7204 (hdd_list_node_t*) pAdapterNode );
7205 spin_unlock(&pHddCtx->hddAdapters.lock);
7206 return status;
7207}
7208
7209hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
7210 tSirMacAddr macAddr )
7211{
7212 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7213 hdd_adapter_t *pAdapter;
7214 VOS_STATUS status;
7215
7216 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7217
7218 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7219 {
7220 pAdapter = pAdapterNode->pAdapter;
7221
7222 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
7223 macAddr, sizeof(tSirMacAddr) ) )
7224 {
7225 return pAdapter;
7226 }
7227 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7228 pAdapterNode = pNext;
7229 }
7230
7231 return NULL;
7232
7233}
7234
7235hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
7236{
7237 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7238 hdd_adapter_t *pAdapter;
7239 VOS_STATUS status;
7240
7241 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7242
7243 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7244 {
7245 pAdapter = pAdapterNode->pAdapter;
7246
7247 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
7248 IFNAMSIZ ) )
7249 {
7250 return pAdapter;
7251 }
7252 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7253 pAdapterNode = pNext;
7254 }
7255
7256 return NULL;
7257
7258}
7259
7260hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
7261{
7262 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7263 hdd_adapter_t *pAdapter;
7264 VOS_STATUS status;
7265
7266 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7267
7268 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7269 {
7270 pAdapter = pAdapterNode->pAdapter;
7271
7272 if( pAdapter && (mode == pAdapter->device_mode) )
7273 {
7274 return pAdapter;
7275 }
7276 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7277 pAdapterNode = pNext;
7278 }
7279
7280 return NULL;
7281
7282}
7283
7284//Remove this function later
7285hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
7286{
7287 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7288 hdd_adapter_t *pAdapter;
7289 VOS_STATUS status;
7290
7291 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7292
7293 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7294 {
7295 pAdapter = pAdapterNode->pAdapter;
7296
7297 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
7298 {
7299 return pAdapter;
7300 }
7301
7302 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7303 pAdapterNode = pNext;
7304 }
7305
7306 return NULL;
7307
7308}
7309
Jeff Johnson295189b2012-06-20 16:38:30 -07007310/**---------------------------------------------------------------------------
7311
7312 \brief hdd_set_monitor_tx_adapter() -
7313
7314 This API initializes the adapter to be used while transmitting on monitor
7315 adapter.
7316
7317 \param - pHddCtx - Pointer to the HDD context.
7318 pAdapter - Adapter that will used for TX. This can be NULL.
7319 \return - None.
7320 --------------------------------------------------------------------------*/
7321void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
7322{
7323 hdd_adapter_t *pMonAdapter;
7324
7325 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
7326
7327 if( NULL != pMonAdapter )
7328 {
7329 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
7330 }
7331}
Jeff Johnson295189b2012-06-20 16:38:30 -07007332/**---------------------------------------------------------------------------
7333
7334 \brief hdd_select_queue() -
7335
7336 This API returns the operating channel of the requested device mode
7337
7338 \param - pHddCtx - Pointer to the HDD context.
7339 - mode - Device mode for which operating channel is required
7340 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
7341 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
7342 \return - channel number. "0" id the requested device is not found OR it is not connected.
7343 --------------------------------------------------------------------------*/
7344v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
7345{
7346 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7347 VOS_STATUS status;
7348 hdd_adapter_t *pAdapter;
7349 v_U8_t operatingChannel = 0;
7350
7351 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7352
7353 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7354 {
7355 pAdapter = pAdapterNode->pAdapter;
7356
7357 if( mode == pAdapter->device_mode )
7358 {
7359 switch(pAdapter->device_mode)
7360 {
7361 case WLAN_HDD_INFRA_STATION:
7362 case WLAN_HDD_P2P_CLIENT:
7363 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
7364 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
7365 break;
7366 case WLAN_HDD_SOFTAP:
7367 case WLAN_HDD_P2P_GO:
7368 /*softap connection info */
7369 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
7370 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
7371 break;
7372 default:
7373 break;
7374 }
7375
7376 break; //Found the device of interest. break the loop
7377 }
7378
7379 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7380 pAdapterNode = pNext;
7381 }
7382 return operatingChannel;
7383}
7384
7385#ifdef WLAN_FEATURE_PACKET_FILTERING
7386/**---------------------------------------------------------------------------
7387
7388 \brief hdd_set_multicast_list() -
7389
7390 This used to set the multicast address list.
7391
7392 \param - dev - Pointer to the WLAN device.
7393 - skb - Pointer to OS packet (sk_buff).
7394 \return - success/fail
7395
7396 --------------------------------------------------------------------------*/
7397static void hdd_set_multicast_list(struct net_device *dev)
7398{
7399 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07007400 int mc_count;
7401 int i = 0;
7402 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307403
7404 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07007405 {
7406 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307407 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007408 return;
7409 }
7410
7411 if (dev->flags & IFF_ALLMULTI)
7412 {
7413 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007414 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307415 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07007416 }
7417 else
7418 {
7419 mc_count = netdev_mc_count(dev);
7420 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007421 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07007422 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
7423 {
7424 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007425 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307426 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07007427 return;
7428 }
7429
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307430 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07007431
7432 netdev_for_each_mc_addr(ha, dev) {
7433 if (i == mc_count)
7434 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307435 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
7436 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
Arif Hussain6d2a3322013-11-17 19:50:10 -08007437 hddLog(VOS_TRACE_LEVEL_INFO, "%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07007438 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307439 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07007440 i++;
7441 }
7442 }
7443 return;
7444}
7445#endif
7446
7447/**---------------------------------------------------------------------------
7448
7449 \brief hdd_select_queue() -
7450
7451 This function is registered with the Linux OS for network
7452 core to decide which queue to use first.
7453
7454 \param - dev - Pointer to the WLAN device.
7455 - skb - Pointer to OS packet (sk_buff).
7456 \return - ac, Queue Index/access category corresponding to UP in IP header
7457
7458 --------------------------------------------------------------------------*/
7459v_U16_t hdd_select_queue(struct net_device *dev,
7460 struct sk_buff *skb)
7461{
7462 return hdd_wmm_select_queue(dev, skb);
7463}
7464
7465
7466/**---------------------------------------------------------------------------
7467
7468 \brief hdd_wlan_initial_scan() -
7469
7470 This function triggers the initial scan
7471
7472 \param - pAdapter - Pointer to the HDD adapter.
7473
7474 --------------------------------------------------------------------------*/
7475void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
7476{
7477 tCsrScanRequest scanReq;
7478 tCsrChannelInfo channelInfo;
7479 eHalStatus halStatus;
Jeff Johnson02797792013-10-26 19:17:13 -07007480 tANI_U32 scanId;
Jeff Johnson295189b2012-06-20 16:38:30 -07007481 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7482
7483 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
7484 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
7485 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
7486
7487 if(sme_Is11dSupported(pHddCtx->hHal))
7488 {
7489 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
7490 if ( HAL_STATUS_SUCCESS( halStatus ) )
7491 {
7492 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
7493 if( !scanReq.ChannelInfo.ChannelList )
7494 {
7495 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
7496 vos_mem_free(channelInfo.ChannelList);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08007497 channelInfo.ChannelList = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007498 return;
7499 }
7500 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
7501 channelInfo.numOfChannels);
7502 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
7503 vos_mem_free(channelInfo.ChannelList);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08007504 channelInfo.ChannelList = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007505 }
7506
7507 scanReq.scanType = eSIR_PASSIVE_SCAN;
7508 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
7509 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
7510 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
7511 }
7512 else
7513 {
7514 scanReq.scanType = eSIR_ACTIVE_SCAN;
7515 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
7516 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
7517 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
7518 }
7519
7520 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
7521 if ( !HAL_STATUS_SUCCESS( halStatus ) )
7522 {
7523 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
7524 __func__, halStatus );
7525 }
7526
7527 if(sme_Is11dSupported(pHddCtx->hHal))
7528 vos_mem_free(scanReq.ChannelInfo.ChannelList);
7529}
7530
Jeff Johnson295189b2012-06-20 16:38:30 -07007531/**---------------------------------------------------------------------------
7532
7533 \brief hdd_full_power_callback() - HDD full power callback function
7534
7535 This is the function invoked by SME to inform the result of a full power
7536 request issued by HDD
7537
7538 \param - callbackcontext - Pointer to cookie
7539 \param - status - result of request
7540
7541 \return - None
7542
7543 --------------------------------------------------------------------------*/
7544static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
7545{
Jeff Johnson72a40512013-12-19 10:14:15 -08007546 struct statsContext *pContext = callbackContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07007547
7548 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307549 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07007550
7551 if (NULL == callbackContext)
7552 {
7553 hddLog(VOS_TRACE_LEVEL_ERROR,
7554 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007555 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07007556 return;
7557 }
7558
Jeff Johnson72a40512013-12-19 10:14:15 -08007559 /* there is a race condition that exists between this callback
7560 function and the caller since the caller could time out either
7561 before or while this code is executing. we use a spinlock to
7562 serialize these actions */
7563 spin_lock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07007564
7565 if (POWER_CONTEXT_MAGIC != pContext->magic)
7566 {
7567 /* the caller presumably timed out so there is nothing we can do */
Jeff Johnson72a40512013-12-19 10:14:15 -08007568 spin_unlock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07007569 hddLog(VOS_TRACE_LEVEL_WARN,
7570 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007571 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07007572 return;
7573 }
7574
Jeff Johnson72a40512013-12-19 10:14:15 -08007575 /* context is valid so caller is still waiting */
7576
7577 /* paranoia: invalidate the magic */
7578 pContext->magic = 0;
7579
7580 /* notify the caller */
Jeff Johnson295189b2012-06-20 16:38:30 -07007581 complete(&pContext->completion);
Jeff Johnson72a40512013-12-19 10:14:15 -08007582
7583 /* serialization is complete */
7584 spin_unlock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07007585}
7586
7587/**---------------------------------------------------------------------------
7588
7589 \brief hdd_wlan_exit() - HDD WLAN exit function
7590
7591 This is the driver exit point (invoked during rmmod)
7592
7593 \param - pHddCtx - Pointer to the HDD Context
7594
7595 \return - None
7596
7597 --------------------------------------------------------------------------*/
7598void hdd_wlan_exit(hdd_context_t *pHddCtx)
7599{
7600 eHalStatus halStatus;
7601 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
7602 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05307603 struct wiphy *wiphy = pHddCtx->wiphy;
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -08007604 hdd_adapter_t* pAdapter = NULL;
Jeff Johnson72a40512013-12-19 10:14:15 -08007605 struct statsContext powerContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07007606 long lrc;
c_hpothu5ab05e92014-06-13 17:34:05 +05307607 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007608
7609 ENTER();
7610
Jeff Johnson88ba7742013-02-27 14:36:02 -08007611 if (VOS_FTM_MODE != hdd_get_conparam())
7612 {
7613 // Unloading, restart logic is no more required.
7614 wlan_hdd_restart_deinit(pHddCtx);
Jeff Johnsone7245742012-09-05 17:12:55 -07007615
c_hpothu5ab05e92014-06-13 17:34:05 +05307616 vosStatus = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7617 while (NULL != pAdapterNode && VOS_STATUS_E_EMPTY != vosStatus)
Jeff Johnson295189b2012-06-20 16:38:30 -07007618 {
c_hpothu5ab05e92014-06-13 17:34:05 +05307619 pAdapter = pAdapterNode->pAdapter;
7620 if (NULL != pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07007621 {
c_hpothu5ab05e92014-06-13 17:34:05 +05307622 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode ||
7623 WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)
7624 {
7625 wlan_hdd_cfg80211_deregister_frames(pAdapter);
7626 hdd_UnregisterWext(pAdapter->dev);
7627 }
7628 // Cancel any outstanding scan requests. We are about to close all
7629 // of our adapters, but an adapter structure is what SME passes back
7630 // to our callback function. Hence if there are any outstanding scan
7631 // requests then there is a race condition between when the adapter
7632 // is closed and when the callback is invoked.We try to resolve that
7633 // race condition here by canceling any outstanding scans before we
7634 // close the adapters.
7635 // Note that the scans may be cancelled in an asynchronous manner,
7636 // so ideally there needs to be some kind of synchronization. Rather
7637 // than introduce a new synchronization here, we will utilize the
7638 // fact that we are about to Request Full Power, and since that is
7639 // synchronized, the expectation is that by the time Request Full
7640 // Power has completed all scans will be cancelled.
7641 if (pHddCtx->scan_info.mScanPending)
7642 {
7643 hddLog(VOS_TRACE_LEVEL_INFO,
7644 FL("abort scan mode: %d sessionId: %d"),
7645 pAdapter->device_mode,
7646 pAdapter->sessionId);
7647 hdd_abort_mac_scan(pHddCtx,
7648 pAdapter->sessionId,
7649 eCSR_SCAN_ABORT_DEFAULT);
7650 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007651 }
c_hpothu5ab05e92014-06-13 17:34:05 +05307652 vosStatus = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7653 pAdapterNode = pNext;
Jeff Johnson295189b2012-06-20 16:38:30 -07007654 }
7655 }
c_hpothu5ab05e92014-06-13 17:34:05 +05307656 else
Jeff Johnson88ba7742013-02-27 14:36:02 -08007657 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307658 hddLog(VOS_TRACE_LEVEL_INFO,"%s: FTM MODE",__func__);
Jeff Johnson88ba7742013-02-27 14:36:02 -08007659 wlan_hdd_ftm_close(pHddCtx);
7660 goto free_hdd_ctx;
7661 }
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307662
Jeff Johnson295189b2012-06-20 16:38:30 -07007663 /* DeRegister with platform driver as client for Suspend/Resume */
7664 vosStatus = hddDeregisterPmOps(pHddCtx);
7665 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
7666 {
7667 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
7668 VOS_ASSERT(0);
7669 }
7670
7671 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
7672 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
7673 {
7674 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
7675 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007676
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07007677 //Stop the traffic monitor timer
7678 if ( VOS_TIMER_STATE_RUNNING ==
7679 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr))
7680 {
7681 vos_timer_stop(&pHddCtx->tx_rx_trafficTmr);
7682 }
7683
7684 // Destroy the traffic monitor timer
7685 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
7686 &pHddCtx->tx_rx_trafficTmr)))
7687 {
7688 hddLog(VOS_TRACE_LEVEL_ERROR,
7689 "%s: Cannot deallocate Traffic monitor timer", __func__);
7690 }
7691
Jeff Johnson295189b2012-06-20 16:38:30 -07007692 //Disable IMPS/BMPS as we do not want the device to enter any power
7693 //save mode during shutdown
7694 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
7695 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
7696 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
7697
7698 //Ensure that device is in full power as we will touch H/W during vos_Stop
7699 init_completion(&powerContext.completion);
7700 powerContext.magic = POWER_CONTEXT_MAGIC;
7701
7702 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
7703 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
7704
7705 if (eHAL_STATUS_SUCCESS != halStatus)
7706 {
7707 if (eHAL_STATUS_PMC_PENDING == halStatus)
7708 {
7709 /* request was sent -- wait for the response */
7710 lrc = wait_for_completion_interruptible_timeout(
7711 &powerContext.completion,
7712 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
Jeff Johnson295189b2012-06-20 16:38:30 -07007713 if (lrc <= 0)
7714 {
7715 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007716 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07007717 }
7718 }
7719 else
7720 {
7721 hddLog(VOS_TRACE_LEVEL_ERROR,
7722 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007723 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07007724 /* continue -- need to clean up as much as possible */
7725 }
7726 }
7727
Jeff Johnson72a40512013-12-19 10:14:15 -08007728 /* either we never sent a request, we sent a request and received a
7729 response or we sent a request and timed out. if we never sent a
7730 request or if we sent a request and got a response, we want to
7731 clear the magic out of paranoia. if we timed out there is a
7732 race condition such that the callback function could be
7733 executing at the same time we are. of primary concern is if the
7734 callback function had already verified the "magic" but had not
7735 yet set the completion variable when a timeout occurred. we
7736 serialize these activities by invalidating the magic while
7737 holding a shared spinlock which will cause us to block if the
7738 callback is currently executing */
7739 spin_lock(&hdd_context_lock);
7740 powerContext.magic = 0;
7741 spin_unlock(&hdd_context_lock);
7742
Yue Ma0d4891e2013-08-06 17:01:45 -07007743 hdd_debugfs_exit(pHddCtx);
7744
Jeff Johnson295189b2012-06-20 16:38:30 -07007745 // Unregister the Net Device Notifier
7746 unregister_netdevice_notifier(&hdd_netdev_notifier);
7747
Jeff Johnson295189b2012-06-20 16:38:30 -07007748 hdd_stop_all_adapters( pHddCtx );
7749
Jeff Johnson295189b2012-06-20 16:38:30 -07007750#ifdef WLAN_BTAMP_FEATURE
7751 vosStatus = WLANBAP_Stop(pVosContext);
7752 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
7753 {
7754 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7755 "%s: Failed to stop BAP",__func__);
7756 }
7757#endif //WLAN_BTAMP_FEATURE
7758
7759 //Stop all the modules
7760 vosStatus = vos_stop( pVosContext );
7761 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
7762 {
7763 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7764 "%s: Failed to stop VOSS",__func__);
7765 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7766 }
7767
Jeff Johnson295189b2012-06-20 16:38:30 -07007768 //Assert Deep sleep signal now to put Libra HW in lowest power state
7769 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
7770 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7771
7772 //Vote off any PMIC voltage supplies
7773 vos_chipPowerDown(NULL, NULL, NULL);
7774
7775 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
7776
Leo Chang59cdc7e2013-07-10 10:08:21 -07007777
Jeff Johnson295189b2012-06-20 16:38:30 -07007778 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07007779 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07007780
7781 //Close the scheduler before calling vos_close to make sure no thread is
7782 // scheduled after the each module close is called i.e after all the data
7783 // structures are freed.
7784 vosStatus = vos_sched_close( pVosContext );
7785 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
7786 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
7787 "%s: Failed to close VOSS Scheduler",__func__);
7788 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7789 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007790#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07007791#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
7792 /* Destroy the wake lock */
7793 wake_lock_destroy(&pHddCtx->rx_wake_lock);
7794#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08007795 /* Destroy the wake lock */
7796 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007797#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007798
Mihir Shete7a24b5f2013-12-21 12:18:31 +05307799#ifdef CONFIG_ENABLE_LINUX_REG
7800 vosStatus = vos_nv_close();
7801 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
7802 {
7803 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7804 "%s: Failed to close NV", __func__);
7805 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7806 }
7807#endif
7808
Jeff Johnson295189b2012-06-20 16:38:30 -07007809 //Close VOSS
7810 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
7811 vos_close(pVosContext);
7812
Jeff Johnson295189b2012-06-20 16:38:30 -07007813 //Close Watchdog
7814 if(pHddCtx->cfg_ini->fIsLogpEnabled)
7815 vos_watchdog_close(pVosContext);
7816
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05307817 //Clean up HDD Nlink Service
7818 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Leo Chang59cdc7e2013-07-10 10:08:21 -07007819#ifdef WLAN_KD_READY_NOTIFIER
7820 nl_srv_exit(pHddCtx->ptt_pid);
7821#else
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05307822 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07007823#endif /* WLAN_KD_READY_NOTIFIER */
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05307824
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05307825#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05307826 if (pHddCtx->cfg_ini->wlanLoggingEnable)
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05307827 {
7828 wlan_logging_sock_deactivate_svc();
7829 }
7830#endif
7831
Jeff Johnson295189b2012-06-20 16:38:30 -07007832 /* Cancel the vote for XO Core ON.
7833 * This is done here to ensure there is no race condition since MC, TX and WD threads have
7834 * exited at this point
7835 */
7836 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
Arif Hussain6d2a3322013-11-17 19:50:10 -08007837 " when WLAN is turned OFF");
Jeff Johnson295189b2012-06-20 16:38:30 -07007838 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
7839 {
7840 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
7841 " Not returning failure."
Arif Hussain6d2a3322013-11-17 19:50:10 -08007842 " Power consumed will be high");
Jeff Johnson295189b2012-06-20 16:38:30 -07007843 }
7844
7845 hdd_close_all_adapters( pHddCtx );
7846
Jeff Johnson295189b2012-06-20 16:38:30 -07007847 /* free the power on lock from platform driver */
7848 if (free_riva_power_on_lock("wlan"))
7849 {
7850 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
7851 __func__);
7852 }
7853
Jeff Johnson88ba7742013-02-27 14:36:02 -08007854free_hdd_ctx:
c_hpothu78c7b602014-05-17 17:35:49 +05307855
7856 //Free up dynamically allocated members inside HDD Adapter
7857 if (pHddCtx->cfg_ini)
7858 {
7859 kfree(pHddCtx->cfg_ini);
7860 pHddCtx->cfg_ini= NULL;
7861 }
7862
Leo Changf04ddad2013-09-18 13:46:38 -07007863 /* FTM mode, WIPHY did not registered
7864 If un-register here, system crash will happen */
7865 if (VOS_FTM_MODE != hdd_get_conparam())
7866 {
7867 wiphy_unregister(wiphy) ;
7868 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007869 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07007870 if (hdd_is_ssr_required())
7871 {
7872 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07007873 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07007874 msleep(5000);
7875 }
7876 hdd_set_ssr_required (VOS_FALSE);
7877}
7878
7879
7880/**---------------------------------------------------------------------------
7881
7882 \brief hdd_update_config_from_nv() - Function to update the contents of
7883 the running configuration with parameters taken from NV storage
7884
7885 \param - pHddCtx - Pointer to the HDD global context
7886
7887 \return - VOS_STATUS_SUCCESS if successful
7888
7889 --------------------------------------------------------------------------*/
7890static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
7891{
Jeff Johnson295189b2012-06-20 16:38:30 -07007892 v_BOOL_t itemIsValid = VOS_FALSE;
7893 VOS_STATUS status;
7894 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
7895 v_U8_t macLoop;
7896
7897 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
7898 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
7899 if(status != VOS_STATUS_SUCCESS)
7900 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08007901 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed");
Jeff Johnson295189b2012-06-20 16:38:30 -07007902 return VOS_STATUS_E_FAILURE;
7903 }
7904
7905 if (itemIsValid == VOS_TRUE)
7906 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08007907 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV");
Jeff Johnson295189b2012-06-20 16:38:30 -07007908 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
7909 VOS_MAX_CONCURRENCY_PERSONA);
7910 if(status != VOS_STATUS_SUCCESS)
7911 {
7912 /* Get MAC from NV fail, not update CFG info
7913 * INI MAC value will be used for MAC setting */
Arif Hussain6d2a3322013-11-17 19:50:10 -08007914 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed");
Jeff Johnson295189b2012-06-20 16:38:30 -07007915 return VOS_STATUS_E_FAILURE;
7916 }
7917
7918 /* If first MAC is not valid, treat all others are not valid
7919 * Then all MACs will be got from ini file */
7920 if(vos_is_macaddr_zero(&macFromNV[0]))
7921 {
7922 /* MAC address in NV file is not configured yet */
7923 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
7924 return VOS_STATUS_E_INVAL;
7925 }
7926
7927 /* Get MAC address from NV, update CFG info */
7928 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
7929 {
7930 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
7931 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307932 hddLog(VOS_TRACE_LEVEL_ERROR,"not valid MAC from NV for %d", macLoop);
Jeff Johnson295189b2012-06-20 16:38:30 -07007933 /* This MAC is not valid, skip it
7934 * This MAC will be got from ini file */
7935 }
7936 else
7937 {
7938 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
7939 (v_U8_t *)&macFromNV[macLoop].bytes[0],
7940 VOS_MAC_ADDR_SIZE);
7941 }
7942 }
7943 }
7944 else
7945 {
7946 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
7947 return VOS_STATUS_E_FAILURE;
7948 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007949
Jeff Johnson295189b2012-06-20 16:38:30 -07007950
7951 return VOS_STATUS_SUCCESS;
7952}
7953
7954/**---------------------------------------------------------------------------
7955
7956 \brief hdd_post_voss_start_config() - HDD post voss start config helper
7957
7958 \param - pAdapter - Pointer to the HDD
7959
7960 \return - None
7961
7962 --------------------------------------------------------------------------*/
7963VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
7964{
7965 eHalStatus halStatus;
7966 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307967 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -07007968
Jeff Johnson295189b2012-06-20 16:38:30 -07007969
7970 // Send ready indication to the HDD. This will kick off the MAC
7971 // into a 'running' state and should kick off an initial scan.
7972 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
7973 if ( !HAL_STATUS_SUCCESS( halStatus ) )
7974 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307975 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07007976 "code %08d [x%08x]",__func__, halStatus, halStatus );
7977 return VOS_STATUS_E_FAILURE;
7978 }
7979
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307980 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -07007981 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
7982 // And RIVA will crash
7983 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
7984 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307985 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
7986 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
7987
7988
Jeff Johnson295189b2012-06-20 16:38:30 -07007989 return VOS_STATUS_SUCCESS;
7990}
7991
Jeff Johnson295189b2012-06-20 16:38:30 -07007992/* wake lock APIs for HDD */
7993void hdd_prevent_suspend(void)
7994{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007995#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007996 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07007997#else
7998 wcnss_prevent_suspend();
7999#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008000}
8001
8002void hdd_allow_suspend(void)
8003{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008004#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008005 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008006#else
8007 wcnss_allow_suspend();
8008#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008009}
8010
Mahesh A Saptasagarb9c50402014-01-16 15:49:22 +05308011void hdd_prevent_suspend_timeout(v_U32_t timeout)
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07008012{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008013#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07008014 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07008015#else
8016 /* Do nothing as there is no API in wcnss for timeout*/
8017#endif
8018}
8019
Jeff Johnson295189b2012-06-20 16:38:30 -07008020/**---------------------------------------------------------------------------
8021
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008022 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
8023 information between Host and Riva
8024
8025 This function gets reported version of FW
8026 It also finds the version of Riva headers used to compile the host
8027 It compares the above two and prints a warning if they are different
8028 It gets the SW and HW version string
8029 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
8030 indicating the features they support through a bitmap
8031
8032 \param - pHddCtx - Pointer to HDD context
8033
8034 \return - void
8035
8036 --------------------------------------------------------------------------*/
8037
8038void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
8039{
8040
8041 tSirVersionType versionCompiled;
8042 tSirVersionType versionReported;
8043 tSirVersionString versionString;
8044 tANI_U8 fwFeatCapsMsgSupported = 0;
8045 VOS_STATUS vstatus;
8046
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -08008047 memset(&versionCompiled, 0, sizeof(versionCompiled));
8048 memset(&versionReported, 0, sizeof(versionReported));
8049
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008050 /* retrieve and display WCNSS version information */
8051 do {
8052
8053 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
8054 &versionCompiled);
8055 if (!VOS_IS_STATUS_SUCCESS(vstatus))
8056 {
8057 hddLog(VOS_TRACE_LEVEL_FATAL,
8058 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008059 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008060 break;
8061 }
8062
8063 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
8064 &versionReported);
8065 if (!VOS_IS_STATUS_SUCCESS(vstatus))
8066 {
8067 hddLog(VOS_TRACE_LEVEL_FATAL,
8068 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008069 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008070 break;
8071 }
8072
8073 if ((versionCompiled.major != versionReported.major) ||
8074 (versionCompiled.minor != versionReported.minor) ||
8075 (versionCompiled.version != versionReported.version) ||
8076 (versionCompiled.revision != versionReported.revision))
8077 {
8078 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
8079 "Host expected %u.%u.%u.%u\n",
8080 WLAN_MODULE_NAME,
8081 (int)versionReported.major,
8082 (int)versionReported.minor,
8083 (int)versionReported.version,
8084 (int)versionReported.revision,
8085 (int)versionCompiled.major,
8086 (int)versionCompiled.minor,
8087 (int)versionCompiled.version,
8088 (int)versionCompiled.revision);
8089 }
8090 else
8091 {
8092 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
8093 WLAN_MODULE_NAME,
8094 (int)versionReported.major,
8095 (int)versionReported.minor,
8096 (int)versionReported.version,
8097 (int)versionReported.revision);
8098 }
8099
8100 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
8101 versionString,
8102 sizeof(versionString));
8103 if (!VOS_IS_STATUS_SUCCESS(vstatus))
8104 {
8105 hddLog(VOS_TRACE_LEVEL_FATAL,
8106 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008107 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008108 break;
8109 }
8110
8111 pr_info("%s: WCNSS software version %s\n",
8112 WLAN_MODULE_NAME, versionString);
8113
8114 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
8115 versionString,
8116 sizeof(versionString));
8117 if (!VOS_IS_STATUS_SUCCESS(vstatus))
8118 {
8119 hddLog(VOS_TRACE_LEVEL_FATAL,
8120 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008121 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008122 break;
8123 }
8124
8125 pr_info("%s: WCNSS hardware version %s\n",
8126 WLAN_MODULE_NAME, versionString);
8127
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07008128 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
8129 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008130 send the message only if it the riva is 1.1
8131 minor numbers for different riva branches:
8132 0 -> (1.0)Mainline Build
8133 1 -> (1.1)Mainline Build
8134 2->(1.04) Stability Build
8135 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07008136 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008137 ((versionReported.minor>=1) && (versionReported.version>=1)))
8138 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
8139 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07008140
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008141 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08008142 {
8143#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
8144 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
8145 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
8146#endif
Ravi Joshid2ca7c42013-07-23 08:37:49 -07008147 /* Indicate if IBSS heartbeat monitoring needs to be offloaded */
8148 if (!pHddCtx->cfg_ini->enableIbssHeartBeatOffload)
8149 {
8150 sme_disableFeatureCapablity(IBSS_HEARTBEAT_OFFLOAD);
8151 }
8152
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008153 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08008154 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008155
8156 } while (0);
8157
8158}
8159
8160/**---------------------------------------------------------------------------
8161
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308162 \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
8163
8164 \param - pHddCtx - Pointer to the hdd context
8165
8166 \return - true if hardware supports 5GHz
8167
8168 --------------------------------------------------------------------------*/
Vinay Krishna Erannafacf5e22014-02-24 13:16:25 +05308169boolean hdd_is_5g_supported(hdd_context_t * pHddCtx)
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308170{
8171 /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
8172 * then hardware support 5Ghz.
8173 */
8174 if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode())
8175 {
Agarwal Ashish971c2882013-10-30 20:11:12 +05308176 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Hardware supports 5Ghz", __func__);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308177 return true;
8178 }
8179 else
8180 {
Agarwal Ashish971c2882013-10-30 20:11:12 +05308181 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Hardware doesn't supports 5Ghz",
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308182 __func__);
8183 return false;
8184 }
8185}
8186
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308187/**---------------------------------------------------------------------------
8188
8189 \brief hdd_generate_iface_mac_addr_auto() - HDD Mac Interface Auto
8190 generate function
8191
8192 This is generate the random mac address for WLAN interface
8193
8194 \param - pHddCtx - Pointer to HDD context
8195 idx - Start interface index to get auto
8196 generated mac addr.
8197 mac_addr - Mac address
8198
8199 \return - 0 for success, < 0 for failure
8200
8201 --------------------------------------------------------------------------*/
8202
8203static int hdd_generate_iface_mac_addr_auto(hdd_context_t *pHddCtx,
8204 int idx, v_MACADDR_t mac_addr)
8205{
8206 int i;
8207 unsigned int serialno;
8208 serialno = wcnss_get_serial_number();
8209
8210 if (0 != serialno)
8211 {
8212 /* MAC address has 3 bytes of OUI so we have a maximum of 3
8213 bytes of the serial number that can be used to generate
8214 the other 3 bytes of the MAC address. Mask off all but
8215 the lower 3 bytes (this will also make sure we don't
8216 overflow in the next step) */
8217 serialno &= 0x00FFFFFF;
8218
8219 /* we need a unique address for each session */
8220 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
8221
8222 /* autogen other Mac addresses */
8223 for (i = idx; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
8224 {
8225 /* start with the entire default address */
8226 pHddCtx->cfg_ini->intfMacAddr[i] = mac_addr;
8227 /* then replace the lower 3 bytes */
8228 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
8229 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
8230 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
8231
8232 serialno++;
8233 hddLog(VOS_TRACE_LEVEL_ERROR,
8234 "%s: Derived Mac Addr: "
8235 MAC_ADDRESS_STR, __func__,
8236 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[i].bytes));
8237 }
8238
8239 }
8240 else
8241 {
8242 hddLog(LOGE, FL("Failed to Get Serial NO"));
8243 return -1;
8244 }
8245 return 0;
8246}
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308247
8248/**---------------------------------------------------------------------------
8249
Mihir Shetefc7ff5b2014-01-27 11:30:05 +05308250 \brief hdd_11d_scan_done - callback to be executed when 11d scan is
8251 completed to flush out the scan results
8252
8253 11d scan is done during driver load and is a passive scan on all
8254 channels supported by the device, 11d scans may find some APs on
8255 frequencies which are forbidden to be used in the regulatory domain
8256 the device is operating in. If these APs are notified to the supplicant
8257 it may try to connect to these APs, thus flush out all the scan results
8258 which are present in SME after 11d scan is done.
8259
8260 \return - eHalStatus
8261
8262 --------------------------------------------------------------------------*/
8263static eHalStatus hdd_11d_scan_done(tHalHandle halHandle, void *pContext,
8264 tANI_U32 scanId, eCsrScanStatus status)
8265{
8266 ENTER();
8267
8268 sme_ScanFlushResult(halHandle, 0);
8269
8270 EXIT();
8271
8272 return eHAL_STATUS_SUCCESS;
8273}
8274
8275/**---------------------------------------------------------------------------
8276
Jeff Johnson295189b2012-06-20 16:38:30 -07008277 \brief hdd_wlan_startup() - HDD init function
8278
8279 This is the driver startup code executed once a WLAN device has been detected
8280
8281 \param - dev - Pointer to the underlying device
8282
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08008283 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07008284
8285 --------------------------------------------------------------------------*/
8286
8287int hdd_wlan_startup(struct device *dev )
8288{
8289 VOS_STATUS status;
8290 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07008291 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07008292 hdd_context_t *pHddCtx = NULL;
8293 v_CONTEXT_t pVosContext= NULL;
8294#ifdef WLAN_BTAMP_FEATURE
8295 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
8296 WLANBAP_ConfigType btAmpConfig;
8297 hdd_config_t *pConfig;
8298#endif
8299 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07008300 struct wiphy *wiphy;
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308301 v_MACADDR_t mac_addr;
Jeff Johnson295189b2012-06-20 16:38:30 -07008302
8303 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07008304 /*
8305 * cfg80211: wiphy allocation
8306 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308307 wiphy = wlan_hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t)) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07008308
8309 if(wiphy == NULL)
8310 {
8311 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08008312 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07008313 }
8314
8315 pHddCtx = wiphy_priv(wiphy);
8316
Jeff Johnson295189b2012-06-20 16:38:30 -07008317 //Initialize the adapter context to zeros.
8318 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
8319
Jeff Johnson295189b2012-06-20 16:38:30 -07008320 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07008321 hdd_prevent_suspend();
Mihir Shete18156292014-03-11 15:38:30 +05308322 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_LOAD_IN_PROGRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -07008323
8324 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
8325
8326 /*Get vos context here bcoz vos_open requires it*/
8327 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
8328
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08008329 if(pVosContext == NULL)
8330 {
8331 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
8332 goto err_free_hdd_context;
8333 }
8334
Jeff Johnson295189b2012-06-20 16:38:30 -07008335 //Save the Global VOSS context in adapter context for future.
8336 pHddCtx->pvosContext = pVosContext;
8337
8338 //Save the adapter context in global context for future.
8339 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
8340
Jeff Johnson295189b2012-06-20 16:38:30 -07008341 pHddCtx->parent_dev = dev;
8342
8343 init_completion(&pHddCtx->full_pwr_comp_var);
8344 init_completion(&pHddCtx->standby_comp_var);
8345 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07008346 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08008347 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Kiet Lam46b8e4e2013-11-06 21:49:53 +05308348 init_completion(&pHddCtx->wiphy_channel_update_event);
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +05308349 init_completion(&pHddCtx->ssr_comp_var);
Amar Singhala49cbc52013-10-08 18:37:44 -07008350
8351#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhalfddc28c2013-09-05 13:03:40 -07008352 init_completion(&pHddCtx->linux_reg_req);
Amar Singhala49cbc52013-10-08 18:37:44 -07008353#else
8354 init_completion(&pHddCtx->driver_crda_req);
8355#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008356
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05308357 spin_lock_init(&pHddCtx->schedScan_lock);
8358
Jeff Johnson295189b2012-06-20 16:38:30 -07008359 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
8360
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05308361#ifdef FEATURE_WLAN_TDLS
8362 /* tdls_lock is initialized before an hdd_open_adapter ( which is
8363 * invoked by other instances also) to protect the concurrent
8364 * access for the Adapters by TDLS module.
8365 */
8366 mutex_init(&pHddCtx->tdls_lock);
8367#endif
8368
Kiet Lam46b8e4e2013-11-06 21:49:53 +05308369 pHddCtx->nEnableStrictRegulatoryForFCC = TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07008370 // Load all config first as TL config is needed during vos_open
8371 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
8372 if(pHddCtx->cfg_ini == NULL)
8373 {
8374 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
8375 goto err_free_hdd_context;
8376 }
8377
8378 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
8379
8380 // Read and parse the qcom_cfg.ini file
8381 status = hdd_parse_config_ini( pHddCtx );
8382 if ( VOS_STATUS_SUCCESS != status )
8383 {
8384 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
8385 __func__, WLAN_INI_FILE);
8386 goto err_config;
8387 }
Arif Hussaind5218912013-12-05 01:10:55 -08008388#ifdef MEMORY_DEBUG
8389 if (pHddCtx->cfg_ini->IsMemoryDebugSupportEnabled)
8390 vos_mem_init();
8391
8392 hddLog(VOS_TRACE_LEVEL_INFO, "%s: gEnableMemoryDebug=%d",
8393 __func__, pHddCtx->cfg_ini->IsMemoryDebugSupportEnabled);
8394#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008395
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05308396 /* INI has been read, initialise the configuredMcastBcastFilter with
8397 * INI value as this will serve as the default value
8398 */
8399 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
8400 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
8401 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308402
8403 if (false == hdd_is_5g_supported(pHddCtx))
8404 {
8405 //5Ghz is not supported.
8406 if (1 != pHddCtx->cfg_ini->nBandCapability)
8407 {
8408 hddLog(VOS_TRACE_LEVEL_INFO,
8409 "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__);
8410 pHddCtx->cfg_ini->nBandCapability = 1;
8411 }
8412 }
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05308413
8414 /* If SNR Monitoring is enabled, FW has to parse all beacons
8415 * for calcaluting and storing the average SNR, so set Nth beacon
8416 * filter to 1 to enable FW to parse all the beaocons
8417 */
8418 if (1 == pHddCtx->cfg_ini->fEnableSNRMonitoring)
8419 {
8420 /* The log level is deliberately set to WARN as overriding
8421 * nthBeaconFilter to 1 will increase power cosumption and this
8422 * might just prove helpful to detect the power issue.
8423 */
8424 hddLog(VOS_TRACE_LEVEL_WARN,
8425 "%s: Setting pHddCtx->cfg_ini->nthBeaconFilter = 1", __func__);
8426 pHddCtx->cfg_ini->nthBeaconFilter = 1;
8427 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008428 /*
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308429 * cfg80211: Initialization ...
Jeff Johnson295189b2012-06-20 16:38:30 -07008430 */
Manjunathappa Prakasheec4ddf2014-01-13 18:23:51 -08008431 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07008432 {
Manjunathappa Prakasheec4ddf2014-01-13 18:23:51 -08008433 if (0 < wlan_hdd_cfg80211_init(dev, wiphy, pHddCtx->cfg_ini))
8434 {
8435 hddLog(VOS_TRACE_LEVEL_FATAL,
8436 "%s: wlan_hdd_cfg80211_init return failure", __func__);
8437 goto err_config;
8438 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008439 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008440
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08008441 // Update VOS trace levels based upon the cfg.ini
8442 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
8443 pHddCtx->cfg_ini->vosTraceEnableBAP);
8444 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
8445 pHddCtx->cfg_ini->vosTraceEnableTL);
8446 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
8447 pHddCtx->cfg_ini->vosTraceEnableWDI);
8448 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
8449 pHddCtx->cfg_ini->vosTraceEnableHDD);
8450 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
8451 pHddCtx->cfg_ini->vosTraceEnableSME);
8452 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
8453 pHddCtx->cfg_ini->vosTraceEnablePE);
Katya Nigam70d68332013-09-16 16:49:45 +05308454 hdd_vos_trace_enable(VOS_MODULE_ID_PMC,
8455 pHddCtx->cfg_ini->vosTraceEnablePMC);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08008456 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
8457 pHddCtx->cfg_ini->vosTraceEnableWDA);
8458 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
8459 pHddCtx->cfg_ini->vosTraceEnableSYS);
8460 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
8461 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08008462 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
8463 pHddCtx->cfg_ini->vosTraceEnableSAP);
8464 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
8465 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08008466
Jeff Johnson295189b2012-06-20 16:38:30 -07008467 // Update WDI trace levels based upon the cfg.ini
8468 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
8469 pHddCtx->cfg_ini->wdiTraceEnableDAL);
8470 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
8471 pHddCtx->cfg_ini->wdiTraceEnableCTL);
8472 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
8473 pHddCtx->cfg_ini->wdiTraceEnableDAT);
8474 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
8475 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07008476
Jeff Johnson88ba7742013-02-27 14:36:02 -08008477 if (VOS_FTM_MODE == hdd_get_conparam())
8478 {
Jeff Johnson295189b2012-06-20 16:38:30 -07008479 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
8480 {
8481 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
8482 goto err_free_hdd_context;
8483 }
8484 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
c_hpothu2de0ef62014-04-15 16:16:15 +05308485
8486 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -07008487 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08008488 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008489
Jeff Johnson88ba7742013-02-27 14:36:02 -08008490 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07008491 if(pHddCtx->cfg_ini->fIsLogpEnabled)
8492 {
8493 status = vos_watchdog_open(pVosContext,
8494 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
8495
8496 if(!VOS_IS_STATUS_SUCCESS( status ))
8497 {
8498 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308499 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07008500 }
8501 }
8502
8503 pHddCtx->isLogpInProgress = FALSE;
8504 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
8505
Jeff Johnson295189b2012-06-20 16:38:30 -07008506 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
8507 if(!VOS_IS_STATUS_SUCCESS(status))
8508 {
8509 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008510 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07008511 }
8512
Amar Singhala49cbc52013-10-08 18:37:44 -07008513#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -07008514 /* initialize the NV module. This is required so that
8515 we can initialize the channel information in wiphy
8516 from the NV.bin data. The channel information in
8517 wiphy needs to be initialized before wiphy registration */
8518
8519 status = vos_nv_open();
8520 if (!VOS_IS_STATUS_SUCCESS(status))
8521 {
8522 /* NV module cannot be initialized */
8523 hddLog( VOS_TRACE_LEVEL_FATAL,
8524 "%s: vos_nv_open failed", __func__);
8525 goto err_clkvote;
8526 }
8527
8528 status = vos_init_wiphy_from_nv_bin();
8529 if (!VOS_IS_STATUS_SUCCESS(status))
8530 {
8531 /* NV module cannot be initialized */
8532 hddLog( VOS_TRACE_LEVEL_FATAL,
8533 "%s: vos_init_wiphy failed", __func__);
8534 goto err_vos_nv_close;
8535 }
8536
Amar Singhala49cbc52013-10-08 18:37:44 -07008537#endif
8538
Arun Kumar Khandavalliebb19482014-03-25 13:56:53 +05308539 status = vos_open( &pVosContext, pHddCtx->parent_dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07008540 if ( !VOS_IS_STATUS_SUCCESS( status ))
8541 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008542 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
Mihir Shetee1093ba2014-01-21 20:13:32 +05308543 goto err_vos_nv_close;
Jeff Johnson295189b2012-06-20 16:38:30 -07008544 }
8545
Jeff Johnson295189b2012-06-20 16:38:30 -07008546 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
8547
8548 if ( NULL == pHddCtx->hHal )
8549 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008550 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008551 goto err_vosclose;
8552 }
8553
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008554 status = vos_preStart( pHddCtx->pvosContext );
8555 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8556 {
8557 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05308558 goto err_vosclose;
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008559 }
Jeff Johnsone7245742012-09-05 17:12:55 -07008560
Arif Hussaineaf68602013-12-30 23:10:44 -08008561 if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan)
8562 {
8563 pHddCtx->cfg_ini->enableDFSChnlScan = enable_dfs_chan_scan;
8564 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_dfs_chan_scan set to %d",
8565 __func__, enable_dfs_chan_scan);
8566 }
8567 if (0 == enable_11d || 1 == enable_11d)
8568 {
8569 pHddCtx->cfg_ini->Is11dSupportEnabled = enable_11d;
8570 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_11d set to %d",
8571 __func__, enable_11d);
8572 }
8573
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008574 /* Note that the vos_preStart() sequence triggers the cfg download.
8575 The cfg download must occur before we update the SME config
8576 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07008577 status = hdd_set_sme_config( pHddCtx );
8578
8579 if ( VOS_STATUS_SUCCESS != status )
8580 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008581 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05308582 goto err_vosclose;
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008583 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008584
8585 //Initialize the WMM module
Leela Venkata Kiran Kumar Reddy Chirala8e69fbc2013-10-30 18:51:13 -07008586 status = hdd_wmm_init(pHddCtx, hddWmmDscpToUpMapInfra);
8587 status = hdd_wmm_init(pHddCtx, hddWmmDscpToUpMapP2p);
Jeff Johnson295189b2012-06-20 16:38:30 -07008588 if (!VOS_IS_STATUS_SUCCESS(status))
8589 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008590 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05308591 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07008592 }
8593
Jeff Johnson295189b2012-06-20 16:38:30 -07008594 /* In the integrated architecture we update the configuration from
8595 the INI file and from NV before vOSS has been started so that
8596 the final contents are available to send down to the cCPU */
8597
8598 // Apply the cfg.ini to cfg.dat
8599 if (FALSE == hdd_update_config_dat(pHddCtx))
8600 {
8601 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05308602 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07008603 }
8604
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308605 // Get mac addr from platform driver
8606 ret = wcnss_get_wlan_mac_address((char*)&mac_addr.bytes);
8607
8608 if ((0 == ret) && (!vos_is_macaddr_zero(&mac_addr)))
Jeff Johnson295189b2012-06-20 16:38:30 -07008609 {
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308610 /* Store the mac addr for first interface */
8611 pHddCtx->cfg_ini->intfMacAddr[0] = mac_addr;
8612
8613 hddLog(VOS_TRACE_LEVEL_ERROR,
8614 "%s: WLAN Mac Addr: "
8615 MAC_ADDRESS_STR, __func__,
8616 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
8617
8618 /* Here, passing Arg2 as 1 because we do not want to change the
8619 last 3 bytes (means non OUI bytes) of first interface mac
8620 addr.
8621 */
8622 if (0 != hdd_generate_iface_mac_addr_auto(pHddCtx, 1, mac_addr))
8623 {
8624 hddLog(VOS_TRACE_LEVEL_ERROR,
8625 "%s: Failed to generate wlan interface mac addr "
8626 "using MAC from ini file ", __func__);
8627 }
8628 }
8629 else if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
8630 {
8631 // Apply the NV to cfg.dat
8632 /* Prima Update MAC address only at here */
Jeff Johnson295189b2012-06-20 16:38:30 -07008633#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
8634 /* There was not a valid set of MAC Addresses in NV. See if the
8635 default addresses were modified by the cfg.ini settings. If so,
8636 we'll use them, but if not, we'll autogenerate a set of MAC
8637 addresses based upon the device serial number */
8638
8639 static const v_MACADDR_t default_address =
8640 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
Jeff Johnson295189b2012-06-20 16:38:30 -07008641
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308642 if (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
8643 sizeof(default_address)))
Jeff Johnson295189b2012-06-20 16:38:30 -07008644 {
8645 /* cfg.ini has the default address, invoke autogen logic */
8646
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308647 /* Here, passing Arg2 as 0 because we want to change the
8648 last 3 bytes (means non OUI bytes) of all the interfaces
8649 mac addr.
8650 */
8651 if (0 != hdd_generate_iface_mac_addr_auto(pHddCtx, 0,
8652 default_address))
Jeff Johnson295189b2012-06-20 16:38:30 -07008653 {
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308654 hddLog(VOS_TRACE_LEVEL_ERROR,
8655 "%s: Failed to generate wlan interface mac addr "
8656 "using MAC from ini file " MAC_ADDRESS_STR, __func__,
8657 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
Jeff Johnson295189b2012-06-20 16:38:30 -07008658 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008659 }
8660 else
8661#endif //WLAN_AUTOGEN_MACADDR_FEATURE
8662 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008663 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07008664 "%s: Invalid MAC address in NV, using MAC from ini file "
8665 MAC_ADDRESS_STR, __func__,
8666 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
8667 }
8668 }
8669 {
8670 eHalStatus halStatus;
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308671
8672 /* Set the MAC Address Currently this is used by HAL to
8673 * add self sta. Remove this once self sta is added as
8674 * part of session open.
8675 */
Jeff Johnson295189b2012-06-20 16:38:30 -07008676 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
8677 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
8678 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308679
Jeff Johnson295189b2012-06-20 16:38:30 -07008680 if (!HAL_STATUS_SUCCESS( halStatus ))
8681 {
8682 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
8683 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05308684 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07008685 }
8686 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008687
8688 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
8689 Note: Firmware image will be read and downloaded inside vos_start API */
8690 status = vos_start( pHddCtx->pvosContext );
8691 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8692 {
8693 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05308694 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07008695 }
8696
Leo Chang6cec3e22014-01-21 15:33:49 -08008697#ifdef FEATURE_WLAN_CH_AVOID
8698 /* Plug in avoid channel notification callback
8699 * This should happen before ADD_SELF_STA
8700 * FW will send first IND with ADD_SELF_STA REQ from host */
8701 sme_AddChAvoidCallback(pHddCtx->hHal,
8702 hdd_hostapd_ch_avoid_cb);
8703#endif /* FEATURE_WLAN_CH_AVOID */
8704
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008705 /* Exchange capability info between Host and FW and also get versioning info from FW */
8706 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07008707
Agarwal Ashishad9281b2014-06-10 14:57:30 +05308708#ifdef CONFIG_ENABLE_LINUX_REG
8709 status = wlan_hdd_init_channels(pHddCtx);
8710 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8711 {
8712 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: wlan_hdd_init_channels failed",
8713 __func__);
8714 goto err_vosstop;
8715 }
8716#endif
8717
Jeff Johnson295189b2012-06-20 16:38:30 -07008718 status = hdd_post_voss_start_config( pHddCtx );
8719 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8720 {
8721 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
8722 __func__);
8723 goto err_vosstop;
8724 }
Amar Singhala49cbc52013-10-08 18:37:44 -07008725
8726#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308727 wlan_hdd_cfg80211_update_reg_info( wiphy );
8728
8729 /* registration of wiphy dev with cfg80211 */
8730 if (0 > wlan_hdd_cfg80211_register(wiphy))
8731 {
8732 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
8733 goto err_vosstop;
8734 }
Amar Singhala49cbc52013-10-08 18:37:44 -07008735#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008736
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05308737#ifdef CONFIG_ENABLE_LINUX_REG
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05308738 /* registration of wiphy dev with cfg80211 */
8739 if (0 > wlan_hdd_cfg80211_register(wiphy))
8740 {
8741 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
8742 goto err_vosstop;
8743 }
8744
8745 status = wlan_hdd_init_channels_for_cc(pHddCtx);
8746 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8747 {
8748 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: wlan_hdd_init_channels_for_cc failed",
8749 __func__);
8750 goto err_unregister_wiphy;
8751 }
8752#endif
8753
Jeff Johnson295189b2012-06-20 16:38:30 -07008754 if (VOS_STA_SAP_MODE == hdd_get_conparam())
8755 {
8756 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
8757 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
8758 }
8759 else
8760 {
Jeff Johnson295189b2012-06-20 16:38:30 -07008761 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
8762 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
8763 if (pAdapter != NULL)
8764 {
kaidde69982014-06-18 13:23:21 +08008765 if (pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated && !(pHddCtx->cfg_ini->intfMacAddr[0].bytes[0] &= 0x02))
Jeff Johnson295189b2012-06-20 16:38:30 -07008766 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05308767 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
8768 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
8769 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07008770
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05308771 /* Generate the P2P Device Address. This consists of the device's
8772 * primary MAC address with the locally administered bit set.
8773 */
8774 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07008775 }
8776 else
8777 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05308778 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
8779 if (p2p_dev_addr != NULL)
8780 {
8781 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
8782 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
8783 }
8784 else
8785 {
8786 hddLog(VOS_TRACE_LEVEL_FATAL,
8787 "%s: Failed to allocate mac_address for p2p_device",
8788 __func__);
8789 goto err_close_adapter;
8790 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008791 }
Jeff Johnsone7245742012-09-05 17:12:55 -07008792
8793 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
8794 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
8795 if ( NULL == pP2pAdapter )
8796 {
8797 hddLog(VOS_TRACE_LEVEL_FATAL,
8798 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008799 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07008800 goto err_close_adapter;
8801 }
Jeff Johnsone7245742012-09-05 17:12:55 -07008802 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008803 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008804
8805 if( pAdapter == NULL )
8806 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008807 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
8808 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07008809 }
Jeff Johnsone7245742012-09-05 17:12:55 -07008810
Arif Hussain66559122013-11-21 10:11:40 -08008811 if (country_code)
8812 {
8813 eHalStatus ret;
Arif Hussaincb607082013-12-20 11:57:42 -08008814 INIT_COMPLETION(pAdapter->change_country_code);
Arif Hussain66559122013-11-21 10:11:40 -08008815 hdd_checkandupdate_dfssetting(pAdapter, country_code);
8816#ifndef CONFIG_ENABLE_LINUX_REG
8817 hdd_checkandupdate_phymode(pAdapter, country_code);
8818#endif
Arif Hussaineaf68602013-12-30 23:10:44 -08008819 ret = sme_ChangeCountryCode(pHddCtx->hHal,
8820 (void *)(tSmeChangeCountryCallback)
8821 wlan_hdd_change_country_code_callback,
Arif Hussain66559122013-11-21 10:11:40 -08008822 country_code,
8823 pAdapter, pHddCtx->pvosContext,
Abhishek Singha306a442013-11-07 18:39:01 +05308824 eSIR_TRUE, eSIR_TRUE);
Arif Hussain66559122013-11-21 10:11:40 -08008825 if (eHAL_STATUS_SUCCESS == ret)
8826 {
Arif Hussaincb607082013-12-20 11:57:42 -08008827 ret = wait_for_completion_interruptible_timeout(
8828 &pAdapter->change_country_code,
8829 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
8830
8831 if (0 >= ret)
8832 {
8833 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8834 "%s: SME while setting country code timed out", __func__);
8835 }
Arif Hussain66559122013-11-21 10:11:40 -08008836 }
8837 else
8838 {
Arif Hussaincb607082013-12-20 11:57:42 -08008839 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8840 "%s: SME Change Country code from module param fail ret=%d",
8841 __func__, ret);
Arif Hussain66559122013-11-21 10:11:40 -08008842 }
8843 }
8844
Jeff Johnson295189b2012-06-20 16:38:30 -07008845#ifdef WLAN_BTAMP_FEATURE
8846 vStatus = WLANBAP_Open(pVosContext);
8847 if(!VOS_IS_STATUS_SUCCESS(vStatus))
8848 {
8849 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8850 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07008851 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07008852 }
8853
8854 vStatus = BSL_Init(pVosContext);
8855 if(!VOS_IS_STATUS_SUCCESS(vStatus))
8856 {
8857 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8858 "%s: Failed to Init BSL",__func__);
8859 goto err_bap_close;
8860 }
8861 vStatus = WLANBAP_Start(pVosContext);
8862 if (!VOS_IS_STATUS_SUCCESS(vStatus))
8863 {
8864 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8865 "%s: Failed to start TL",__func__);
8866 goto err_bap_close;
8867 }
8868
8869 pConfig = pHddCtx->cfg_ini;
8870 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
8871 status = WLANBAP_SetConfig(&btAmpConfig);
8872
8873#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07008874
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07008875#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
8876 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
8877 {
8878 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
8879 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
8880 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
8881 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
8882 }
8883#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008884
Mihir Shetefc7ff5b2014-01-27 11:30:05 +05308885 sme_Register11dScanDoneCallback(pHddCtx->hHal, hdd_11d_scan_done);
8886
Jeff Johnson295189b2012-06-20 16:38:30 -07008887 /* Register with platform driver as client for Suspend/Resume */
8888 status = hddRegisterPmOps(pHddCtx);
8889 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8890 {
8891 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
8892#ifdef WLAN_BTAMP_FEATURE
8893 goto err_bap_stop;
8894#else
Jeff Johnsone7245742012-09-05 17:12:55 -07008895 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07008896#endif //WLAN_BTAMP_FEATURE
8897 }
8898
Yue Ma0d4891e2013-08-06 17:01:45 -07008899 /* Open debugfs interface */
8900 if (VOS_STATUS_SUCCESS != hdd_debugfs_init(pAdapter))
8901 {
8902 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8903 "%s: hdd_debugfs_init failed!", __func__);
Yue Ma0d4891e2013-08-06 17:01:45 -07008904 }
8905
Jeff Johnson295189b2012-06-20 16:38:30 -07008906 /* Register TM level change handler function to the platform */
8907 status = hddDevTmRegisterNotifyCallback(pHddCtx);
8908 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8909 {
8910 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
8911 goto err_unregister_pmops;
8912 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008913
8914 /* register for riva power on lock to platform driver */
8915 if (req_riva_power_on_lock("wlan"))
8916 {
8917 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
8918 __func__);
8919 goto err_unregister_pmops;
8920 }
8921
Jeff Johnson295189b2012-06-20 16:38:30 -07008922 // register net device notifier for device change notification
8923 ret = register_netdevice_notifier(&hdd_netdev_notifier);
8924
8925 if(ret < 0)
8926 {
8927 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
8928 goto err_free_power_on_lock;
8929 }
8930
8931 //Initialize the nlink service
8932 if(nl_srv_init() != 0)
8933 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308934 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008935 goto err_reg_netdev;
8936 }
8937
Leo Chang4ce1cc52013-10-21 18:27:15 -07008938#ifdef WLAN_KD_READY_NOTIFIER
8939 pHddCtx->kd_nl_init = 1;
8940#endif /* WLAN_KD_READY_NOTIFIER */
8941
Jeff Johnson295189b2012-06-20 16:38:30 -07008942 //Initialize the BTC service
8943 if(btc_activate_service(pHddCtx) != 0)
8944 {
8945 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
8946 goto err_nl_srv;
8947 }
8948
8949#ifdef PTT_SOCK_SVC_ENABLE
8950 //Initialize the PTT service
8951 if(ptt_sock_activate_svc(pHddCtx) != 0)
8952 {
8953 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
8954 goto err_nl_srv;
8955 }
8956#endif
8957
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05308958#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
8959 if(pHddCtx->cfg_ini && pHddCtx->cfg_ini->wlanLoggingEnable)
8960 {
8961 if(wlan_logging_sock_activate_svc(
8962 pHddCtx->cfg_ini->wlanLoggingFEToConsole,
8963 pHddCtx->cfg_ini->wlanLoggingNumBuf))
8964 {
8965 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wlan_logging_sock_activate_svc"
8966 " failed", __func__);
8967 goto err_nl_srv;
8968 }
8969 }
8970#endif
8971
Jeff Johnson295189b2012-06-20 16:38:30 -07008972 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07008973 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07008974 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07008975 /* Action frame registered in one adapter which will
8976 * applicable to all interfaces
8977 */
Agarwal Ashish8fa0e9a2014-05-23 00:40:12 +05308978 wlan_hdd_cfg80211_register_frames(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07008979 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008980
8981 mutex_init(&pHddCtx->sap_lock);
8982
Jeff Johnson295189b2012-06-20 16:38:30 -07008983
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008984#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07008985#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
8986 /* Initialize the wake lcok */
8987 wake_lock_init(&pHddCtx->rx_wake_lock,
8988 WAKE_LOCK_SUSPEND,
8989 "qcom_rx_wakelock");
8990#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08008991 /* Initialize the wake lcok */
8992 wake_lock_init(&pHddCtx->sap_wake_lock,
8993 WAKE_LOCK_SUSPEND,
8994 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008995#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07008996
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07008997 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
8998 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07008999
Katya Nigam5c306ea2014-06-19 15:39:54 +05309000 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_NO_LOAD_UNLOAD_IN_PROGRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -07009001 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
9002 hdd_allow_suspend();
Katya Nigam5c306ea2014-06-19 15:39:54 +05309003
9004#ifdef FEATURE_WLAN_SCAN_PNO
9005 /*SME must send channel update configuration to RIVA*/
9006 sme_UpdateChannelConfig(pHddCtx->hHal);
9007#endif
9008
Abhishek Singha306a442013-11-07 18:39:01 +05309009#ifndef CONFIG_ENABLE_LINUX_REG
9010 /*updating wiphy so that regulatory user hints can be processed*/
9011 if (wiphy)
9012 {
9013 regulatory_hint(wiphy, "00");
9014 }
9015#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07009016 // Initialize the restart logic
9017 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05309018
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07009019 //Register the traffic monitor timer now
9020 if ( pHddCtx->cfg_ini->dynSplitscan)
9021 {
9022 vos_timer_init(&pHddCtx->tx_rx_trafficTmr,
9023 VOS_TIMER_TYPE_SW,
9024 hdd_tx_rx_pkt_cnt_stat_timer_handler,
9025 (void *)pHddCtx);
9026 }
Dino Mycle6fb96c12014-06-10 11:52:40 +05309027#ifdef WLAN_FEATURE_EXTSCAN
9028 sme_EXTScanRegisterCallback(pHddCtx->hHal,
9029 wlan_hdd_cfg80211_extscan_callback,
9030 pHddCtx);
9031#endif /* WLAN_FEATURE_EXTSCAN */
Jeff Johnson295189b2012-06-20 16:38:30 -07009032 goto success;
9033
9034err_nl_srv:
Leo Chang59cdc7e2013-07-10 10:08:21 -07009035#ifdef WLAN_KD_READY_NOTIFIER
9036 nl_srv_exit(pHddCtx->ptt_pid);
9037#else
Jeff Johnson295189b2012-06-20 16:38:30 -07009038 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07009039#endif /* WLAN_KD_READY_NOTIFIER */
Jeff Johnson295189b2012-06-20 16:38:30 -07009040err_reg_netdev:
9041 unregister_netdevice_notifier(&hdd_netdev_notifier);
9042
9043err_free_power_on_lock:
9044 free_riva_power_on_lock("wlan");
9045
9046err_unregister_pmops:
9047 hddDevTmUnregisterNotifyCallback(pHddCtx);
9048 hddDeregisterPmOps(pHddCtx);
9049
Yue Ma0d4891e2013-08-06 17:01:45 -07009050 hdd_debugfs_exit(pHddCtx);
9051
Jeff Johnson295189b2012-06-20 16:38:30 -07009052#ifdef WLAN_BTAMP_FEATURE
9053err_bap_stop:
9054 WLANBAP_Stop(pVosContext);
9055#endif
9056
9057#ifdef WLAN_BTAMP_FEATURE
9058err_bap_close:
9059 WLANBAP_Close(pVosContext);
9060#endif
9061
Jeff Johnson295189b2012-06-20 16:38:30 -07009062err_close_adapter:
9063 hdd_close_all_adapters( pHddCtx );
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05309064err_unregister_wiphy:
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05309065 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07009066err_vosstop:
9067 vos_stop(pVosContext);
9068
Amar Singhala49cbc52013-10-08 18:37:44 -07009069err_vosclose:
Jeff Johnson295189b2012-06-20 16:38:30 -07009070 status = vos_sched_close( pVosContext );
9071 if (!VOS_IS_STATUS_SUCCESS(status)) {
9072 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
9073 "%s: Failed to close VOSS Scheduler", __func__);
9074 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
9075 }
Amar Singhala49cbc52013-10-08 18:37:44 -07009076 vos_close(pVosContext );
9077
Amar Singhal0a402232013-10-11 20:57:16 -07009078err_vos_nv_close:
9079
c_hpothue6a36282014-03-19 12:27:38 +05309080#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -07009081 vos_nv_close();
9082
Jeff Johnson295189b2012-06-20 16:38:30 -07009083err_clkvote:
c_hpothu70f8d812014-03-22 22:59:23 +05309084#endif
Jeff Johnsonbc676b42013-02-14 16:04:08 -08009085 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07009086
9087err_wdclose:
9088 if(pHddCtx->cfg_ini->fIsLogpEnabled)
9089 vos_watchdog_close(pVosContext);
9090
Jeff Johnson295189b2012-06-20 16:38:30 -07009091err_config:
9092 kfree(pHddCtx->cfg_ini);
9093 pHddCtx->cfg_ini= NULL;
9094
9095err_free_hdd_context:
9096 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07009097 wiphy_free(wiphy) ;
9098 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07009099 VOS_BUG(1);
9100
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08009101 if (hdd_is_ssr_required())
9102 {
9103 /* WDI timeout had happened during load, so SSR is needed here */
9104 subsystem_restart("wcnss");
9105 msleep(5000);
9106 }
9107 hdd_set_ssr_required (VOS_FALSE);
9108
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08009109 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07009110
9111success:
9112 EXIT();
9113 return 0;
9114}
9115
9116/**---------------------------------------------------------------------------
9117
Jeff Johnson32d95a32012-09-10 13:15:23 -07009118 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07009119
Jeff Johnson32d95a32012-09-10 13:15:23 -07009120 This is the driver entry point - called in different timeline depending
9121 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07009122
9123 \param - None
9124
9125 \return - 0 for success, non zero for failure
9126
9127 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07009128static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07009129{
9130 VOS_STATUS status;
9131 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07009132 struct device *dev = NULL;
9133 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07009134#ifdef HAVE_WCNSS_CAL_DOWNLOAD
9135 int max_retries = 0;
9136#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009137
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05309138#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9139 wlan_logging_sock_init_svc();
9140#endif
9141
Jeff Johnson295189b2012-06-20 16:38:30 -07009142 ENTER();
9143
Sameer Thalappil50dc0092013-02-19 17:23:33 -08009144#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07009145 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07009146#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009147
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05309148 hddTraceInit();
Jeff Johnson295189b2012-06-20 16:38:30 -07009149 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
9150 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
9151
9152 //Power Up Libra WLAN card first if not already powered up
9153 status = vos_chipPowerUp(NULL,NULL,NULL);
9154 if (!VOS_IS_STATUS_SUCCESS(status))
9155 {
9156 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
9157 "exiting", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05309158#ifdef WLAN_OPEN_SOURCE
9159 wake_lock_destroy(&wlan_wake_lock);
9160#endif
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05309161
9162#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9163 wlan_logging_sock_deinit_svc();
9164#endif
9165
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08009166 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07009167 }
9168
Jeff Johnson295189b2012-06-20 16:38:30 -07009169#ifdef ANI_BUS_TYPE_PCI
9170
9171 dev = wcnss_wlan_get_device();
9172
9173#endif // ANI_BUS_TYPE_PCI
9174
9175#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07009176
9177#ifdef HAVE_WCNSS_CAL_DOWNLOAD
9178 /* wait until WCNSS driver downloads NV */
9179 while (!wcnss_device_ready() && 5 >= ++max_retries) {
9180 msleep(1000);
9181 }
9182 if (max_retries >= 5) {
9183 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05309184#ifdef WLAN_OPEN_SOURCE
9185 wake_lock_destroy(&wlan_wake_lock);
9186#endif
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05309187
9188#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9189 wlan_logging_sock_deinit_svc();
9190#endif
9191
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07009192 return -ENODEV;
9193 }
9194#endif
9195
Jeff Johnson295189b2012-06-20 16:38:30 -07009196 dev = wcnss_wlan_get_device();
9197#endif // ANI_BUS_TYPE_PLATFORM
9198
9199
9200 do {
9201 if (NULL == dev) {
9202 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
9203 ret_status = -1;
9204 break;
9205 }
9206
Jeff Johnson295189b2012-06-20 16:38:30 -07009207#ifdef TIMER_MANAGER
9208 vos_timer_manager_init();
9209#endif
9210
9211 /* Preopen VOSS so that it is ready to start at least SAL */
9212 status = vos_preOpen(&pVosContext);
9213
9214 if (!VOS_IS_STATUS_SUCCESS(status))
9215 {
9216 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
9217 ret_status = -1;
9218 break;
9219 }
9220
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009221#ifndef MODULE
9222 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
9223 */
9224 hdd_set_conparam((v_UINT_t)con_mode);
9225#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009226
9227 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08009228 if (hdd_wlan_startup(dev))
9229 {
Jeff Johnson295189b2012-06-20 16:38:30 -07009230 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08009231 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009232 vos_preClose( &pVosContext );
9233 ret_status = -1;
9234 break;
9235 }
9236
9237 /* Cancel the vote for XO Core ON
9238 * This is done here for safety purposes in case we re-initialize without turning
9239 * it OFF in any error scenario.
9240 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07009241 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07009242 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07009243 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07009244 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
9245 {
9246 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
Arif Hussain6d2a3322013-11-17 19:50:10 -08009247 " Power consumed will be high");
Jeff Johnson295189b2012-06-20 16:38:30 -07009248 }
9249 } while (0);
9250
9251 if (0 != ret_status)
9252 {
9253 //Assert Deep sleep signal now to put Libra HW in lowest power state
9254 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
9255 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
9256
9257 //Vote off any PMIC voltage supplies
9258 vos_chipPowerDown(NULL, NULL, NULL);
9259#ifdef TIMER_MANAGER
9260 vos_timer_exit();
9261#endif
9262#ifdef MEMORY_DEBUG
9263 vos_mem_exit();
9264#endif
9265
Sameer Thalappil50dc0092013-02-19 17:23:33 -08009266#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07009267 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07009268#endif
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05309269
9270#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9271 wlan_logging_sock_deinit_svc();
9272#endif
9273
Jeff Johnson295189b2012-06-20 16:38:30 -07009274 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
9275 }
9276 else
9277 {
9278 //Send WLAN UP indication to Nlink Service
9279 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
9280
9281 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Jeff Johnson295189b2012-06-20 16:38:30 -07009282 }
9283
9284 EXIT();
9285
9286 return ret_status;
9287}
9288
Jeff Johnson32d95a32012-09-10 13:15:23 -07009289/**---------------------------------------------------------------------------
9290
9291 \brief hdd_module_init() - Init Function
9292
9293 This is the driver entry point (invoked when module is loaded using insmod)
9294
9295 \param - None
9296
9297 \return - 0 for success, non zero for failure
9298
9299 --------------------------------------------------------------------------*/
9300#ifdef MODULE
9301static int __init hdd_module_init ( void)
9302{
9303 return hdd_driver_init();
9304}
Jeff Johnson32d95a32012-09-10 13:15:23 -07009305#else /* #ifdef MODULE */
9306static int __init hdd_module_init ( void)
9307{
9308 /* Driver initialization is delayed to fwpath_changed_handler */
9309 return 0;
9310}
Jeff Johnson32d95a32012-09-10 13:15:23 -07009311#endif /* #ifdef MODULE */
9312
Jeff Johnson295189b2012-06-20 16:38:30 -07009313
9314/**---------------------------------------------------------------------------
9315
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009316 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07009317
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009318 This is the driver exit point (invoked when module is unloaded using rmmod
9319 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07009320
9321 \param - None
9322
9323 \return - None
9324
9325 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009326static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07009327{
9328 hdd_context_t *pHddCtx = NULL;
9329 v_CONTEXT_t pVosContext = NULL;
Agarwal Ashish5e414792014-06-08 15:25:23 +05309330 v_REGDOMAIN_t regId;
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +05309331 unsigned long rc = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07009332
9333 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
9334
9335 //Get the global vos context
9336 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
9337
9338 if(!pVosContext)
9339 {
9340 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
9341 goto done;
9342 }
9343
9344 //Get the HDD context.
9345 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
9346
9347 if(!pHddCtx)
9348 {
9349 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
9350 }
9351 else
9352 {
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +05309353 INIT_COMPLETION(pHddCtx->ssr_comp_var);
9354
9355 if (pHddCtx->isLogpInProgress)
9356 {
Sameer Thalappil451ebb92013-06-28 15:49:58 -07009357 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +05309358 "%s:SSR in Progress; block rmmod !!!", __func__);
9359 rc = wait_for_completion_timeout(&pHddCtx->ssr_comp_var,
9360 msecs_to_jiffies(30000));
9361 if(!rc)
9362 {
9363 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
9364 "%s:SSR timedout, fatal error", __func__);
9365 VOS_BUG(0);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07009366 }
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +05309367 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009368
Mihir Shete18156292014-03-11 15:38:30 +05309369 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_UNLOAD_IN_PROGRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -07009370 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
9371
Agarwal Ashish5e414792014-06-08 15:25:23 +05309372 if (eANI_BOOLEAN_TRUE == sme_Is11dCountrycode(pHddCtx->hHal) &&
9373 pHddCtx->cfg_ini->fSupplicantCountryCodeHasPriority )
9374 {
9375 vos_nv_getRegDomainFromCountryCode(&regId , "00", COUNTRY_USER);
9376 }
9377
Jeff Johnson295189b2012-06-20 16:38:30 -07009378 //Do all the cleanup before deregistering the driver
9379 hdd_wlan_exit(pHddCtx);
9380 }
9381
Jeff Johnson295189b2012-06-20 16:38:30 -07009382 vos_preClose( &pVosContext );
9383
9384#ifdef TIMER_MANAGER
9385 vos_timer_exit();
9386#endif
9387#ifdef MEMORY_DEBUG
9388 vos_mem_exit();
9389#endif
9390
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05309391#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9392 wlan_logging_sock_deinit_svc();
9393#endif
9394
Jeff Johnson295189b2012-06-20 16:38:30 -07009395done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08009396#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07009397 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07009398#endif
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05309399
Jeff Johnson295189b2012-06-20 16:38:30 -07009400 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
9401}
9402
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009403/**---------------------------------------------------------------------------
9404
9405 \brief hdd_module_exit() - Exit function
9406
9407 This is the driver exit point (invoked when module is unloaded using rmmod)
9408
9409 \param - None
9410
9411 \return - None
9412
9413 --------------------------------------------------------------------------*/
9414static void __exit hdd_module_exit(void)
9415{
9416 hdd_driver_exit();
9417}
9418
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009419#ifdef MODULE
9420static int fwpath_changed_handler(const char *kmessage,
9421 struct kernel_param *kp)
9422{
Jeff Johnson76052702013-04-16 13:55:05 -07009423 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009424}
9425
9426static int con_mode_handler(const char *kmessage,
9427 struct kernel_param *kp)
9428{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07009429 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009430}
9431#else /* #ifdef MODULE */
9432/**---------------------------------------------------------------------------
9433
Jeff Johnson76052702013-04-16 13:55:05 -07009434 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009435
Jeff Johnson76052702013-04-16 13:55:05 -07009436 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009437 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07009438 - invoked when module parameter fwpath is modified from userspace to signal
9439 initializing the WLAN driver or when con_mode is modified from userspace
9440 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009441
9442 \return - 0 for success, non zero for failure
9443
9444 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07009445static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009446{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07009447 int ret_status;
9448
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009449 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07009450 ret_status = hdd_driver_init();
9451 wlan_hdd_inited = ret_status ? 0 : 1;
9452 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009453 }
9454
9455 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07009456
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009457 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07009458
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07009459 ret_status = hdd_driver_init();
9460 wlan_hdd_inited = ret_status ? 0 : 1;
9461 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009462}
9463
Jeff Johnson295189b2012-06-20 16:38:30 -07009464/**---------------------------------------------------------------------------
9465
Jeff Johnson76052702013-04-16 13:55:05 -07009466 \brief fwpath_changed_handler() - Handler Function
9467
9468 Handle changes to the fwpath parameter
9469
9470 \return - 0 for success, non zero for failure
9471
9472 --------------------------------------------------------------------------*/
9473static int fwpath_changed_handler(const char *kmessage,
9474 struct kernel_param *kp)
9475{
9476 int ret;
9477
9478 ret = param_set_copystring(kmessage, kp);
9479 if (0 == ret)
9480 ret = kickstart_driver();
9481 return ret;
9482}
9483
9484/**---------------------------------------------------------------------------
9485
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009486 \brief con_mode_handler() -
9487
9488 Handler function for module param con_mode when it is changed by userspace
9489 Dynamically linked - do nothing
9490 Statically linked - exit and init driver, as in rmmod and insmod
9491
Jeff Johnson76052702013-04-16 13:55:05 -07009492 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009493
Jeff Johnson76052702013-04-16 13:55:05 -07009494 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009495
9496 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07009497static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009498{
Jeff Johnson76052702013-04-16 13:55:05 -07009499 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009500
Jeff Johnson76052702013-04-16 13:55:05 -07009501 ret = param_set_int(kmessage, kp);
9502 if (0 == ret)
9503 ret = kickstart_driver();
9504 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009505}
9506#endif /* #ifdef MODULE */
9507
9508/**---------------------------------------------------------------------------
9509
Jeff Johnson295189b2012-06-20 16:38:30 -07009510 \brief hdd_get_conparam() -
9511
9512 This is the driver exit point (invoked when module is unloaded using rmmod)
9513
9514 \param - None
9515
9516 \return - tVOS_CON_MODE
9517
9518 --------------------------------------------------------------------------*/
9519tVOS_CON_MODE hdd_get_conparam ( void )
9520{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009521#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07009522 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009523#else
9524 return (tVOS_CON_MODE)curr_con_mode;
9525#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009526}
9527void hdd_set_conparam ( v_UINT_t newParam )
9528{
9529 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009530#ifndef MODULE
9531 curr_con_mode = con_mode;
9532#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009533}
9534/**---------------------------------------------------------------------------
9535
9536 \brief hdd_softap_sta_deauth() - function
9537
9538 This to take counter measure to handle deauth req from HDD
9539
9540 \param - pAdapter - Pointer to the HDD
9541
9542 \param - enable - boolean value
9543
9544 \return - None
9545
9546 --------------------------------------------------------------------------*/
9547
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009548VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07009549{
Jeff Johnson295189b2012-06-20 16:38:30 -07009550 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009551 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07009552
9553 ENTER();
9554
Rajesh Chauhan18488fc2013-08-22 10:15:03 -07009555 hddLog(LOG1, "hdd_softap_sta_deauth:(%p, false)",
9556 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07009557
9558 //Ignore request to deauth bcmc station
9559 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009560 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07009561
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009562 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07009563
9564 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009565 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07009566}
9567
9568/**---------------------------------------------------------------------------
9569
9570 \brief hdd_softap_sta_disassoc() - function
9571
9572 This to take counter measure to handle deauth req from HDD
9573
9574 \param - pAdapter - Pointer to the HDD
9575
9576 \param - enable - boolean value
9577
9578 \return - None
9579
9580 --------------------------------------------------------------------------*/
9581
9582void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
9583{
9584 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
9585
9586 ENTER();
9587
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05309588 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07009589
9590 //Ignore request to disassoc bcmc station
9591 if( pDestMacAddress[0] & 0x1 )
9592 return;
9593
9594 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
9595}
9596
9597void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
9598{
9599 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
9600
9601 ENTER();
9602
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05309603 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07009604
9605 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
9606}
9607
Jeff Johnson295189b2012-06-20 16:38:30 -07009608/**---------------------------------------------------------------------------
9609 *
9610 * \brief hdd_get__concurrency_mode() -
9611 *
9612 *
9613 * \param - None
9614 *
9615 * \return - CONCURRENCY MODE
9616 *
9617 * --------------------------------------------------------------------------*/
9618tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
9619{
9620 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
9621 hdd_context_t *pHddCtx;
9622
9623 if (NULL != pVosContext)
9624 {
9625 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
9626 if (NULL != pHddCtx)
9627 {
9628 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
9629 }
9630 }
9631
9632 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07009633 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009634 return VOS_STA;
9635}
9636
9637/* Decide whether to allow/not the apps power collapse.
9638 * Allow apps power collapse if we are in connected state.
9639 * if not, allow only if we are in IMPS */
9640v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
9641{
9642 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08009643 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08009644 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07009645 hdd_config_t *pConfig = pHddCtx->cfg_ini;
9646 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
9647 hdd_adapter_t *pAdapter = NULL;
9648 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08009649 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07009650
Jeff Johnson295189b2012-06-20 16:38:30 -07009651 if (VOS_STA_SAP_MODE == hdd_get_conparam())
9652 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07009653
Yathish9f22e662012-12-10 14:21:35 -08009654 concurrent_state = hdd_get_concurrency_mode();
9655
9656#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
9657 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
9658 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
9659 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
9660 return TRUE;
9661#endif
9662
Jeff Johnson295189b2012-06-20 16:38:30 -07009663 /*loop through all adapters. TBD fix for Concurrency */
9664 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
9665 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
9666 {
9667 pAdapter = pAdapterNode->pAdapter;
9668 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
9669 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
9670 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08009671 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
c_hpothu4e8faac2014-05-16 17:38:44 +05309672 && (pmcState != IMPS && pmcState != BMPS && pmcState != UAPSD
Srikant Kuppafef66a72013-01-30 17:32:44 -08009673 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08009674 (eANI_BOOLEAN_TRUE == scanRspPending) ||
9675 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07009676 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08009677 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08009678 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
9679 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07009680 return FALSE;
9681 }
9682 }
9683 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
9684 pAdapterNode = pNext;
9685 }
9686 return TRUE;
9687}
9688
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08009689/* Decides whether to send suspend notification to Riva
9690 * if any adapter is in BMPS; then it is required */
9691v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
9692{
9693 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
9694 hdd_config_t *pConfig = pHddCtx->cfg_ini;
9695
9696 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
9697 {
9698 return TRUE;
9699 }
9700 return FALSE;
9701}
9702
Jeff Johnson295189b2012-06-20 16:38:30 -07009703void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
9704{
9705 switch(mode)
9706 {
Chilam Ngc4244af2013-04-01 15:37:32 -07009707 case VOS_STA_MODE:
9708 case VOS_P2P_CLIENT_MODE:
9709 case VOS_P2P_GO_MODE:
9710 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07009711 pHddCtx->concurrency_mode |= (1 << mode);
9712 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07009713 break;
9714 default:
9715 break;
9716
9717 }
9718 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
9719 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
9720}
9721
9722
9723void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
9724{
9725 switch(mode)
9726 {
Chilam Ngc4244af2013-04-01 15:37:32 -07009727 case VOS_STA_MODE:
9728 case VOS_P2P_CLIENT_MODE:
9729 case VOS_P2P_GO_MODE:
9730 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07009731 pHddCtx->no_of_sessions[mode]--;
9732 if (!(pHddCtx->no_of_sessions[mode]))
9733 pHddCtx->concurrency_mode &= (~(1 << mode));
9734 break;
9735 default:
9736 break;
9737 }
9738 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
9739 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
9740}
9741
Jeff Johnsone7245742012-09-05 17:12:55 -07009742/**---------------------------------------------------------------------------
9743 *
9744 * \brief wlan_hdd_restart_init
9745 *
9746 * This function initalizes restart timer/flag. An internal function.
9747 *
9748 * \param - pHddCtx
9749 *
9750 * \return - None
9751 *
9752 * --------------------------------------------------------------------------*/
9753
9754static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
9755{
9756 /* Initialize */
9757 pHddCtx->hdd_restart_retries = 0;
9758 atomic_set(&pHddCtx->isRestartInProgress, 0);
9759 vos_timer_init(&pHddCtx->hdd_restart_timer,
9760 VOS_TIMER_TYPE_SW,
9761 wlan_hdd_restart_timer_cb,
9762 pHddCtx);
9763}
9764/**---------------------------------------------------------------------------
9765 *
9766 * \brief wlan_hdd_restart_deinit
9767 *
9768 * This function cleans up the resources used. An internal function.
9769 *
9770 * \param - pHddCtx
9771 *
9772 * \return - None
9773 *
9774 * --------------------------------------------------------------------------*/
9775
9776static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
9777{
9778
9779 VOS_STATUS vos_status;
9780 /* Block any further calls */
9781 atomic_set(&pHddCtx->isRestartInProgress, 1);
9782 /* Cleanup */
9783 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
9784 if (!VOS_IS_STATUS_SUCCESS(vos_status))
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309785 hddLog(LOGE, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07009786 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
9787 if (!VOS_IS_STATUS_SUCCESS(vos_status))
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309788 hddLog(LOGE, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07009789
9790}
9791
9792/**---------------------------------------------------------------------------
9793 *
9794 * \brief wlan_hdd_framework_restart
9795 *
9796 * This function uses a cfg80211 API to start a framework initiated WLAN
9797 * driver module unload/load.
9798 *
9799 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
9800 *
9801 *
9802 * \param - pHddCtx
9803 *
9804 * \return - VOS_STATUS_SUCCESS: Success
9805 * VOS_STATUS_E_EMPTY: Adapter is Empty
9806 * VOS_STATUS_E_NOMEM: No memory
9807
9808 * --------------------------------------------------------------------------*/
9809
9810static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
9811{
9812 VOS_STATUS status = VOS_STATUS_SUCCESS;
9813 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07009814 int len = (sizeof (struct ieee80211_mgmt));
9815 struct ieee80211_mgmt *mgmt = NULL;
9816
9817 /* Prepare the DEAUTH managment frame with reason code */
9818 mgmt = kzalloc(len, GFP_KERNEL);
9819 if(mgmt == NULL)
9820 {
9821 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
9822 "%s: memory allocation failed (%d bytes)", __func__, len);
9823 return VOS_STATUS_E_NOMEM;
9824 }
9825 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -07009826
9827 /* Iterate over all adapters/devices */
9828 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
9829 do
9830 {
9831 if( (status == VOS_STATUS_SUCCESS) &&
9832 pAdapterNode &&
9833 pAdapterNode->pAdapter)
9834 {
9835 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
9836 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
9837 pAdapterNode->pAdapter->dev->name,
9838 pAdapterNode->pAdapter->device_mode,
9839 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07009840 /*
9841 * CFG80211 event to restart the driver
9842 *
9843 * 'cfg80211_send_unprot_deauth' sends a
9844 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
9845 * of SME(Linux Kernel) state machine.
9846 *
9847 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
9848 * the driver.
9849 *
9850 */
9851
9852 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -07009853 }
9854 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
9855 pAdapterNode = pNext;
9856 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
9857
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07009858
9859 /* Free the allocated management frame */
9860 kfree(mgmt);
9861
Jeff Johnsone7245742012-09-05 17:12:55 -07009862 /* Retry until we unload or reach max count */
9863 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
9864 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
9865
9866 return status;
9867
9868}
9869/**---------------------------------------------------------------------------
9870 *
9871 * \brief wlan_hdd_restart_timer_cb
9872 *
9873 * Restart timer callback. An internal function.
9874 *
9875 * \param - User data:
9876 *
9877 * \return - None
9878 *
9879 * --------------------------------------------------------------------------*/
9880
9881void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
9882{
9883 hdd_context_t *pHddCtx = usrDataForCallback;
9884 wlan_hdd_framework_restart(pHddCtx);
9885 return;
9886
9887}
9888
9889
9890/**---------------------------------------------------------------------------
9891 *
9892 * \brief wlan_hdd_restart_driver
9893 *
9894 * This function sends an event to supplicant to restart the WLAN driver.
9895 *
9896 * This function is called from vos_wlanRestart.
9897 *
9898 * \param - pHddCtx
9899 *
9900 * \return - VOS_STATUS_SUCCESS: Success
9901 * VOS_STATUS_E_EMPTY: Adapter is Empty
9902 * VOS_STATUS_E_ALREADY: Request already in progress
9903
9904 * --------------------------------------------------------------------------*/
9905VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
9906{
9907 VOS_STATUS status = VOS_STATUS_SUCCESS;
9908
9909 /* A tight check to make sure reentrancy */
9910 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
9911 {
Mihir Shetefd528652014-06-23 19:07:50 +05309912 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnsone7245742012-09-05 17:12:55 -07009913 "%s: WLAN restart is already in progress", __func__);
9914
9915 return VOS_STATUS_E_ALREADY;
9916 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07009917 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08009918#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07009919 wcnss_reset_intr();
9920#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07009921
Jeff Johnsone7245742012-09-05 17:12:55 -07009922 return status;
9923}
9924
Mihir Shetee1093ba2014-01-21 20:13:32 +05309925/**---------------------------------------------------------------------------
9926 *
9927 * \brief wlan_hdd_init_channels
9928 *
9929 * This function is used to initialize the channel list in CSR
9930 *
9931 * This function is called from hdd_wlan_startup
9932 *
9933 * \param - pHddCtx: HDD context
9934 *
9935 * \return - VOS_STATUS_SUCCESS: Success
9936 * VOS_STATUS_E_FAULT: Failure reported by SME
9937
9938 * --------------------------------------------------------------------------*/
9939static VOS_STATUS wlan_hdd_init_channels(hdd_context_t *pHddCtx)
9940{
9941 eHalStatus status;
9942
9943 status = sme_InitChannels(pHddCtx->hHal);
9944 if (HAL_STATUS_SUCCESS(status))
9945 {
9946 return VOS_STATUS_SUCCESS;
9947 }
9948 else
9949 {
9950 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Channel initialization failed(%d)",
9951 __func__, status);
9952 return VOS_STATUS_E_FAULT;
9953 }
9954}
9955
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05309956static VOS_STATUS wlan_hdd_init_channels_for_cc(hdd_context_t *pHddCtx)
9957{
9958 eHalStatus status;
9959
9960 status = sme_InitChannelsForCC(pHddCtx->hHal);
9961 if (HAL_STATUS_SUCCESS(status))
9962 {
9963 return VOS_STATUS_SUCCESS;
9964 }
9965 else
9966 {
9967 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Issue reg hint failed(%d)",
9968 __func__, status);
9969 return VOS_STATUS_E_FAULT;
9970 }
9971}
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -07009972/*
9973 * API to find if there is any STA or P2P-Client is connected
9974 */
9975VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
9976{
9977 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
9978}
Jeff Johnsone7245742012-09-05 17:12:55 -07009979
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +05309980int wlan_hdd_scan_abort(hdd_adapter_t *pAdapter)
9981{
9982 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9983 hdd_scaninfo_t *pScanInfo = NULL;
Girish Gowli4bf7a632014-06-12 13:42:11 +05309984 long status = 0;
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +05309985
9986 pScanInfo = &pHddCtx->scan_info;
9987 if (pScanInfo->mScanPending)
9988 {
9989 INIT_COMPLETION(pScanInfo->abortscan_event_var);
9990 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
9991 eCSR_SCAN_ABORT_DEFAULT);
9992
9993 status = wait_for_completion_interruptible_timeout(
9994 &pScanInfo->abortscan_event_var,
9995 msecs_to_jiffies(5000));
Girish Gowli4bf7a632014-06-12 13:42:11 +05309996 if (0 >= status)
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +05309997 {
9998 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Girish Gowli4bf7a632014-06-12 13:42:11 +05309999 "%s: Timeout or Interrupt occurred while waiting for abort"
10000 "scan, status- %ld", __func__, status);
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053010001 return -ETIMEDOUT;
10002 }
10003 }
Girish Gowli4bf7a632014-06-12 13:42:11 +053010004 return 0;
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053010005}
10006
Jeff Johnson295189b2012-06-20 16:38:30 -070010007//Register the module init/exit functions
10008module_init(hdd_module_init);
10009module_exit(hdd_module_exit);
10010
10011MODULE_LICENSE("Dual BSD/GPL");
10012MODULE_AUTHOR("Qualcomm Atheros, Inc.");
10013MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
10014
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070010015module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
10016 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -070010017
Jeff Johnson76052702013-04-16 13:55:05 -070010018module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -070010019 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Arif Hussain66559122013-11-21 10:11:40 -080010020
10021module_param(enable_dfs_chan_scan, int,
10022 S_IRUSR | S_IRGRP | S_IROTH);
10023
10024module_param(enable_11d, int,
10025 S_IRUSR | S_IRGRP | S_IROTH);
10026
10027module_param(country_code, charp,
10028 S_IRUSR | S_IRGRP | S_IROTH);