blob: 1dad07d8f1cbffae9ddaf0793e3c78139585c697 [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
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05305087 /* Nothing to be done if the interface is not opened */
5088 if (VOS_FALSE == test_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags))
5089 {
5090 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5091 "%s: NETDEV Interface is not OPENED", __func__);
5092 return -ENODEV;
5093 }
5094
5095 /* Make sure the interface is marked as closed */
Jeff Johnson6a81ca42013-04-05 10:37:08 -07005096 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07005097 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05305098
5099 /* Disable TX on the interface, after this hard_start_xmit() will not
5100 * be called on that interface
5101 */
Jeff Johnson295189b2012-06-20 16:38:30 -07005102 netif_tx_disable(pAdapter->dev);
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05305103
5104 /* Mark the interface status as "down" for outside world */
Jeff Johnson295189b2012-06-20 16:38:30 -07005105 netif_carrier_off(pAdapter->dev);
5106
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05305107 /* The interface is marked as down for outside world (aka kernel)
5108 * But the driver is pretty much alive inside. The driver needs to
5109 * tear down the existing connection on the netdev (session)
5110 * cleanup the data pipes and wait until the control plane is stabilized
5111 * for this interface. The call also needs to wait until the above
5112 * mentioned actions are completed before returning to the caller.
5113 * Notice that the hdd_stop_adapter is requested not to close the session
5114 * That is intentional to be able to scan if it is a STA/P2P interface
5115 */
5116 hdd_stop_adapter(pHddCtx, pAdapter, VOS_FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -07005117
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05305118 /* DeInit the adapter. This ensures datapath cleanup as well */
5119 hdd_deinit_adapter(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005120 /* SoftAP ifaces should never go in power save mode
5121 making sure same here. */
5122 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
5123 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07005124 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07005125 )
5126 {
5127 /* SoftAP mode, so return from here */
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305128 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5129 "%s: In SAP MODE", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005130 EXIT();
5131 return 0;
5132 }
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05305133 /* Find if any iface is up. If any iface is up then can't put device to
5134 * sleep/power save mode
5135 */
Jeff Johnson295189b2012-06-20 16:38:30 -07005136 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5137 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
5138 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07005139 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
5140 {
5141 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305142 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07005143 enter_standby = FALSE;
5144 break;
5145 }
5146 else
5147 {
5148 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5149 pAdapterNode = pNext;
5150 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005151 }
5152
5153 if (TRUE == enter_standby)
5154 {
5155 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
5156 "entering standby", __func__);
5157 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
5158 {
5159 /*log and return success*/
5160 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
5161 "wlan in power save", __func__);
5162 }
5163 }
5164
5165 EXIT();
5166 return 0;
5167}
5168
5169/**---------------------------------------------------------------------------
5170
5171 \brief hdd_uninit() - HDD uninit function
5172
5173 This is called during the netdev unregister to uninitialize all data
5174associated with the device
5175
5176 \param - dev Pointer to net_device structure
5177
5178 \return - void
5179
5180 --------------------------------------------------------------------------*/
5181static void hdd_uninit (struct net_device *dev)
5182{
5183 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5184
5185 ENTER();
5186
5187 do
5188 {
5189 if (NULL == pAdapter)
5190 {
5191 hddLog(VOS_TRACE_LEVEL_FATAL,
5192 "%s: NULL pAdapter", __func__);
5193 break;
5194 }
5195
5196 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
5197 {
5198 hddLog(VOS_TRACE_LEVEL_FATAL,
5199 "%s: Invalid magic", __func__);
5200 break;
5201 }
5202
5203 if (NULL == pAdapter->pHddCtx)
5204 {
5205 hddLog(VOS_TRACE_LEVEL_FATAL,
5206 "%s: NULL pHddCtx", __func__);
5207 break;
5208 }
5209
5210 if (dev != pAdapter->dev)
5211 {
5212 hddLog(VOS_TRACE_LEVEL_FATAL,
5213 "%s: Invalid device reference", __func__);
5214 /* we haven't validated all cases so let this go for now */
5215 }
5216
5217 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
5218
5219 /* after uninit our adapter structure will no longer be valid */
5220 pAdapter->dev = NULL;
5221 pAdapter->magic = 0;
5222 } while (0);
5223
5224 EXIT();
5225}
5226
5227/**---------------------------------------------------------------------------
5228
5229 \brief hdd_release_firmware() -
5230
5231 This function calls the release firmware API to free the firmware buffer.
5232
5233 \param - pFileName Pointer to the File Name.
5234 pCtx - Pointer to the adapter .
5235
5236
5237 \return - 0 for success, non zero for failure
5238
5239 --------------------------------------------------------------------------*/
5240
5241VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
5242{
5243 VOS_STATUS status = VOS_STATUS_SUCCESS;
5244 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
5245 ENTER();
5246
5247
5248 if (!strcmp(WLAN_FW_FILE, pFileName)) {
5249
5250 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
5251
5252 if(pHddCtx->fw) {
5253 release_firmware(pHddCtx->fw);
5254 pHddCtx->fw = NULL;
5255 }
5256 else
5257 status = VOS_STATUS_E_FAILURE;
5258 }
5259 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
5260 if(pHddCtx->nv) {
5261 release_firmware(pHddCtx->nv);
5262 pHddCtx->nv = NULL;
5263 }
5264 else
5265 status = VOS_STATUS_E_FAILURE;
5266
5267 }
5268
5269 EXIT();
5270 return status;
5271}
5272
5273/**---------------------------------------------------------------------------
5274
5275 \brief hdd_request_firmware() -
5276
5277 This function reads the firmware file using the request firmware
5278 API and returns the the firmware data and the firmware file size.
5279
5280 \param - pfileName - Pointer to the file name.
5281 - pCtx - Pointer to the adapter .
5282 - ppfw_data - Pointer to the pointer of the firmware data.
5283 - pSize - Pointer to the file size.
5284
5285 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
5286
5287 --------------------------------------------------------------------------*/
5288
5289
5290VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
5291{
5292 int status;
5293 VOS_STATUS retval = VOS_STATUS_SUCCESS;
5294 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
5295 ENTER();
5296
5297 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
5298
5299 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
5300
5301 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
5302 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
5303 __func__, pfileName);
5304 retval = VOS_STATUS_E_FAILURE;
5305 }
5306
5307 else {
5308 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
5309 *pSize = pHddCtx->fw->size;
5310 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
5311 __func__, *pSize);
5312 }
5313 }
5314 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
5315
5316 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
5317
5318 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
5319 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
5320 __func__, pfileName);
5321 retval = VOS_STATUS_E_FAILURE;
5322 }
5323
5324 else {
5325 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
5326 *pSize = pHddCtx->nv->size;
5327 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
5328 __func__, *pSize);
5329 }
5330 }
5331
5332 EXIT();
5333 return retval;
5334}
5335/**---------------------------------------------------------------------------
5336 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
5337
5338 This is the function invoked by SME to inform the result of a full power
5339 request issued by HDD
5340
5341 \param - callbackcontext - Pointer to cookie
5342 status - result of request
5343
5344 \return - None
5345
5346--------------------------------------------------------------------------*/
5347void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
5348{
5349 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
5350
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07005351 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07005352 if(&pHddCtx->full_pwr_comp_var)
5353 {
5354 complete(&pHddCtx->full_pwr_comp_var);
5355 }
5356}
5357
5358/**---------------------------------------------------------------------------
5359
5360 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
5361
5362 This is the function invoked by SME to inform the result of BMPS
5363 request issued by HDD
5364
5365 \param - callbackcontext - Pointer to cookie
5366 status - result of request
5367
5368 \return - None
5369
5370--------------------------------------------------------------------------*/
5371void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
5372{
5373
5374 struct completion *completion_var = (struct completion*) callbackContext;
5375
Arif Hussain6d2a3322013-11-17 19:50:10 -08005376 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07005377 if(completion_var != NULL)
5378 {
5379 complete(completion_var);
5380 }
5381}
5382
5383/**---------------------------------------------------------------------------
5384
5385 \brief hdd_get_cfg_file_size() -
5386
5387 This function reads the configuration file using the request firmware
5388 API and returns the configuration file size.
5389
5390 \param - pCtx - Pointer to the adapter .
5391 - pFileName - Pointer to the file name.
5392 - pBufSize - Pointer to the buffer size.
5393
5394 \return - 0 for success, non zero for failure
5395
5396 --------------------------------------------------------------------------*/
5397
5398VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
5399{
5400 int status;
5401 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
5402
5403 ENTER();
5404
5405 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
5406
5407 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
5408 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
5409 status = VOS_STATUS_E_FAILURE;
5410 }
5411 else {
5412 *pBufSize = pHddCtx->fw->size;
5413 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
5414 release_firmware(pHddCtx->fw);
5415 pHddCtx->fw = NULL;
5416 }
5417
5418 EXIT();
5419 return VOS_STATUS_SUCCESS;
5420}
5421
5422/**---------------------------------------------------------------------------
5423
5424 \brief hdd_read_cfg_file() -
5425
5426 This function reads the configuration file using the request firmware
5427 API and returns the cfg data and the buffer size of the configuration file.
5428
5429 \param - pCtx - Pointer to the adapter .
5430 - pFileName - Pointer to the file name.
5431 - pBuffer - Pointer to the data buffer.
5432 - pBufSize - Pointer to the buffer size.
5433
5434 \return - 0 for success, non zero for failure
5435
5436 --------------------------------------------------------------------------*/
5437
5438VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
5439 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
5440{
5441 int status;
5442 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
5443
5444 ENTER();
5445
5446 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
5447
5448 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
5449 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
5450 return VOS_STATUS_E_FAILURE;
5451 }
5452 else {
5453 if(*pBufSize != pHddCtx->fw->size) {
5454 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
5455 "file size", __func__);
5456 release_firmware(pHddCtx->fw);
5457 pHddCtx->fw = NULL;
5458 return VOS_STATUS_E_FAILURE;
5459 }
5460 else {
5461 if(pBuffer) {
5462 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
5463 }
5464 release_firmware(pHddCtx->fw);
5465 pHddCtx->fw = NULL;
5466 }
5467 }
5468
5469 EXIT();
5470
5471 return VOS_STATUS_SUCCESS;
5472}
5473
5474/**---------------------------------------------------------------------------
5475
Jeff Johnson295189b2012-06-20 16:38:30 -07005476 \brief hdd_set_mac_address() -
5477
5478 This function sets the user specified mac address using
5479 the command ifconfig wlanX hw ether <mac adress>.
5480
5481 \param - dev - Pointer to the net device.
5482 - addr - Pointer to the sockaddr.
5483 \return - 0 for success, non zero for failure
5484
5485 --------------------------------------------------------------------------*/
5486
5487static int hdd_set_mac_address(struct net_device *dev, void *addr)
5488{
5489 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5490 struct sockaddr *psta_mac_addr = addr;
5491 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5492
5493 ENTER();
5494
5495 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
Jeff Johnson295189b2012-06-20 16:38:30 -07005496 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
5497
5498 EXIT();
5499 return halStatus;
5500}
5501
5502tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
5503{
5504 int i;
5505 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5506 {
Abhishek Singheb183782014-02-06 13:37:21 +05305507 if( 0 == ((pHddCtx->cfg_ini->intfAddrMask) & (1 << i)) )
Jeff Johnson295189b2012-06-20 16:38:30 -07005508 break;
5509 }
5510
5511 if( VOS_MAX_CONCURRENCY_PERSONA == i)
5512 return NULL;
5513
5514 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
5515 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
5516}
5517
5518void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
5519{
5520 int i;
5521 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5522 {
5523 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
5524 {
5525 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
5526 break;
5527 }
5528 }
5529 return;
5530}
5531
5532#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
5533 static struct net_device_ops wlan_drv_ops = {
5534 .ndo_open = hdd_open,
5535 .ndo_stop = hdd_stop,
5536 .ndo_uninit = hdd_uninit,
5537 .ndo_start_xmit = hdd_hard_start_xmit,
5538 .ndo_tx_timeout = hdd_tx_timeout,
5539 .ndo_get_stats = hdd_stats,
5540 .ndo_do_ioctl = hdd_ioctl,
5541 .ndo_set_mac_address = hdd_set_mac_address,
5542 .ndo_select_queue = hdd_select_queue,
5543#ifdef WLAN_FEATURE_PACKET_FILTERING
5544#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
5545 .ndo_set_rx_mode = hdd_set_multicast_list,
5546#else
5547 .ndo_set_multicast_list = hdd_set_multicast_list,
5548#endif //LINUX_VERSION_CODE
5549#endif
5550 };
Jeff Johnson295189b2012-06-20 16:38:30 -07005551 static struct net_device_ops wlan_mon_drv_ops = {
5552 .ndo_open = hdd_mon_open,
5553 .ndo_stop = hdd_stop,
5554 .ndo_uninit = hdd_uninit,
5555 .ndo_start_xmit = hdd_mon_hard_start_xmit,
5556 .ndo_tx_timeout = hdd_tx_timeout,
5557 .ndo_get_stats = hdd_stats,
5558 .ndo_do_ioctl = hdd_ioctl,
5559 .ndo_set_mac_address = hdd_set_mac_address,
5560 };
Jeff Johnson295189b2012-06-20 16:38:30 -07005561
5562#endif
5563
5564void hdd_set_station_ops( struct net_device *pWlanDev )
5565{
5566#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
Jeff Johnson295189b2012-06-20 16:38:30 -07005567 pWlanDev->netdev_ops = &wlan_drv_ops;
5568#else
5569 pWlanDev->open = hdd_open;
5570 pWlanDev->stop = hdd_stop;
5571 pWlanDev->uninit = hdd_uninit;
5572 pWlanDev->hard_start_xmit = NULL;
5573 pWlanDev->tx_timeout = hdd_tx_timeout;
5574 pWlanDev->get_stats = hdd_stats;
5575 pWlanDev->do_ioctl = hdd_ioctl;
Jeff Johnson295189b2012-06-20 16:38:30 -07005576 pWlanDev->set_mac_address = hdd_set_mac_address;
5577#endif
5578}
5579
Jeff Johnsoneed415b2013-01-18 16:11:20 -08005580static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07005581{
5582 struct net_device *pWlanDev = NULL;
5583 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005584 /*
5585 * cfg80211 initialization and registration....
5586 */
5587 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
5588
Jeff Johnson295189b2012-06-20 16:38:30 -07005589 if(pWlanDev != NULL)
5590 {
5591
5592 //Save the pointer to the net_device in the HDD adapter
5593 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
5594
Jeff Johnson295189b2012-06-20 16:38:30 -07005595 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
5596
5597 pAdapter->dev = pWlanDev;
5598 pAdapter->pHddCtx = pHddCtx;
5599 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
5600
5601 init_completion(&pAdapter->session_open_comp_var);
5602 init_completion(&pAdapter->session_close_comp_var);
5603 init_completion(&pAdapter->disconnect_comp_var);
5604 init_completion(&pAdapter->linkup_event_var);
5605 init_completion(&pAdapter->cancel_rem_on_chan_var);
5606 init_completion(&pAdapter->rem_on_chan_ready_event);
Vinay Krishna Erannaf0e523b2014-03-01 21:00:16 +05305607 init_completion(&pAdapter->pno_comp_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07005608#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
5609 init_completion(&pAdapter->offchannel_tx_event);
5610#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005611 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005612#ifdef FEATURE_WLAN_TDLS
5613 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07005614 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08005615 init_completion(&pAdapter->tdls_mgmt_comp);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05305616 init_completion(&pAdapter->tdls_link_establish_req_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005617#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005618 init_completion(&pHddCtx->mc_sus_event_var);
5619 init_completion(&pHddCtx->tx_sus_event_var);
Gopichand Nakkala05621412013-06-19 19:37:38 +05305620 init_completion(&pHddCtx->rx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07005621 init_completion(&pAdapter->ula_complete);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07005622 init_completion(&pAdapter->change_country_code);
Jeff Johnson295189b2012-06-20 16:38:30 -07005623
Rajeev79dbe4c2013-10-05 11:03:42 +05305624#ifdef FEATURE_WLAN_BATCH_SCAN
5625 init_completion(&pAdapter->hdd_set_batch_scan_req_var);
5626 init_completion(&pAdapter->hdd_get_batch_scan_req_var);
5627 pAdapter->pBatchScanRsp = NULL;
5628 pAdapter->numScanList = 0;
Rajeev Kumar20140c12013-10-21 19:39:02 -07005629 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
Kiet Lamaa8e15a2014-02-11 23:30:06 -08005630 pAdapter->prev_batch_id = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05305631 mutex_init(&pAdapter->hdd_batch_scan_lock);
5632#endif
5633
Jeff Johnson295189b2012-06-20 16:38:30 -07005634 pAdapter->isLinkUpSvcNeeded = FALSE;
5635 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
5636 //Init the net_device structure
5637 strlcpy(pWlanDev->name, name, IFNAMSIZ);
5638
5639 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
5640 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
5641 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
5642 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
5643
5644 hdd_set_station_ops( pAdapter->dev );
5645
5646 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07005647 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
5648 pAdapter->wdev.wiphy = pHddCtx->wiphy;
5649 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07005650 /* set pWlanDev's parent to underlying device */
5651 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
Kumar Anand82c009f2014-05-29 00:29:42 -07005652
5653 hdd_wmm_init( pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07005654 }
5655
5656 return pAdapter;
5657}
5658
5659VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
5660{
5661 struct net_device *pWlanDev = pAdapter->dev;
5662 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
5663 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
5664 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5665
5666 if( rtnl_lock_held )
5667 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08005668 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07005669 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
5670 {
5671 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
5672 return VOS_STATUS_E_FAILURE;
5673 }
5674 }
5675 if (register_netdevice(pWlanDev))
5676 {
5677 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
5678 return VOS_STATUS_E_FAILURE;
5679 }
5680 }
5681 else
5682 {
5683 if(register_netdev(pWlanDev))
5684 {
5685 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
5686 return VOS_STATUS_E_FAILURE;
5687 }
5688 }
5689 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
5690
5691 return VOS_STATUS_SUCCESS;
5692}
5693
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005694static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07005695{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005696 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07005697
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005698 if (NULL == pAdapter)
5699 {
5700 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
5701 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07005702 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005703
5704 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
5705 {
5706 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
5707 return eHAL_STATUS_NOT_INITIALIZED;
5708 }
5709
5710 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
5711
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005712#ifndef WLAN_OPEN_SOURCE
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005713 /* need to make sure all of our scheduled work has completed.
5714 * This callback is called from MC thread context, so it is safe to
5715 * to call below flush workqueue API from here.
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005716 *
5717 * Even though this is called from MC thread context, if there is a faulty
5718 * work item in the system, that can hang this call forever. So flushing
5719 * this global work queue is not safe; and now we make sure that
5720 * individual work queues are stopped correctly. But the cancel work queue
5721 * is a GPL only API, so the proprietary version of the driver would still
5722 * rely on the global work queue flush.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005723 */
5724 flush_scheduled_work();
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005725#endif
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005726
5727 /* We can be blocked while waiting for scheduled work to be
5728 * flushed, and the adapter structure can potentially be freed, in
5729 * which case the magic will have been reset. So make sure the
5730 * magic is still good, and hence the adapter structure is still
5731 * valid, before signaling completion */
5732 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
5733 {
5734 complete(&pAdapter->session_close_comp_var);
5735 }
5736
Jeff Johnson295189b2012-06-20 16:38:30 -07005737 return eHAL_STATUS_SUCCESS;
5738}
5739
5740VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
5741{
5742 struct net_device *pWlanDev = pAdapter->dev;
5743 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
5744 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
5745 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5746 VOS_STATUS status = VOS_STATUS_E_FAILURE;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305747 long rc = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07005748
5749 INIT_COMPLETION(pAdapter->session_open_comp_var);
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07005750 sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07005751 //Open a SME session for future operation
5752 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07005753 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07005754 if ( !HAL_STATUS_SUCCESS( halStatus ) )
5755 {
5756 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005757 "sme_OpenSession() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005758 halStatus, halStatus );
5759 status = VOS_STATUS_E_FAILURE;
5760 goto error_sme_open;
5761 }
5762
5763 //Block on a completion variable. Can't wait forever though.
Vinay Krishna Eranna0fe2e7c2014-04-09 21:32:08 +05305764 rc = wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07005765 &pAdapter->session_open_comp_var,
5766 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305767 if (rc <= 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07005768 {
5769 hddLog(VOS_TRACE_LEVEL_FATAL,
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305770 "Session is not opened within timeout period code %ld", rc );
Jeff Johnson295189b2012-06-20 16:38:30 -07005771 status = VOS_STATUS_E_FAILURE;
5772 goto error_sme_open;
5773 }
5774
5775 // Register wireless extensions
5776 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
5777 {
5778 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005779 "hdd_register_wext() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005780 halStatus, halStatus );
5781 status = VOS_STATUS_E_FAILURE;
5782 goto error_register_wext;
5783 }
5784 //Safe to register the hard_start_xmit function again
5785#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
5786 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
5787#else
5788 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
5789#endif
5790
5791 //Set the Connection State to Not Connected
Abhishek Singhf4669da2014-05-26 15:07:49 +05305792 hddLog(VOS_TRACE_LEVEL_INFO,
5793 "%s: Set HDD connState to eConnectionState_NotConnected",
5794 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005795 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
5796
5797 //Set the default operation channel
5798 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
5799
5800 /* Make the default Auth Type as OPEN*/
5801 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
5802
5803 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
5804 {
5805 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005806 "hdd_init_tx_rx() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005807 status, status );
5808 goto error_init_txrx;
5809 }
5810
5811 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5812
5813 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
5814 {
5815 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005816 "hdd_wmm_adapter_init() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005817 status, status );
5818 goto error_wmm_init;
5819 }
5820
5821 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5822
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005823#ifdef FEATURE_WLAN_TDLS
5824 if(0 != wlan_hdd_tdls_init(pAdapter))
5825 {
5826 status = VOS_STATUS_E_FAILURE;
5827 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
5828 goto error_tdls_init;
5829 }
5830 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
5831#endif
5832
Jeff Johnson295189b2012-06-20 16:38:30 -07005833 return VOS_STATUS_SUCCESS;
5834
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005835#ifdef FEATURE_WLAN_TDLS
5836error_tdls_init:
5837 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5838 hdd_wmm_adapter_close(pAdapter);
5839#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005840error_wmm_init:
5841 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5842 hdd_deinit_tx_rx(pAdapter);
5843error_init_txrx:
5844 hdd_UnregisterWext(pWlanDev);
5845error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005846 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07005847 {
5848 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005849 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07005850 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005851 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07005852 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305853 unsigned long rc;
5854
Jeff Johnson295189b2012-06-20 16:38:30 -07005855 //Block on a completion variable. Can't wait forever though.
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305856 rc = wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07005857 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005858 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305859 if (rc <= 0)
5860 hddLog(VOS_TRACE_LEVEL_ERROR,
5861 FL("Session is not opened within timeout period code %ld"), rc);
Jeff Johnson295189b2012-06-20 16:38:30 -07005862 }
5863}
5864error_sme_open:
5865 return status;
5866}
5867
Jeff Johnson295189b2012-06-20 16:38:30 -07005868void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5869{
5870 hdd_cfg80211_state_t *cfgState;
5871
5872 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
5873
5874 if( NULL != cfgState->buf )
5875 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305876 long rc;
Jeff Johnson295189b2012-06-20 16:38:30 -07005877 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
5878 rc = wait_for_completion_interruptible_timeout(
5879 &pAdapter->tx_action_cnf_event,
5880 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305881 if (rc <= 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07005882 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08005883 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305884 "%s ERROR: HDD Wait for Action Confirmation Failed!! %ld"
5885 , __func__, rc);
Jeff Johnson295189b2012-06-20 16:38:30 -07005886 }
5887 }
5888 return;
5889}
Jeff Johnson295189b2012-06-20 16:38:30 -07005890
5891void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5892{
5893 ENTER();
5894 switch ( pAdapter->device_mode )
5895 {
5896 case WLAN_HDD_INFRA_STATION:
5897 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005898 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005899 {
5900 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
5901 {
5902 hdd_deinit_tx_rx( pAdapter );
5903 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5904 }
5905
5906 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
5907 {
5908 hdd_wmm_adapter_close( pAdapter );
5909 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5910 }
5911
Jeff Johnson295189b2012-06-20 16:38:30 -07005912 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005913#ifdef FEATURE_WLAN_TDLS
5914 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
5915 {
5916 wlan_hdd_tdls_exit(pAdapter);
5917 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
5918 }
5919#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005920
5921 break;
5922 }
5923
5924 case WLAN_HDD_SOFTAP:
5925 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005926 {
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05305927
5928 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
5929 {
5930 hdd_wmm_adapter_close( pAdapter );
5931 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5932 }
5933
Jeff Johnson295189b2012-06-20 16:38:30 -07005934 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005935
5936 hdd_unregister_hostapd(pAdapter);
5937 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07005938 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07005939 break;
5940 }
5941
5942 case WLAN_HDD_MONITOR:
5943 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005944 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07005945 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
5946 {
5947 hdd_deinit_tx_rx( pAdapter );
5948 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5949 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005950 if(NULL != pAdapterforTx)
5951 {
5952 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
5953 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005954 break;
5955 }
5956
5957
5958 default:
5959 break;
5960 }
5961
5962 EXIT();
5963}
5964
5965void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
5966{
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -08005967 struct net_device *pWlanDev = NULL;
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05305968
5969 ENTER();
5970 if (NULL == pAdapter)
5971 {
5972 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5973 "%s: HDD adapter is Null", __func__);
5974 return;
5975 }
5976
5977 pWlanDev = pAdapter->dev;
Jeff Johnson295189b2012-06-20 16:38:30 -07005978
Rajeev79dbe4c2013-10-05 11:03:42 +05305979#ifdef FEATURE_WLAN_BATCH_SCAN
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05305980 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
5981 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Rajeev Kumarf999e582014-01-09 17:33:29 -08005982 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05305983 || (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)
5984 )
5985 {
Rajeev Kumarf999e582014-01-09 17:33:29 -08005986 if (pAdapter)
Rajeev79dbe4c2013-10-05 11:03:42 +05305987 {
Rajeev Kumarf999e582014-01-09 17:33:29 -08005988 if (eHDD_BATCH_SCAN_STATE_STARTED == pAdapter->batchScanState)
5989 {
5990 hdd_deinit_batch_scan(pAdapter);
5991 }
Rajeev79dbe4c2013-10-05 11:03:42 +05305992 }
Rajeev Kumarf999e582014-01-09 17:33:29 -08005993 }
Rajeev79dbe4c2013-10-05 11:03:42 +05305994#endif
5995
Jeff Johnson295189b2012-06-20 16:38:30 -07005996 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
5997 if( rtnl_held )
5998 {
5999 unregister_netdevice(pWlanDev);
6000 }
6001 else
6002 {
6003 unregister_netdev(pWlanDev);
6004 }
6005 // note that the pAdapter is no longer valid at this point
6006 // since the memory has been reclaimed
6007 }
6008
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05306009 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07006010}
6011
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006012void hdd_set_pwrparams(hdd_context_t *pHddCtx)
6013{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306014 VOS_STATUS status;
6015 hdd_adapter_t *pAdapter = NULL;
6016 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006017
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306018 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006019
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306020 /*loop through all adapters.*/
6021 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006022 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306023 pAdapter = pAdapterNode->pAdapter;
6024 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
6025 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006026
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306027 { // we skip this registration for modes other than STA and P2P client modes.
6028 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6029 pAdapterNode = pNext;
6030 continue;
6031 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006032
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306033 //Apply Dynamic DTIM For P2P
6034 //Only if ignoreDynamicDtimInP2pMode is not set in ini
6035 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
6036 pHddCtx->cfg_ini->enableModulatedDTIM) &&
6037 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
6038 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
6039 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
6040 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
6041 (eConnectionState_Associated ==
6042 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
6043 (pHddCtx->cfg_ini->fIsBmpsEnabled))
6044 {
6045 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006046
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306047 powerRequest.uIgnoreDTIM = 1;
6048 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
6049
6050 if (pHddCtx->cfg_ini->enableModulatedDTIM)
6051 {
6052 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
6053 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
6054 }
6055 else
6056 {
6057 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
6058 }
6059
6060 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
6061 * specified during Enter/Exit BMPS when LCD off*/
6062 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
6063 NULL, eANI_BOOLEAN_FALSE);
6064 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
6065 NULL, eANI_BOOLEAN_FALSE);
6066
6067 /* switch to the DTIM specified in cfg.ini */
6068 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6069 "Switch to DTIM %d", powerRequest.uListenInterval);
6070 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
6071 break;
6072
6073 }
6074
6075 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6076 pAdapterNode = pNext;
6077 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006078}
6079
6080void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
6081{
6082 /*Switch back to DTIM 1*/
6083 tSirSetPowerParamsReq powerRequest = { 0 };
6084
6085 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
6086 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07006087 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006088
6089 /* Update ignoreDTIM and ListedInterval in CFG with default values */
6090 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
6091 NULL, eANI_BOOLEAN_FALSE);
6092 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
6093 NULL, eANI_BOOLEAN_FALSE);
6094
6095 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6096 "Switch to DTIM%d",powerRequest.uListenInterval);
6097 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
6098
6099}
6100
Jeff Johnson295189b2012-06-20 16:38:30 -07006101VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
6102{
6103 VOS_STATUS status = VOS_STATUS_SUCCESS;
6104
6105 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
6106 {
6107 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
6108 }
6109
6110 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
6111 {
6112 sme_StartAutoBmpsTimer(pHddCtx->hHal);
6113 }
6114
6115 if (pHddCtx->cfg_ini->fIsImpsEnabled)
6116 {
6117 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
6118 }
6119
6120 return status;
6121}
6122
6123VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
6124{
6125 hdd_adapter_t *pAdapter = NULL;
6126 eHalStatus halStatus;
6127 VOS_STATUS status = VOS_STATUS_E_INVAL;
6128 v_BOOL_t disableBmps = FALSE;
6129 v_BOOL_t disableImps = FALSE;
6130
6131 switch(session_type)
6132 {
6133 case WLAN_HDD_INFRA_STATION:
6134 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07006135 case WLAN_HDD_P2P_CLIENT:
6136 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07006137 //Exit BMPS -> Is Sta/P2P Client is already connected
6138 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
6139 if((NULL != pAdapter)&&
6140 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
6141 {
6142 disableBmps = TRUE;
6143 }
6144
6145 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
6146 if((NULL != pAdapter)&&
6147 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
6148 {
6149 disableBmps = TRUE;
6150 }
6151
6152 //Exit both Bmps and Imps incase of Go/SAP Mode
6153 if((WLAN_HDD_SOFTAP == session_type) ||
6154 (WLAN_HDD_P2P_GO == session_type))
6155 {
6156 disableBmps = TRUE;
6157 disableImps = TRUE;
6158 }
6159
6160 if(TRUE == disableImps)
6161 {
6162 if (pHddCtx->cfg_ini->fIsImpsEnabled)
6163 {
6164 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
6165 }
6166 }
6167
6168 if(TRUE == disableBmps)
6169 {
6170 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
6171 {
6172 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
6173
6174 if(eHAL_STATUS_SUCCESS != halStatus)
6175 {
6176 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08006177 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006178 VOS_ASSERT(0);
6179 return status;
6180 }
6181 }
6182
6183 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
6184 {
6185 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
6186
6187 if(eHAL_STATUS_SUCCESS != halStatus)
6188 {
6189 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08006190 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006191 VOS_ASSERT(0);
6192 return status;
6193 }
6194 }
6195 }
6196
6197 if((TRUE == disableBmps) ||
6198 (TRUE == disableImps))
6199 {
6200 /* Now, get the chip into Full Power now */
6201 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
6202 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
6203 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
6204
6205 if(halStatus != eHAL_STATUS_SUCCESS)
6206 {
6207 if(halStatus == eHAL_STATUS_PMC_PENDING)
6208 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306209 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07006210 //Block on a completion variable. Can't wait forever though
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306211 ret = wait_for_completion_interruptible_timeout(
6212 &pHddCtx->full_pwr_comp_var,
6213 msecs_to_jiffies(1000));
6214 if (ret <= 0)
6215 {
6216 hddLog(VOS_TRACE_LEVEL_ERROR,
6217 "%s: wait on full_pwr_comp_var failed %ld",
6218 __func__, ret);
6219 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006220 }
6221 else
6222 {
6223 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08006224 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006225 VOS_ASSERT(0);
6226 return status;
6227 }
6228 }
6229
6230 status = VOS_STATUS_SUCCESS;
6231 }
6232
6233 break;
6234 }
6235 return status;
6236}
6237
6238hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08006239 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07006240 tANI_U8 rtnl_held )
6241{
6242 hdd_adapter_t *pAdapter = NULL;
6243 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
6244 VOS_STATUS status = VOS_STATUS_E_FAILURE;
6245 VOS_STATUS exitbmpsStatus;
6246
Arif Hussain6d2a3322013-11-17 19:50:10 -08006247 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d",__func__,iface_name,session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006248
Nirav Shah436658f2014-02-28 17:05:45 +05306249 if(macAddr == NULL)
6250 {
6251 /* Not received valid macAddr */
6252 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6253 "%s:Unable to add virtual intf: Not able to get"
6254 "valid mac address",__func__);
6255 return NULL;
6256 }
6257
Jeff Johnson295189b2012-06-20 16:38:30 -07006258 //Disable BMPS incase of Concurrency
6259 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
6260
6261 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
6262 {
6263 //Fail to Exit BMPS
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306264 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Exit BMPS", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006265 VOS_ASSERT(0);
6266 return NULL;
6267 }
6268
6269 switch(session_type)
6270 {
6271 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07006272 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006273 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07006274 {
6275 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
6276
6277 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306278 {
6279 hddLog(VOS_TRACE_LEVEL_FATAL,
6280 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006281 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306282 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006283
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306284#ifdef FEATURE_WLAN_TDLS
6285 /* A Mutex Lock is introduced while changing/initializing the mode to
6286 * protect the concurrent access for the Adapters by TDLS module.
6287 */
Rajesh Chauhana34c6e62014-03-25 16:37:58 +05306288 mutex_lock(&pHddCtx->tdls_lock);
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306289#endif
6290
Jeff Johnsone7245742012-09-05 17:12:55 -07006291 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
6292 NL80211_IFTYPE_P2P_CLIENT:
6293 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07006294
Jeff Johnson295189b2012-06-20 16:38:30 -07006295 pAdapter->device_mode = session_type;
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306296#ifdef FEATURE_WLAN_TDLS
6297 mutex_unlock(&pHddCtx->tdls_lock);
6298#endif
Sunil Dutt66485cb2013-12-19 19:05:03 +05306299
6300 status = hdd_init_station_mode( pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07006301 if( VOS_STATUS_SUCCESS != status )
6302 goto err_free_netdev;
6303
6304 status = hdd_register_interface( pAdapter, rtnl_held );
6305 if( VOS_STATUS_SUCCESS != status )
6306 {
6307 hdd_deinit_adapter(pHddCtx, pAdapter);
6308 goto err_free_netdev;
6309 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306310
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05306311 // Workqueue which gets scheduled in IPv4 notification callback.
6312 INIT_WORK(&pAdapter->ipv4NotifierWorkQueue, hdd_ipv4_notifier_work_queue);
6313
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306314#ifdef WLAN_NS_OFFLOAD
6315 // Workqueue which gets scheduled in IPv6 notification callback.
6316 INIT_WORK(&pAdapter->ipv6NotifierWorkQueue, hdd_ipv6_notifier_work_queue);
6317#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006318 //Stop the Interface TX queue.
6319 netif_tx_disable(pAdapter->dev);
6320 //netif_tx_disable(pWlanDev);
6321 netif_carrier_off(pAdapter->dev);
6322
6323 break;
6324 }
6325
Jeff Johnson295189b2012-06-20 16:38:30 -07006326 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07006327 case WLAN_HDD_SOFTAP:
6328 {
6329 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
6330 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306331 {
6332 hddLog(VOS_TRACE_LEVEL_FATAL,
6333 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006334 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306335 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006336
Jeff Johnson295189b2012-06-20 16:38:30 -07006337 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
6338 NL80211_IFTYPE_AP:
6339 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07006340 pAdapter->device_mode = session_type;
6341
6342 status = hdd_init_ap_mode(pAdapter);
6343 if( VOS_STATUS_SUCCESS != status )
6344 goto err_free_netdev;
6345
6346 status = hdd_register_hostapd( pAdapter, rtnl_held );
6347 if( VOS_STATUS_SUCCESS != status )
6348 {
6349 hdd_deinit_adapter(pHddCtx, pAdapter);
6350 goto err_free_netdev;
6351 }
6352
6353 netif_tx_disable(pAdapter->dev);
6354 netif_carrier_off(pAdapter->dev);
6355
6356 hdd_set_conparam( 1 );
6357 break;
6358 }
6359 case WLAN_HDD_MONITOR:
6360 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006361 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
6362 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306363 {
6364 hddLog(VOS_TRACE_LEVEL_FATAL,
6365 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006366 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306367 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006368
6369 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
6370 pAdapter->device_mode = session_type;
6371 status = hdd_register_interface( pAdapter, rtnl_held );
6372#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
6373 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
6374#else
6375 pAdapter->dev->open = hdd_mon_open;
6376 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
6377#endif
6378 hdd_init_tx_rx( pAdapter );
6379 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
6380 //Set adapter to be used for data tx. It will use either GO or softap.
6381 pAdapter->sessionCtx.monitor.pAdapterForTx =
6382 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07006383 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
6384 {
6385 pAdapter->sessionCtx.monitor.pAdapterForTx =
6386 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
6387 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006388 /* This workqueue will be used to transmit management packet over
6389 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07006390 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
6391 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
6392 return NULL;
6393 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07006394
Jeff Johnson295189b2012-06-20 16:38:30 -07006395 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
6396 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07006397 }
6398 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07006399 case WLAN_HDD_FTM:
6400 {
6401 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
6402
6403 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306404 {
6405 hddLog(VOS_TRACE_LEVEL_FATAL,
6406 FL("failed to allocate adapter for session %d"), session_type);
6407 return NULL;
6408 }
6409
Jeff Johnson295189b2012-06-20 16:38:30 -07006410 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
6411 * message while loading driver in FTM mode. */
6412 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
6413 pAdapter->device_mode = session_type;
6414 status = hdd_register_interface( pAdapter, rtnl_held );
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05306415
6416 hdd_init_tx_rx( pAdapter );
6417
6418 //Stop the Interface TX queue.
6419 netif_tx_disable(pAdapter->dev);
6420 netif_carrier_off(pAdapter->dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07006421 }
6422 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07006423 default:
6424 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306425 hddLog(VOS_TRACE_LEVEL_FATAL,"%s Invalid session type %d",
6426 __func__, session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006427 VOS_ASSERT(0);
6428 return NULL;
6429 }
6430 }
6431
Jeff Johnson295189b2012-06-20 16:38:30 -07006432 if( VOS_STATUS_SUCCESS == status )
6433 {
6434 //Add it to the hdd's session list.
6435 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
6436 if( NULL == pHddAdapterNode )
6437 {
6438 status = VOS_STATUS_E_NOMEM;
6439 }
6440 else
6441 {
6442 pHddAdapterNode->pAdapter = pAdapter;
6443 status = hdd_add_adapter_back ( pHddCtx,
6444 pHddAdapterNode );
6445 }
6446 }
6447
6448 if( VOS_STATUS_SUCCESS != status )
6449 {
6450 if( NULL != pAdapter )
6451 {
6452 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
6453 pAdapter = NULL;
6454 }
6455 if( NULL != pHddAdapterNode )
6456 {
6457 vos_mem_free( pHddAdapterNode );
6458 }
6459
6460 goto resume_bmps;
6461 }
6462
6463 if(VOS_STATUS_SUCCESS == status)
6464 {
6465 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
6466
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07006467 //Initialize the WoWL service
6468 if(!hdd_init_wowl(pAdapter))
6469 {
6470 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
6471 goto err_free_netdev;
6472 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006473 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006474 return pAdapter;
6475
6476err_free_netdev:
6477 free_netdev(pAdapter->dev);
6478 wlan_hdd_release_intf_addr( pHddCtx,
6479 pAdapter->macAddressCurrent.bytes );
6480
6481resume_bmps:
6482 //If bmps disabled enable it
6483 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
6484 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306485 if (pHddCtx->hdd_wlan_suspended)
6486 {
6487 hdd_set_pwrparams(pHddCtx);
6488 }
6489 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07006490 }
6491 return NULL;
6492}
6493
6494VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
6495 tANI_U8 rtnl_held )
6496{
6497 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
6498 VOS_STATUS status;
6499
6500 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
6501 if( VOS_STATUS_SUCCESS != status )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306502 {
6503 hddLog(VOS_TRACE_LEVEL_WARN,"%s: adapter list empty %d",
6504 __func__, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07006505 return status;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306506 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006507
6508 while ( pCurrent->pAdapter != pAdapter )
6509 {
6510 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
6511 if( VOS_STATUS_SUCCESS != status )
6512 break;
6513
6514 pCurrent = pNext;
6515 }
6516 pAdapterNode = pCurrent;
6517 if( VOS_STATUS_SUCCESS == status )
6518 {
6519 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
6520 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306521
6522#ifdef FEATURE_WLAN_TDLS
6523
6524 /* A Mutex Lock is introduced while changing/initializing the mode to
6525 * protect the concurrent access for the Adapters by TDLS module.
6526 */
Rajesh Chauhana34c6e62014-03-25 16:37:58 +05306527 mutex_lock(&pHddCtx->tdls_lock);
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306528#endif
6529
Jeff Johnson295189b2012-06-20 16:38:30 -07006530 hdd_remove_adapter( pHddCtx, pAdapterNode );
6531 vos_mem_free( pAdapterNode );
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08006532 pAdapterNode = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006533
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306534#ifdef FEATURE_WLAN_TDLS
6535 mutex_unlock(&pHddCtx->tdls_lock);
6536#endif
6537
Jeff Johnson295189b2012-06-20 16:38:30 -07006538
6539 /* If there is a single session of STA/P2P client, re-enable BMPS */
6540 if ((!vos_concurrent_sessions_running()) &&
6541 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
6542 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
6543 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306544 if (pHddCtx->hdd_wlan_suspended)
6545 {
6546 hdd_set_pwrparams(pHddCtx);
6547 }
6548 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07006549 }
6550
6551 return VOS_STATUS_SUCCESS;
6552 }
6553
6554 return VOS_STATUS_E_FAILURE;
6555}
6556
6557VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
6558{
6559 hdd_adapter_list_node_t *pHddAdapterNode;
6560 VOS_STATUS status;
6561
6562 ENTER();
6563
6564 do
6565 {
6566 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
6567 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
6568 {
6569 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
6570 vos_mem_free( pHddAdapterNode );
6571 }
6572 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
6573
6574 EXIT();
6575
6576 return VOS_STATUS_SUCCESS;
6577}
6578
6579void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
6580{
6581 v_U8_t addIE[1] = {0};
6582
6583 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6584 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
6585 eANI_BOOLEAN_FALSE) )
6586 {
6587 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006588 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006589 }
6590
6591 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6592 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
6593 eANI_BOOLEAN_FALSE) )
6594 {
6595 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006596 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006597 }
6598
6599 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6600 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
6601 eANI_BOOLEAN_FALSE) )
6602 {
6603 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006604 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006605 }
6606}
6607
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05306608VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
6609 const v_BOOL_t bCloseSession )
Jeff Johnson295189b2012-06-20 16:38:30 -07006610{
6611 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
6612 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6613 union iwreq_data wrqu;
Kaushik, Sushant7005e372014-04-08 11:36:54 +05306614 v_U8_t retry = 0;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306615 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07006616
6617 ENTER();
6618
6619 switch(pAdapter->device_mode)
6620 {
6621 case WLAN_HDD_INFRA_STATION:
6622 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006623 case WLAN_HDD_P2P_DEVICE:
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05306624 {
6625 hdd_station_ctx_t *pstation = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6626 if( hdd_connIsConnected(pstation) ||
6627 (pstation->conn_info.connState == eConnectionState_Connecting) )
Jeff Johnson295189b2012-06-20 16:38:30 -07006628 {
6629 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
6630 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
6631 pAdapter->sessionId,
6632 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
6633 else
6634 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
6635 pAdapter->sessionId,
6636 eCSR_DISCONNECT_REASON_UNSPECIFIED);
6637 //success implies disconnect command got queued up successfully
6638 if(halStatus == eHAL_STATUS_SUCCESS)
6639 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306640 ret = wait_for_completion_interruptible_timeout(
6641 &pAdapter->disconnect_comp_var,
6642 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6643 if (ret <= 0)
6644 {
6645 hddLog(VOS_TRACE_LEVEL_ERROR,
6646 "%s: wait on disconnect_comp_var failed %ld",
6647 __func__, ret);
6648 }
6649 }
6650 else
6651 {
6652 hddLog(LOGE, "%s: failed to post disconnect event to SME",
6653 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006654 }
6655 memset(&wrqu, '\0', sizeof(wrqu));
6656 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
6657 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
6658 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
6659 }
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05306660 else if(pstation->conn_info.connState ==
6661 eConnectionState_Disconnecting)
6662 {
6663 ret = wait_for_completion_interruptible_timeout(
6664 &pAdapter->disconnect_comp_var,
6665 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6666 if (ret <= 0)
6667 {
6668 hddLog(VOS_TRACE_LEVEL_ERROR,
6669 FL("wait on disconnect_comp_var failed %ld"), ret);
6670 }
6671 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006672 else
6673 {
Srinivas, Dasari138af4f2014-02-07 11:13:45 +05306674 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
6675 eCSR_SCAN_ABORT_DEFAULT);
Jeff Johnson295189b2012-06-20 16:38:30 -07006676 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +05306677 if (pAdapter->device_mode != WLAN_HDD_INFRA_STATION)
6678 {
6679 while (pAdapter->is_roc_inprogress)
6680 {
6681 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6682 "%s: ROC in progress for session %d!!!",
6683 __func__, pAdapter->sessionId);
6684 // waiting for ROC to expire
6685 msleep(500);
6686 /* In GO present case , if retry exceeds 3,
6687 it means something went wrong. */
6688 if ( retry++ > MAX_WAIT_FOR_ROC_COMPLETION )
6689 {
6690 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6691 "%s: ROC completion is not received.!!!", __func__);
6692 sme_CancelRemainOnChannel(WLAN_HDD_GET_HAL_CTX(pAdapter),
6693 pAdapter->sessionId);
6694 wait_for_completion_interruptible_timeout(
6695 &pAdapter->cancel_rem_on_chan_var,
6696 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
6697 break;
6698 }
6699 }
6700 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306701#ifdef WLAN_NS_OFFLOAD
Vinay Krishna Eranna941360f2014-01-16 15:38:22 +05306702#ifdef WLAN_OPEN_SOURCE
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306703 cancel_work_sync(&pAdapter->ipv6NotifierWorkQueue);
6704#endif
Vinay Krishna Eranna941360f2014-01-16 15:38:22 +05306705 if (pAdapter->ipv6_notifier_registered)
6706 {
6707 hddLog(LOG1, FL("Unregistered IPv6 notifier"));
6708 unregister_inet6addr_notifier(&pAdapter->ipv6_notifier);
6709 pAdapter->ipv6_notifier_registered = false;
6710 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306711#endif
Vinay Krishna Erannad9cbdb32014-01-16 12:59:10 +05306712 if (pAdapter->ipv4_notifier_registered)
6713 {
6714 hddLog(LOG1, FL("Unregistered IPv4 notifier"));
6715 unregister_inetaddr_notifier(&pAdapter->ipv4_notifier);
6716 pAdapter->ipv4_notifier_registered = false;
6717 }
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05306718#ifdef WLAN_OPEN_SOURCE
6719 cancel_work_sync(&pAdapter->ipv4NotifierWorkQueue);
6720#endif
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05306721 /* It is possible that the caller of this function does not
6722 * wish to close the session
6723 */
6724 if (VOS_TRUE == bCloseSession &&
6725 test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07006726 {
6727 INIT_COMPLETION(pAdapter->session_close_comp_var);
6728 if (eHAL_STATUS_SUCCESS ==
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05306729 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
6730 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07006731 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306732 unsigned long ret;
6733
Jeff Johnson295189b2012-06-20 16:38:30 -07006734 //Block on a completion variable. Can't wait forever though.
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306735 ret = wait_for_completion_timeout(
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05306736 &pAdapter->session_close_comp_var,
6737 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306738 if ( 0 >= ret)
6739 {
6740 hddLog(LOGE, "%s: failure waiting for session_close_comp_var %ld",
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05306741 __func__, ret);
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306742 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006743 }
6744 }
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05306745 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006746 break;
6747
6748 case WLAN_HDD_SOFTAP:
6749 case WLAN_HDD_P2P_GO:
6750 //Any softap specific cleanup here...
Kaushik, Sushant7005e372014-04-08 11:36:54 +05306751 if (pAdapter->device_mode == WLAN_HDD_P2P_GO) {
6752 while (pAdapter->is_roc_inprogress) {
6753 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6754 "%s: ROC in progress for session %d!!!",
6755 __func__, pAdapter->sessionId);
6756 msleep(500);
6757 if ( retry++ > MAX_WAIT_FOR_ROC_COMPLETION ) {
6758 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6759 "%s: ROC completion is not received.!!!", __func__);
6760 WLANSAP_CancelRemainOnChannel(
6761 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
6762 wait_for_completion_interruptible_timeout(
6763 &pAdapter->cancel_rem_on_chan_var,
6764 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
6765 break;
6766 }
6767 }
6768 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006769 mutex_lock(&pHddCtx->sap_lock);
6770 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
6771 {
6772 VOS_STATUS status;
6773 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6774
6775 //Stop Bss.
6776 status = WLANSAP_StopBss(pHddCtx->pvosContext);
6777 if (VOS_IS_STATUS_SUCCESS(status))
6778 {
6779 hdd_hostapd_state_t *pHostapdState =
6780 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6781
6782 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
6783
6784 if (!VOS_IS_STATUS_SUCCESS(status))
6785 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306786 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss %d",
6787 __func__, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07006788 }
6789 }
6790 else
6791 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006792 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006793 }
6794 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
6795
6796 if (eHAL_STATUS_FAILURE ==
6797 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
6798 0, NULL, eANI_BOOLEAN_FALSE))
6799 {
6800 hddLog(LOGE,
6801 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006802 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006803 }
6804
6805 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
6806 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
6807 eANI_BOOLEAN_FALSE) )
6808 {
6809 hddLog(LOGE,
6810 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
6811 }
6812
6813 // Reset WNI_CFG_PROBE_RSP Flags
6814 wlan_hdd_reset_prob_rspies(pAdapter);
6815 kfree(pAdapter->sessionCtx.ap.beacon);
6816 pAdapter->sessionCtx.ap.beacon = NULL;
6817 }
6818 mutex_unlock(&pHddCtx->sap_lock);
6819 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006820
Jeff Johnson295189b2012-06-20 16:38:30 -07006821 case WLAN_HDD_MONITOR:
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006822#ifdef WLAN_OPEN_SOURCE
6823 cancel_work_sync(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue);
6824#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006825 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006826
Jeff Johnson295189b2012-06-20 16:38:30 -07006827 default:
6828 break;
6829 }
6830
6831 EXIT();
6832 return VOS_STATUS_SUCCESS;
6833}
6834
6835VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
6836{
6837 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6838 VOS_STATUS status;
6839 hdd_adapter_t *pAdapter;
6840
6841 ENTER();
6842
6843 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6844
6845 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6846 {
6847 pAdapter = pAdapterNode->pAdapter;
6848 netif_tx_disable(pAdapter->dev);
6849 netif_carrier_off(pAdapter->dev);
6850
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05306851 hdd_stop_adapter( pHddCtx, pAdapter, VOS_TRUE );
Jeff Johnson295189b2012-06-20 16:38:30 -07006852
6853 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6854 pAdapterNode = pNext;
6855 }
6856
6857 EXIT();
6858
6859 return VOS_STATUS_SUCCESS;
6860}
6861
Rajeev Kumarf999e582014-01-09 17:33:29 -08006862
6863#ifdef FEATURE_WLAN_BATCH_SCAN
6864/**---------------------------------------------------------------------------
6865
6866 \brief hdd_deinit_batch_scan () - This function cleans up batch scan data
6867 structures
6868
6869 \param - pAdapter Pointer to HDD adapter
6870
6871 \return - None
6872
6873 --------------------------------------------------------------------------*/
6874void hdd_deinit_batch_scan(hdd_adapter_t *pAdapter)
6875{
6876 tHddBatchScanRsp *pNode;
6877 tHddBatchScanRsp *pPrev;
6878
Siddharth Bhalb3e9b792014-02-24 15:14:16 +05306879 if (NULL == pAdapter)
Rajeev Kumarf999e582014-01-09 17:33:29 -08006880 {
Siddharth Bhalb3e9b792014-02-24 15:14:16 +05306881 hddLog(VOS_TRACE_LEVEL_ERROR,
6882 "%s: Adapter context is Null", __func__);
6883 return;
6884 }
6885
6886 pNode = pAdapter->pBatchScanRsp;
6887 while (pNode)
6888 {
6889 pPrev = pNode;
6890 pNode = pNode->pNext;
6891 vos_mem_free((v_VOID_t * )pPrev);
Rajeev Kumarf999e582014-01-09 17:33:29 -08006892 }
6893
6894 pAdapter->pBatchScanRsp = NULL;
6895 pAdapter->numScanList = 0;
6896 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
6897 pAdapter->prev_batch_id = 0;
6898
6899 return;
6900}
6901#endif
6902
6903
Jeff Johnson295189b2012-06-20 16:38:30 -07006904VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
6905{
6906 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6907 VOS_STATUS status;
6908 hdd_adapter_t *pAdapter;
6909
6910 ENTER();
6911
6912 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6913
6914 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6915 {
6916 pAdapter = pAdapterNode->pAdapter;
6917 netif_tx_disable(pAdapter->dev);
6918 netif_carrier_off(pAdapter->dev);
6919
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07006920 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
6921
Jeff Johnson295189b2012-06-20 16:38:30 -07006922 hdd_deinit_tx_rx(pAdapter);
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05306923 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
6924 {
6925 hdd_wmm_adapter_close( pAdapter );
6926 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
6927 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006928
Rajeev Kumarf999e582014-01-09 17:33:29 -08006929#ifdef FEATURE_WLAN_BATCH_SCAN
6930 if (eHDD_BATCH_SCAN_STATE_STARTED == pAdapter->batchScanState)
6931 {
6932 hdd_deinit_batch_scan(pAdapter);
6933 }
6934#endif
6935
Jeff Johnson295189b2012-06-20 16:38:30 -07006936 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6937 pAdapterNode = pNext;
6938 }
6939
6940 EXIT();
6941
6942 return VOS_STATUS_SUCCESS;
6943}
6944
6945VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
6946{
6947 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6948 VOS_STATUS status;
6949 hdd_adapter_t *pAdapter;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306950 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -07006951
6952 ENTER();
6953
6954 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6955
6956 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6957 {
6958 pAdapter = pAdapterNode->pAdapter;
6959
Kumar Anand82c009f2014-05-29 00:29:42 -07006960 hdd_wmm_init( pAdapter );
6961
Jeff Johnson295189b2012-06-20 16:38:30 -07006962 switch(pAdapter->device_mode)
6963 {
6964 case WLAN_HDD_INFRA_STATION:
6965 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006966 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306967
6968 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
6969
Jeff Johnson295189b2012-06-20 16:38:30 -07006970 hdd_init_station_mode(pAdapter);
6971 /* Open the gates for HDD to receive Wext commands */
6972 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07006973 pHddCtx->scan_info.mScanPending = FALSE;
6974 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006975
6976 //Trigger the initial scan
6977 hdd_wlan_initial_scan(pAdapter);
6978
6979 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306980 if (eConnectionState_Associated == connState ||
6981 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -07006982 {
6983 union iwreq_data wrqu;
6984 memset(&wrqu, '\0', sizeof(wrqu));
6985 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
6986 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
6987 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07006988 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006989
Jeff Johnson295189b2012-06-20 16:38:30 -07006990 /* indicate disconnected event to nl80211 */
6991 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
6992 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07006993 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306994 else if (eConnectionState_Connecting == connState)
6995 {
6996 /*
6997 * Indicate connect failure to supplicant if we were in the
6998 * process of connecting
6999 */
7000 cfg80211_connect_result(pAdapter->dev, NULL,
7001 NULL, 0, NULL, 0,
7002 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
7003 GFP_KERNEL);
7004 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007005 break;
7006
7007 case WLAN_HDD_SOFTAP:
7008 /* softAP can handle SSR */
7009 break;
7010
7011 case WLAN_HDD_P2P_GO:
Sameer Thalappiledf0d792013-08-09 14:31:03 -07007012 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send stop ap to supplicant",
Jeff Johnson295189b2012-06-20 16:38:30 -07007013 __func__);
Sameer Thalappiledf0d792013-08-09 14:31:03 -07007014 cfg80211_ap_stopped(pAdapter->dev, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07007015 break;
7016
7017 case WLAN_HDD_MONITOR:
7018 /* monitor interface start */
7019 break;
7020 default:
7021 break;
7022 }
7023
7024 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7025 pAdapterNode = pNext;
7026 }
7027
7028 EXIT();
7029
7030 return VOS_STATUS_SUCCESS;
7031}
7032
7033VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
7034{
7035 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7036 hdd_adapter_t *pAdapter;
7037 VOS_STATUS status;
7038 v_U32_t roamId;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307039 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07007040
7041 ENTER();
7042
7043 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7044
7045 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7046 {
7047 pAdapter = pAdapterNode->pAdapter;
7048
7049 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
7050 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
7051 {
7052 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7053 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
7054
Abhishek Singhf4669da2014-05-26 15:07:49 +05307055 hddLog(VOS_TRACE_LEVEL_INFO,
7056 "%s: Set HDD connState to eConnectionState_NotConnected",
7057 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007058 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
7059 init_completion(&pAdapter->disconnect_comp_var);
7060 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
7061 eCSR_DISCONNECT_REASON_UNSPECIFIED);
7062
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307063 ret = wait_for_completion_interruptible_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07007064 &pAdapter->disconnect_comp_var,
7065 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307066 if (0 >= ret)
7067 hddLog(LOGE, "%s: failure waiting for disconnect_comp_var %ld",
7068 __func__, ret);
Jeff Johnson295189b2012-06-20 16:38:30 -07007069
7070 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
7071 pHddCtx->isAmpAllowed = VOS_FALSE;
7072 sme_RoamConnect(pHddCtx->hHal,
7073 pAdapter->sessionId, &(pWextState->roamProfile),
7074 &roamId);
7075 }
7076
7077 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7078 pAdapterNode = pNext;
7079 }
7080
7081 EXIT();
7082
7083 return VOS_STATUS_SUCCESS;
7084}
7085
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07007086void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
7087{
7088 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7089 VOS_STATUS status;
7090 hdd_adapter_t *pAdapter;
7091 hdd_station_ctx_t *pHddStaCtx;
7092 hdd_ap_ctx_t *pHddApCtx;
7093 hdd_hostapd_state_t * pHostapdState;
7094 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
7095 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
7096 const char *p2pMode = "DEV";
7097 const char *ccMode = "Standalone";
7098 int n;
7099
7100 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7101 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7102 {
7103 pAdapter = pAdapterNode->pAdapter;
7104 switch (pAdapter->device_mode) {
7105 case WLAN_HDD_INFRA_STATION:
7106 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7107 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
7108 staChannel = pHddStaCtx->conn_info.operationChannel;
7109 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
7110 }
7111 break;
7112 case WLAN_HDD_P2P_CLIENT:
7113 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7114 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
7115 p2pChannel = pHddStaCtx->conn_info.operationChannel;
7116 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
7117 p2pMode = "CLI";
7118 }
7119 break;
7120 case WLAN_HDD_P2P_GO:
7121 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
7122 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
7123 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
7124 p2pChannel = pHddApCtx->operatingChannel;
7125 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
7126 }
7127 p2pMode = "GO";
7128 break;
7129 case WLAN_HDD_SOFTAP:
7130 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
7131 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
7132 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
7133 apChannel = pHddApCtx->operatingChannel;
7134 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
7135 }
7136 break;
7137 default:
7138 break;
7139 }
7140 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7141 pAdapterNode = pNext;
7142 }
7143 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
7144 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
7145 }
7146 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
7147 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
7148 if (p2pChannel > 0) {
7149 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
7150 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
7151 }
7152 if (apChannel > 0) {
7153 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
7154 apChannel, MAC_ADDR_ARRAY(apBssid));
7155 }
7156
7157 if (p2pChannel > 0 && apChannel > 0) {
7158 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
7159 }
7160}
7161
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07007162bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07007163{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07007164 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07007165}
7166
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07007167/* Once SSR is disabled then it cannot be set. */
7168void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07007169{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07007170 if (HDD_SSR_DISABLED == isSsrRequired)
7171 return;
7172
Jeff Johnson295189b2012-06-20 16:38:30 -07007173 isSsrRequired = value;
7174}
7175
7176VOS_STATUS hdd_get_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_peek_front ( &pHddCtx->hddAdapters,
7182 (hdd_list_node_t**) ppAdapterNode );
7183 spin_unlock(&pHddCtx->hddAdapters.lock);
7184 return status;
7185}
7186
7187VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
7188 hdd_adapter_list_node_t* pAdapterNode,
7189 hdd_adapter_list_node_t** pNextAdapterNode)
7190{
7191 VOS_STATUS status;
7192 spin_lock(&pHddCtx->hddAdapters.lock);
7193 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
7194 (hdd_list_node_t*) pAdapterNode,
7195 (hdd_list_node_t**)pNextAdapterNode );
7196
7197 spin_unlock(&pHddCtx->hddAdapters.lock);
7198 return status;
7199}
7200
7201VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
7202 hdd_adapter_list_node_t* pAdapterNode)
7203{
7204 VOS_STATUS status;
7205 spin_lock(&pHddCtx->hddAdapters.lock);
7206 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
7207 &pAdapterNode->node );
7208 spin_unlock(&pHddCtx->hddAdapters.lock);
7209 return status;
7210}
7211
7212VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
7213 hdd_adapter_list_node_t** ppAdapterNode)
7214{
7215 VOS_STATUS status;
7216 spin_lock(&pHddCtx->hddAdapters.lock);
7217 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
7218 (hdd_list_node_t**) ppAdapterNode );
7219 spin_unlock(&pHddCtx->hddAdapters.lock);
7220 return status;
7221}
7222
7223VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
7224 hdd_adapter_list_node_t* pAdapterNode)
7225{
7226 VOS_STATUS status;
7227 spin_lock(&pHddCtx->hddAdapters.lock);
7228 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
7229 (hdd_list_node_t*) pAdapterNode );
7230 spin_unlock(&pHddCtx->hddAdapters.lock);
7231 return status;
7232}
7233
7234VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
7235 hdd_adapter_list_node_t* pAdapterNode)
7236{
7237 VOS_STATUS status;
7238 spin_lock(&pHddCtx->hddAdapters.lock);
7239 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
7240 (hdd_list_node_t*) pAdapterNode );
7241 spin_unlock(&pHddCtx->hddAdapters.lock);
7242 return status;
7243}
7244
7245hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
7246 tSirMacAddr macAddr )
7247{
7248 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7249 hdd_adapter_t *pAdapter;
7250 VOS_STATUS status;
7251
7252 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7253
7254 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7255 {
7256 pAdapter = pAdapterNode->pAdapter;
7257
7258 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
7259 macAddr, sizeof(tSirMacAddr) ) )
7260 {
7261 return pAdapter;
7262 }
7263 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7264 pAdapterNode = pNext;
7265 }
7266
7267 return NULL;
7268
7269}
7270
7271hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
7272{
7273 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7274 hdd_adapter_t *pAdapter;
7275 VOS_STATUS status;
7276
7277 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7278
7279 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7280 {
7281 pAdapter = pAdapterNode->pAdapter;
7282
7283 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
7284 IFNAMSIZ ) )
7285 {
7286 return pAdapter;
7287 }
7288 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7289 pAdapterNode = pNext;
7290 }
7291
7292 return NULL;
7293
7294}
7295
7296hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
7297{
7298 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7299 hdd_adapter_t *pAdapter;
7300 VOS_STATUS status;
7301
7302 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7303
7304 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7305 {
7306 pAdapter = pAdapterNode->pAdapter;
7307
7308 if( pAdapter && (mode == pAdapter->device_mode) )
7309 {
7310 return pAdapter;
7311 }
7312 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7313 pAdapterNode = pNext;
7314 }
7315
7316 return NULL;
7317
7318}
7319
7320//Remove this function later
7321hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
7322{
7323 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7324 hdd_adapter_t *pAdapter;
7325 VOS_STATUS status;
7326
7327 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7328
7329 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7330 {
7331 pAdapter = pAdapterNode->pAdapter;
7332
7333 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
7334 {
7335 return pAdapter;
7336 }
7337
7338 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7339 pAdapterNode = pNext;
7340 }
7341
7342 return NULL;
7343
7344}
7345
Jeff Johnson295189b2012-06-20 16:38:30 -07007346/**---------------------------------------------------------------------------
7347
7348 \brief hdd_set_monitor_tx_adapter() -
7349
7350 This API initializes the adapter to be used while transmitting on monitor
7351 adapter.
7352
7353 \param - pHddCtx - Pointer to the HDD context.
7354 pAdapter - Adapter that will used for TX. This can be NULL.
7355 \return - None.
7356 --------------------------------------------------------------------------*/
7357void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
7358{
7359 hdd_adapter_t *pMonAdapter;
7360
7361 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
7362
7363 if( NULL != pMonAdapter )
7364 {
7365 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
7366 }
7367}
Jeff Johnson295189b2012-06-20 16:38:30 -07007368/**---------------------------------------------------------------------------
7369
7370 \brief hdd_select_queue() -
7371
7372 This API returns the operating channel of the requested device mode
7373
7374 \param - pHddCtx - Pointer to the HDD context.
7375 - mode - Device mode for which operating channel is required
7376 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
7377 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
7378 \return - channel number. "0" id the requested device is not found OR it is not connected.
7379 --------------------------------------------------------------------------*/
7380v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
7381{
7382 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7383 VOS_STATUS status;
7384 hdd_adapter_t *pAdapter;
7385 v_U8_t operatingChannel = 0;
7386
7387 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7388
7389 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7390 {
7391 pAdapter = pAdapterNode->pAdapter;
7392
7393 if( mode == pAdapter->device_mode )
7394 {
7395 switch(pAdapter->device_mode)
7396 {
7397 case WLAN_HDD_INFRA_STATION:
7398 case WLAN_HDD_P2P_CLIENT:
7399 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
7400 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
7401 break;
7402 case WLAN_HDD_SOFTAP:
7403 case WLAN_HDD_P2P_GO:
7404 /*softap connection info */
7405 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
7406 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
7407 break;
7408 default:
7409 break;
7410 }
7411
7412 break; //Found the device of interest. break the loop
7413 }
7414
7415 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7416 pAdapterNode = pNext;
7417 }
7418 return operatingChannel;
7419}
7420
7421#ifdef WLAN_FEATURE_PACKET_FILTERING
7422/**---------------------------------------------------------------------------
7423
7424 \brief hdd_set_multicast_list() -
7425
7426 This used to set the multicast address list.
7427
7428 \param - dev - Pointer to the WLAN device.
7429 - skb - Pointer to OS packet (sk_buff).
7430 \return - success/fail
7431
7432 --------------------------------------------------------------------------*/
7433static void hdd_set_multicast_list(struct net_device *dev)
7434{
7435 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07007436 int mc_count;
7437 int i = 0;
7438 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307439
7440 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07007441 {
7442 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307443 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007444 return;
7445 }
7446
7447 if (dev->flags & IFF_ALLMULTI)
7448 {
7449 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007450 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307451 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07007452 }
7453 else
7454 {
7455 mc_count = netdev_mc_count(dev);
7456 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007457 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07007458 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
7459 {
7460 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007461 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307462 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07007463 return;
7464 }
7465
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307466 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07007467
7468 netdev_for_each_mc_addr(ha, dev) {
7469 if (i == mc_count)
7470 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307471 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
7472 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
Arif Hussain6d2a3322013-11-17 19:50:10 -08007473 hddLog(VOS_TRACE_LEVEL_INFO, "%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07007474 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307475 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07007476 i++;
7477 }
7478 }
7479 return;
7480}
7481#endif
7482
7483/**---------------------------------------------------------------------------
7484
7485 \brief hdd_select_queue() -
7486
7487 This function is registered with the Linux OS for network
7488 core to decide which queue to use first.
7489
7490 \param - dev - Pointer to the WLAN device.
7491 - skb - Pointer to OS packet (sk_buff).
7492 \return - ac, Queue Index/access category corresponding to UP in IP header
7493
7494 --------------------------------------------------------------------------*/
7495v_U16_t hdd_select_queue(struct net_device *dev,
7496 struct sk_buff *skb)
7497{
7498 return hdd_wmm_select_queue(dev, skb);
7499}
7500
7501
7502/**---------------------------------------------------------------------------
7503
7504 \brief hdd_wlan_initial_scan() -
7505
7506 This function triggers the initial scan
7507
7508 \param - pAdapter - Pointer to the HDD adapter.
7509
7510 --------------------------------------------------------------------------*/
7511void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
7512{
7513 tCsrScanRequest scanReq;
7514 tCsrChannelInfo channelInfo;
7515 eHalStatus halStatus;
Jeff Johnson02797792013-10-26 19:17:13 -07007516 tANI_U32 scanId;
Jeff Johnson295189b2012-06-20 16:38:30 -07007517 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7518
7519 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
7520 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
7521 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
7522
7523 if(sme_Is11dSupported(pHddCtx->hHal))
7524 {
7525 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
7526 if ( HAL_STATUS_SUCCESS( halStatus ) )
7527 {
7528 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
7529 if( !scanReq.ChannelInfo.ChannelList )
7530 {
7531 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
7532 vos_mem_free(channelInfo.ChannelList);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08007533 channelInfo.ChannelList = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007534 return;
7535 }
7536 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
7537 channelInfo.numOfChannels);
7538 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
7539 vos_mem_free(channelInfo.ChannelList);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08007540 channelInfo.ChannelList = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007541 }
7542
7543 scanReq.scanType = eSIR_PASSIVE_SCAN;
7544 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
7545 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
7546 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
7547 }
7548 else
7549 {
7550 scanReq.scanType = eSIR_ACTIVE_SCAN;
7551 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
7552 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
7553 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
7554 }
7555
7556 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
7557 if ( !HAL_STATUS_SUCCESS( halStatus ) )
7558 {
7559 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
7560 __func__, halStatus );
7561 }
7562
7563 if(sme_Is11dSupported(pHddCtx->hHal))
7564 vos_mem_free(scanReq.ChannelInfo.ChannelList);
7565}
7566
Jeff Johnson295189b2012-06-20 16:38:30 -07007567/**---------------------------------------------------------------------------
7568
7569 \brief hdd_full_power_callback() - HDD full power callback function
7570
7571 This is the function invoked by SME to inform the result of a full power
7572 request issued by HDD
7573
7574 \param - callbackcontext - Pointer to cookie
7575 \param - status - result of request
7576
7577 \return - None
7578
7579 --------------------------------------------------------------------------*/
7580static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
7581{
Jeff Johnson72a40512013-12-19 10:14:15 -08007582 struct statsContext *pContext = callbackContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07007583
7584 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307585 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07007586
7587 if (NULL == callbackContext)
7588 {
7589 hddLog(VOS_TRACE_LEVEL_ERROR,
7590 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007591 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07007592 return;
7593 }
7594
Jeff Johnson72a40512013-12-19 10:14:15 -08007595 /* there is a race condition that exists between this callback
7596 function and the caller since the caller could time out either
7597 before or while this code is executing. we use a spinlock to
7598 serialize these actions */
7599 spin_lock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07007600
7601 if (POWER_CONTEXT_MAGIC != pContext->magic)
7602 {
7603 /* the caller presumably timed out so there is nothing we can do */
Jeff Johnson72a40512013-12-19 10:14:15 -08007604 spin_unlock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07007605 hddLog(VOS_TRACE_LEVEL_WARN,
7606 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007607 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07007608 return;
7609 }
7610
Jeff Johnson72a40512013-12-19 10:14:15 -08007611 /* context is valid so caller is still waiting */
7612
7613 /* paranoia: invalidate the magic */
7614 pContext->magic = 0;
7615
7616 /* notify the caller */
Jeff Johnson295189b2012-06-20 16:38:30 -07007617 complete(&pContext->completion);
Jeff Johnson72a40512013-12-19 10:14:15 -08007618
7619 /* serialization is complete */
7620 spin_unlock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07007621}
7622
7623/**---------------------------------------------------------------------------
7624
7625 \brief hdd_wlan_exit() - HDD WLAN exit function
7626
7627 This is the driver exit point (invoked during rmmod)
7628
7629 \param - pHddCtx - Pointer to the HDD Context
7630
7631 \return - None
7632
7633 --------------------------------------------------------------------------*/
7634void hdd_wlan_exit(hdd_context_t *pHddCtx)
7635{
7636 eHalStatus halStatus;
7637 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
7638 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05307639 struct wiphy *wiphy = pHddCtx->wiphy;
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -08007640 hdd_adapter_t* pAdapter = NULL;
Jeff Johnson72a40512013-12-19 10:14:15 -08007641 struct statsContext powerContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07007642 long lrc;
c_hpothu5ab05e92014-06-13 17:34:05 +05307643 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007644
7645 ENTER();
7646
Jeff Johnson88ba7742013-02-27 14:36:02 -08007647 if (VOS_FTM_MODE != hdd_get_conparam())
7648 {
7649 // Unloading, restart logic is no more required.
7650 wlan_hdd_restart_deinit(pHddCtx);
Jeff Johnsone7245742012-09-05 17:12:55 -07007651
c_hpothu5ab05e92014-06-13 17:34:05 +05307652 vosStatus = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7653 while (NULL != pAdapterNode && VOS_STATUS_E_EMPTY != vosStatus)
Jeff Johnson295189b2012-06-20 16:38:30 -07007654 {
c_hpothu5ab05e92014-06-13 17:34:05 +05307655 pAdapter = pAdapterNode->pAdapter;
7656 if (NULL != pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07007657 {
c_hpothu5ab05e92014-06-13 17:34:05 +05307658 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode ||
7659 WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)
7660 {
7661 wlan_hdd_cfg80211_deregister_frames(pAdapter);
7662 hdd_UnregisterWext(pAdapter->dev);
7663 }
7664 // Cancel any outstanding scan requests. We are about to close all
7665 // of our adapters, but an adapter structure is what SME passes back
7666 // to our callback function. Hence if there are any outstanding scan
7667 // requests then there is a race condition between when the adapter
7668 // is closed and when the callback is invoked.We try to resolve that
7669 // race condition here by canceling any outstanding scans before we
7670 // close the adapters.
7671 // Note that the scans may be cancelled in an asynchronous manner,
7672 // so ideally there needs to be some kind of synchronization. Rather
7673 // than introduce a new synchronization here, we will utilize the
7674 // fact that we are about to Request Full Power, and since that is
7675 // synchronized, the expectation is that by the time Request Full
7676 // Power has completed all scans will be cancelled.
7677 if (pHddCtx->scan_info.mScanPending)
7678 {
7679 hddLog(VOS_TRACE_LEVEL_INFO,
7680 FL("abort scan mode: %d sessionId: %d"),
7681 pAdapter->device_mode,
7682 pAdapter->sessionId);
7683 hdd_abort_mac_scan(pHddCtx,
7684 pAdapter->sessionId,
7685 eCSR_SCAN_ABORT_DEFAULT);
7686 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007687 }
c_hpothu5ab05e92014-06-13 17:34:05 +05307688 vosStatus = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7689 pAdapterNode = pNext;
Jeff Johnson295189b2012-06-20 16:38:30 -07007690 }
7691 }
c_hpothu5ab05e92014-06-13 17:34:05 +05307692 else
Jeff Johnson88ba7742013-02-27 14:36:02 -08007693 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307694 hddLog(VOS_TRACE_LEVEL_INFO,"%s: FTM MODE",__func__);
Jeff Johnson88ba7742013-02-27 14:36:02 -08007695 wlan_hdd_ftm_close(pHddCtx);
7696 goto free_hdd_ctx;
7697 }
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307698
Jeff Johnson295189b2012-06-20 16:38:30 -07007699 /* DeRegister with platform driver as client for Suspend/Resume */
7700 vosStatus = hddDeregisterPmOps(pHddCtx);
7701 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
7702 {
7703 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
7704 VOS_ASSERT(0);
7705 }
7706
7707 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
7708 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
7709 {
7710 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
7711 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007712
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07007713 //Stop the traffic monitor timer
7714 if ( VOS_TIMER_STATE_RUNNING ==
7715 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr))
7716 {
7717 vos_timer_stop(&pHddCtx->tx_rx_trafficTmr);
7718 }
7719
7720 // Destroy the traffic monitor timer
7721 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
7722 &pHddCtx->tx_rx_trafficTmr)))
7723 {
7724 hddLog(VOS_TRACE_LEVEL_ERROR,
7725 "%s: Cannot deallocate Traffic monitor timer", __func__);
7726 }
7727
Jeff Johnson295189b2012-06-20 16:38:30 -07007728 //Disable IMPS/BMPS as we do not want the device to enter any power
7729 //save mode during shutdown
7730 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
7731 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
7732 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
7733
7734 //Ensure that device is in full power as we will touch H/W during vos_Stop
7735 init_completion(&powerContext.completion);
7736 powerContext.magic = POWER_CONTEXT_MAGIC;
7737
7738 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
7739 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
7740
7741 if (eHAL_STATUS_SUCCESS != halStatus)
7742 {
7743 if (eHAL_STATUS_PMC_PENDING == halStatus)
7744 {
7745 /* request was sent -- wait for the response */
7746 lrc = wait_for_completion_interruptible_timeout(
7747 &powerContext.completion,
7748 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
Jeff Johnson295189b2012-06-20 16:38:30 -07007749 if (lrc <= 0)
7750 {
7751 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007752 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07007753 }
7754 }
7755 else
7756 {
7757 hddLog(VOS_TRACE_LEVEL_ERROR,
7758 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007759 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07007760 /* continue -- need to clean up as much as possible */
7761 }
7762 }
7763
Jeff Johnson72a40512013-12-19 10:14:15 -08007764 /* either we never sent a request, we sent a request and received a
7765 response or we sent a request and timed out. if we never sent a
7766 request or if we sent a request and got a response, we want to
7767 clear the magic out of paranoia. if we timed out there is a
7768 race condition such that the callback function could be
7769 executing at the same time we are. of primary concern is if the
7770 callback function had already verified the "magic" but had not
7771 yet set the completion variable when a timeout occurred. we
7772 serialize these activities by invalidating the magic while
7773 holding a shared spinlock which will cause us to block if the
7774 callback is currently executing */
7775 spin_lock(&hdd_context_lock);
7776 powerContext.magic = 0;
7777 spin_unlock(&hdd_context_lock);
7778
Yue Ma0d4891e2013-08-06 17:01:45 -07007779 hdd_debugfs_exit(pHddCtx);
7780
Jeff Johnson295189b2012-06-20 16:38:30 -07007781 // Unregister the Net Device Notifier
7782 unregister_netdevice_notifier(&hdd_netdev_notifier);
7783
Jeff Johnson295189b2012-06-20 16:38:30 -07007784 hdd_stop_all_adapters( pHddCtx );
7785
Jeff Johnson295189b2012-06-20 16:38:30 -07007786#ifdef WLAN_BTAMP_FEATURE
7787 vosStatus = WLANBAP_Stop(pVosContext);
7788 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
7789 {
7790 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7791 "%s: Failed to stop BAP",__func__);
7792 }
7793#endif //WLAN_BTAMP_FEATURE
7794
7795 //Stop all the modules
7796 vosStatus = vos_stop( pVosContext );
7797 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
7798 {
7799 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7800 "%s: Failed to stop VOSS",__func__);
7801 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7802 }
7803
Jeff Johnson295189b2012-06-20 16:38:30 -07007804 //Assert Deep sleep signal now to put Libra HW in lowest power state
7805 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
7806 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7807
7808 //Vote off any PMIC voltage supplies
7809 vos_chipPowerDown(NULL, NULL, NULL);
7810
7811 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
7812
Leo Chang59cdc7e2013-07-10 10:08:21 -07007813
Jeff Johnson295189b2012-06-20 16:38:30 -07007814 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07007815 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07007816
7817 //Close the scheduler before calling vos_close to make sure no thread is
7818 // scheduled after the each module close is called i.e after all the data
7819 // structures are freed.
7820 vosStatus = vos_sched_close( pVosContext );
7821 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
7822 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
7823 "%s: Failed to close VOSS Scheduler",__func__);
7824 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7825 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007826#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07007827#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
7828 /* Destroy the wake lock */
7829 wake_lock_destroy(&pHddCtx->rx_wake_lock);
7830#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08007831 /* Destroy the wake lock */
7832 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007833#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007834
Mihir Shete7a24b5f2013-12-21 12:18:31 +05307835#ifdef CONFIG_ENABLE_LINUX_REG
7836 vosStatus = vos_nv_close();
7837 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
7838 {
7839 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7840 "%s: Failed to close NV", __func__);
7841 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7842 }
7843#endif
7844
Jeff Johnson295189b2012-06-20 16:38:30 -07007845 //Close VOSS
7846 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
7847 vos_close(pVosContext);
7848
Jeff Johnson295189b2012-06-20 16:38:30 -07007849 //Close Watchdog
7850 if(pHddCtx->cfg_ini->fIsLogpEnabled)
7851 vos_watchdog_close(pVosContext);
7852
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05307853 //Clean up HDD Nlink Service
7854 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Leo Chang59cdc7e2013-07-10 10:08:21 -07007855#ifdef WLAN_KD_READY_NOTIFIER
7856 nl_srv_exit(pHddCtx->ptt_pid);
7857#else
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05307858 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07007859#endif /* WLAN_KD_READY_NOTIFIER */
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05307860
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05307861#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05307862 if (pHddCtx->cfg_ini->wlanLoggingEnable)
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05307863 {
7864 wlan_logging_sock_deactivate_svc();
7865 }
7866#endif
7867
Jeff Johnson295189b2012-06-20 16:38:30 -07007868 /* Cancel the vote for XO Core ON.
7869 * This is done here to ensure there is no race condition since MC, TX and WD threads have
7870 * exited at this point
7871 */
7872 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
Arif Hussain6d2a3322013-11-17 19:50:10 -08007873 " when WLAN is turned OFF");
Jeff Johnson295189b2012-06-20 16:38:30 -07007874 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
7875 {
7876 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
7877 " Not returning failure."
Arif Hussain6d2a3322013-11-17 19:50:10 -08007878 " Power consumed will be high");
Jeff Johnson295189b2012-06-20 16:38:30 -07007879 }
7880
7881 hdd_close_all_adapters( pHddCtx );
7882
Jeff Johnson295189b2012-06-20 16:38:30 -07007883 /* free the power on lock from platform driver */
7884 if (free_riva_power_on_lock("wlan"))
7885 {
7886 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
7887 __func__);
7888 }
7889
Jeff Johnson88ba7742013-02-27 14:36:02 -08007890free_hdd_ctx:
c_hpothu78c7b602014-05-17 17:35:49 +05307891
7892 //Free up dynamically allocated members inside HDD Adapter
7893 if (pHddCtx->cfg_ini)
7894 {
7895 kfree(pHddCtx->cfg_ini);
7896 pHddCtx->cfg_ini= NULL;
7897 }
7898
Leo Changf04ddad2013-09-18 13:46:38 -07007899 /* FTM mode, WIPHY did not registered
7900 If un-register here, system crash will happen */
7901 if (VOS_FTM_MODE != hdd_get_conparam())
7902 {
7903 wiphy_unregister(wiphy) ;
7904 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007905 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07007906 if (hdd_is_ssr_required())
7907 {
7908 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07007909 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07007910 msleep(5000);
7911 }
7912 hdd_set_ssr_required (VOS_FALSE);
7913}
7914
7915
7916/**---------------------------------------------------------------------------
7917
7918 \brief hdd_update_config_from_nv() - Function to update the contents of
7919 the running configuration with parameters taken from NV storage
7920
7921 \param - pHddCtx - Pointer to the HDD global context
7922
7923 \return - VOS_STATUS_SUCCESS if successful
7924
7925 --------------------------------------------------------------------------*/
7926static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
7927{
Jeff Johnson295189b2012-06-20 16:38:30 -07007928 v_BOOL_t itemIsValid = VOS_FALSE;
7929 VOS_STATUS status;
7930 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
7931 v_U8_t macLoop;
7932
7933 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
7934 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
7935 if(status != VOS_STATUS_SUCCESS)
7936 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08007937 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed");
Jeff Johnson295189b2012-06-20 16:38:30 -07007938 return VOS_STATUS_E_FAILURE;
7939 }
7940
7941 if (itemIsValid == VOS_TRUE)
7942 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08007943 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV");
Jeff Johnson295189b2012-06-20 16:38:30 -07007944 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
7945 VOS_MAX_CONCURRENCY_PERSONA);
7946 if(status != VOS_STATUS_SUCCESS)
7947 {
7948 /* Get MAC from NV fail, not update CFG info
7949 * INI MAC value will be used for MAC setting */
Arif Hussain6d2a3322013-11-17 19:50:10 -08007950 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed");
Jeff Johnson295189b2012-06-20 16:38:30 -07007951 return VOS_STATUS_E_FAILURE;
7952 }
7953
7954 /* If first MAC is not valid, treat all others are not valid
7955 * Then all MACs will be got from ini file */
7956 if(vos_is_macaddr_zero(&macFromNV[0]))
7957 {
7958 /* MAC address in NV file is not configured yet */
7959 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
7960 return VOS_STATUS_E_INVAL;
7961 }
7962
7963 /* Get MAC address from NV, update CFG info */
7964 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
7965 {
7966 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
7967 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307968 hddLog(VOS_TRACE_LEVEL_ERROR,"not valid MAC from NV for %d", macLoop);
Jeff Johnson295189b2012-06-20 16:38:30 -07007969 /* This MAC is not valid, skip it
7970 * This MAC will be got from ini file */
7971 }
7972 else
7973 {
7974 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
7975 (v_U8_t *)&macFromNV[macLoop].bytes[0],
7976 VOS_MAC_ADDR_SIZE);
7977 }
7978 }
7979 }
7980 else
7981 {
7982 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
7983 return VOS_STATUS_E_FAILURE;
7984 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007985
Jeff Johnson295189b2012-06-20 16:38:30 -07007986
7987 return VOS_STATUS_SUCCESS;
7988}
7989
7990/**---------------------------------------------------------------------------
7991
7992 \brief hdd_post_voss_start_config() - HDD post voss start config helper
7993
7994 \param - pAdapter - Pointer to the HDD
7995
7996 \return - None
7997
7998 --------------------------------------------------------------------------*/
7999VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
8000{
8001 eHalStatus halStatus;
8002 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308003 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -07008004
Jeff Johnson295189b2012-06-20 16:38:30 -07008005
8006 // Send ready indication to the HDD. This will kick off the MAC
8007 // into a 'running' state and should kick off an initial scan.
8008 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
8009 if ( !HAL_STATUS_SUCCESS( halStatus ) )
8010 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308011 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07008012 "code %08d [x%08x]",__func__, halStatus, halStatus );
8013 return VOS_STATUS_E_FAILURE;
8014 }
8015
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308016 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -07008017 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
8018 // And RIVA will crash
8019 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
8020 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308021 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
8022 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
8023
8024
Jeff Johnson295189b2012-06-20 16:38:30 -07008025 return VOS_STATUS_SUCCESS;
8026}
8027
Jeff Johnson295189b2012-06-20 16:38:30 -07008028/* wake lock APIs for HDD */
8029void hdd_prevent_suspend(void)
8030{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008031#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008032 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008033#else
8034 wcnss_prevent_suspend();
8035#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008036}
8037
8038void hdd_allow_suspend(void)
8039{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008040#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008041 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008042#else
8043 wcnss_allow_suspend();
8044#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008045}
8046
Mahesh A Saptasagarb9c50402014-01-16 15:49:22 +05308047void hdd_prevent_suspend_timeout(v_U32_t timeout)
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07008048{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008049#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07008050 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07008051#else
8052 /* Do nothing as there is no API in wcnss for timeout*/
8053#endif
8054}
8055
Jeff Johnson295189b2012-06-20 16:38:30 -07008056/**---------------------------------------------------------------------------
8057
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008058 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
8059 information between Host and Riva
8060
8061 This function gets reported version of FW
8062 It also finds the version of Riva headers used to compile the host
8063 It compares the above two and prints a warning if they are different
8064 It gets the SW and HW version string
8065 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
8066 indicating the features they support through a bitmap
8067
8068 \param - pHddCtx - Pointer to HDD context
8069
8070 \return - void
8071
8072 --------------------------------------------------------------------------*/
8073
8074void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
8075{
8076
8077 tSirVersionType versionCompiled;
8078 tSirVersionType versionReported;
8079 tSirVersionString versionString;
8080 tANI_U8 fwFeatCapsMsgSupported = 0;
8081 VOS_STATUS vstatus;
8082
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -08008083 memset(&versionCompiled, 0, sizeof(versionCompiled));
8084 memset(&versionReported, 0, sizeof(versionReported));
8085
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008086 /* retrieve and display WCNSS version information */
8087 do {
8088
8089 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
8090 &versionCompiled);
8091 if (!VOS_IS_STATUS_SUCCESS(vstatus))
8092 {
8093 hddLog(VOS_TRACE_LEVEL_FATAL,
8094 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008095 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008096 break;
8097 }
8098
8099 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
8100 &versionReported);
8101 if (!VOS_IS_STATUS_SUCCESS(vstatus))
8102 {
8103 hddLog(VOS_TRACE_LEVEL_FATAL,
8104 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008105 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008106 break;
8107 }
8108
8109 if ((versionCompiled.major != versionReported.major) ||
8110 (versionCompiled.minor != versionReported.minor) ||
8111 (versionCompiled.version != versionReported.version) ||
8112 (versionCompiled.revision != versionReported.revision))
8113 {
8114 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
8115 "Host expected %u.%u.%u.%u\n",
8116 WLAN_MODULE_NAME,
8117 (int)versionReported.major,
8118 (int)versionReported.minor,
8119 (int)versionReported.version,
8120 (int)versionReported.revision,
8121 (int)versionCompiled.major,
8122 (int)versionCompiled.minor,
8123 (int)versionCompiled.version,
8124 (int)versionCompiled.revision);
8125 }
8126 else
8127 {
8128 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
8129 WLAN_MODULE_NAME,
8130 (int)versionReported.major,
8131 (int)versionReported.minor,
8132 (int)versionReported.version,
8133 (int)versionReported.revision);
8134 }
8135
8136 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
8137 versionString,
8138 sizeof(versionString));
8139 if (!VOS_IS_STATUS_SUCCESS(vstatus))
8140 {
8141 hddLog(VOS_TRACE_LEVEL_FATAL,
8142 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008143 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008144 break;
8145 }
8146
8147 pr_info("%s: WCNSS software version %s\n",
8148 WLAN_MODULE_NAME, versionString);
8149
8150 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
8151 versionString,
8152 sizeof(versionString));
8153 if (!VOS_IS_STATUS_SUCCESS(vstatus))
8154 {
8155 hddLog(VOS_TRACE_LEVEL_FATAL,
8156 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008157 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008158 break;
8159 }
8160
8161 pr_info("%s: WCNSS hardware version %s\n",
8162 WLAN_MODULE_NAME, versionString);
8163
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07008164 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
8165 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008166 send the message only if it the riva is 1.1
8167 minor numbers for different riva branches:
8168 0 -> (1.0)Mainline Build
8169 1 -> (1.1)Mainline Build
8170 2->(1.04) Stability Build
8171 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07008172 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008173 ((versionReported.minor>=1) && (versionReported.version>=1)))
8174 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
8175 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07008176
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008177 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08008178 {
8179#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
8180 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
8181 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
8182#endif
Ravi Joshid2ca7c42013-07-23 08:37:49 -07008183 /* Indicate if IBSS heartbeat monitoring needs to be offloaded */
8184 if (!pHddCtx->cfg_ini->enableIbssHeartBeatOffload)
8185 {
8186 sme_disableFeatureCapablity(IBSS_HEARTBEAT_OFFLOAD);
8187 }
8188
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008189 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08008190 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008191
8192 } while (0);
8193
8194}
8195
8196/**---------------------------------------------------------------------------
8197
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308198 \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
8199
8200 \param - pHddCtx - Pointer to the hdd context
8201
8202 \return - true if hardware supports 5GHz
8203
8204 --------------------------------------------------------------------------*/
Vinay Krishna Erannafacf5e22014-02-24 13:16:25 +05308205boolean hdd_is_5g_supported(hdd_context_t * pHddCtx)
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308206{
8207 /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
8208 * then hardware support 5Ghz.
8209 */
8210 if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode())
8211 {
Agarwal Ashish971c2882013-10-30 20:11:12 +05308212 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Hardware supports 5Ghz", __func__);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308213 return true;
8214 }
8215 else
8216 {
Agarwal Ashish971c2882013-10-30 20:11:12 +05308217 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Hardware doesn't supports 5Ghz",
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308218 __func__);
8219 return false;
8220 }
8221}
8222
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308223/**---------------------------------------------------------------------------
8224
8225 \brief hdd_generate_iface_mac_addr_auto() - HDD Mac Interface Auto
8226 generate function
8227
8228 This is generate the random mac address for WLAN interface
8229
8230 \param - pHddCtx - Pointer to HDD context
8231 idx - Start interface index to get auto
8232 generated mac addr.
8233 mac_addr - Mac address
8234
8235 \return - 0 for success, < 0 for failure
8236
8237 --------------------------------------------------------------------------*/
8238
8239static int hdd_generate_iface_mac_addr_auto(hdd_context_t *pHddCtx,
8240 int idx, v_MACADDR_t mac_addr)
8241{
8242 int i;
8243 unsigned int serialno;
8244 serialno = wcnss_get_serial_number();
8245
8246 if (0 != serialno)
8247 {
8248 /* MAC address has 3 bytes of OUI so we have a maximum of 3
8249 bytes of the serial number that can be used to generate
8250 the other 3 bytes of the MAC address. Mask off all but
8251 the lower 3 bytes (this will also make sure we don't
8252 overflow in the next step) */
8253 serialno &= 0x00FFFFFF;
8254
8255 /* we need a unique address for each session */
8256 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
8257
8258 /* autogen other Mac addresses */
8259 for (i = idx; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
8260 {
8261 /* start with the entire default address */
8262 pHddCtx->cfg_ini->intfMacAddr[i] = mac_addr;
8263 /* then replace the lower 3 bytes */
8264 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
8265 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
8266 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
8267
8268 serialno++;
8269 hddLog(VOS_TRACE_LEVEL_ERROR,
8270 "%s: Derived Mac Addr: "
8271 MAC_ADDRESS_STR, __func__,
8272 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[i].bytes));
8273 }
8274
8275 }
8276 else
8277 {
8278 hddLog(LOGE, FL("Failed to Get Serial NO"));
8279 return -1;
8280 }
8281 return 0;
8282}
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308283
8284/**---------------------------------------------------------------------------
8285
Mihir Shetefc7ff5b2014-01-27 11:30:05 +05308286 \brief hdd_11d_scan_done - callback to be executed when 11d scan is
8287 completed to flush out the scan results
8288
8289 11d scan is done during driver load and is a passive scan on all
8290 channels supported by the device, 11d scans may find some APs on
8291 frequencies which are forbidden to be used in the regulatory domain
8292 the device is operating in. If these APs are notified to the supplicant
8293 it may try to connect to these APs, thus flush out all the scan results
8294 which are present in SME after 11d scan is done.
8295
8296 \return - eHalStatus
8297
8298 --------------------------------------------------------------------------*/
8299static eHalStatus hdd_11d_scan_done(tHalHandle halHandle, void *pContext,
8300 tANI_U32 scanId, eCsrScanStatus status)
8301{
8302 ENTER();
8303
8304 sme_ScanFlushResult(halHandle, 0);
8305
8306 EXIT();
8307
8308 return eHAL_STATUS_SUCCESS;
8309}
8310
8311/**---------------------------------------------------------------------------
8312
Jeff Johnson295189b2012-06-20 16:38:30 -07008313 \brief hdd_wlan_startup() - HDD init function
8314
8315 This is the driver startup code executed once a WLAN device has been detected
8316
8317 \param - dev - Pointer to the underlying device
8318
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08008319 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07008320
8321 --------------------------------------------------------------------------*/
8322
8323int hdd_wlan_startup(struct device *dev )
8324{
8325 VOS_STATUS status;
8326 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07008327 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07008328 hdd_context_t *pHddCtx = NULL;
8329 v_CONTEXT_t pVosContext= NULL;
8330#ifdef WLAN_BTAMP_FEATURE
8331 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
8332 WLANBAP_ConfigType btAmpConfig;
8333 hdd_config_t *pConfig;
8334#endif
8335 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07008336 struct wiphy *wiphy;
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308337 v_MACADDR_t mac_addr;
Jeff Johnson295189b2012-06-20 16:38:30 -07008338
8339 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07008340 /*
8341 * cfg80211: wiphy allocation
8342 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308343 wiphy = wlan_hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t)) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07008344
8345 if(wiphy == NULL)
8346 {
8347 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08008348 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07008349 }
8350
8351 pHddCtx = wiphy_priv(wiphy);
8352
Jeff Johnson295189b2012-06-20 16:38:30 -07008353 //Initialize the adapter context to zeros.
8354 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
8355
Jeff Johnson295189b2012-06-20 16:38:30 -07008356 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07008357 hdd_prevent_suspend();
Mihir Shete18156292014-03-11 15:38:30 +05308358 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_LOAD_IN_PROGRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -07008359
8360 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
8361
8362 /*Get vos context here bcoz vos_open requires it*/
8363 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
8364
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08008365 if(pVosContext == NULL)
8366 {
8367 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
8368 goto err_free_hdd_context;
8369 }
8370
Jeff Johnson295189b2012-06-20 16:38:30 -07008371 //Save the Global VOSS context in adapter context for future.
8372 pHddCtx->pvosContext = pVosContext;
8373
8374 //Save the adapter context in global context for future.
8375 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
8376
Jeff Johnson295189b2012-06-20 16:38:30 -07008377 pHddCtx->parent_dev = dev;
8378
8379 init_completion(&pHddCtx->full_pwr_comp_var);
8380 init_completion(&pHddCtx->standby_comp_var);
8381 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07008382 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08008383 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Kiet Lam46b8e4e2013-11-06 21:49:53 +05308384 init_completion(&pHddCtx->wiphy_channel_update_event);
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +05308385 init_completion(&pHddCtx->ssr_comp_var);
Amar Singhala49cbc52013-10-08 18:37:44 -07008386
8387#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhalfddc28c2013-09-05 13:03:40 -07008388 init_completion(&pHddCtx->linux_reg_req);
Amar Singhala49cbc52013-10-08 18:37:44 -07008389#else
8390 init_completion(&pHddCtx->driver_crda_req);
8391#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008392
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05308393 spin_lock_init(&pHddCtx->schedScan_lock);
8394
Jeff Johnson295189b2012-06-20 16:38:30 -07008395 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
8396
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05308397#ifdef FEATURE_WLAN_TDLS
8398 /* tdls_lock is initialized before an hdd_open_adapter ( which is
8399 * invoked by other instances also) to protect the concurrent
8400 * access for the Adapters by TDLS module.
8401 */
8402 mutex_init(&pHddCtx->tdls_lock);
8403#endif
8404
Kiet Lam46b8e4e2013-11-06 21:49:53 +05308405 pHddCtx->nEnableStrictRegulatoryForFCC = TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07008406 // Load all config first as TL config is needed during vos_open
8407 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
8408 if(pHddCtx->cfg_ini == NULL)
8409 {
8410 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
8411 goto err_free_hdd_context;
8412 }
8413
8414 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
8415
8416 // Read and parse the qcom_cfg.ini file
8417 status = hdd_parse_config_ini( pHddCtx );
8418 if ( VOS_STATUS_SUCCESS != status )
8419 {
8420 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
8421 __func__, WLAN_INI_FILE);
8422 goto err_config;
8423 }
Arif Hussaind5218912013-12-05 01:10:55 -08008424#ifdef MEMORY_DEBUG
8425 if (pHddCtx->cfg_ini->IsMemoryDebugSupportEnabled)
8426 vos_mem_init();
8427
8428 hddLog(VOS_TRACE_LEVEL_INFO, "%s: gEnableMemoryDebug=%d",
8429 __func__, pHddCtx->cfg_ini->IsMemoryDebugSupportEnabled);
8430#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008431
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05308432 /* INI has been read, initialise the configuredMcastBcastFilter with
8433 * INI value as this will serve as the default value
8434 */
8435 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
8436 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
8437 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308438
8439 if (false == hdd_is_5g_supported(pHddCtx))
8440 {
8441 //5Ghz is not supported.
8442 if (1 != pHddCtx->cfg_ini->nBandCapability)
8443 {
8444 hddLog(VOS_TRACE_LEVEL_INFO,
8445 "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__);
8446 pHddCtx->cfg_ini->nBandCapability = 1;
8447 }
8448 }
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05308449
8450 /* If SNR Monitoring is enabled, FW has to parse all beacons
8451 * for calcaluting and storing the average SNR, so set Nth beacon
8452 * filter to 1 to enable FW to parse all the beaocons
8453 */
8454 if (1 == pHddCtx->cfg_ini->fEnableSNRMonitoring)
8455 {
8456 /* The log level is deliberately set to WARN as overriding
8457 * nthBeaconFilter to 1 will increase power cosumption and this
8458 * might just prove helpful to detect the power issue.
8459 */
8460 hddLog(VOS_TRACE_LEVEL_WARN,
8461 "%s: Setting pHddCtx->cfg_ini->nthBeaconFilter = 1", __func__);
8462 pHddCtx->cfg_ini->nthBeaconFilter = 1;
8463 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008464 /*
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308465 * cfg80211: Initialization ...
Jeff Johnson295189b2012-06-20 16:38:30 -07008466 */
Manjunathappa Prakasheec4ddf2014-01-13 18:23:51 -08008467 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07008468 {
Manjunathappa Prakasheec4ddf2014-01-13 18:23:51 -08008469 if (0 < wlan_hdd_cfg80211_init(dev, wiphy, pHddCtx->cfg_ini))
8470 {
8471 hddLog(VOS_TRACE_LEVEL_FATAL,
8472 "%s: wlan_hdd_cfg80211_init return failure", __func__);
8473 goto err_config;
8474 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008475 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008476
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08008477 // Update VOS trace levels based upon the cfg.ini
8478 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
8479 pHddCtx->cfg_ini->vosTraceEnableBAP);
8480 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
8481 pHddCtx->cfg_ini->vosTraceEnableTL);
8482 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
8483 pHddCtx->cfg_ini->vosTraceEnableWDI);
8484 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
8485 pHddCtx->cfg_ini->vosTraceEnableHDD);
8486 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
8487 pHddCtx->cfg_ini->vosTraceEnableSME);
8488 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
8489 pHddCtx->cfg_ini->vosTraceEnablePE);
Katya Nigam70d68332013-09-16 16:49:45 +05308490 hdd_vos_trace_enable(VOS_MODULE_ID_PMC,
8491 pHddCtx->cfg_ini->vosTraceEnablePMC);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08008492 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
8493 pHddCtx->cfg_ini->vosTraceEnableWDA);
8494 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
8495 pHddCtx->cfg_ini->vosTraceEnableSYS);
8496 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
8497 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08008498 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
8499 pHddCtx->cfg_ini->vosTraceEnableSAP);
8500 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
8501 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08008502
Jeff Johnson295189b2012-06-20 16:38:30 -07008503 // Update WDI trace levels based upon the cfg.ini
8504 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
8505 pHddCtx->cfg_ini->wdiTraceEnableDAL);
8506 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
8507 pHddCtx->cfg_ini->wdiTraceEnableCTL);
8508 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
8509 pHddCtx->cfg_ini->wdiTraceEnableDAT);
8510 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
8511 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07008512
Jeff Johnson88ba7742013-02-27 14:36:02 -08008513 if (VOS_FTM_MODE == hdd_get_conparam())
8514 {
Jeff Johnson295189b2012-06-20 16:38:30 -07008515 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
8516 {
8517 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
8518 goto err_free_hdd_context;
8519 }
8520 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
c_hpothu2de0ef62014-04-15 16:16:15 +05308521
8522 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -07008523 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08008524 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008525
Jeff Johnson88ba7742013-02-27 14:36:02 -08008526 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07008527 if(pHddCtx->cfg_ini->fIsLogpEnabled)
8528 {
8529 status = vos_watchdog_open(pVosContext,
8530 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
8531
8532 if(!VOS_IS_STATUS_SUCCESS( status ))
8533 {
8534 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308535 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07008536 }
8537 }
8538
8539 pHddCtx->isLogpInProgress = FALSE;
8540 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
8541
Jeff Johnson295189b2012-06-20 16:38:30 -07008542 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
8543 if(!VOS_IS_STATUS_SUCCESS(status))
8544 {
8545 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008546 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07008547 }
8548
Amar Singhala49cbc52013-10-08 18:37:44 -07008549#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -07008550 /* initialize the NV module. This is required so that
8551 we can initialize the channel information in wiphy
8552 from the NV.bin data. The channel information in
8553 wiphy needs to be initialized before wiphy registration */
8554
8555 status = vos_nv_open();
8556 if (!VOS_IS_STATUS_SUCCESS(status))
8557 {
8558 /* NV module cannot be initialized */
8559 hddLog( VOS_TRACE_LEVEL_FATAL,
8560 "%s: vos_nv_open failed", __func__);
8561 goto err_clkvote;
8562 }
8563
8564 status = vos_init_wiphy_from_nv_bin();
8565 if (!VOS_IS_STATUS_SUCCESS(status))
8566 {
8567 /* NV module cannot be initialized */
8568 hddLog( VOS_TRACE_LEVEL_FATAL,
8569 "%s: vos_init_wiphy failed", __func__);
8570 goto err_vos_nv_close;
8571 }
8572
Amar Singhala49cbc52013-10-08 18:37:44 -07008573#endif
8574
Arun Kumar Khandavalliebb19482014-03-25 13:56:53 +05308575 status = vos_open( &pVosContext, pHddCtx->parent_dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07008576 if ( !VOS_IS_STATUS_SUCCESS( status ))
8577 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008578 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
Mihir Shetee1093ba2014-01-21 20:13:32 +05308579 goto err_vos_nv_close;
Jeff Johnson295189b2012-06-20 16:38:30 -07008580 }
8581
Jeff Johnson295189b2012-06-20 16:38:30 -07008582 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
8583
8584 if ( NULL == pHddCtx->hHal )
8585 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008586 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008587 goto err_vosclose;
8588 }
8589
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008590 status = vos_preStart( pHddCtx->pvosContext );
8591 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8592 {
8593 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05308594 goto err_vosclose;
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008595 }
Jeff Johnsone7245742012-09-05 17:12:55 -07008596
Arif Hussaineaf68602013-12-30 23:10:44 -08008597 if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan)
8598 {
8599 pHddCtx->cfg_ini->enableDFSChnlScan = enable_dfs_chan_scan;
8600 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_dfs_chan_scan set to %d",
8601 __func__, enable_dfs_chan_scan);
8602 }
8603 if (0 == enable_11d || 1 == enable_11d)
8604 {
8605 pHddCtx->cfg_ini->Is11dSupportEnabled = enable_11d;
8606 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_11d set to %d",
8607 __func__, enable_11d);
8608 }
8609
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008610 /* Note that the vos_preStart() sequence triggers the cfg download.
8611 The cfg download must occur before we update the SME config
8612 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07008613 status = hdd_set_sme_config( pHddCtx );
8614
8615 if ( VOS_STATUS_SUCCESS != status )
8616 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008617 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05308618 goto err_vosclose;
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008619 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008620
Jeff Johnson295189b2012-06-20 16:38:30 -07008621 /* In the integrated architecture we update the configuration from
8622 the INI file and from NV before vOSS has been started so that
8623 the final contents are available to send down to the cCPU */
8624
8625 // Apply the cfg.ini to cfg.dat
8626 if (FALSE == hdd_update_config_dat(pHddCtx))
8627 {
8628 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05308629 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07008630 }
8631
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308632 // Get mac addr from platform driver
8633 ret = wcnss_get_wlan_mac_address((char*)&mac_addr.bytes);
8634
8635 if ((0 == ret) && (!vos_is_macaddr_zero(&mac_addr)))
Jeff Johnson295189b2012-06-20 16:38:30 -07008636 {
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308637 /* Store the mac addr for first interface */
8638 pHddCtx->cfg_ini->intfMacAddr[0] = mac_addr;
8639
8640 hddLog(VOS_TRACE_LEVEL_ERROR,
8641 "%s: WLAN Mac Addr: "
8642 MAC_ADDRESS_STR, __func__,
8643 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
8644
8645 /* Here, passing Arg2 as 1 because we do not want to change the
8646 last 3 bytes (means non OUI bytes) of first interface mac
8647 addr.
8648 */
8649 if (0 != hdd_generate_iface_mac_addr_auto(pHddCtx, 1, mac_addr))
8650 {
8651 hddLog(VOS_TRACE_LEVEL_ERROR,
8652 "%s: Failed to generate wlan interface mac addr "
8653 "using MAC from ini file ", __func__);
8654 }
8655 }
8656 else if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
8657 {
8658 // Apply the NV to cfg.dat
8659 /* Prima Update MAC address only at here */
Jeff Johnson295189b2012-06-20 16:38:30 -07008660#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
8661 /* There was not a valid set of MAC Addresses in NV. See if the
8662 default addresses were modified by the cfg.ini settings. If so,
8663 we'll use them, but if not, we'll autogenerate a set of MAC
8664 addresses based upon the device serial number */
8665
8666 static const v_MACADDR_t default_address =
8667 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
Jeff Johnson295189b2012-06-20 16:38:30 -07008668
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308669 if (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
8670 sizeof(default_address)))
Jeff Johnson295189b2012-06-20 16:38:30 -07008671 {
8672 /* cfg.ini has the default address, invoke autogen logic */
8673
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308674 /* Here, passing Arg2 as 0 because we want to change the
8675 last 3 bytes (means non OUI bytes) of all the interfaces
8676 mac addr.
8677 */
8678 if (0 != hdd_generate_iface_mac_addr_auto(pHddCtx, 0,
8679 default_address))
Jeff Johnson295189b2012-06-20 16:38:30 -07008680 {
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308681 hddLog(VOS_TRACE_LEVEL_ERROR,
8682 "%s: Failed to generate wlan interface mac addr "
8683 "using MAC from ini file " MAC_ADDRESS_STR, __func__,
8684 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
Jeff Johnson295189b2012-06-20 16:38:30 -07008685 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008686 }
8687 else
8688#endif //WLAN_AUTOGEN_MACADDR_FEATURE
8689 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008690 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07008691 "%s: Invalid MAC address in NV, using MAC from ini file "
8692 MAC_ADDRESS_STR, __func__,
8693 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
8694 }
8695 }
8696 {
8697 eHalStatus halStatus;
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308698
8699 /* Set the MAC Address Currently this is used by HAL to
8700 * add self sta. Remove this once self sta is added as
8701 * part of session open.
8702 */
Jeff Johnson295189b2012-06-20 16:38:30 -07008703 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
8704 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
8705 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308706
Jeff Johnson295189b2012-06-20 16:38:30 -07008707 if (!HAL_STATUS_SUCCESS( halStatus ))
8708 {
8709 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
8710 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05308711 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07008712 }
8713 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008714
8715 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
8716 Note: Firmware image will be read and downloaded inside vos_start API */
8717 status = vos_start( pHddCtx->pvosContext );
8718 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8719 {
8720 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05308721 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07008722 }
8723
Leo Chang6cec3e22014-01-21 15:33:49 -08008724#ifdef FEATURE_WLAN_CH_AVOID
8725 /* Plug in avoid channel notification callback
8726 * This should happen before ADD_SELF_STA
8727 * FW will send first IND with ADD_SELF_STA REQ from host */
Pradeep Reddy POTTETI5c2e16d2014-06-27 16:47:38 +05308728
8729 /* check the Channel Avoidance is enabled */
8730 if (TRUE == pHddCtx->cfg_ini->fenableCHAvoidance)
8731 {
8732 sme_AddChAvoidCallback(pHddCtx->hHal,
8733 hdd_hostapd_ch_avoid_cb);
8734 }
Leo Chang6cec3e22014-01-21 15:33:49 -08008735#endif /* FEATURE_WLAN_CH_AVOID */
8736
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008737 /* Exchange capability info between Host and FW and also get versioning info from FW */
8738 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07008739
Agarwal Ashishad9281b2014-06-10 14:57:30 +05308740#ifdef CONFIG_ENABLE_LINUX_REG
8741 status = wlan_hdd_init_channels(pHddCtx);
8742 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8743 {
8744 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: wlan_hdd_init_channels failed",
8745 __func__);
8746 goto err_vosstop;
8747 }
8748#endif
8749
Jeff Johnson295189b2012-06-20 16:38:30 -07008750 status = hdd_post_voss_start_config( pHddCtx );
8751 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8752 {
8753 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
8754 __func__);
8755 goto err_vosstop;
8756 }
Amar Singhala49cbc52013-10-08 18:37:44 -07008757
8758#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308759 wlan_hdd_cfg80211_update_reg_info( wiphy );
8760
8761 /* registration of wiphy dev with cfg80211 */
8762 if (0 > wlan_hdd_cfg80211_register(wiphy))
8763 {
8764 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
8765 goto err_vosstop;
8766 }
Amar Singhala49cbc52013-10-08 18:37:44 -07008767#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008768
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05308769#ifdef CONFIG_ENABLE_LINUX_REG
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05308770 /* registration of wiphy dev with cfg80211 */
8771 if (0 > wlan_hdd_cfg80211_register(wiphy))
8772 {
8773 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
8774 goto err_vosstop;
8775 }
8776
8777 status = wlan_hdd_init_channels_for_cc(pHddCtx);
8778 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8779 {
8780 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: wlan_hdd_init_channels_for_cc failed",
8781 __func__);
8782 goto err_unregister_wiphy;
8783 }
8784#endif
8785
Jeff Johnson295189b2012-06-20 16:38:30 -07008786 if (VOS_STA_SAP_MODE == hdd_get_conparam())
8787 {
8788 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
8789 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
8790 }
8791 else
8792 {
Jeff Johnson295189b2012-06-20 16:38:30 -07008793 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
8794 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
8795 if (pAdapter != NULL)
8796 {
kaidde69982014-06-18 13:23:21 +08008797 if (pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated && !(pHddCtx->cfg_ini->intfMacAddr[0].bytes[0] &= 0x02))
Jeff Johnson295189b2012-06-20 16:38:30 -07008798 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05308799 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
8800 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
8801 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07008802
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05308803 /* Generate the P2P Device Address. This consists of the device's
8804 * primary MAC address with the locally administered bit set.
8805 */
8806 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07008807 }
8808 else
8809 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05308810 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
8811 if (p2p_dev_addr != NULL)
8812 {
8813 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
8814 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
8815 }
8816 else
8817 {
8818 hddLog(VOS_TRACE_LEVEL_FATAL,
8819 "%s: Failed to allocate mac_address for p2p_device",
8820 __func__);
8821 goto err_close_adapter;
8822 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008823 }
Jeff Johnsone7245742012-09-05 17:12:55 -07008824
8825 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
8826 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
8827 if ( NULL == pP2pAdapter )
8828 {
8829 hddLog(VOS_TRACE_LEVEL_FATAL,
8830 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008831 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07008832 goto err_close_adapter;
8833 }
Jeff Johnsone7245742012-09-05 17:12:55 -07008834 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008835 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008836
8837 if( pAdapter == NULL )
8838 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008839 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
8840 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07008841 }
Jeff Johnsone7245742012-09-05 17:12:55 -07008842
Arif Hussain66559122013-11-21 10:11:40 -08008843 if (country_code)
8844 {
8845 eHalStatus ret;
Arif Hussaincb607082013-12-20 11:57:42 -08008846 INIT_COMPLETION(pAdapter->change_country_code);
Arif Hussain66559122013-11-21 10:11:40 -08008847 hdd_checkandupdate_dfssetting(pAdapter, country_code);
8848#ifndef CONFIG_ENABLE_LINUX_REG
8849 hdd_checkandupdate_phymode(pAdapter, country_code);
8850#endif
Arif Hussaineaf68602013-12-30 23:10:44 -08008851 ret = sme_ChangeCountryCode(pHddCtx->hHal,
8852 (void *)(tSmeChangeCountryCallback)
8853 wlan_hdd_change_country_code_callback,
Arif Hussain66559122013-11-21 10:11:40 -08008854 country_code,
8855 pAdapter, pHddCtx->pvosContext,
Abhishek Singha306a442013-11-07 18:39:01 +05308856 eSIR_TRUE, eSIR_TRUE);
Arif Hussain66559122013-11-21 10:11:40 -08008857 if (eHAL_STATUS_SUCCESS == ret)
8858 {
Arif Hussaincb607082013-12-20 11:57:42 -08008859 ret = wait_for_completion_interruptible_timeout(
8860 &pAdapter->change_country_code,
8861 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
8862
8863 if (0 >= ret)
8864 {
8865 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8866 "%s: SME while setting country code timed out", __func__);
8867 }
Arif Hussain66559122013-11-21 10:11:40 -08008868 }
8869 else
8870 {
Arif Hussaincb607082013-12-20 11:57:42 -08008871 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8872 "%s: SME Change Country code from module param fail ret=%d",
8873 __func__, ret);
Arif Hussain66559122013-11-21 10:11:40 -08008874 }
8875 }
8876
Jeff Johnson295189b2012-06-20 16:38:30 -07008877#ifdef WLAN_BTAMP_FEATURE
8878 vStatus = WLANBAP_Open(pVosContext);
8879 if(!VOS_IS_STATUS_SUCCESS(vStatus))
8880 {
8881 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8882 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07008883 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07008884 }
8885
8886 vStatus = BSL_Init(pVosContext);
8887 if(!VOS_IS_STATUS_SUCCESS(vStatus))
8888 {
8889 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8890 "%s: Failed to Init BSL",__func__);
8891 goto err_bap_close;
8892 }
8893 vStatus = WLANBAP_Start(pVosContext);
8894 if (!VOS_IS_STATUS_SUCCESS(vStatus))
8895 {
8896 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8897 "%s: Failed to start TL",__func__);
8898 goto err_bap_close;
8899 }
8900
8901 pConfig = pHddCtx->cfg_ini;
8902 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
8903 status = WLANBAP_SetConfig(&btAmpConfig);
8904
8905#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07008906
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07008907#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
8908 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
8909 {
8910 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
8911 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
8912 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
8913 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
8914 }
8915#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008916
Mihir Shetefc7ff5b2014-01-27 11:30:05 +05308917 sme_Register11dScanDoneCallback(pHddCtx->hHal, hdd_11d_scan_done);
8918
Jeff Johnson295189b2012-06-20 16:38:30 -07008919 /* Register with platform driver as client for Suspend/Resume */
8920 status = hddRegisterPmOps(pHddCtx);
8921 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8922 {
8923 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
8924#ifdef WLAN_BTAMP_FEATURE
8925 goto err_bap_stop;
8926#else
Jeff Johnsone7245742012-09-05 17:12:55 -07008927 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07008928#endif //WLAN_BTAMP_FEATURE
8929 }
8930
Yue Ma0d4891e2013-08-06 17:01:45 -07008931 /* Open debugfs interface */
8932 if (VOS_STATUS_SUCCESS != hdd_debugfs_init(pAdapter))
8933 {
8934 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8935 "%s: hdd_debugfs_init failed!", __func__);
Yue Ma0d4891e2013-08-06 17:01:45 -07008936 }
8937
Jeff Johnson295189b2012-06-20 16:38:30 -07008938 /* Register TM level change handler function to the platform */
8939 status = hddDevTmRegisterNotifyCallback(pHddCtx);
8940 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8941 {
8942 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
8943 goto err_unregister_pmops;
8944 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008945
8946 /* register for riva power on lock to platform driver */
8947 if (req_riva_power_on_lock("wlan"))
8948 {
8949 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
8950 __func__);
8951 goto err_unregister_pmops;
8952 }
8953
Jeff Johnson295189b2012-06-20 16:38:30 -07008954 // register net device notifier for device change notification
8955 ret = register_netdevice_notifier(&hdd_netdev_notifier);
8956
8957 if(ret < 0)
8958 {
8959 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
8960 goto err_free_power_on_lock;
8961 }
8962
8963 //Initialize the nlink service
8964 if(nl_srv_init() != 0)
8965 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308966 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008967 goto err_reg_netdev;
8968 }
8969
Leo Chang4ce1cc52013-10-21 18:27:15 -07008970#ifdef WLAN_KD_READY_NOTIFIER
8971 pHddCtx->kd_nl_init = 1;
8972#endif /* WLAN_KD_READY_NOTIFIER */
8973
Jeff Johnson295189b2012-06-20 16:38:30 -07008974 //Initialize the BTC service
8975 if(btc_activate_service(pHddCtx) != 0)
8976 {
8977 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
8978 goto err_nl_srv;
8979 }
8980
8981#ifdef PTT_SOCK_SVC_ENABLE
8982 //Initialize the PTT service
8983 if(ptt_sock_activate_svc(pHddCtx) != 0)
8984 {
8985 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
8986 goto err_nl_srv;
8987 }
8988#endif
8989
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05308990#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
8991 if(pHddCtx->cfg_ini && pHddCtx->cfg_ini->wlanLoggingEnable)
8992 {
8993 if(wlan_logging_sock_activate_svc(
8994 pHddCtx->cfg_ini->wlanLoggingFEToConsole,
8995 pHddCtx->cfg_ini->wlanLoggingNumBuf))
8996 {
8997 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wlan_logging_sock_activate_svc"
8998 " failed", __func__);
8999 goto err_nl_srv;
9000 }
9001 }
9002#endif
9003
Jeff Johnson295189b2012-06-20 16:38:30 -07009004 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07009005 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07009006 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07009007 /* Action frame registered in one adapter which will
9008 * applicable to all interfaces
9009 */
Agarwal Ashish8fa0e9a2014-05-23 00:40:12 +05309010 wlan_hdd_cfg80211_register_frames(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07009011 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009012
9013 mutex_init(&pHddCtx->sap_lock);
9014
Jeff Johnson295189b2012-06-20 16:38:30 -07009015
Sameer Thalappil50dc0092013-02-19 17:23:33 -08009016#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07009017#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
9018 /* Initialize the wake lcok */
9019 wake_lock_init(&pHddCtx->rx_wake_lock,
9020 WAKE_LOCK_SUSPEND,
9021 "qcom_rx_wakelock");
9022#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08009023 /* Initialize the wake lcok */
9024 wake_lock_init(&pHddCtx->sap_wake_lock,
9025 WAKE_LOCK_SUSPEND,
9026 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08009027#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07009028
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07009029 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
9030 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07009031
Katya Nigam5c306ea2014-06-19 15:39:54 +05309032 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_NO_LOAD_UNLOAD_IN_PROGRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -07009033 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
9034 hdd_allow_suspend();
Katya Nigam5c306ea2014-06-19 15:39:54 +05309035
9036#ifdef FEATURE_WLAN_SCAN_PNO
9037 /*SME must send channel update configuration to RIVA*/
9038 sme_UpdateChannelConfig(pHddCtx->hHal);
9039#endif
9040
Abhishek Singha306a442013-11-07 18:39:01 +05309041#ifndef CONFIG_ENABLE_LINUX_REG
9042 /*updating wiphy so that regulatory user hints can be processed*/
9043 if (wiphy)
9044 {
9045 regulatory_hint(wiphy, "00");
9046 }
9047#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07009048 // Initialize the restart logic
9049 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05309050
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07009051 //Register the traffic monitor timer now
9052 if ( pHddCtx->cfg_ini->dynSplitscan)
9053 {
9054 vos_timer_init(&pHddCtx->tx_rx_trafficTmr,
9055 VOS_TIMER_TYPE_SW,
9056 hdd_tx_rx_pkt_cnt_stat_timer_handler,
9057 (void *)pHddCtx);
9058 }
Dino Mycle6fb96c12014-06-10 11:52:40 +05309059#ifdef WLAN_FEATURE_EXTSCAN
9060 sme_EXTScanRegisterCallback(pHddCtx->hHal,
9061 wlan_hdd_cfg80211_extscan_callback,
9062 pHddCtx);
9063#endif /* WLAN_FEATURE_EXTSCAN */
Jeff Johnson295189b2012-06-20 16:38:30 -07009064 goto success;
9065
9066err_nl_srv:
Leo Chang59cdc7e2013-07-10 10:08:21 -07009067#ifdef WLAN_KD_READY_NOTIFIER
9068 nl_srv_exit(pHddCtx->ptt_pid);
9069#else
Jeff Johnson295189b2012-06-20 16:38:30 -07009070 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07009071#endif /* WLAN_KD_READY_NOTIFIER */
Jeff Johnson295189b2012-06-20 16:38:30 -07009072err_reg_netdev:
9073 unregister_netdevice_notifier(&hdd_netdev_notifier);
9074
9075err_free_power_on_lock:
9076 free_riva_power_on_lock("wlan");
9077
9078err_unregister_pmops:
9079 hddDevTmUnregisterNotifyCallback(pHddCtx);
9080 hddDeregisterPmOps(pHddCtx);
9081
Yue Ma0d4891e2013-08-06 17:01:45 -07009082 hdd_debugfs_exit(pHddCtx);
9083
Jeff Johnson295189b2012-06-20 16:38:30 -07009084#ifdef WLAN_BTAMP_FEATURE
9085err_bap_stop:
9086 WLANBAP_Stop(pVosContext);
9087#endif
9088
9089#ifdef WLAN_BTAMP_FEATURE
9090err_bap_close:
9091 WLANBAP_Close(pVosContext);
9092#endif
9093
Jeff Johnson295189b2012-06-20 16:38:30 -07009094err_close_adapter:
9095 hdd_close_all_adapters( pHddCtx );
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05309096err_unregister_wiphy:
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05309097 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07009098err_vosstop:
9099 vos_stop(pVosContext);
9100
Amar Singhala49cbc52013-10-08 18:37:44 -07009101err_vosclose:
Jeff Johnson295189b2012-06-20 16:38:30 -07009102 status = vos_sched_close( pVosContext );
9103 if (!VOS_IS_STATUS_SUCCESS(status)) {
9104 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
9105 "%s: Failed to close VOSS Scheduler", __func__);
9106 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
9107 }
Amar Singhala49cbc52013-10-08 18:37:44 -07009108 vos_close(pVosContext );
9109
Amar Singhal0a402232013-10-11 20:57:16 -07009110err_vos_nv_close:
9111
c_hpothue6a36282014-03-19 12:27:38 +05309112#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -07009113 vos_nv_close();
9114
Jeff Johnson295189b2012-06-20 16:38:30 -07009115err_clkvote:
c_hpothu70f8d812014-03-22 22:59:23 +05309116#endif
Jeff Johnsonbc676b42013-02-14 16:04:08 -08009117 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07009118
9119err_wdclose:
9120 if(pHddCtx->cfg_ini->fIsLogpEnabled)
9121 vos_watchdog_close(pVosContext);
9122
Jeff Johnson295189b2012-06-20 16:38:30 -07009123err_config:
9124 kfree(pHddCtx->cfg_ini);
9125 pHddCtx->cfg_ini= NULL;
9126
9127err_free_hdd_context:
9128 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07009129 wiphy_free(wiphy) ;
9130 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07009131 VOS_BUG(1);
9132
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08009133 if (hdd_is_ssr_required())
9134 {
9135 /* WDI timeout had happened during load, so SSR is needed here */
9136 subsystem_restart("wcnss");
9137 msleep(5000);
9138 }
9139 hdd_set_ssr_required (VOS_FALSE);
9140
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08009141 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07009142
9143success:
9144 EXIT();
9145 return 0;
9146}
9147
9148/**---------------------------------------------------------------------------
9149
Jeff Johnson32d95a32012-09-10 13:15:23 -07009150 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07009151
Jeff Johnson32d95a32012-09-10 13:15:23 -07009152 This is the driver entry point - called in different timeline depending
9153 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07009154
9155 \param - None
9156
9157 \return - 0 for success, non zero for failure
9158
9159 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07009160static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07009161{
9162 VOS_STATUS status;
9163 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07009164 struct device *dev = NULL;
9165 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07009166#ifdef HAVE_WCNSS_CAL_DOWNLOAD
9167 int max_retries = 0;
9168#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009169
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05309170#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9171 wlan_logging_sock_init_svc();
9172#endif
9173
Jeff Johnson295189b2012-06-20 16:38:30 -07009174 ENTER();
9175
Sameer Thalappil50dc0092013-02-19 17:23:33 -08009176#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07009177 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07009178#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009179
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05309180 hddTraceInit();
Jeff Johnson295189b2012-06-20 16:38:30 -07009181 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
9182 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
9183
9184 //Power Up Libra WLAN card first if not already powered up
9185 status = vos_chipPowerUp(NULL,NULL,NULL);
9186 if (!VOS_IS_STATUS_SUCCESS(status))
9187 {
9188 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
9189 "exiting", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05309190#ifdef WLAN_OPEN_SOURCE
9191 wake_lock_destroy(&wlan_wake_lock);
9192#endif
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05309193
9194#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9195 wlan_logging_sock_deinit_svc();
9196#endif
9197
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08009198 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07009199 }
9200
Jeff Johnson295189b2012-06-20 16:38:30 -07009201#ifdef ANI_BUS_TYPE_PCI
9202
9203 dev = wcnss_wlan_get_device();
9204
9205#endif // ANI_BUS_TYPE_PCI
9206
9207#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07009208
9209#ifdef HAVE_WCNSS_CAL_DOWNLOAD
9210 /* wait until WCNSS driver downloads NV */
9211 while (!wcnss_device_ready() && 5 >= ++max_retries) {
9212 msleep(1000);
9213 }
9214 if (max_retries >= 5) {
9215 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05309216#ifdef WLAN_OPEN_SOURCE
9217 wake_lock_destroy(&wlan_wake_lock);
9218#endif
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05309219
9220#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9221 wlan_logging_sock_deinit_svc();
9222#endif
9223
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07009224 return -ENODEV;
9225 }
9226#endif
9227
Jeff Johnson295189b2012-06-20 16:38:30 -07009228 dev = wcnss_wlan_get_device();
9229#endif // ANI_BUS_TYPE_PLATFORM
9230
9231
9232 do {
9233 if (NULL == dev) {
9234 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
9235 ret_status = -1;
9236 break;
9237 }
9238
Jeff Johnson295189b2012-06-20 16:38:30 -07009239#ifdef TIMER_MANAGER
9240 vos_timer_manager_init();
9241#endif
9242
9243 /* Preopen VOSS so that it is ready to start at least SAL */
9244 status = vos_preOpen(&pVosContext);
9245
9246 if (!VOS_IS_STATUS_SUCCESS(status))
9247 {
9248 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
9249 ret_status = -1;
9250 break;
9251 }
9252
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009253#ifndef MODULE
9254 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
9255 */
9256 hdd_set_conparam((v_UINT_t)con_mode);
9257#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009258
9259 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08009260 if (hdd_wlan_startup(dev))
9261 {
Jeff Johnson295189b2012-06-20 16:38:30 -07009262 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08009263 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009264 vos_preClose( &pVosContext );
9265 ret_status = -1;
9266 break;
9267 }
9268
9269 /* Cancel the vote for XO Core ON
9270 * This is done here for safety purposes in case we re-initialize without turning
9271 * it OFF in any error scenario.
9272 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07009273 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07009274 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07009275 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07009276 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
9277 {
9278 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
Arif Hussain6d2a3322013-11-17 19:50:10 -08009279 " Power consumed will be high");
Jeff Johnson295189b2012-06-20 16:38:30 -07009280 }
9281 } while (0);
9282
9283 if (0 != ret_status)
9284 {
9285 //Assert Deep sleep signal now to put Libra HW in lowest power state
9286 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
9287 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
9288
9289 //Vote off any PMIC voltage supplies
9290 vos_chipPowerDown(NULL, NULL, NULL);
9291#ifdef TIMER_MANAGER
9292 vos_timer_exit();
9293#endif
9294#ifdef MEMORY_DEBUG
9295 vos_mem_exit();
9296#endif
9297
Sameer Thalappil50dc0092013-02-19 17:23:33 -08009298#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07009299 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07009300#endif
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05309301
9302#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9303 wlan_logging_sock_deinit_svc();
9304#endif
9305
Jeff Johnson295189b2012-06-20 16:38:30 -07009306 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
9307 }
9308 else
9309 {
9310 //Send WLAN UP indication to Nlink Service
9311 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
9312
9313 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Jeff Johnson295189b2012-06-20 16:38:30 -07009314 }
9315
9316 EXIT();
9317
9318 return ret_status;
9319}
9320
Jeff Johnson32d95a32012-09-10 13:15:23 -07009321/**---------------------------------------------------------------------------
9322
9323 \brief hdd_module_init() - Init Function
9324
9325 This is the driver entry point (invoked when module is loaded using insmod)
9326
9327 \param - None
9328
9329 \return - 0 for success, non zero for failure
9330
9331 --------------------------------------------------------------------------*/
9332#ifdef MODULE
9333static int __init hdd_module_init ( void)
9334{
9335 return hdd_driver_init();
9336}
Jeff Johnson32d95a32012-09-10 13:15:23 -07009337#else /* #ifdef MODULE */
9338static int __init hdd_module_init ( void)
9339{
9340 /* Driver initialization is delayed to fwpath_changed_handler */
9341 return 0;
9342}
Jeff Johnson32d95a32012-09-10 13:15:23 -07009343#endif /* #ifdef MODULE */
9344
Jeff Johnson295189b2012-06-20 16:38:30 -07009345
9346/**---------------------------------------------------------------------------
9347
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009348 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07009349
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009350 This is the driver exit point (invoked when module is unloaded using rmmod
9351 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07009352
9353 \param - None
9354
9355 \return - None
9356
9357 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009358static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07009359{
9360 hdd_context_t *pHddCtx = NULL;
9361 v_CONTEXT_t pVosContext = NULL;
Agarwal Ashish5e414792014-06-08 15:25:23 +05309362 v_REGDOMAIN_t regId;
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +05309363 unsigned long rc = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07009364
9365 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
9366
9367 //Get the global vos context
9368 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
9369
9370 if(!pVosContext)
9371 {
9372 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
9373 goto done;
9374 }
9375
9376 //Get the HDD context.
9377 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
9378
9379 if(!pHddCtx)
9380 {
9381 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
9382 }
9383 else
9384 {
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +05309385 INIT_COMPLETION(pHddCtx->ssr_comp_var);
9386
9387 if (pHddCtx->isLogpInProgress)
9388 {
Sameer Thalappil451ebb92013-06-28 15:49:58 -07009389 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +05309390 "%s:SSR in Progress; block rmmod !!!", __func__);
9391 rc = wait_for_completion_timeout(&pHddCtx->ssr_comp_var,
9392 msecs_to_jiffies(30000));
9393 if(!rc)
9394 {
9395 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
9396 "%s:SSR timedout, fatal error", __func__);
9397 VOS_BUG(0);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07009398 }
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +05309399 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009400
Mihir Shete18156292014-03-11 15:38:30 +05309401 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_UNLOAD_IN_PROGRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -07009402 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
9403
Agarwal Ashish5e414792014-06-08 15:25:23 +05309404 if (eANI_BOOLEAN_TRUE == sme_Is11dCountrycode(pHddCtx->hHal) &&
9405 pHddCtx->cfg_ini->fSupplicantCountryCodeHasPriority )
9406 {
9407 vos_nv_getRegDomainFromCountryCode(&regId , "00", COUNTRY_USER);
9408 }
9409
Jeff Johnson295189b2012-06-20 16:38:30 -07009410 //Do all the cleanup before deregistering the driver
9411 hdd_wlan_exit(pHddCtx);
9412 }
9413
Jeff Johnson295189b2012-06-20 16:38:30 -07009414 vos_preClose( &pVosContext );
9415
9416#ifdef TIMER_MANAGER
9417 vos_timer_exit();
9418#endif
9419#ifdef MEMORY_DEBUG
9420 vos_mem_exit();
9421#endif
9422
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05309423#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9424 wlan_logging_sock_deinit_svc();
9425#endif
9426
Jeff Johnson295189b2012-06-20 16:38:30 -07009427done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08009428#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07009429 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07009430#endif
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05309431
Jeff Johnson295189b2012-06-20 16:38:30 -07009432 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
9433}
9434
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009435/**---------------------------------------------------------------------------
9436
9437 \brief hdd_module_exit() - Exit function
9438
9439 This is the driver exit point (invoked when module is unloaded using rmmod)
9440
9441 \param - None
9442
9443 \return - None
9444
9445 --------------------------------------------------------------------------*/
9446static void __exit hdd_module_exit(void)
9447{
9448 hdd_driver_exit();
9449}
9450
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009451#ifdef MODULE
9452static int fwpath_changed_handler(const char *kmessage,
9453 struct kernel_param *kp)
9454{
Jeff Johnson76052702013-04-16 13:55:05 -07009455 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009456}
9457
9458static int con_mode_handler(const char *kmessage,
9459 struct kernel_param *kp)
9460{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07009461 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009462}
9463#else /* #ifdef MODULE */
9464/**---------------------------------------------------------------------------
9465
Jeff Johnson76052702013-04-16 13:55:05 -07009466 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009467
Jeff Johnson76052702013-04-16 13:55:05 -07009468 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009469 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07009470 - invoked when module parameter fwpath is modified from userspace to signal
9471 initializing the WLAN driver or when con_mode is modified from userspace
9472 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009473
9474 \return - 0 for success, non zero for failure
9475
9476 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07009477static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009478{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07009479 int ret_status;
9480
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009481 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07009482 ret_status = hdd_driver_init();
9483 wlan_hdd_inited = ret_status ? 0 : 1;
9484 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009485 }
9486
9487 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07009488
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009489 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07009490
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07009491 ret_status = hdd_driver_init();
9492 wlan_hdd_inited = ret_status ? 0 : 1;
9493 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009494}
9495
Jeff Johnson295189b2012-06-20 16:38:30 -07009496/**---------------------------------------------------------------------------
9497
Jeff Johnson76052702013-04-16 13:55:05 -07009498 \brief fwpath_changed_handler() - Handler Function
9499
9500 Handle changes to the fwpath parameter
9501
9502 \return - 0 for success, non zero for failure
9503
9504 --------------------------------------------------------------------------*/
9505static int fwpath_changed_handler(const char *kmessage,
9506 struct kernel_param *kp)
9507{
9508 int ret;
9509
9510 ret = param_set_copystring(kmessage, kp);
9511 if (0 == ret)
9512 ret = kickstart_driver();
9513 return ret;
9514}
9515
9516/**---------------------------------------------------------------------------
9517
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009518 \brief con_mode_handler() -
9519
9520 Handler function for module param con_mode when it is changed by userspace
9521 Dynamically linked - do nothing
9522 Statically linked - exit and init driver, as in rmmod and insmod
9523
Jeff Johnson76052702013-04-16 13:55:05 -07009524 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009525
Jeff Johnson76052702013-04-16 13:55:05 -07009526 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009527
9528 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07009529static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009530{
Jeff Johnson76052702013-04-16 13:55:05 -07009531 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009532
Jeff Johnson76052702013-04-16 13:55:05 -07009533 ret = param_set_int(kmessage, kp);
9534 if (0 == ret)
9535 ret = kickstart_driver();
9536 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009537}
9538#endif /* #ifdef MODULE */
9539
9540/**---------------------------------------------------------------------------
9541
Jeff Johnson295189b2012-06-20 16:38:30 -07009542 \brief hdd_get_conparam() -
9543
9544 This is the driver exit point (invoked when module is unloaded using rmmod)
9545
9546 \param - None
9547
9548 \return - tVOS_CON_MODE
9549
9550 --------------------------------------------------------------------------*/
9551tVOS_CON_MODE hdd_get_conparam ( void )
9552{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009553#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07009554 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009555#else
9556 return (tVOS_CON_MODE)curr_con_mode;
9557#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009558}
9559void hdd_set_conparam ( v_UINT_t newParam )
9560{
9561 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009562#ifndef MODULE
9563 curr_con_mode = con_mode;
9564#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009565}
9566/**---------------------------------------------------------------------------
9567
9568 \brief hdd_softap_sta_deauth() - function
9569
9570 This to take counter measure to handle deauth req from HDD
9571
9572 \param - pAdapter - Pointer to the HDD
9573
9574 \param - enable - boolean value
9575
9576 \return - None
9577
9578 --------------------------------------------------------------------------*/
9579
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009580VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07009581{
Jeff Johnson295189b2012-06-20 16:38:30 -07009582 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009583 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07009584
9585 ENTER();
9586
Rajesh Chauhan18488fc2013-08-22 10:15:03 -07009587 hddLog(LOG1, "hdd_softap_sta_deauth:(%p, false)",
9588 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07009589
9590 //Ignore request to deauth bcmc station
9591 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009592 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07009593
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009594 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07009595
9596 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009597 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07009598}
9599
9600/**---------------------------------------------------------------------------
9601
9602 \brief hdd_softap_sta_disassoc() - function
9603
9604 This to take counter measure to handle deauth req from HDD
9605
9606 \param - pAdapter - Pointer to the HDD
9607
9608 \param - enable - boolean value
9609
9610 \return - None
9611
9612 --------------------------------------------------------------------------*/
9613
9614void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
9615{
9616 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
9617
9618 ENTER();
9619
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05309620 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07009621
9622 //Ignore request to disassoc bcmc station
9623 if( pDestMacAddress[0] & 0x1 )
9624 return;
9625
9626 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
9627}
9628
9629void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
9630{
9631 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
9632
9633 ENTER();
9634
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05309635 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07009636
9637 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
9638}
9639
Jeff Johnson295189b2012-06-20 16:38:30 -07009640/**---------------------------------------------------------------------------
9641 *
9642 * \brief hdd_get__concurrency_mode() -
9643 *
9644 *
9645 * \param - None
9646 *
9647 * \return - CONCURRENCY MODE
9648 *
9649 * --------------------------------------------------------------------------*/
9650tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
9651{
9652 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
9653 hdd_context_t *pHddCtx;
9654
9655 if (NULL != pVosContext)
9656 {
9657 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
9658 if (NULL != pHddCtx)
9659 {
9660 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
9661 }
9662 }
9663
9664 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07009665 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009666 return VOS_STA;
9667}
9668
9669/* Decide whether to allow/not the apps power collapse.
9670 * Allow apps power collapse if we are in connected state.
9671 * if not, allow only if we are in IMPS */
9672v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
9673{
9674 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08009675 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08009676 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07009677 hdd_config_t *pConfig = pHddCtx->cfg_ini;
9678 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
9679 hdd_adapter_t *pAdapter = NULL;
9680 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08009681 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07009682
Jeff Johnson295189b2012-06-20 16:38:30 -07009683 if (VOS_STA_SAP_MODE == hdd_get_conparam())
9684 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07009685
Yathish9f22e662012-12-10 14:21:35 -08009686 concurrent_state = hdd_get_concurrency_mode();
9687
9688#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
9689 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
9690 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
9691 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
9692 return TRUE;
9693#endif
9694
Jeff Johnson295189b2012-06-20 16:38:30 -07009695 /*loop through all adapters. TBD fix for Concurrency */
9696 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
9697 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
9698 {
9699 pAdapter = pAdapterNode->pAdapter;
9700 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
9701 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
9702 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08009703 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
c_hpothu4e8faac2014-05-16 17:38:44 +05309704 && (pmcState != IMPS && pmcState != BMPS && pmcState != UAPSD
Srikant Kuppafef66a72013-01-30 17:32:44 -08009705 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08009706 (eANI_BOOLEAN_TRUE == scanRspPending) ||
9707 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07009708 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08009709 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08009710 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
9711 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07009712 return FALSE;
9713 }
9714 }
9715 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
9716 pAdapterNode = pNext;
9717 }
9718 return TRUE;
9719}
9720
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08009721/* Decides whether to send suspend notification to Riva
9722 * if any adapter is in BMPS; then it is required */
9723v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
9724{
9725 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
9726 hdd_config_t *pConfig = pHddCtx->cfg_ini;
9727
9728 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
9729 {
9730 return TRUE;
9731 }
9732 return FALSE;
9733}
9734
Jeff Johnson295189b2012-06-20 16:38:30 -07009735void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
9736{
9737 switch(mode)
9738 {
Chilam Ngc4244af2013-04-01 15:37:32 -07009739 case VOS_STA_MODE:
9740 case VOS_P2P_CLIENT_MODE:
9741 case VOS_P2P_GO_MODE:
9742 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07009743 pHddCtx->concurrency_mode |= (1 << mode);
9744 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07009745 break;
9746 default:
9747 break;
9748
9749 }
9750 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
9751 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
9752}
9753
9754
9755void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
9756{
9757 switch(mode)
9758 {
Chilam Ngc4244af2013-04-01 15:37:32 -07009759 case VOS_STA_MODE:
9760 case VOS_P2P_CLIENT_MODE:
9761 case VOS_P2P_GO_MODE:
9762 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07009763 pHddCtx->no_of_sessions[mode]--;
9764 if (!(pHddCtx->no_of_sessions[mode]))
9765 pHddCtx->concurrency_mode &= (~(1 << mode));
9766 break;
9767 default:
9768 break;
9769 }
9770 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
9771 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
9772}
9773
Jeff Johnsone7245742012-09-05 17:12:55 -07009774/**---------------------------------------------------------------------------
9775 *
9776 * \brief wlan_hdd_restart_init
9777 *
9778 * This function initalizes restart timer/flag. An internal function.
9779 *
9780 * \param - pHddCtx
9781 *
9782 * \return - None
9783 *
9784 * --------------------------------------------------------------------------*/
9785
9786static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
9787{
9788 /* Initialize */
9789 pHddCtx->hdd_restart_retries = 0;
9790 atomic_set(&pHddCtx->isRestartInProgress, 0);
9791 vos_timer_init(&pHddCtx->hdd_restart_timer,
9792 VOS_TIMER_TYPE_SW,
9793 wlan_hdd_restart_timer_cb,
9794 pHddCtx);
9795}
9796/**---------------------------------------------------------------------------
9797 *
9798 * \brief wlan_hdd_restart_deinit
9799 *
9800 * This function cleans up the resources used. An internal function.
9801 *
9802 * \param - pHddCtx
9803 *
9804 * \return - None
9805 *
9806 * --------------------------------------------------------------------------*/
9807
9808static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
9809{
9810
9811 VOS_STATUS vos_status;
9812 /* Block any further calls */
9813 atomic_set(&pHddCtx->isRestartInProgress, 1);
9814 /* Cleanup */
9815 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
9816 if (!VOS_IS_STATUS_SUCCESS(vos_status))
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309817 hddLog(LOGE, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07009818 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
9819 if (!VOS_IS_STATUS_SUCCESS(vos_status))
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309820 hddLog(LOGE, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07009821
9822}
9823
9824/**---------------------------------------------------------------------------
9825 *
9826 * \brief wlan_hdd_framework_restart
9827 *
9828 * This function uses a cfg80211 API to start a framework initiated WLAN
9829 * driver module unload/load.
9830 *
9831 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
9832 *
9833 *
9834 * \param - pHddCtx
9835 *
9836 * \return - VOS_STATUS_SUCCESS: Success
9837 * VOS_STATUS_E_EMPTY: Adapter is Empty
9838 * VOS_STATUS_E_NOMEM: No memory
9839
9840 * --------------------------------------------------------------------------*/
9841
9842static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
9843{
9844 VOS_STATUS status = VOS_STATUS_SUCCESS;
9845 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07009846 int len = (sizeof (struct ieee80211_mgmt));
9847 struct ieee80211_mgmt *mgmt = NULL;
9848
9849 /* Prepare the DEAUTH managment frame with reason code */
9850 mgmt = kzalloc(len, GFP_KERNEL);
9851 if(mgmt == NULL)
9852 {
9853 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
9854 "%s: memory allocation failed (%d bytes)", __func__, len);
9855 return VOS_STATUS_E_NOMEM;
9856 }
9857 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -07009858
9859 /* Iterate over all adapters/devices */
9860 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
9861 do
9862 {
9863 if( (status == VOS_STATUS_SUCCESS) &&
9864 pAdapterNode &&
9865 pAdapterNode->pAdapter)
9866 {
9867 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
9868 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
9869 pAdapterNode->pAdapter->dev->name,
9870 pAdapterNode->pAdapter->device_mode,
9871 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07009872 /*
9873 * CFG80211 event to restart the driver
9874 *
9875 * 'cfg80211_send_unprot_deauth' sends a
9876 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
9877 * of SME(Linux Kernel) state machine.
9878 *
9879 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
9880 * the driver.
9881 *
9882 */
9883
9884 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -07009885 }
9886 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
9887 pAdapterNode = pNext;
9888 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
9889
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07009890
9891 /* Free the allocated management frame */
9892 kfree(mgmt);
9893
Jeff Johnsone7245742012-09-05 17:12:55 -07009894 /* Retry until we unload or reach max count */
9895 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
9896 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
9897
9898 return status;
9899
9900}
9901/**---------------------------------------------------------------------------
9902 *
9903 * \brief wlan_hdd_restart_timer_cb
9904 *
9905 * Restart timer callback. An internal function.
9906 *
9907 * \param - User data:
9908 *
9909 * \return - None
9910 *
9911 * --------------------------------------------------------------------------*/
9912
9913void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
9914{
9915 hdd_context_t *pHddCtx = usrDataForCallback;
9916 wlan_hdd_framework_restart(pHddCtx);
9917 return;
9918
9919}
9920
9921
9922/**---------------------------------------------------------------------------
9923 *
9924 * \brief wlan_hdd_restart_driver
9925 *
9926 * This function sends an event to supplicant to restart the WLAN driver.
9927 *
9928 * This function is called from vos_wlanRestart.
9929 *
9930 * \param - pHddCtx
9931 *
9932 * \return - VOS_STATUS_SUCCESS: Success
9933 * VOS_STATUS_E_EMPTY: Adapter is Empty
9934 * VOS_STATUS_E_ALREADY: Request already in progress
9935
9936 * --------------------------------------------------------------------------*/
9937VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
9938{
9939 VOS_STATUS status = VOS_STATUS_SUCCESS;
9940
9941 /* A tight check to make sure reentrancy */
9942 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
9943 {
Mihir Shetefd528652014-06-23 19:07:50 +05309944 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnsone7245742012-09-05 17:12:55 -07009945 "%s: WLAN restart is already in progress", __func__);
9946
9947 return VOS_STATUS_E_ALREADY;
9948 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07009949 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08009950#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07009951 wcnss_reset_intr();
9952#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07009953
Jeff Johnsone7245742012-09-05 17:12:55 -07009954 return status;
9955}
9956
Mihir Shetee1093ba2014-01-21 20:13:32 +05309957/**---------------------------------------------------------------------------
9958 *
9959 * \brief wlan_hdd_init_channels
9960 *
9961 * This function is used to initialize the channel list in CSR
9962 *
9963 * This function is called from hdd_wlan_startup
9964 *
9965 * \param - pHddCtx: HDD context
9966 *
9967 * \return - VOS_STATUS_SUCCESS: Success
9968 * VOS_STATUS_E_FAULT: Failure reported by SME
9969
9970 * --------------------------------------------------------------------------*/
9971static VOS_STATUS wlan_hdd_init_channels(hdd_context_t *pHddCtx)
9972{
9973 eHalStatus status;
9974
9975 status = sme_InitChannels(pHddCtx->hHal);
9976 if (HAL_STATUS_SUCCESS(status))
9977 {
9978 return VOS_STATUS_SUCCESS;
9979 }
9980 else
9981 {
9982 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Channel initialization failed(%d)",
9983 __func__, status);
9984 return VOS_STATUS_E_FAULT;
9985 }
9986}
9987
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05309988static VOS_STATUS wlan_hdd_init_channels_for_cc(hdd_context_t *pHddCtx)
9989{
9990 eHalStatus status;
9991
9992 status = sme_InitChannelsForCC(pHddCtx->hHal);
9993 if (HAL_STATUS_SUCCESS(status))
9994 {
9995 return VOS_STATUS_SUCCESS;
9996 }
9997 else
9998 {
9999 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Issue reg hint failed(%d)",
10000 __func__, status);
10001 return VOS_STATUS_E_FAULT;
10002 }
10003}
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -070010004/*
10005 * API to find if there is any STA or P2P-Client is connected
10006 */
10007VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
10008{
10009 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
10010}
Jeff Johnsone7245742012-09-05 17:12:55 -070010011
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053010012int wlan_hdd_scan_abort(hdd_adapter_t *pAdapter)
10013{
10014 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10015 hdd_scaninfo_t *pScanInfo = NULL;
Girish Gowli4bf7a632014-06-12 13:42:11 +053010016 long status = 0;
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053010017
10018 pScanInfo = &pHddCtx->scan_info;
10019 if (pScanInfo->mScanPending)
10020 {
10021 INIT_COMPLETION(pScanInfo->abortscan_event_var);
10022 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
10023 eCSR_SCAN_ABORT_DEFAULT);
10024
10025 status = wait_for_completion_interruptible_timeout(
10026 &pScanInfo->abortscan_event_var,
10027 msecs_to_jiffies(5000));
Girish Gowli4bf7a632014-06-12 13:42:11 +053010028 if (0 >= status)
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053010029 {
10030 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Girish Gowli4bf7a632014-06-12 13:42:11 +053010031 "%s: Timeout or Interrupt occurred while waiting for abort"
10032 "scan, status- %ld", __func__, status);
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053010033 return -ETIMEDOUT;
10034 }
10035 }
Girish Gowli4bf7a632014-06-12 13:42:11 +053010036 return 0;
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053010037}
10038
Jeff Johnson295189b2012-06-20 16:38:30 -070010039//Register the module init/exit functions
10040module_init(hdd_module_init);
10041module_exit(hdd_module_exit);
10042
10043MODULE_LICENSE("Dual BSD/GPL");
10044MODULE_AUTHOR("Qualcomm Atheros, Inc.");
10045MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
10046
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070010047module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
10048 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -070010049
Jeff Johnson76052702013-04-16 13:55:05 -070010050module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -070010051 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Arif Hussain66559122013-11-21 10:11:40 -080010052
10053module_param(enable_dfs_chan_scan, int,
10054 S_IRUSR | S_IRGRP | S_IROTH);
10055
10056module_param(enable_11d, int,
10057 S_IRUSR | S_IRGRP | S_IROTH);
10058
10059module_param(country_code, charp,
10060 S_IRUSR | S_IRGRP | S_IROTH);