blob: 81265518431bdb39062eddaf434c89f8a22a3fb6 [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{
c_hpothu39eb1e32014-06-26 16:31:50 +05301930 bcnMissRateContext_t *pCBCtx;
1931
1932 if (NULL == data)
1933 {
1934 hddLog(VOS_TRACE_LEVEL_ERROR, FL("argument data is NULL"));
1935 return;
1936 }
c_hpothu92367912014-05-01 15:18:17 +05301937
1938 /* there is a race condition that exists between this callback
1939 function and the caller since the caller could time out either
1940 before or while this code is executing. we use a spinlock to
1941 serialize these actions */
1942 spin_lock(&hdd_context_lock);
1943
c_hpothu39eb1e32014-06-26 16:31:50 +05301944 pCBCtx = (bcnMissRateContext_t *)data;
c_hpothu92367912014-05-01 15:18:17 +05301945 gbcnMissRate = -1;
1946
c_hpothu39eb1e32014-06-26 16:31:50 +05301947 if (pCBCtx->magic != BCN_MISS_RATE_CONTEXT_MAGIC)
c_hpothu92367912014-05-01 15:18:17 +05301948 {
1949 hddLog(VOS_TRACE_LEVEL_ERROR,
c_hpothu39eb1e32014-06-26 16:31:50 +05301950 FL("invalid context magic: %08x"), pCBCtx->magic);
c_hpothu92367912014-05-01 15:18:17 +05301951 spin_unlock(&hdd_context_lock);
1952 return ;
1953 }
1954
1955 if (VOS_STATUS_SUCCESS == status)
1956 {
c_hpothu39eb1e32014-06-26 16:31:50 +05301957 gbcnMissRate = bcnMissRate;
c_hpothu92367912014-05-01 15:18:17 +05301958 }
c_hpothu39eb1e32014-06-26 16:31:50 +05301959 else
1960 {
1961 hddLog(VOS_TRACE_LEVEL_ERROR, FL("failed to get bcnMissRate"));
1962 }
1963
c_hpothu92367912014-05-01 15:18:17 +05301964 complete(&(pCBCtx->completion));
1965 spin_unlock(&hdd_context_lock);
1966
1967 return;
1968}
1969
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05301970static int hdd_get_dwell_time(hdd_config_t *pCfg, tANI_U8 *command, char *extra, tANI_U8 n, tANI_U8 *len)
1971{
1972 int ret = 0;
1973
1974 if (!pCfg || !command || !extra || !len)
1975 {
1976 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1977 "%s: argument passsed for GETDWELLTIME is incorrect", __func__);
1978 ret = -EINVAL;
1979 return ret;
1980 }
1981
1982 if (strncmp(command, "GETDWELLTIME ACTIVE MAX", 23) == 0)
1983 {
1984 *len = scnprintf(extra, n, "GETDWELLTIME ACTIVE MAX %u\n",
1985 (int)pCfg->nActiveMaxChnTime);
1986 return ret;
1987 }
1988 else if (strncmp(command, "GETDWELLTIME ACTIVE MIN", 23) == 0)
1989 {
1990 *len = scnprintf(extra, n, "GETDWELLTIME ACTIVE MIN %u\n",
1991 (int)pCfg->nActiveMinChnTime);
1992 return ret;
1993 }
1994 else if (strncmp(command, "GETDWELLTIME PASSIVE MAX", 24) == 0)
1995 {
1996 *len = scnprintf(extra, n, "GETDWELLTIME PASSIVE MAX %u\n",
1997 (int)pCfg->nPassiveMaxChnTime);
1998 return ret;
1999 }
2000 else if (strncmp(command, "GETDWELLTIME PASSIVE MIN", 24) == 0)
2001 {
2002 *len = scnprintf(extra, n, "GETDWELLTIME PASSIVE MIN %u\n",
2003 (int)pCfg->nPassiveMinChnTime);
2004 return ret;
2005 }
Rajesh Babu Prathipati0fd227e2014-07-05 12:50:00 +05302006 else if (strncmp(command, "GETDWELLTIME", 12) == 0)
2007 {
2008 *len = scnprintf(extra, n, "GETDWELLTIME %u \n",
2009 (int)pCfg->nActiveMaxChnTime);
2010 return ret;
2011 }
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302012 else
2013 {
2014 ret = -EINVAL;
2015 }
2016
2017 return ret;
2018}
2019
2020static int hdd_set_dwell_time(hdd_adapter_t *pAdapter, tANI_U8 *command)
2021{
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302022 tHalHandle hHal;
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302023 hdd_config_t *pCfg;
2024 tANI_U8 *value = command;
2025 int val = 0, ret = 0, temp = 0;
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302026 tSmeConfigParams smeConfig;
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302027
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302028 if (!pAdapter || !command || !(pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini)
2029 || !(hHal = (WLAN_HDD_GET_HAL_CTX(pAdapter))))
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302030 {
2031 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2032 "%s: argument passed for SETDWELLTIME is incorrect", __func__);
2033 ret = -EINVAL;
2034 return ret;
2035 }
2036
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302037 vos_mem_zero(&smeConfig, sizeof(smeConfig));
2038 sme_GetConfigParam(hHal, &smeConfig);
2039
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302040 if (strncmp(command, "SETDWELLTIME ACTIVE MAX", 23) == 0 )
2041 {
2042 value = value + 24;
2043 temp = kstrtou32(value, 10, &val);
2044 if (temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_MIN ||
2045 val > CFG_ACTIVE_MAX_CHANNEL_TIME_MAX )
2046 {
2047 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2048 "%s: argument passed for SETDWELLTIME ACTIVE MAX is incorrect", __func__);
2049 ret = -EFAULT;
2050 return ret;
2051 }
2052 pCfg->nActiveMaxChnTime = val;
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302053 smeConfig.csrConfig.nActiveMaxChnTime = val;
2054 sme_UpdateConfig(hHal, &smeConfig);
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302055 }
2056 else if (strncmp(command, "SETDWELLTIME ACTIVE MIN", 23) == 0)
2057 {
2058 value = value + 24;
2059 temp = kstrtou32(value, 10, &val);
2060 if (temp !=0 || val < CFG_ACTIVE_MIN_CHANNEL_TIME_MIN ||
2061 val > CFG_ACTIVE_MIN_CHANNEL_TIME_MAX )
2062 {
2063 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2064 "%s: argument passsed for SETDWELLTIME ACTIVE MIN is incorrect", __func__);
2065 ret = -EFAULT;
2066 return ret;
2067 }
2068 pCfg->nActiveMinChnTime = val;
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302069 smeConfig.csrConfig.nActiveMinChnTime = val;
2070 sme_UpdateConfig(hHal, &smeConfig);
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302071 }
2072 else if (strncmp(command, "SETDWELLTIME PASSIVE MAX", 24) == 0)
2073 {
2074 value = value + 25;
2075 temp = kstrtou32(value, 10, &val);
2076 if (temp != 0 || val < CFG_PASSIVE_MAX_CHANNEL_TIME_MIN ||
2077 val > CFG_PASSIVE_MAX_CHANNEL_TIME_MAX )
2078 {
2079 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2080 "%s: argument passed for SETDWELLTIME PASSIVE MAX is incorrect", __func__);
2081 ret = -EFAULT;
2082 return ret;
2083 }
2084 pCfg->nPassiveMaxChnTime = val;
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302085 smeConfig.csrConfig.nPassiveMaxChnTime = val;
2086 sme_UpdateConfig(hHal, &smeConfig);
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302087 }
2088 else if (strncmp(command, "SETDWELLTIME PASSIVE MIN", 24) == 0)
2089 {
2090 value = value + 25;
2091 temp = kstrtou32(value, 10, &val);
2092 if (temp != 0 || val < CFG_PASSIVE_MIN_CHANNEL_TIME_MIN ||
2093 val > CFG_PASSIVE_MIN_CHANNEL_TIME_MAX )
2094 {
2095 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2096 "%s: argument passed for SETDWELLTIME PASSIVE MIN is incorrect", __func__);
2097 ret = -EFAULT;
2098 return ret;
2099 }
2100 pCfg->nPassiveMinChnTime = val;
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302101 smeConfig.csrConfig.nPassiveMinChnTime = val;
2102 sme_UpdateConfig(hHal, &smeConfig);
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302103 }
Rajesh Babu Prathipati0fd227e2014-07-05 12:50:00 +05302104 else if (strncmp(command, "SETDWELLTIME", 12) == 0)
2105 {
2106 value = value + 13;
2107 temp = kstrtou32(value, 10, &val);
2108 if (temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_MIN ||
2109 val > CFG_ACTIVE_MAX_CHANNEL_TIME_MAX )
2110 {
2111 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2112 "%s: argument passed for SETDWELLTIME is incorrect", __func__);
2113 ret = -EFAULT;
2114 return ret;
2115 }
2116 pCfg->nActiveMaxChnTime = val;
2117 smeConfig.csrConfig.nActiveMaxChnTime = val;
2118 sme_UpdateConfig(hHal, &smeConfig);
2119 }
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302120 else
2121 {
2122 ret = -EINVAL;
2123 }
2124
2125 return ret;
2126}
2127
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002128static int hdd_driver_command(hdd_adapter_t *pAdapter,
2129 hdd_priv_data_t *ppriv_data)
Jeff Johnson295189b2012-06-20 16:38:30 -07002130{
Jeff Johnson295189b2012-06-20 16:38:30 -07002131 hdd_priv_data_t priv_data;
2132 tANI_U8 *command = NULL;
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002133 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07002134
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002135 /*
2136 * Note that valid pointers are provided by caller
2137 */
Jeff Johnson295189b2012-06-20 16:38:30 -07002138
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002139 /* copy to local struct to avoid numerous changes to legacy code */
2140 priv_data = *ppriv_data;
Jeff Johnson295189b2012-06-20 16:38:30 -07002141
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002142 if (priv_data.total_len <= 0 ||
2143 priv_data.total_len > WLAN_PRIV_DATA_MAX_LEN)
Sameer Thalappil8ef3a0e2013-04-05 14:36:04 -07002144 {
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002145 hddLog(VOS_TRACE_LEVEL_WARN,
2146 "%s:invalid priv_data.total_len(%d)!!!", __func__,
2147 priv_data.total_len);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07002148 ret = -EINVAL;
2149 goto exit;
2150 }
2151
2152 /* Allocate +1 for '\0' */
2153 command = kmalloc(priv_data.total_len + 1, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07002154 if (!command)
2155 {
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002156 hddLog(VOS_TRACE_LEVEL_ERROR,
2157 "%s: failed to allocate memory", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002158 ret = -ENOMEM;
2159 goto exit;
2160 }
2161
2162 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
2163 {
2164 ret = -EFAULT;
2165 goto exit;
2166 }
2167
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002168 /* Make sure the command is NUL-terminated */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07002169 command[priv_data.total_len] = '\0';
2170
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002171 /* at one time the following block of code was conditional. braces
2172 * have been retained to avoid re-indenting the legacy code
2173 */
Jeff Johnson295189b2012-06-20 16:38:30 -07002174 {
2175 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2176
2177 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07002178 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -07002179
2180 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
2181 {
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302182 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2183 TRACE_CODE_HDD_P2P_DEV_ADDR_IOCTL,
2184 pAdapter->sessionId, (unsigned)
2185 (*(pHddCtx->p2pDeviceAddress.bytes+2)<<24 |
2186 *(pHddCtx->p2pDeviceAddress.bytes+3)<<16 |
2187 *(pHddCtx->p2pDeviceAddress.bytes+4)<<8 |
2188 *(pHddCtx->p2pDeviceAddress.bytes+5))));
Jeff Johnson295189b2012-06-20 16:38:30 -07002189 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
2190 sizeof(tSirMacAddr)))
2191 {
2192 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Arif Hussain6d2a3322013-11-17 19:50:10 -08002193 "%s: failed to copy data to user buffer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002194 ret = -EFAULT;
2195 }
2196 }
Amar Singhal0974e402013-02-12 14:27:46 -08002197 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07002198 {
Amar Singhal0974e402013-02-12 14:27:46 -08002199 tANI_U8 *ptr = command ;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002200
Jeff Johnson295189b2012-06-20 16:38:30 -07002201 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -08002202
2203 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -07002204 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07002205 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -08002206 "%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 -07002207 /* Change band request received */
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002208 ret = hdd_setBand_helper(pAdapter->dev, ptr);
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302209 if(ret != 0)
2210 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002211 "%s: failed to set band ret=%d", __func__, ret);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002212 }
Kiet Lamf040f472013-11-20 21:15:23 +05302213 else if(strncmp(command, "SETWMMPS", 8) == 0)
2214 {
2215 tANI_U8 *ptr = command;
2216 ret = hdd_wmmps_helper(pAdapter, ptr);
2217 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07002218 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
2219 {
2220 char *country_code;
2221
2222 country_code = command + 8;
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07002223
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002224 INIT_COMPLETION(pAdapter->change_country_code);
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07002225 hdd_checkandupdate_dfssetting(pAdapter, country_code);
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -07002226#ifndef CONFIG_ENABLE_LINUX_REG
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +05302227 hdd_checkandupdate_phymode(pAdapter, country_code);
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -07002228#endif
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002229 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal,
2230 (void *)(tSmeChangeCountryCallback)
2231 wlan_hdd_change_country_code_callback,
Abhishek Singha306a442013-11-07 18:39:01 +05302232 country_code, pAdapter, pHddCtx->pvosContext, eSIR_TRUE, eSIR_TRUE);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002233 if (eHAL_STATUS_SUCCESS == ret)
2234 {
2235 ret = wait_for_completion_interruptible_timeout(
2236 &pAdapter->change_country_code,
2237 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
2238 if (0 >= ret)
2239 {
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002240 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: SME while setting country code timed out %d",
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302241 __func__, ret);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002242 }
2243 }
2244 else
Jeff Johnson32d95a32012-09-10 13:15:23 -07002245 {
2246 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002247 "%s: SME Change Country code fail ret=%d", __func__, ret);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002248 ret = -EINVAL;
Jeff Johnson32d95a32012-09-10 13:15:23 -07002249 }
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002250
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07002251 }
2252 /*
2253 command should be a string having format
2254 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
2255 */
Amar Singhal0974e402013-02-12 14:27:46 -08002256 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07002257 {
Amar Singhal0974e402013-02-12 14:27:46 -08002258 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07002259
2260 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002261 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07002262
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -08002263 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -07002264 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -08002265 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
2266 {
2267 int suspend = 0;
2268 tANI_U8 *ptr = (tANI_U8*)command + 15;
2269
2270 suspend = *ptr - '0';
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302271 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2272 TRACE_CODE_HDD_SETSUSPENDMODE_IOCTL,
2273 pAdapter->sessionId, suspend));
Sameer Thalappil45931fb2013-02-01 11:18:05 -08002274 hdd_set_wlan_suspend_mode(suspend);
2275 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002276#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
2277 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
2278 {
2279 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002280 tANI_S8 rssi = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002281 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
2282 eHalStatus status = eHAL_STATUS_SUCCESS;
2283
2284 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
2285 value = value + 15;
2286
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002287 /* Convert the value from ascii to integer */
2288 ret = kstrtos8(value, 10, &rssi);
2289 if (ret < 0)
2290 {
2291 /* If the input value is greater than max value of datatype, then also
2292 kstrtou8 fails */
2293 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2294 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdafa7157d2013-10-31 10:14:22 -07002295 __func__,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002296 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
2297 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
2298 ret = -EINVAL;
2299 goto exit;
2300 }
2301
Srinivas Girigowdade697412013-02-14 16:31:48 -08002302 lookUpThreshold = abs(rssi);
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002303
Srinivas Girigowdade697412013-02-14 16:31:48 -08002304 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
2305 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
2306 {
2307 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2308 "Neighbor lookup threshold value %d is out of range"
2309 " (Min: %d Max: %d)", lookUpThreshold,
2310 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
2311 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
2312 ret = -EINVAL;
2313 goto exit;
2314 }
2315
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302316 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2317 TRACE_CODE_HDD_SETROAMTRIGGER_IOCTL,
2318 pAdapter->sessionId, lookUpThreshold));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002319 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2320 "%s: Received Command to Set Roam trigger"
2321 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
2322
2323 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
2324 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
2325 if (eHAL_STATUS_SUCCESS != status)
2326 {
2327 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2328 "%s: Failed to set roam trigger, try again", __func__);
2329 ret = -EPERM;
2330 goto exit;
2331 }
2332
2333 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
mukul sharmad6e1fdd2014-06-23 19:19:09 +05302334 pHddCtx->cfg_ini->nNeighborReassocRssiThreshold = lookUpThreshold + 5;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002335 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
2336 }
2337 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
2338 {
2339 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
2340 int rssi = (-1) * lookUpThreshold;
2341 char extra[32];
2342 tANI_U8 len = 0;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302343 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2344 TRACE_CODE_HDD_GETROAMTRIGGER_IOCTL,
2345 pAdapter->sessionId, lookUpThreshold));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002346 len = scnprintf(extra, sizeof(extra), "%s %d", command, rssi);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002347 if (copy_to_user(priv_data.buf, &extra, len + 1))
2348 {
2349 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2350 "%s: failed to copy data to user buffer", __func__);
2351 ret = -EFAULT;
2352 goto exit;
2353 }
2354 }
2355 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
2356 {
2357 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002358 tANI_U8 roamScanPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002359 tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002360
Srinivas Girigowdade697412013-02-14 16:31:48 -08002361 /* input refresh period is in terms of seconds */
2362 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
2363 value = value + 18;
2364 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002365 ret = kstrtou8(value, 10, &roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002366 if (ret < 0)
2367 {
2368 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002369 kstrtou8 fails */
Srinivas Girigowdade697412013-02-14 16:31:48 -08002370 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002371 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdade697412013-02-14 16:31:48 -08002372 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07002373 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
2374 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002375 ret = -EINVAL;
2376 goto exit;
2377 }
2378
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002379 if ((roamScanPeriod < (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000)) ||
2380 (roamScanPeriod > (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000)))
Srinivas Girigowdade697412013-02-14 16:31:48 -08002381 {
2382 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002383 "Roam scan period value %d is out of range"
2384 " (Min: %d Max: %d)", roamScanPeriod,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07002385 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
2386 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002387 ret = -EINVAL;
2388 goto exit;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302389 }
2390 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2391 TRACE_CODE_HDD_SETROAMSCANPERIOD_IOCTL,
2392 pAdapter->sessionId, roamScanPeriod));
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002393 neighborEmptyScanRefreshPeriod = roamScanPeriod * 1000;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002394
2395 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2396 "%s: Received Command to Set roam scan period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002397 " (Empty Scan refresh period) = %d", __func__, roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002398
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002399 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod;
2400 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002401 }
2402 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
2403 {
2404 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
2405 char extra[32];
2406 tANI_U8 len = 0;
2407
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302408 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2409 TRACE_CODE_HDD_GETROAMSCANPERIOD_IOCTL,
2410 pAdapter->sessionId, nEmptyScanRefreshPeriod));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002411 len = scnprintf(extra, sizeof(extra), "%s %d",
2412 "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002413 /* Returned value is in units of seconds */
2414 if (copy_to_user(priv_data.buf, &extra, len + 1))
2415 {
2416 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2417 "%s: failed to copy data to user buffer", __func__);
2418 ret = -EFAULT;
2419 goto exit;
2420 }
2421 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002422 else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0)
2423 {
2424 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002425 tANI_U8 roamScanRefreshPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002426 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002427
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002428 /* input refresh period is in terms of seconds */
2429 /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */
2430 value = value + 25;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002431
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002432 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002433 ret = kstrtou8(value, 10, &roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002434 if (ret < 0)
2435 {
2436 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002437 kstrtou8 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002438 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002439 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002440 __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002441 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
2442 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
2443 ret = -EINVAL;
2444 goto exit;
2445 }
2446
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002447 if ((roamScanRefreshPeriod < (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000)) ||
2448 (roamScanRefreshPeriod > (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000)))
2449 {
2450 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2451 "Neighbor scan results refresh period value %d is out of range"
2452 " (Min: %d Max: %d)", roamScanRefreshPeriod,
2453 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
2454 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
2455 ret = -EINVAL;
2456 goto exit;
2457 }
2458 neighborScanRefreshPeriod = roamScanRefreshPeriod * 1000;
2459
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002460 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2461 "%s: Received Command to Set roam scan refresh period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002462 " (Scan refresh period) = %d", __func__, roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002463
2464 pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod;
2465 sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
2466 }
2467 else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0)
2468 {
2469 tANI_U16 value = sme_getNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
2470 char extra[32];
2471 tANI_U8 len = 0;
2472
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002473 len = scnprintf(extra, sizeof(extra), "%s %d",
2474 "GETROAMSCANREFRESHPERIOD", (value/1000));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002475 /* Returned value is in units of seconds */
2476 if (copy_to_user(priv_data.buf, &extra, len + 1))
2477 {
2478 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2479 "%s: failed to copy data to user buffer", __func__);
2480 ret = -EFAULT;
2481 goto exit;
2482 }
2483 }
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07002484#ifdef FEATURE_WLAN_LFR
2485 /* SETROAMMODE */
2486 else if (strncmp(command, "SETROAMMODE", SIZE_OF_SETROAMMODE) == 0)
2487 {
2488 tANI_U8 *value = command;
2489 tANI_BOOLEAN roamMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
2490
2491 /* Move pointer to ahead of SETROAMMODE<delimiter> */
2492 value = value + SIZE_OF_SETROAMMODE + 1;
2493
2494 /* Convert the value from ascii to integer */
2495 ret = kstrtou8(value, SIZE_OF_SETROAMMODE, &roamMode);
2496 if (ret < 0)
2497 {
2498 /* If the input value is greater than max value of datatype, then also
2499 kstrtou8 fails */
2500 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2501 "%s: kstrtou8 failed range [%d - %d]", __func__,
2502 CFG_LFR_FEATURE_ENABLED_MIN,
2503 CFG_LFR_FEATURE_ENABLED_MAX);
2504 ret = -EINVAL;
2505 goto exit;
2506 }
2507 if ((roamMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
2508 (roamMode > CFG_LFR_FEATURE_ENABLED_MAX))
2509 {
2510 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2511 "Roam Mode value %d is out of range"
2512 " (Min: %d Max: %d)", roamMode,
2513 CFG_LFR_FEATURE_ENABLED_MIN,
2514 CFG_LFR_FEATURE_ENABLED_MAX);
2515 ret = -EINVAL;
2516 goto exit;
2517 }
2518
2519 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2520 "%s: Received Command to Set Roam Mode = %d", __func__, roamMode);
2521 /*
2522 * Note that
2523 * SETROAMMODE 0 is to enable LFR while
2524 * SETROAMMODE 1 is to disable LFR, but
2525 * NotifyIsFastRoamIniFeatureEnabled 0/1 is to enable/disable.
2526 * So, we have to invert the value to call sme_UpdateIsFastRoamIniFeatureEnabled.
2527 */
2528 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
2529 roamMode = CFG_LFR_FEATURE_ENABLED_MAX; /* Roam enable */
2530 else
2531 roamMode = CFG_LFR_FEATURE_ENABLED_MIN; /* Roam disable */
2532
2533 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = roamMode;
2534 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), roamMode);
2535 }
2536 /* GETROAMMODE */
2537 else if (strncmp(priv_data.buf, "GETROAMMODE", SIZE_OF_GETROAMMODE) == 0)
2538 {
2539 tANI_BOOLEAN roamMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2540 char extra[32];
2541 tANI_U8 len = 0;
2542
2543 /*
2544 * roamMode value shall be inverted because the sementics is different.
2545 */
2546 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
2547 roamMode = CFG_LFR_FEATURE_ENABLED_MAX;
2548 else
2549 roamMode = CFG_LFR_FEATURE_ENABLED_MIN;
2550
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002551 len = scnprintf(extra, sizeof(extra), "%s %d", command, roamMode);
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07002552 if (copy_to_user(priv_data.buf, &extra, len + 1))
2553 {
2554 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2555 "%s: failed to copy data to user buffer", __func__);
2556 ret = -EFAULT;
2557 goto exit;
2558 }
2559 }
2560#endif
Srinivas Girigowdade697412013-02-14 16:31:48 -08002561#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002562#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -08002563 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
2564 {
2565 tANI_U8 *value = command;
2566 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
2567
2568 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
2569 value = value + 13;
2570 /* Convert the value from ascii to integer */
2571 ret = kstrtou8(value, 10, &roamRssiDiff);
2572 if (ret < 0)
2573 {
2574 /* If the input value is greater than max value of datatype, then also
2575 kstrtou8 fails */
2576 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2577 "%s: kstrtou8 failed range [%d - %d]", __func__,
2578 CFG_ROAM_RSSI_DIFF_MIN,
2579 CFG_ROAM_RSSI_DIFF_MAX);
2580 ret = -EINVAL;
2581 goto exit;
2582 }
2583
2584 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
2585 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
2586 {
2587 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2588 "Roam rssi diff value %d is out of range"
2589 " (Min: %d Max: %d)", roamRssiDiff,
2590 CFG_ROAM_RSSI_DIFF_MIN,
2591 CFG_ROAM_RSSI_DIFF_MAX);
2592 ret = -EINVAL;
2593 goto exit;
2594 }
2595
2596 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2597 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
2598
2599 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
2600 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
2601 }
2602 else if (strncmp(priv_data.buf, "GETROAMDELTA", 12) == 0)
2603 {
2604 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
2605 char extra[32];
2606 tANI_U8 len = 0;
2607
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302608 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2609 TRACE_CODE_HDD_GETROAMDELTA_IOCTL,
2610 pAdapter->sessionId, roamRssiDiff));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002611 len = scnprintf(extra, sizeof(extra), "%s %d",
2612 command, roamRssiDiff);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002613 if (copy_to_user(priv_data.buf, &extra, len + 1))
2614 {
2615 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2616 "%s: failed to copy data to user buffer", __func__);
2617 ret = -EFAULT;
2618 goto exit;
2619 }
2620 }
2621#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002622#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -08002623 else if (strncmp(command, "GETBAND", 7) == 0)
2624 {
2625 int band = -1;
2626 char extra[32];
2627 tANI_U8 len = 0;
2628 hdd_getBand_helper(pHddCtx, &band);
2629
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302630 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2631 TRACE_CODE_HDD_GETBAND_IOCTL,
2632 pAdapter->sessionId, band));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002633 len = scnprintf(extra, sizeof(extra), "%s %d", command, band);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002634 if (copy_to_user(priv_data.buf, &extra, len + 1))
2635 {
2636 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2637 "%s: failed to copy data to user buffer", __func__);
2638 ret = -EFAULT;
2639 goto exit;
2640 }
2641 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002642 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
2643 {
2644 tANI_U8 *value = command;
2645 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2646 tANI_U8 numChannels = 0;
2647 eHalStatus status = eHAL_STATUS_SUCCESS;
2648
2649 status = hdd_parse_channellist(value, ChannelList, &numChannels);
2650 if (eHAL_STATUS_SUCCESS != status)
2651 {
2652 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2653 "%s: Failed to parse channel list information", __func__);
2654 ret = -EINVAL;
2655 goto exit;
2656 }
2657
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302658 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2659 TRACE_CODE_HDD_SETROAMSCANCHANNELS_IOCTL,
2660 pAdapter->sessionId, numChannels));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002661 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
2662 {
2663 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2664 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
2665 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
2666 ret = -EINVAL;
2667 goto exit;
2668 }
2669 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
2670 numChannels);
2671 if (eHAL_STATUS_SUCCESS != status)
2672 {
2673 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2674 "%s: Failed to update channel list information", __func__);
2675 ret = -EINVAL;
2676 goto exit;
2677 }
2678 }
2679 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
2680 {
2681 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2682 tANI_U8 numChannels = 0;
Jeff Johnson51b67782013-04-05 12:35:41 -07002683 tANI_U8 j = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002684 char extra[128] = {0};
Jeff Johnson51b67782013-04-05 12:35:41 -07002685 int len;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002686
2687 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
2688 ChannelList, &numChannels ))
2689 {
2690 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2691 "%s: failed to get roam scan channel list", __func__);
2692 ret = -EFAULT;
2693 goto exit;
2694 }
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302695 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2696 TRACE_CODE_HDD_GETROAMSCANCHANNELS_IOCTL,
2697 pAdapter->sessionId, numChannels));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002698 /* output channel list is of the format
2699 [Number of roam scan channels][Channel1][Channel2]... */
2700 /* copy the number of channels in the 0th index */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002701 len = scnprintf(extra, sizeof(extra), "%s %d", command, numChannels);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002702 for (j = 0; (j < numChannels); j++)
2703 {
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002704 len += scnprintf(extra + len, sizeof(extra) - len, " %d",
2705 ChannelList[j]);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002706 }
2707
2708 if (copy_to_user(priv_data.buf, &extra, len + 1))
2709 {
2710 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2711 "%s: failed to copy data to user buffer", __func__);
2712 ret = -EFAULT;
2713 goto exit;
2714 }
2715 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002716 else if (strncmp(command, "GETCCXMODE", 10) == 0)
2717 {
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002718 tANI_BOOLEAN eseMode = sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002719 char extra[32];
2720 tANI_U8 len = 0;
2721
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002722 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002723 then this operation is not permitted (return FAILURE) */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002724 if (eseMode &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002725 hdd_is_okc_mode_enabled(pHddCtx) &&
2726 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2727 {
2728 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002729 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002730 " hence this operation is not permitted!", __func__);
2731 ret = -EPERM;
2732 goto exit;
2733 }
2734
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002735 len = scnprintf(extra, sizeof(extra), "%s %d",
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002736 "GETCCXMODE", eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002737 if (copy_to_user(priv_data.buf, &extra, len + 1))
2738 {
2739 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2740 "%s: failed to copy data to user buffer", __func__);
2741 ret = -EFAULT;
2742 goto exit;
2743 }
2744 }
2745 else if (strncmp(command, "GETOKCMODE", 10) == 0)
2746 {
2747 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
2748 char extra[32];
2749 tANI_U8 len = 0;
2750
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002751 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002752 then this operation is not permitted (return FAILURE) */
2753 if (okcMode &&
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002754 sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002755 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2756 {
2757 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002758 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002759 " hence this operation is not permitted!", __func__);
2760 ret = -EPERM;
2761 goto exit;
2762 }
2763
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002764 len = scnprintf(extra, sizeof(extra), "%s %d",
2765 "GETOKCMODE", okcMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002766 if (copy_to_user(priv_data.buf, &extra, len + 1))
2767 {
2768 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2769 "%s: failed to copy data to user buffer", __func__);
2770 ret = -EFAULT;
2771 goto exit;
2772 }
2773 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002774 else if (strncmp(command, "GETFASTROAM", 11) == 0)
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002775 {
2776 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2777 char extra[32];
2778 tANI_U8 len = 0;
2779
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002780 len = scnprintf(extra, sizeof(extra), "%s %d",
2781 "GETFASTROAM", lfrMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002782 if (copy_to_user(priv_data.buf, &extra, len + 1))
2783 {
2784 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2785 "%s: failed to copy data to user buffer", __func__);
2786 ret = -EFAULT;
2787 goto exit;
2788 }
2789 }
2790 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
2791 {
2792 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2793 char extra[32];
2794 tANI_U8 len = 0;
2795
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002796 len = scnprintf(extra, sizeof(extra), "%s %d",
2797 "GETFASTTRANSITION", ft);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002798 if (copy_to_user(priv_data.buf, &extra, len + 1))
2799 {
2800 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2801 "%s: failed to copy data to user buffer", __func__);
2802 ret = -EFAULT;
2803 goto exit;
2804 }
2805 }
2806 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
2807 {
2808 tANI_U8 *value = command;
2809 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
2810
2811 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
2812 value = value + 26;
2813 /* Convert the value from ascii to integer */
2814 ret = kstrtou8(value, 10, &minTime);
2815 if (ret < 0)
2816 {
2817 /* If the input value is greater than max value of datatype, then also
2818 kstrtou8 fails */
2819 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2820 "%s: kstrtou8 failed range [%d - %d]", __func__,
2821 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
2822 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
2823 ret = -EINVAL;
2824 goto exit;
2825 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002826 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
2827 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
2828 {
2829 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2830 "scan min channel time value %d is out of range"
2831 " (Min: %d Max: %d)", minTime,
2832 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
2833 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
2834 ret = -EINVAL;
2835 goto exit;
2836 }
2837
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302838 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2839 TRACE_CODE_HDD_SETROAMSCANCHANNELMINTIME_IOCTL,
2840 pAdapter->sessionId, minTime));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002841 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2842 "%s: Received Command to change channel min time = %d", __func__, minTime);
2843
2844 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
2845 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
2846 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002847 else if (strncmp(command, "SENDACTIONFRAME", 15) == 0)
2848 {
2849 tANI_U8 *value = command;
2850 tANI_U8 channel = 0;
2851 tANI_U8 dwellTime = 0;
2852 tANI_U8 bufLen = 0;
2853 tANI_U8 *buf = NULL;
2854 tSirMacAddr targetApBssid;
2855 eHalStatus status = eHAL_STATUS_SUCCESS;
2856 struct ieee80211_channel chan;
2857 tANI_U8 finalLen = 0;
2858 tANI_U8 *finalBuf = NULL;
2859 tANI_U8 temp = 0;
2860 u64 cookie;
2861 hdd_station_ctx_t *pHddStaCtx = NULL;
2862 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2863
2864 /* if not associated, no need to send action frame */
2865 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2866 {
2867 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2868 ret = -EINVAL;
2869 goto exit;
2870 }
2871
2872 status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel,
2873 &dwellTime, &buf, &bufLen);
2874 if (eHAL_STATUS_SUCCESS != status)
2875 {
2876 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2877 "%s: Failed to parse send action frame data", __func__);
2878 ret = -EINVAL;
2879 goto exit;
2880 }
2881
2882 /* if the target bssid is different from currently associated AP,
2883 then no need to send action frame */
2884 if (VOS_TRUE != vos_mem_compare(targetApBssid,
2885 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2886 {
2887 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__);
2888 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002889 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002890 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002891 goto exit;
2892 }
2893
2894 /* if the channel number is different from operating channel then
2895 no need to send action frame */
2896 if (channel != pHddStaCtx->conn_info.operationChannel)
2897 {
2898 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2899 "%s: channel(%d) is different from operating channel(%d)",
2900 __func__, channel, pHddStaCtx->conn_info.operationChannel);
2901 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002902 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002903 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002904 goto exit;
2905 }
2906 chan.center_freq = sme_ChnToFreq(channel);
2907
2908 finalLen = bufLen + 24;
2909 finalBuf = vos_mem_malloc(finalLen);
2910 if (NULL == finalBuf)
2911 {
2912 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__);
2913 ret = -ENOMEM;
Jeff Johnson11c33152013-04-16 17:52:40 -07002914 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002915 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002916 goto exit;
2917 }
2918 vos_mem_zero(finalBuf, finalLen);
2919
2920 /* Fill subtype */
2921 temp = SIR_MAC_MGMT_ACTION << 4;
2922 vos_mem_copy(finalBuf + 0, &temp, sizeof(temp));
2923
2924 /* Fill type */
2925 temp = SIR_MAC_MGMT_FRAME;
2926 vos_mem_copy(finalBuf + 2, &temp, sizeof(temp));
2927
2928 /* Fill destination address (bssid of the AP) */
2929 vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid));
2930
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07002931 /* Fill source address (STA mac address) */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002932 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
2933
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07002934 /* Fill BSSID (AP mac address) */
2935 vos_mem_copy(finalBuf + 16, targetApBssid, sizeof(targetApBssid));
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002936
2937 /* Fill received buffer from 24th address */
2938 vos_mem_copy(finalBuf + 24, buf, bufLen);
2939
Jeff Johnson11c33152013-04-16 17:52:40 -07002940 /* done with the parsed buffer */
2941 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002942 buf = NULL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002943
DARAM SUDHA39eede62014-02-12 11:16:40 +05302944 wlan_hdd_mgmt_tx( NULL,
Yue Maf49ba872013-08-19 12:04:25 -07002945#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2946 &(pAdapter->wdev),
2947#else
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002948 pAdapter->dev,
Yue Maf49ba872013-08-19 12:04:25 -07002949#endif
2950 &chan, 0,
2951#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
2952 NL80211_CHAN_HT20, 1,
2953#endif
2954 dwellTime, finalBuf, finalLen, 1,
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002955 1, &cookie );
2956 vos_mem_free(finalBuf);
2957 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002958 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
2959 {
2960 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
2961 char extra[32];
2962 tANI_U8 len = 0;
2963
2964 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002965 len = scnprintf(extra, sizeof(extra), "%s %d",
2966 "GETROAMSCANCHANNELMINTIME", val);
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302967 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2968 TRACE_CODE_HDD_GETROAMSCANCHANNELMINTIME_IOCTL,
2969 pAdapter->sessionId, val));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002970 if (copy_to_user(priv_data.buf, &extra, len + 1))
2971 {
2972 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2973 "%s: failed to copy data to user buffer", __func__);
2974 ret = -EFAULT;
2975 goto exit;
2976 }
2977 }
2978 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
2979 {
2980 tANI_U8 *value = command;
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002981 tANI_U16 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002982
2983 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
2984 value = value + 19;
2985 /* Convert the value from ascii to integer */
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002986 ret = kstrtou16(value, 10, &maxTime);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002987 if (ret < 0)
2988 {
2989 /* If the input value is greater than max value of datatype, then also
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002990 kstrtou16 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002991 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002992 "%s: kstrtou16 failed range [%d - %d]", __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002993 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
2994 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
2995 ret = -EINVAL;
2996 goto exit;
2997 }
2998
2999 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
3000 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
3001 {
3002 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3003 "lfr mode value %d is out of range"
3004 " (Min: %d Max: %d)", maxTime,
3005 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
3006 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
3007 ret = -EINVAL;
3008 goto exit;
3009 }
3010
3011 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3012 "%s: Received Command to change channel max time = %d", __func__, maxTime);
3013
3014 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
3015 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
3016 }
3017 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
3018 {
3019 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
3020 char extra[32];
3021 tANI_U8 len = 0;
3022
3023 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003024 len = scnprintf(extra, sizeof(extra), "%s %d",
3025 "GETSCANCHANNELTIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003026 if (copy_to_user(priv_data.buf, &extra, len + 1))
3027 {
3028 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3029 "%s: failed to copy data to user buffer", __func__);
3030 ret = -EFAULT;
3031 goto exit;
3032 }
3033 }
3034 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
3035 {
3036 tANI_U8 *value = command;
3037 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
3038
3039 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
3040 value = value + 16;
3041 /* Convert the value from ascii to integer */
3042 ret = kstrtou16(value, 10, &val);
3043 if (ret < 0)
3044 {
3045 /* If the input value is greater than max value of datatype, then also
3046 kstrtou16 fails */
3047 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3048 "%s: kstrtou16 failed range [%d - %d]", __func__,
3049 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
3050 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
3051 ret = -EINVAL;
3052 goto exit;
3053 }
3054
3055 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
3056 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
3057 {
3058 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3059 "scan home time value %d is out of range"
3060 " (Min: %d Max: %d)", val,
3061 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
3062 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
3063 ret = -EINVAL;
3064 goto exit;
3065 }
3066
3067 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3068 "%s: Received Command to change scan home time = %d", __func__, val);
3069
3070 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
3071 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
3072 }
3073 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
3074 {
3075 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
3076 char extra[32];
3077 tANI_U8 len = 0;
3078
3079 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003080 len = scnprintf(extra, sizeof(extra), "%s %d",
3081 "GETSCANHOMETIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003082 if (copy_to_user(priv_data.buf, &extra, len + 1))
3083 {
3084 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3085 "%s: failed to copy data to user buffer", __func__);
3086 ret = -EFAULT;
3087 goto exit;
3088 }
3089 }
3090 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
3091 {
3092 tANI_U8 *value = command;
3093 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
3094
3095 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
3096 value = value + 17;
3097 /* Convert the value from ascii to integer */
3098 ret = kstrtou8(value, 10, &val);
3099 if (ret < 0)
3100 {
3101 /* If the input value is greater than max value of datatype, then also
3102 kstrtou8 fails */
3103 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3104 "%s: kstrtou8 failed range [%d - %d]", __func__,
3105 CFG_ROAM_INTRA_BAND_MIN,
3106 CFG_ROAM_INTRA_BAND_MAX);
3107 ret = -EINVAL;
3108 goto exit;
3109 }
3110
3111 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
3112 (val > CFG_ROAM_INTRA_BAND_MAX))
3113 {
3114 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3115 "intra band mode value %d is out of range"
3116 " (Min: %d Max: %d)", val,
3117 CFG_ROAM_INTRA_BAND_MIN,
3118 CFG_ROAM_INTRA_BAND_MAX);
3119 ret = -EINVAL;
3120 goto exit;
3121 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003122 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3123 "%s: Received Command to change intra band = %d", __func__, val);
3124
3125 pHddCtx->cfg_ini->nRoamIntraBand = val;
3126 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
3127 }
3128 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
3129 {
3130 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
3131 char extra[32];
3132 tANI_U8 len = 0;
3133
3134 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003135 len = scnprintf(extra, sizeof(extra), "%s %d",
3136 "GETROAMINTRABAND", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003137 if (copy_to_user(priv_data.buf, &extra, len + 1))
3138 {
3139 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3140 "%s: failed to copy data to user buffer", __func__);
3141 ret = -EFAULT;
3142 goto exit;
3143 }
3144 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003145 else if (strncmp(command, "SETSCANNPROBES", 14) == 0)
3146 {
3147 tANI_U8 *value = command;
3148 tANI_U8 nProbes = CFG_ROAM_SCAN_N_PROBES_DEFAULT;
3149
3150 /* Move pointer to ahead of SETSCANNPROBES<delimiter> */
3151 value = value + 15;
3152 /* Convert the value from ascii to integer */
3153 ret = kstrtou8(value, 10, &nProbes);
3154 if (ret < 0)
3155 {
3156 /* If the input value is greater than max value of datatype, then also
3157 kstrtou8 fails */
3158 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3159 "%s: kstrtou8 failed range [%d - %d]", __func__,
3160 CFG_ROAM_SCAN_N_PROBES_MIN,
3161 CFG_ROAM_SCAN_N_PROBES_MAX);
3162 ret = -EINVAL;
3163 goto exit;
3164 }
3165
3166 if ((nProbes < CFG_ROAM_SCAN_N_PROBES_MIN) ||
3167 (nProbes > CFG_ROAM_SCAN_N_PROBES_MAX))
3168 {
3169 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3170 "NProbes value %d is out of range"
3171 " (Min: %d Max: %d)", nProbes,
3172 CFG_ROAM_SCAN_N_PROBES_MIN,
3173 CFG_ROAM_SCAN_N_PROBES_MAX);
3174 ret = -EINVAL;
3175 goto exit;
3176 }
3177
3178 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3179 "%s: Received Command to Set nProbes = %d", __func__, nProbes);
3180
3181 pHddCtx->cfg_ini->nProbes = nProbes;
3182 sme_UpdateRoamScanNProbes((tHalHandle)(pHddCtx->hHal), nProbes);
3183 }
3184 else if (strncmp(priv_data.buf, "GETSCANNPROBES", 14) == 0)
3185 {
3186 tANI_U8 val = sme_getRoamScanNProbes((tHalHandle)(pHddCtx->hHal));
3187 char extra[32];
3188 tANI_U8 len = 0;
3189
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003190 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003191 if (copy_to_user(priv_data.buf, &extra, len + 1))
3192 {
3193 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3194 "%s: failed to copy data to user buffer", __func__);
3195 ret = -EFAULT;
3196 goto exit;
3197 }
3198 }
3199 else if (strncmp(command, "SETSCANHOMEAWAYTIME", 19) == 0)
3200 {
3201 tANI_U8 *value = command;
3202 tANI_U16 homeAwayTime = CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT;
3203
3204 /* Move pointer to ahead of SETSCANHOMEAWAYTIME<delimiter> */
3205 /* input value is in units of msec */
3206 value = value + 20;
3207 /* Convert the value from ascii to integer */
3208 ret = kstrtou16(value, 10, &homeAwayTime);
3209 if (ret < 0)
3210 {
3211 /* If the input value is greater than max value of datatype, then also
3212 kstrtou8 fails */
3213 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3214 "%s: kstrtou8 failed range [%d - %d]", __func__,
3215 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
3216 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
3217 ret = -EINVAL;
3218 goto exit;
3219 }
3220
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003221 if ((homeAwayTime < CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN) ||
3222 (homeAwayTime > CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX))
3223 {
3224 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3225 "homeAwayTime value %d is out of range"
3226 " (Min: %d Max: %d)", homeAwayTime,
3227 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
3228 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
3229 ret = -EINVAL;
3230 goto exit;
3231 }
3232
3233 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3234 "%s: Received Command to Set scan away time = %d", __func__, homeAwayTime);
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07003235 if (pHddCtx->cfg_ini->nRoamScanHomeAwayTime != homeAwayTime)
3236 {
3237 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
3238 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_TRUE);
3239 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003240 }
3241 else if (strncmp(priv_data.buf, "GETSCANHOMEAWAYTIME", 19) == 0)
3242 {
3243 tANI_U16 val = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
3244 char extra[32];
3245 tANI_U8 len = 0;
3246
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003247 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003248 if (copy_to_user(priv_data.buf, &extra, len + 1))
3249 {
3250 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3251 "%s: failed to copy data to user buffer", __func__);
3252 ret = -EFAULT;
3253 goto exit;
3254 }
3255 }
3256 else if (strncmp(command, "REASSOC", 7) == 0)
3257 {
3258 tANI_U8 *value = command;
3259 tANI_U8 channel = 0;
3260 tSirMacAddr targetApBssid;
3261 eHalStatus status = eHAL_STATUS_SUCCESS;
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07003262#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
3263 tCsrHandoffRequest handoffInfo;
3264#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003265 hdd_station_ctx_t *pHddStaCtx = NULL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003266 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3267
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003268 /* if not associated, no need to proceed with reassoc */
3269 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3270 {
3271 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
3272 ret = -EINVAL;
3273 goto exit;
3274 }
3275
3276 status = hdd_parse_reassoc_command_data(value, targetApBssid, &channel);
3277 if (eHAL_STATUS_SUCCESS != status)
3278 {
3279 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3280 "%s: Failed to parse reassoc command data", __func__);
3281 ret = -EINVAL;
3282 goto exit;
3283 }
3284
3285 /* if the target bssid is same as currently associated AP,
3286 then no need to proceed with reassoc */
3287 if (VOS_TRUE == vos_mem_compare(targetApBssid,
3288 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
3289 {
3290 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Reassoc BSSID is same as currently associated AP bssid",__func__);
3291 ret = -EINVAL;
3292 goto exit;
3293 }
3294
3295 /* Check channel number is a valid channel number */
3296 if(VOS_STATUS_SUCCESS !=
3297 wlan_hdd_validate_operation_channel(pAdapter, channel))
3298 {
3299 hddLog(VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08003300 "%s: Invalid Channel [%d]", __func__, channel);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003301 return -EINVAL;
3302 }
3303
3304 /* Proceed with reassoc */
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07003305#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
3306 handoffInfo.channel = channel;
3307 vos_mem_copy(handoffInfo.bssid, targetApBssid, sizeof(tSirMacAddr));
3308 sme_HandoffRequest(pHddCtx->hHal, &handoffInfo);
3309#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003310 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07003311 else if (strncmp(command, "SETWESMODE", 10) == 0)
3312 {
3313 tANI_U8 *value = command;
3314 tANI_BOOLEAN wesMode = CFG_ENABLE_WES_MODE_NAME_DEFAULT;
3315
3316 /* Move pointer to ahead of SETWESMODE<delimiter> */
3317 value = value + 11;
3318 /* Convert the value from ascii to integer */
3319 ret = kstrtou8(value, 10, &wesMode);
3320 if (ret < 0)
3321 {
3322 /* If the input value is greater than max value of datatype, then also
3323 kstrtou8 fails */
3324 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3325 "%s: kstrtou8 failed range [%d - %d]", __func__,
3326 CFG_ENABLE_WES_MODE_NAME_MIN,
3327 CFG_ENABLE_WES_MODE_NAME_MAX);
3328 ret = -EINVAL;
3329 goto exit;
3330 }
3331
3332 if ((wesMode < CFG_ENABLE_WES_MODE_NAME_MIN) ||
3333 (wesMode > CFG_ENABLE_WES_MODE_NAME_MAX))
3334 {
3335 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3336 "WES Mode value %d is out of range"
3337 " (Min: %d Max: %d)", wesMode,
3338 CFG_ENABLE_WES_MODE_NAME_MIN,
3339 CFG_ENABLE_WES_MODE_NAME_MAX);
3340 ret = -EINVAL;
3341 goto exit;
3342 }
3343 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3344 "%s: Received Command to Set WES Mode rssi diff = %d", __func__, wesMode);
3345
3346 pHddCtx->cfg_ini->isWESModeEnabled = wesMode;
3347 sme_UpdateWESMode((tHalHandle)(pHddCtx->hHal), wesMode);
3348 }
3349 else if (strncmp(priv_data.buf, "GETWESMODE", 10) == 0)
3350 {
3351 tANI_BOOLEAN wesMode = sme_GetWESMode((tHalHandle)(pHddCtx->hHal));
3352 char extra[32];
3353 tANI_U8 len = 0;
3354
Arif Hussain826d9412013-11-12 16:44:54 -08003355 len = scnprintf(extra, sizeof(extra), "%s %d", command, wesMode);
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07003356 if (copy_to_user(priv_data.buf, &extra, len + 1))
3357 {
3358 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3359 "%s: failed to copy data to user buffer", __func__);
3360 ret = -EFAULT;
3361 goto exit;
3362 }
3363 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003364#endif /* WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_ESE || FEATURE_WLAN_LFR */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003365#ifdef FEATURE_WLAN_LFR
3366 else if (strncmp(command, "SETFASTROAM", 11) == 0)
3367 {
3368 tANI_U8 *value = command;
3369 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
3370
3371 /* Move pointer to ahead of SETFASTROAM<delimiter> */
3372 value = value + 12;
3373 /* Convert the value from ascii to integer */
3374 ret = kstrtou8(value, 10, &lfrMode);
3375 if (ret < 0)
3376 {
3377 /* If the input value is greater than max value of datatype, then also
3378 kstrtou8 fails */
3379 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3380 "%s: kstrtou8 failed range [%d - %d]", __func__,
3381 CFG_LFR_FEATURE_ENABLED_MIN,
3382 CFG_LFR_FEATURE_ENABLED_MAX);
3383 ret = -EINVAL;
3384 goto exit;
3385 }
3386
3387 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
3388 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
3389 {
3390 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3391 "lfr mode value %d is out of range"
3392 " (Min: %d Max: %d)", lfrMode,
3393 CFG_LFR_FEATURE_ENABLED_MIN,
3394 CFG_LFR_FEATURE_ENABLED_MAX);
3395 ret = -EINVAL;
3396 goto exit;
3397 }
3398
3399 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3400 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
3401
3402 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
3403 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
3404 }
3405#endif
3406#ifdef WLAN_FEATURE_VOWIFI_11R
3407 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
3408 {
3409 tANI_U8 *value = command;
3410 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
3411
3412 /* Move pointer to ahead of SETFASTROAM<delimiter> */
3413 value = value + 18;
3414 /* Convert the value from ascii to integer */
3415 ret = kstrtou8(value, 10, &ft);
3416 if (ret < 0)
3417 {
3418 /* If the input value is greater than max value of datatype, then also
3419 kstrtou8 fails */
3420 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3421 "%s: kstrtou8 failed range [%d - %d]", __func__,
3422 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
3423 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
3424 ret = -EINVAL;
3425 goto exit;
3426 }
3427
3428 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
3429 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
3430 {
3431 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3432 "ft mode value %d is out of range"
3433 " (Min: %d Max: %d)", ft,
3434 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
3435 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
3436 ret = -EINVAL;
3437 goto exit;
3438 }
3439
3440 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3441 "%s: Received Command to change ft mode = %d", __func__, ft);
3442
3443 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
3444 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
3445 }
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05303446
3447 else if (strncmp(command, "FASTREASSOC", 11) == 0)
3448 {
3449 tANI_U8 *value = command;
3450 tSirMacAddr targetApBssid;
3451 tANI_U8 trigger = 0;
3452 eHalStatus status = eHAL_STATUS_SUCCESS;
3453 hdd_station_ctx_t *pHddStaCtx = NULL;
3454 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3455
3456 /* if not associated, no need to proceed with reassoc */
3457 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3458 {
3459 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
3460 ret = -EINVAL;
3461 goto exit;
3462 }
3463
3464 status = hdd_parse_reassoc_command_data(value, targetApBssid, &trigger);
3465 if (eHAL_STATUS_SUCCESS != status)
3466 {
3467 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3468 "%s: Failed to parse reassoc command data", __func__);
3469 ret = -EINVAL;
3470 goto exit;
3471 }
3472
3473 /* if the target bssid is same as currently associated AP,
3474 then no need to proceed with reassoc */
3475 if (VOS_TRUE == vos_mem_compare(targetApBssid,
3476 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
3477 {
3478 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3479 "%s:11r Reassoc BSSID is same as currently associated AP bssid",
3480 __func__);
3481 ret = -EINVAL;
3482 goto exit;
3483 }
3484
3485 /* Proceed with scan/roam */
3486 smeIssueFastRoamNeighborAPEvent(WLAN_HDD_GET_HAL_CTX(pAdapter),
3487 &targetApBssid[0],
3488 (tSmeFastRoamTrigger)(trigger));
3489 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003490#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003491#ifdef FEATURE_WLAN_ESE
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003492 else if (strncmp(command, "SETCCXMODE", 10) == 0)
3493 {
3494 tANI_U8 *value = command;
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003495 tANI_U8 eseMode = CFG_ESE_FEATURE_ENABLED_DEFAULT;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003496
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003497 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003498 then this operation is not permitted (return FAILURE) */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003499 if (sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003500 hdd_is_okc_mode_enabled(pHddCtx) &&
3501 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
3502 {
3503 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003504 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003505 " hence this operation is not permitted!", __func__);
3506 ret = -EPERM;
3507 goto exit;
3508 }
3509
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003510 /* Move pointer to ahead of SETCCXMODE<delimiter> */
3511 value = value + 11;
3512 /* Convert the value from ascii to integer */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003513 ret = kstrtou8(value, 10, &eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003514 if (ret < 0)
3515 {
3516 /* If the input value is greater than max value of datatype, then also
3517 kstrtou8 fails */
3518 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3519 "%s: kstrtou8 failed range [%d - %d]", __func__,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003520 CFG_ESE_FEATURE_ENABLED_MIN,
3521 CFG_ESE_FEATURE_ENABLED_MAX);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003522 ret = -EINVAL;
3523 goto exit;
3524 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003525 if ((eseMode < CFG_ESE_FEATURE_ENABLED_MIN) ||
3526 (eseMode > CFG_ESE_FEATURE_ENABLED_MAX))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003527 {
3528 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003529 "Ese mode value %d is out of range"
3530 " (Min: %d Max: %d)", eseMode,
3531 CFG_ESE_FEATURE_ENABLED_MIN,
3532 CFG_ESE_FEATURE_ENABLED_MAX);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003533 ret = -EINVAL;
3534 goto exit;
3535 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003536 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003537 "%s: Received Command to change ese mode = %d", __func__, eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003538
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003539 pHddCtx->cfg_ini->isEseIniFeatureEnabled = eseMode;
3540 sme_UpdateIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal), eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003541 }
3542#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003543 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
3544 {
3545 tANI_U8 *value = command;
3546 tANI_BOOLEAN roamScanControl = 0;
3547
3548 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
3549 value = value + 19;
3550 /* Convert the value from ascii to integer */
3551 ret = kstrtou8(value, 10, &roamScanControl);
3552 if (ret < 0)
3553 {
3554 /* If the input value is greater than max value of datatype, then also
3555 kstrtou8 fails */
3556 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3557 "%s: kstrtou8 failed ", __func__);
3558 ret = -EINVAL;
3559 goto exit;
3560 }
3561
3562 if (0 != roamScanControl)
3563 {
3564 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3565 "roam scan control invalid value = %d",
3566 roamScanControl);
3567 ret = -EINVAL;
3568 goto exit;
3569 }
3570 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3571 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
3572
3573 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
3574 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003575#ifdef FEATURE_WLAN_OKC
3576 else if (strncmp(command, "SETOKCMODE", 10) == 0)
3577 {
3578 tANI_U8 *value = command;
3579 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
3580
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003581 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003582 then this operation is not permitted (return FAILURE) */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003583 if (sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003584 hdd_is_okc_mode_enabled(pHddCtx) &&
3585 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
3586 {
3587 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003588 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003589 " hence this operation is not permitted!", __func__);
3590 ret = -EPERM;
3591 goto exit;
3592 }
3593
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003594 /* Move pointer to ahead of SETOKCMODE<delimiter> */
3595 value = value + 11;
3596 /* Convert the value from ascii to integer */
3597 ret = kstrtou8(value, 10, &okcMode);
3598 if (ret < 0)
3599 {
3600 /* If the input value is greater than max value of datatype, then also
3601 kstrtou8 fails */
3602 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3603 "%s: kstrtou8 failed range [%d - %d]", __func__,
3604 CFG_OKC_FEATURE_ENABLED_MIN,
3605 CFG_OKC_FEATURE_ENABLED_MAX);
3606 ret = -EINVAL;
3607 goto exit;
3608 }
3609
3610 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
3611 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
3612 {
3613 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3614 "Okc mode value %d is out of range"
3615 " (Min: %d Max: %d)", okcMode,
3616 CFG_OKC_FEATURE_ENABLED_MIN,
3617 CFG_OKC_FEATURE_ENABLED_MAX);
3618 ret = -EINVAL;
3619 goto exit;
3620 }
3621
3622 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3623 "%s: Received Command to change okc mode = %d", __func__, okcMode);
3624
3625 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
3626 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07003627#endif /* FEATURE_WLAN_OKC */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003628 else if (strncmp(priv_data.buf, "GETROAMSCANCONTROL", 18) == 0)
3629 {
3630 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
3631 char extra[32];
3632 tANI_U8 len = 0;
3633
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003634 len = scnprintf(extra, sizeof(extra), "%s %d",
3635 command, roamScanControl);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003636 if (copy_to_user(priv_data.buf, &extra, len + 1))
3637 {
3638 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3639 "%s: failed to copy data to user buffer", __func__);
3640 ret = -EFAULT;
3641 goto exit;
3642 }
3643 }
Gopichand Nakkala227c7f32013-06-26 22:44:57 +05303644#ifdef WLAN_FEATURE_PACKET_FILTERING
3645 else if (strncmp(command, "ENABLE_PKTFILTER_IPV6", 21) == 0)
3646 {
3647 tANI_U8 filterType = 0;
3648 tANI_U8 *value = command;
3649
3650 /* Move pointer to ahead of ENABLE_PKTFILTER_IPV6<delimiter> */
3651 value = value + 22;
3652
3653 /* Convert the value from ascii to integer */
3654 ret = kstrtou8(value, 10, &filterType);
3655 if (ret < 0)
3656 {
3657 /* If the input value is greater than max value of datatype,
3658 * then also kstrtou8 fails
3659 */
3660 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3661 "%s: kstrtou8 failed range ", __func__);
3662 ret = -EINVAL;
3663 goto exit;
3664 }
3665
3666 if (filterType != 0 && filterType != 1)
3667 {
3668 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3669 "%s: Accepted Values are 0 and 1 ", __func__);
3670 ret = -EINVAL;
3671 goto exit;
3672 }
3673 wlan_hdd_setIPv6Filter(WLAN_HDD_GET_CTX(pAdapter), filterType,
3674 pAdapter->sessionId);
3675 }
3676#endif
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303677 else if (strncmp(command, "BTCOEXMODE", 10) == 0 )
3678 {
Kiet Lamad161252014-07-22 11:23:32 -07003679 char *dhcpPhase;
3680 dhcpPhase = command + 11;
3681 if ('1' == *dhcpPhase)
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303682 {
c_hpothu9b781ba2013-12-30 20:57:45 +05303683 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Kiet Lamad161252014-07-22 11:23:32 -07003684 FL("send DHCP START indication"));
c_hpothu9b781ba2013-12-30 20:57:45 +05303685
3686 pHddCtx->btCoexModeSet = TRUE;
Kiet Lamad161252014-07-22 11:23:32 -07003687
3688 sme_DHCPStartInd(pHddCtx->hHal, pAdapter->device_mode,
3689 pAdapter->sessionId);
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303690 }
Kiet Lamad161252014-07-22 11:23:32 -07003691 else if ('2' == *dhcpPhase)
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303692 {
c_hpothu9b781ba2013-12-30 20:57:45 +05303693 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Kiet Lamad161252014-07-22 11:23:32 -07003694 FL("send DHCP STOP indication"));
c_hpothu9b781ba2013-12-30 20:57:45 +05303695
3696 pHddCtx->btCoexModeSet = FALSE;
Kiet Lamad161252014-07-22 11:23:32 -07003697
3698 sme_DHCPStopInd(pHddCtx->hHal, pAdapter->device_mode,
3699 pAdapter->sessionId);
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303700 }
3701 }
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07003702 else if (strncmp(command, "SCAN-ACTIVE", 11) == 0)
3703 {
c_hpothudbefd3e2014-04-28 15:59:47 +05303704 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3705 FL("making default scan to ACTIVE"));
3706 pHddCtx->scan_info.scan_mode = eSIR_ACTIVE_SCAN;
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07003707 }
3708 else if (strncmp(command, "SCAN-PASSIVE", 12) == 0)
3709 {
c_hpothudbefd3e2014-04-28 15:59:47 +05303710 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3711 FL("making default scan to PASSIVE"));
3712 pHddCtx->scan_info.scan_mode = eSIR_PASSIVE_SCAN;
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07003713 }
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303714 else if (strncmp(command, "GETDWELLTIME", 12) == 0)
3715 {
3716 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3717 char extra[32];
3718 tANI_U8 len = 0;
3719
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05303720 memset(extra, 0, sizeof(extra));
3721 ret = hdd_get_dwell_time(pCfg, command, extra, sizeof(extra), &len);
3722 if (ret != 0 || copy_to_user(priv_data.buf, &extra, len + 1))
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303723 {
3724 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3725 "%s: failed to copy data to user buffer", __func__);
3726 ret = -EFAULT;
3727 goto exit;
3728 }
3729 ret = len;
3730 }
3731 else if (strncmp(command, "SETDWELLTIME", 12) == 0)
3732 {
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05303733 ret = hdd_set_dwell_time(pAdapter, command);
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303734 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07003735 else if ( strncasecmp(command, "MIRACAST", 8) == 0 )
3736 {
3737 tANI_U8 filterType = 0;
3738 tANI_U8 *value;
3739 value = command + 9;
3740
3741 /* Convert the value from ascii to integer */
3742 ret = kstrtou8(value, 10, &filterType);
3743 if (ret < 0)
3744 {
3745 /* If the input value is greater than max value of datatype,
3746 * then also kstrtou8 fails
3747 */
3748 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3749 "%s: kstrtou8 failed range ", __func__);
3750 ret = -EINVAL;
3751 goto exit;
3752 }
3753 if ((filterType < WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL ) ||
3754 (filterType > WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL))
3755 {
3756 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3757 "%s: Accepted Values are 0 to 2. 0-Disabled, 1-Source,"
3758 " 2-Sink ", __func__);
3759 ret = -EINVAL;
3760 goto exit;
3761 }
3762 //Filtertype value should be either 0-Disabled, 1-Source, 2-sink
3763 pHddCtx->drvr_miracast = filterType;
3764 hdd_tx_rx_pkt_cnt_stat_timer_handler(pHddCtx);
3765 }
Leo Chang614d2072013-08-22 14:59:44 -07003766 else if (strncmp(command, "SETMCRATE", 9) == 0)
3767 {
Leo Chang614d2072013-08-22 14:59:44 -07003768 tANI_U8 *value = command;
3769 int targetRate;
Leo Chang1f98cbd2013-10-17 15:03:52 -07003770 tSirRateUpdateInd *rateUpdate;
3771 eHalStatus status;
Leo Chang614d2072013-08-22 14:59:44 -07003772
3773 /* Only valid for SAP mode */
3774 if (WLAN_HDD_SOFTAP != pAdapter->device_mode)
3775 {
3776 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3777 "%s: SAP mode is not running", __func__);
3778 ret = -EFAULT;
3779 goto exit;
3780 }
3781
3782 /* Move pointer to ahead of SETMCRATE<delimiter> */
3783 /* input value is in units of hundred kbps */
3784 value = value + 10;
3785 /* Convert the value from ascii to integer, decimal base */
3786 ret = kstrtouint(value, 10, &targetRate);
3787
Leo Chang1f98cbd2013-10-17 15:03:52 -07003788 rateUpdate = (tSirRateUpdateInd *)vos_mem_malloc(sizeof(tSirRateUpdateInd));
3789 if (NULL == rateUpdate)
Leo Chang614d2072013-08-22 14:59:44 -07003790 {
Leo Chang1f98cbd2013-10-17 15:03:52 -07003791 hddLog(VOS_TRACE_LEVEL_ERROR,
3792 "%s: SETMCRATE indication alloc fail", __func__);
3793 ret = -EFAULT;
3794 goto exit;
3795 }
3796 vos_mem_zero(rateUpdate, sizeof(tSirRateUpdateInd ));
3797
3798 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3799 "MC Target rate %d", targetRate);
3800 /* Ignore unicast */
3801 rateUpdate->ucastDataRate = -1;
3802 rateUpdate->mcastDataRate24GHz = targetRate;
3803 rateUpdate->mcastDataRate5GHz = targetRate;
3804 rateUpdate->mcastDataRate24GHzTxFlag = 0;
3805 rateUpdate->mcastDataRate5GHzTxFlag = 0;
3806 status = sme_SendRateUpdateInd(pHddCtx->hHal, rateUpdate);
3807 if (eHAL_STATUS_SUCCESS != status)
3808 {
3809 hddLog(VOS_TRACE_LEVEL_ERROR,
3810 "%s: SET_MC_RATE failed", __func__);
3811 vos_mem_free(rateUpdate);
3812 ret = -EFAULT;
3813 goto exit;
Leo Chang614d2072013-08-22 14:59:44 -07003814 }
3815 }
Rajeev79dbe4c2013-10-05 11:03:42 +05303816#ifdef FEATURE_WLAN_BATCH_SCAN
Rajeev Kumar8b373292014-01-08 20:36:55 -08003817 else if (strncmp(command, "WLS_BATCHING", 12) == 0)
Rajeev79dbe4c2013-10-05 11:03:42 +05303818 {
Rajeev Kumar8b373292014-01-08 20:36:55 -08003819 ret = hdd_handle_batch_scan_ioctl(pAdapter, &priv_data, command);
Rajeev79dbe4c2013-10-05 11:03:42 +05303820 }
3821#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003822#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003823 else if (strncmp(command, "SETCCXROAMSCANCHANNELS", 22) == 0)
3824 {
3825 tANI_U8 *value = command;
3826 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
3827 tANI_U8 numChannels = 0;
3828 eHalStatus status = eHAL_STATUS_SUCCESS;
3829
3830 status = hdd_parse_channellist(value, ChannelList, &numChannels);
3831 if (eHAL_STATUS_SUCCESS != status)
3832 {
3833 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3834 "%s: Failed to parse channel list information", __func__);
3835 ret = -EINVAL;
3836 goto exit;
3837 }
3838
3839 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
3840 {
3841 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3842 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
3843 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
3844 ret = -EINVAL;
3845 goto exit;
3846 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003847 status = sme_SetEseRoamScanChannelList((tHalHandle)(pHddCtx->hHal),
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003848 ChannelList,
3849 numChannels);
3850 if (eHAL_STATUS_SUCCESS != status)
3851 {
3852 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3853 "%s: Failed to update channel list information", __func__);
3854 ret = -EINVAL;
3855 goto exit;
3856 }
3857 }
3858 else if (strncmp(command, "GETTSMSTATS", 11) == 0)
3859 {
3860 tANI_U8 *value = command;
3861 char extra[128] = {0};
3862 int len = 0;
3863 tANI_U8 tid = 0;
3864 hdd_station_ctx_t *pHddStaCtx = NULL;
3865 tAniTrafStrmMetrics tsmMetrics;
3866 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3867
3868 /* if not associated, return error */
3869 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3870 {
3871 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:Not associated!",__func__);
3872 ret = -EINVAL;
3873 goto exit;
3874 }
3875
3876 /* Move pointer to ahead of GETTSMSTATS<delimiter> */
3877 value = value + 12;
3878 /* Convert the value from ascii to integer */
3879 ret = kstrtou8(value, 10, &tid);
3880 if (ret < 0)
3881 {
3882 /* If the input value is greater than max value of datatype, then also
3883 kstrtou8 fails */
3884 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3885 "%s: kstrtou8 failed range [%d - %d]", __func__,
3886 TID_MIN_VALUE,
3887 TID_MAX_VALUE);
3888 ret = -EINVAL;
3889 goto exit;
3890 }
3891
3892 if ((tid < TID_MIN_VALUE) || (tid > TID_MAX_VALUE))
3893 {
3894 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3895 "tid value %d is out of range"
3896 " (Min: %d Max: %d)", tid,
3897 TID_MIN_VALUE,
3898 TID_MAX_VALUE);
3899 ret = -EINVAL;
3900 goto exit;
3901 }
3902
3903 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3904 "%s: Received Command to get tsm stats tid = %d", __func__, tid);
3905
3906 if (VOS_STATUS_SUCCESS != hdd_get_tsm_stats(pAdapter, tid, &tsmMetrics))
3907 {
3908 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3909 "%s: failed to get tsm stats", __func__);
3910 ret = -EFAULT;
3911 goto exit;
3912 }
3913
3914 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3915 "UplinkPktQueueDly(%d)\n"
3916 "UplinkPktQueueDlyHist[0](%d)\n"
3917 "UplinkPktQueueDlyHist[1](%d)\n"
3918 "UplinkPktQueueDlyHist[2](%d)\n"
3919 "UplinkPktQueueDlyHist[3](%d)\n"
Arun Kumar Khandavallie8768212014-02-17 16:43:34 +05303920 "UplinkPktTxDly(%u)\n"
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003921 "UplinkPktLoss(%d)\n"
3922 "UplinkPktCount(%d)\n"
3923 "RoamingCount(%d)\n"
3924 "RoamingDly(%d)", tsmMetrics.UplinkPktQueueDly,
3925 tsmMetrics.UplinkPktQueueDlyHist[0],
3926 tsmMetrics.UplinkPktQueueDlyHist[1],
3927 tsmMetrics.UplinkPktQueueDlyHist[2],
3928 tsmMetrics.UplinkPktQueueDlyHist[3],
3929 tsmMetrics.UplinkPktTxDly, tsmMetrics.UplinkPktLoss,
3930 tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount, tsmMetrics.RoamingDly);
3931
3932 /* Output TSM stats is of the format
3933 GETTSMSTATS [PktQueueDly] [PktQueueDlyHist[0]]:[PktQueueDlyHist[1]] ...[RoamingDly]
3934 eg., GETTSMSTATS 10 1:0:0:161 20 1 17 8 39800 */
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003935 len = scnprintf(extra, sizeof(extra), "%s %d %d:%d:%d:%d %u %d %d %d %d", command,
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003936 tsmMetrics.UplinkPktQueueDly, tsmMetrics.UplinkPktQueueDlyHist[0],
3937 tsmMetrics.UplinkPktQueueDlyHist[1], tsmMetrics.UplinkPktQueueDlyHist[2],
3938 tsmMetrics.UplinkPktQueueDlyHist[3], tsmMetrics.UplinkPktTxDly,
3939 tsmMetrics.UplinkPktLoss, tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount,
3940 tsmMetrics.RoamingDly);
3941
3942 if (copy_to_user(priv_data.buf, &extra, len + 1))
3943 {
3944 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3945 "%s: failed to copy data to user buffer", __func__);
3946 ret = -EFAULT;
3947 goto exit;
3948 }
3949 }
3950 else if (strncmp(command, "SETCCKMIE", 9) == 0)
3951 {
3952 tANI_U8 *value = command;
3953 tANI_U8 *cckmIe = NULL;
3954 tANI_U8 cckmIeLen = 0;
3955 eHalStatus status = eHAL_STATUS_SUCCESS;
3956
3957 status = hdd_parse_get_cckm_ie(value, &cckmIe, &cckmIeLen);
3958 if (eHAL_STATUS_SUCCESS != status)
3959 {
3960 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3961 "%s: Failed to parse cckm ie data", __func__);
3962 ret = -EINVAL;
3963 goto exit;
3964 }
3965
3966 if (cckmIeLen > DOT11F_IE_RSN_MAX_LEN)
3967 {
3968 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3969 "%s: CCKM Ie input length is more than max[%d]", __func__,
3970 DOT11F_IE_RSN_MAX_LEN);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08003971 vos_mem_free(cckmIe);
3972 cckmIe = NULL;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003973 ret = -EINVAL;
3974 goto exit;
3975 }
3976 sme_SetCCKMIe((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, cckmIe, cckmIeLen);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08003977 vos_mem_free(cckmIe);
3978 cckmIe = NULL;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003979 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003980 else if (strncmp(command, "CCXBEACONREQ", 12) == 0)
3981 {
3982 tANI_U8 *value = command;
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003983 tCsrEseBeaconReq eseBcnReq;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003984 eHalStatus status = eHAL_STATUS_SUCCESS;
Srinivas Girigowda0c6d7fe2014-05-28 18:18:10 -07003985
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003986 status = hdd_parse_ese_beacon_req(value, &eseBcnReq);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003987 if (eHAL_STATUS_SUCCESS != status)
3988 {
3989 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003990 "%s: Failed to parse ese beacon req", __func__);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003991 ret = -EINVAL;
3992 goto exit;
3993 }
Srinivas Girigowda0c6d7fe2014-05-28 18:18:10 -07003994 if (!hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))) {
3995 hddLog(VOS_TRACE_LEVEL_INFO, FL("Not associated"));
3996 hdd_indicateEseBcnReportNoResults (pAdapter,
3997 eseBcnReq.bcnReq[0].measurementToken,
3998 0x02, //BIT(1) set for measurement done
3999 0); // no BSS
4000 goto exit;
4001 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004002
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004003 status = sme_SetEseBeaconRequest((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, &eseBcnReq);
4004 if (eHAL_STATUS_SUCCESS != status)
4005 {
4006 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4007 "%s: sme_SetEseBeaconRequest failed (%d)", __func__, status);
4008 ret = -EINVAL;
4009 goto exit;
4010 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004011 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004012#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
c_hpothu92367912014-05-01 15:18:17 +05304013 else if (strncmp(command, "GETBCNMISSRATE", 14) == 0)
4014 {
4015 eHalStatus status;
4016 char buf[32], len;
4017 long waitRet;
4018 bcnMissRateContext_t getBcnMissRateCtx;
4019
4020 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4021
4022 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
4023 {
4024 hddLog(VOS_TRACE_LEVEL_WARN,
4025 FL("GETBCNMISSRATE: STA is not in connected state"));
4026 ret = -1;
4027 goto exit;
4028 }
4029
4030 init_completion(&(getBcnMissRateCtx.completion));
4031 getBcnMissRateCtx.magic = BCN_MISS_RATE_CONTEXT_MAGIC;
4032
4033 status = sme_getBcnMissRate((tHalHandle)(pHddCtx->hHal),
4034 pAdapter->sessionId,
4035 (void *)getBcnMissRateCB,
4036 (void *)(&getBcnMissRateCtx));
4037 if( eHAL_STATUS_SUCCESS != status)
4038 {
4039 hddLog(VOS_TRACE_LEVEL_INFO,
4040 FL("GETBCNMISSRATE: fail to post WDA cmd"));
4041 ret = -EINVAL;
4042 goto exit;
4043 }
4044
4045 waitRet = wait_for_completion_interruptible_timeout
4046 (&getBcnMissRateCtx.completion, BCN_MISS_RATE_TIME);
4047 if(waitRet <= 0)
4048 {
4049 hddLog(VOS_TRACE_LEVEL_ERROR,
4050 FL("failed to wait on bcnMissRateComp %d"), ret);
4051
4052 //Make magic number to zero so that callback is not called.
4053 spin_lock(&hdd_context_lock);
4054 getBcnMissRateCtx.magic = 0x0;
4055 spin_unlock(&hdd_context_lock);
4056 ret = -EINVAL;
4057 goto exit;
4058 }
4059
4060 hddLog(VOS_TRACE_LEVEL_INFO,
4061 FL("GETBCNMISSRATE: bcnMissRate: %d"), gbcnMissRate);
4062
4063 len = snprintf(buf, sizeof(buf), "GETBCNMISSRATE %d", gbcnMissRate);
4064 if (copy_to_user(priv_data.buf, &buf, len + 1))
4065 {
4066 hddLog(VOS_TRACE_LEVEL_ERROR,
4067 "%s: failed to copy data to user buffer", __func__);
4068 ret = -EFAULT;
4069 goto exit;
4070 }
4071 ret = len;
4072 }
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07004073 else {
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05304074 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
4075 TRACE_CODE_HDD_UNSUPPORTED_IOCTL,
4076 pAdapter->sessionId, 0));
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07004077 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
4078 __func__, command);
4079 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004080 }
4081exit:
4082 if (command)
4083 {
4084 kfree(command);
4085 }
4086 return ret;
4087}
4088
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07004089#ifdef CONFIG_COMPAT
4090static int hdd_driver_compat_ioctl(hdd_adapter_t *pAdapter, struct ifreq *ifr)
4091{
4092 struct {
4093 compat_uptr_t buf;
4094 int used_len;
4095 int total_len;
4096 } compat_priv_data;
4097 hdd_priv_data_t priv_data;
4098 int ret = 0;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004099
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07004100 /*
4101 * Note that pAdapter and ifr have already been verified by caller,
4102 * and HDD context has also been validated
4103 */
4104 if (copy_from_user(&compat_priv_data, ifr->ifr_data,
4105 sizeof(compat_priv_data))) {
4106 ret = -EFAULT;
4107 goto exit;
4108 }
4109 priv_data.buf = compat_ptr(compat_priv_data.buf);
4110 priv_data.used_len = compat_priv_data.used_len;
4111 priv_data.total_len = compat_priv_data.total_len;
4112 ret = hdd_driver_command(pAdapter, &priv_data);
4113 exit:
4114 return ret;
4115}
4116#else /* CONFIG_COMPAT */
4117static int hdd_driver_compat_ioctl(hdd_adapter_t *pAdapter, struct ifreq *ifr)
4118{
4119 /* will never be invoked */
4120 return 0;
4121}
4122#endif /* CONFIG_COMPAT */
4123
4124static int hdd_driver_ioctl(hdd_adapter_t *pAdapter, struct ifreq *ifr)
4125{
4126 hdd_priv_data_t priv_data;
4127 int ret = 0;
4128
4129 /*
4130 * Note that pAdapter and ifr have already been verified by caller,
4131 * and HDD context has also been validated
4132 */
4133 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(priv_data))) {
4134 ret = -EFAULT;
4135 } else {
4136 ret = hdd_driver_command(pAdapter, &priv_data);
4137 }
4138 return ret;
4139}
4140
4141int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
4142{
4143 hdd_adapter_t *pAdapter;
4144 hdd_context_t *pHddCtx;
4145 int ret;
4146
4147 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4148 if (NULL == pAdapter) {
4149 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4150 "%s: HDD adapter context is Null", __func__);
4151 ret = -ENODEV;
4152 goto exit;
4153 }
4154 if (dev != pAdapter->dev) {
4155 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4156 "%s: HDD adapter/dev inconsistency", __func__);
4157 ret = -ENODEV;
4158 goto exit;
4159 }
4160
4161 if ((!ifr) || (!ifr->ifr_data)) {
4162 ret = -EINVAL;
4163 goto exit;
4164 }
4165
4166 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4167 ret = wlan_hdd_validate_context(pHddCtx);
4168 if (ret) {
4169 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4170 "%s: invalid context", __func__);
4171 ret = -EBUSY;
4172 goto exit;
4173 }
4174
4175 switch (cmd) {
4176 case (SIOCDEVPRIVATE + 1):
4177 if (is_compat_task())
4178 ret = hdd_driver_compat_ioctl(pAdapter, ifr);
4179 else
4180 ret = hdd_driver_ioctl(pAdapter, ifr);
4181 break;
4182 default:
4183 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unknown ioctl %d",
4184 __func__, cmd);
4185 ret = -EINVAL;
4186 break;
4187 }
4188 exit:
4189 return ret;
4190}
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004191
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004192#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004193/**---------------------------------------------------------------------------
4194
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004195 \brief hdd_parse_ese_beacon_req() - Parse ese beacon request
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004196
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004197 This function parses the ese beacon request passed in the format
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004198 CCXBEACONREQ<space><Number of fields><space><Measurement token>
4199 <space>Channel 1<space>Scan Mode <space>Meas Duration<space>Channel N
4200 <space>Scan Mode N<space>Meas Duration N
4201 if the Number of bcn req fields (N) does not match with the actual number of fields passed
4202 then take N.
4203 <Meas Token><Channel><Scan Mode> and <Meas Duration> are treated as one pair
4204 For example, CCXBEACONREQ 2 1 1 1 30 2 44 0 40.
4205 This function does not take care of removing duplicate channels from the list
4206
4207 \param - pValue Pointer to data
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004208 \param - pEseBcnReq output pointer to store parsed ie information
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004209
4210 \return - 0 for success non-zero for failure
4211
4212 --------------------------------------------------------------------------*/
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004213static VOS_STATUS hdd_parse_ese_beacon_req(tANI_U8 *pValue,
4214 tCsrEseBeaconReq *pEseBcnReq)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004215{
4216 tANI_U8 *inPtr = pValue;
4217 int tempInt = 0;
4218 int j = 0, i = 0, v = 0;
4219 char buf[32];
4220
4221 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4222 /*no argument after the command*/
4223 if (NULL == inPtr)
4224 {
4225 return -EINVAL;
4226 }
4227 /*no space after the command*/
4228 else if (SPACE_ASCII_VALUE != *inPtr)
4229 {
4230 return -EINVAL;
4231 }
4232
4233 /*removing empty spaces*/
4234 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
4235
4236 /*no argument followed by spaces*/
4237 if ('\0' == *inPtr) return -EINVAL;
4238
4239 /*getting the first argument ie measurement token*/
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004240 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004241 if (1 != v) return -EINVAL;
4242
4243 v = kstrtos32(buf, 10, &tempInt);
4244 if ( v < 0) return -EINVAL;
4245
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004246 pEseBcnReq->numBcnReqIe = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004247
4248 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004249 "Number of Bcn Req Ie fields(%d)", pEseBcnReq->numBcnReqIe);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004250
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004251 for (j = 0; j < (pEseBcnReq->numBcnReqIe); j++)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004252 {
4253 for (i = 0; i < 4; i++)
4254 {
4255 /*inPtr pointing to the beginning of first space after number of ie fields*/
4256 inPtr = strpbrk( inPtr, " " );
4257 /*no ie data after the number of ie fields argument*/
4258 if (NULL == inPtr) return -EINVAL;
4259
4260 /*removing empty space*/
4261 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
4262
4263 /*no ie data after the number of ie fields argument and spaces*/
4264 if ( '\0' == *inPtr ) return -EINVAL;
4265
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004266 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004267 if (1 != v) return -EINVAL;
4268
4269 v = kstrtos32(buf, 10, &tempInt);
4270 if (v < 0) return -EINVAL;
4271
4272 switch (i)
4273 {
4274 case 0: /* Measurement token */
4275 if (tempInt <= 0)
4276 {
4277 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4278 "Invalid Measurement Token(%d)", tempInt);
4279 return -EINVAL;
4280 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004281 pEseBcnReq->bcnReq[j].measurementToken = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004282 break;
4283
4284 case 1: /* Channel number */
4285 if ((tempInt <= 0) ||
4286 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4287 {
4288 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4289 "Invalid Channel Number(%d)", tempInt);
4290 return -EINVAL;
4291 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004292 pEseBcnReq->bcnReq[j].channel = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004293 break;
4294
4295 case 2: /* Scan mode */
Varun Reddy Yeturu0b18d5a2013-12-04 11:42:23 -08004296 if ((tempInt < eSIR_PASSIVE_SCAN) || (tempInt > eSIR_BEACON_TABLE))
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004297 {
4298 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4299 "Invalid Scan Mode(%d) Expected{0|1|2}", tempInt);
4300 return -EINVAL;
4301 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004302 pEseBcnReq->bcnReq[j].scanMode= tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004303 break;
4304
4305 case 3: /* Measurement duration */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004306 if (((tempInt <= 0) && (pEseBcnReq->bcnReq[j].scanMode != eSIR_BEACON_TABLE)) ||
4307 ((tempInt < 0) && (pEseBcnReq->bcnReq[j].scanMode == eSIR_BEACON_TABLE)))
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004308 {
4309 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4310 "Invalid Measurement Duration(%d)", tempInt);
4311 return -EINVAL;
4312 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004313 pEseBcnReq->bcnReq[j].measurementDuration = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004314 break;
4315 }
4316 }
4317 }
4318
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004319 for (j = 0; j < pEseBcnReq->numBcnReqIe; j++)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004320 {
4321 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arun Kumar Khandavallie8768212014-02-17 16:43:34 +05304322 "Index(%d) Measurement Token(%u)Channel(%u) Scan Mode(%u) Measurement Duration(%u)\n",
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004323 j,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004324 pEseBcnReq->bcnReq[j].measurementToken,
4325 pEseBcnReq->bcnReq[j].channel,
4326 pEseBcnReq->bcnReq[j].scanMode,
4327 pEseBcnReq->bcnReq[j].measurementDuration);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004328 }
4329
4330 return VOS_STATUS_SUCCESS;
4331}
4332
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004333static void hdd_GetTsmStatsCB( tAniTrafStrmMetrics tsmMetrics, const tANI_U32 staId, void *pContext )
4334{
4335 struct statsContext *pStatsContext = NULL;
4336 hdd_adapter_t *pAdapter = NULL;
4337
4338 if (NULL == pContext)
4339 {
4340 hddLog(VOS_TRACE_LEVEL_ERROR,
4341 "%s: Bad param, pContext [%p]",
4342 __func__, pContext);
4343 return;
4344 }
4345
Jeff Johnson72a40512013-12-19 10:14:15 -08004346 /* there is a race condition that exists between this callback
4347 function and the caller since the caller could time out either
4348 before or while this code is executing. we use a spinlock to
4349 serialize these actions */
4350 spin_lock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004351
4352 pStatsContext = pContext;
4353 pAdapter = pStatsContext->pAdapter;
4354 if ((NULL == pAdapter) || (STATS_CONTEXT_MAGIC != pStatsContext->magic))
4355 {
4356 /* the caller presumably timed out so there is nothing we can do */
Jeff Johnson72a40512013-12-19 10:14:15 -08004357 spin_unlock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004358 hddLog(VOS_TRACE_LEVEL_WARN,
4359 "%s: Invalid context, pAdapter [%p] magic [%08x]",
4360 __func__, pAdapter, pStatsContext->magic);
4361 return;
4362 }
4363
Jeff Johnson72a40512013-12-19 10:14:15 -08004364 /* context is valid so caller is still waiting */
4365
4366 /* paranoia: invalidate the magic */
4367 pStatsContext->magic = 0;
4368
4369 /* copy over the tsm stats */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004370 pAdapter->tsmStats.UplinkPktQueueDly = tsmMetrics.UplinkPktQueueDly;
4371 vos_mem_copy(pAdapter->tsmStats.UplinkPktQueueDlyHist,
4372 tsmMetrics.UplinkPktQueueDlyHist,
4373 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
4374 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
4375 pAdapter->tsmStats.UplinkPktTxDly = tsmMetrics.UplinkPktTxDly;
4376 pAdapter->tsmStats.UplinkPktLoss = tsmMetrics.UplinkPktLoss;
4377 pAdapter->tsmStats.UplinkPktCount = tsmMetrics.UplinkPktCount;
4378 pAdapter->tsmStats.RoamingCount = tsmMetrics.RoamingCount;
4379 pAdapter->tsmStats.RoamingDly = tsmMetrics.RoamingDly;
4380
Jeff Johnson72a40512013-12-19 10:14:15 -08004381 /* notify the caller */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004382 complete(&pStatsContext->completion);
Jeff Johnson72a40512013-12-19 10:14:15 -08004383
4384 /* serialization is complete */
4385 spin_unlock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004386}
4387
4388
4389
4390static VOS_STATUS hdd_get_tsm_stats(hdd_adapter_t *pAdapter, const tANI_U8 tid,
4391 tAniTrafStrmMetrics* pTsmMetrics)
4392{
4393 hdd_station_ctx_t *pHddStaCtx = NULL;
4394 eHalStatus hstatus;
Jeff Johnson72a40512013-12-19 10:14:15 -08004395 VOS_STATUS vstatus = VOS_STATUS_SUCCESS;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004396 long lrc;
4397 struct statsContext context;
4398 hdd_context_t *pHddCtx = NULL;
4399
4400 if (NULL == pAdapter)
4401 {
4402 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: pAdapter is NULL", __func__);
4403 return VOS_STATUS_E_FAULT;
4404 }
4405
4406 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4407 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4408
4409 /* we are connected prepare our callback context */
4410 init_completion(&context.completion);
4411 context.pAdapter = pAdapter;
4412 context.magic = STATS_CONTEXT_MAGIC;
4413
4414 /* query tsm stats */
4415 hstatus = sme_GetTsmStats(pHddCtx->hHal, hdd_GetTsmStatsCB,
4416 pHddStaCtx->conn_info.staId[ 0 ],
4417 pHddStaCtx->conn_info.bssId,
4418 &context, pHddCtx->pvosContext, tid);
4419
4420 if (eHAL_STATUS_SUCCESS != hstatus)
4421 {
Jeff Johnson72a40512013-12-19 10:14:15 -08004422 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unable to retrieve statistics",
4423 __func__);
4424 vstatus = VOS_STATUS_E_FAULT;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004425 }
4426 else
4427 {
4428 /* request was sent -- wait for the response */
4429 lrc = wait_for_completion_interruptible_timeout(&context.completion,
4430 msecs_to_jiffies(WLAN_WAIT_TIME_STATS));
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004431 if (lrc <= 0)
4432 {
4433 hddLog(VOS_TRACE_LEVEL_ERROR,
4434 "%s: SME %s while retrieving statistics",
4435 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson72a40512013-12-19 10:14:15 -08004436 vstatus = VOS_STATUS_E_TIMEOUT;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004437 }
4438 }
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004439
Jeff Johnson72a40512013-12-19 10:14:15 -08004440 /* either we never sent a request, we sent a request and received a
4441 response or we sent a request and timed out. if we never sent a
4442 request or if we sent a request and got a response, we want to
4443 clear the magic out of paranoia. if we timed out there is a
4444 race condition such that the callback function could be
4445 executing at the same time we are. of primary concern is if the
4446 callback function had already verified the "magic" but had not
4447 yet set the completion variable when a timeout occurred. we
4448 serialize these activities by invalidating the magic while
4449 holding a shared spinlock which will cause us to block if the
4450 callback is currently executing */
4451 spin_lock(&hdd_context_lock);
4452 context.magic = 0;
4453 spin_unlock(&hdd_context_lock);
4454
4455 if (VOS_STATUS_SUCCESS == vstatus)
4456 {
4457 pTsmMetrics->UplinkPktQueueDly = pAdapter->tsmStats.UplinkPktQueueDly;
4458 vos_mem_copy(pTsmMetrics->UplinkPktQueueDlyHist,
4459 pAdapter->tsmStats.UplinkPktQueueDlyHist,
4460 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
4461 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
4462 pTsmMetrics->UplinkPktTxDly = pAdapter->tsmStats.UplinkPktTxDly;
4463 pTsmMetrics->UplinkPktLoss = pAdapter->tsmStats.UplinkPktLoss;
4464 pTsmMetrics->UplinkPktCount = pAdapter->tsmStats.UplinkPktCount;
4465 pTsmMetrics->RoamingCount = pAdapter->tsmStats.RoamingCount;
4466 pTsmMetrics->RoamingDly = pAdapter->tsmStats.RoamingDly;
4467 }
4468 return vstatus;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004469}
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004470#endif /*FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004471
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004472#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -08004473void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
4474{
4475 eCsrBand band = -1;
4476 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
4477 switch (band)
4478 {
4479 case eCSR_BAND_ALL:
4480 *pBand = WLAN_HDD_UI_BAND_AUTO;
4481 break;
4482
4483 case eCSR_BAND_24:
4484 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
4485 break;
4486
4487 case eCSR_BAND_5G:
4488 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
4489 break;
4490
4491 default:
4492 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
4493 *pBand = -1;
4494 break;
4495 }
4496}
4497
4498/**---------------------------------------------------------------------------
4499
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004500 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
4501
4502 This function parses the send action frame data passed in the format
4503 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
4504
Srinivas Girigowda56076852013-08-20 14:00:50 -07004505 \param - pValue Pointer to input data
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004506 \param - pTargetApBssid Pointer to target Ap bssid
4507 \param - pChannel Pointer to the Target AP channel
4508 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
4509 \param - pBuf Pointer to data
4510 \param - pBufLen Pointer to data length
4511
4512 \return - 0 for success non-zero for failure
4513
4514 --------------------------------------------------------------------------*/
4515VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
4516 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
4517{
4518 tANI_U8 *inPtr = pValue;
4519 tANI_U8 *dataEnd;
4520 int tempInt;
4521 int j = 0;
4522 int i = 0;
4523 int v = 0;
4524 tANI_U8 tempBuf[32];
4525 tANI_U8 tempByte = 0;
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004526 /* 12 hexa decimal digits, 5 ':' and '\0' */
4527 tANI_U8 macAddress[18];
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004528
4529 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4530 /*no argument after the command*/
4531 if (NULL == inPtr)
4532 {
4533 return -EINVAL;
4534 }
4535
4536 /*no space after the command*/
4537 else if (SPACE_ASCII_VALUE != *inPtr)
4538 {
4539 return -EINVAL;
4540 }
4541
4542 /*removing empty spaces*/
4543 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4544
4545 /*no argument followed by spaces*/
4546 if ('\0' == *inPtr)
4547 {
4548 return -EINVAL;
4549 }
4550
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004551 v = sscanf(inPtr, "%17s", macAddress);
4552 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004553 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004554 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4555 "Invalid MAC address or All hex inputs are not read (%d)", v);
4556 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004557 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004558
4559 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
4560 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
4561 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
4562 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
4563 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
4564 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004565
4566 /* point to the next argument */
4567 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4568 /*no argument after the command*/
4569 if (NULL == inPtr) return -EINVAL;
4570
4571 /*removing empty spaces*/
4572 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4573
4574 /*no argument followed by spaces*/
4575 if ('\0' == *inPtr)
4576 {
4577 return -EINVAL;
4578 }
4579
4580 /*getting the next argument ie the channel number */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004581 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004582 if (1 != v) return -EINVAL;
4583
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004584 v = kstrtos32(tempBuf, 10, &tempInt);
Agarwal Ashish353b3a82014-04-08 14:55:11 +05304585 if ( v < 0 || tempInt <= 0 || tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX )
Kiet Lambe150c22013-11-21 16:30:32 +05304586 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004587
4588 *pChannel = tempInt;
4589
4590 /* point to the next argument */
4591 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4592 /*no argument after the command*/
4593 if (NULL == inPtr) return -EINVAL;
4594 /*removing empty spaces*/
4595 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4596
4597 /*no argument followed by spaces*/
4598 if ('\0' == *inPtr)
4599 {
4600 return -EINVAL;
4601 }
4602
4603 /*getting the next argument ie the dwell time */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004604 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004605 if (1 != v) return -EINVAL;
4606
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004607 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda5a6e0672014-01-09 14:42:57 -08004608 if ( v < 0 || tempInt < 0) return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004609
4610 *pDwellTime = tempInt;
4611
4612 /* point to the next argument */
4613 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4614 /*no argument after the command*/
4615 if (NULL == inPtr) return -EINVAL;
4616 /*removing empty spaces*/
4617 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4618
4619 /*no argument followed by spaces*/
4620 if ('\0' == *inPtr)
4621 {
4622 return -EINVAL;
4623 }
4624
4625 /* find the length of data */
4626 dataEnd = inPtr;
4627 while(('\0' != *dataEnd) )
4628 {
4629 dataEnd++;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004630 }
Kiet Lambe150c22013-11-21 16:30:32 +05304631 *pBufLen = dataEnd - inPtr ;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004632 if ( *pBufLen <= 0) return -EINVAL;
4633
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07004634 /* Allocate the number of bytes based on the number of input characters
4635 whether it is even or odd.
4636 if the number of input characters are even, then we need N/2 byte.
4637 if the number of input characters are odd, then we need do (N+1)/2 to
4638 compensate rounding off.
4639 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
4640 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
4641 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004642 if (NULL == *pBuf)
4643 {
4644 hddLog(VOS_TRACE_LEVEL_FATAL,
4645 "%s: vos_mem_alloc failed ", __func__);
4646 return -EINVAL;
4647 }
4648
4649 /* the buffer received from the upper layer is character buffer,
4650 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
4651 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
4652 and f0 in 3rd location */
4653 for (i = 0, j = 0; j < *pBufLen; j += 2)
4654 {
Kiet Lambe150c22013-11-21 16:30:32 +05304655 if( j+1 == *pBufLen)
4656 {
4657 tempByte = hdd_parse_hex(inPtr[j]);
4658 }
4659 else
4660 {
4661 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
4662 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004663 (*pBuf)[i++] = tempByte;
4664 }
4665 *pBufLen = i;
4666 return VOS_STATUS_SUCCESS;
4667}
4668
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004669/**---------------------------------------------------------------------------
4670
Srinivas Girigowdade697412013-02-14 16:31:48 -08004671 \brief hdd_parse_channellist() - HDD Parse channel list
4672
4673 This function parses the channel list passed in the format
4674 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004675 if the Number of channels (N) does not match with the actual number of channels passed
4676 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
4677 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
4678 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
4679 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08004680
4681 \param - pValue Pointer to input channel list
4682 \param - ChannelList Pointer to local output array to record channel list
4683 \param - pNumChannels Pointer to number of roam scan channels
4684
4685 \return - 0 for success non-zero for failure
4686
4687 --------------------------------------------------------------------------*/
4688VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
4689{
4690 tANI_U8 *inPtr = pValue;
4691 int tempInt;
4692 int j = 0;
4693 int v = 0;
4694 char buf[32];
4695
4696 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4697 /*no argument after the command*/
4698 if (NULL == inPtr)
4699 {
4700 return -EINVAL;
4701 }
4702
4703 /*no space after the command*/
4704 else if (SPACE_ASCII_VALUE != *inPtr)
4705 {
4706 return -EINVAL;
4707 }
4708
4709 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004710 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08004711
4712 /*no argument followed by spaces*/
4713 if ('\0' == *inPtr)
4714 {
4715 return -EINVAL;
4716 }
4717
4718 /*getting the first argument ie the number of channels*/
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004719 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004720 if (1 != v) return -EINVAL;
4721
Srinivas Girigowdade697412013-02-14 16:31:48 -08004722 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004723 if ((v < 0) ||
4724 (tempInt <= 0) ||
4725 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
4726 {
4727 return -EINVAL;
4728 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004729
4730 *pNumChannels = tempInt;
4731
4732 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
4733 "Number of channels are: %d", *pNumChannels);
4734
4735 for (j = 0; j < (*pNumChannels); j++)
4736 {
4737 /*inPtr pointing to the beginning of first space after number of channels*/
4738 inPtr = strpbrk( inPtr, " " );
4739 /*no channel list after the number of channels argument*/
4740 if (NULL == inPtr)
4741 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004742 if (0 != j)
4743 {
4744 *pNumChannels = j;
4745 return VOS_STATUS_SUCCESS;
4746 }
4747 else
4748 {
4749 return -EINVAL;
4750 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004751 }
4752
4753 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004754 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08004755
4756 /*no channel list after the number of channels argument and spaces*/
4757 if ( '\0' == *inPtr )
4758 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004759 if (0 != j)
4760 {
4761 *pNumChannels = j;
4762 return VOS_STATUS_SUCCESS;
4763 }
4764 else
4765 {
4766 return -EINVAL;
4767 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004768 }
4769
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004770 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004771 if (1 != v) return -EINVAL;
4772
Srinivas Girigowdade697412013-02-14 16:31:48 -08004773 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004774 if ((v < 0) ||
4775 (tempInt <= 0) ||
4776 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4777 {
4778 return -EINVAL;
4779 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004780 pChannelList[j] = tempInt;
4781
4782 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
4783 "Channel %d added to preferred channel list",
4784 pChannelList[j] );
4785 }
4786
Srinivas Girigowdade697412013-02-14 16:31:48 -08004787 return VOS_STATUS_SUCCESS;
4788}
4789
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004790
4791/**---------------------------------------------------------------------------
4792
4793 \brief hdd_parse_reassoc_command_data() - HDD Parse reassoc command data
4794
4795 This function parses the reasoc command data passed in the format
4796 REASSOC<space><bssid><space><channel>
4797
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004798 \param - pValue Pointer to input data (its a NUL terminated string)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004799 \param - pTargetApBssid Pointer to target Ap bssid
4800 \param - pChannel Pointer to the Target AP channel
4801
4802 \return - 0 for success non-zero for failure
4803
4804 --------------------------------------------------------------------------*/
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004805VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue,
4806 tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004807{
4808 tANI_U8 *inPtr = pValue;
4809 int tempInt;
4810 int v = 0;
4811 tANI_U8 tempBuf[32];
Kiet Lamaa8e15a2014-02-11 23:30:06 -08004812 /* 12 hexa decimal digits, 5 ':' and '\0' */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004813 tANI_U8 macAddress[18];
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004814
4815 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4816 /*no argument after the command*/
4817 if (NULL == inPtr)
4818 {
4819 return -EINVAL;
4820 }
4821
4822 /*no space after the command*/
4823 else if (SPACE_ASCII_VALUE != *inPtr)
4824 {
4825 return -EINVAL;
4826 }
4827
4828 /*removing empty spaces*/
4829 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4830
4831 /*no argument followed by spaces*/
4832 if ('\0' == *inPtr)
4833 {
4834 return -EINVAL;
4835 }
4836
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004837 v = sscanf(inPtr, "%17s", macAddress);
4838 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004839 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004840 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4841 "Invalid MAC address or All hex inputs are not read (%d)", v);
4842 return -EINVAL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004843 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004844
4845 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
4846 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
4847 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
4848 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
4849 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
4850 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004851
4852 /* point to the next argument */
4853 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4854 /*no argument after the command*/
4855 if (NULL == inPtr) return -EINVAL;
4856
4857 /*removing empty spaces*/
4858 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4859
4860 /*no argument followed by spaces*/
4861 if ('\0' == *inPtr)
4862 {
4863 return -EINVAL;
4864 }
4865
4866 /*getting the next argument ie the channel number */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004867 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004868 if (1 != v) return -EINVAL;
4869
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004870 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004871 if ((v < 0) ||
4872 (tempInt <= 0) ||
4873 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4874 {
4875 return -EINVAL;
4876 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004877
4878 *pChannel = tempInt;
4879 return VOS_STATUS_SUCCESS;
4880}
4881
4882#endif
4883
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004884#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004885/**---------------------------------------------------------------------------
4886
4887 \brief hdd_parse_get_cckm_ie() - HDD Parse and fetch the CCKM IE
4888
4889 This function parses the SETCCKM IE command
4890 SETCCKMIE<space><ie data>
4891
4892 \param - pValue Pointer to input data
4893 \param - pCckmIe Pointer to output cckm Ie
4894 \param - pCckmIeLen Pointer to output cckm ie length
4895
4896 \return - 0 for success non-zero for failure
4897
4898 --------------------------------------------------------------------------*/
4899VOS_STATUS hdd_parse_get_cckm_ie(tANI_U8 *pValue, tANI_U8 **pCckmIe,
4900 tANI_U8 *pCckmIeLen)
4901{
4902 tANI_U8 *inPtr = pValue;
4903 tANI_U8 *dataEnd;
4904 int j = 0;
4905 int i = 0;
4906 tANI_U8 tempByte = 0;
4907
4908 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4909 /*no argument after the command*/
4910 if (NULL == inPtr)
4911 {
4912 return -EINVAL;
4913 }
4914
4915 /*no space after the command*/
4916 else if (SPACE_ASCII_VALUE != *inPtr)
4917 {
4918 return -EINVAL;
4919 }
4920
4921 /*removing empty spaces*/
4922 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4923
4924 /*no argument followed by spaces*/
4925 if ('\0' == *inPtr)
4926 {
4927 return -EINVAL;
4928 }
4929
4930 /* find the length of data */
4931 dataEnd = inPtr;
4932 while(('\0' != *dataEnd) )
4933 {
4934 dataEnd++;
4935 ++(*pCckmIeLen);
4936 }
4937 if ( *pCckmIeLen <= 0) return -EINVAL;
4938
4939 /* Allocate the number of bytes based on the number of input characters
4940 whether it is even or odd.
4941 if the number of input characters are even, then we need N/2 byte.
4942 if the number of input characters are odd, then we need do (N+1)/2 to
4943 compensate rounding off.
4944 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
4945 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
4946 *pCckmIe = vos_mem_malloc((*pCckmIeLen + 1)/2);
4947 if (NULL == *pCckmIe)
4948 {
4949 hddLog(VOS_TRACE_LEVEL_FATAL,
4950 "%s: vos_mem_alloc failed ", __func__);
4951 return -EINVAL;
4952 }
4953 vos_mem_zero(*pCckmIe, (*pCckmIeLen + 1)/2);
4954 /* the buffer received from the upper layer is character buffer,
4955 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
4956 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
4957 and f0 in 3rd location */
4958 for (i = 0, j = 0; j < *pCckmIeLen; j += 2)
4959 {
4960 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
4961 (*pCckmIe)[i++] = tempByte;
4962 }
4963 *pCckmIeLen = i;
4964
4965 return VOS_STATUS_SUCCESS;
4966}
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004967#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004968
Jeff Johnson295189b2012-06-20 16:38:30 -07004969/**---------------------------------------------------------------------------
4970
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004971 \brief hdd_is_valid_mac_address() - Validate MAC address
4972
4973 This function validates whether the given MAC address is valid or not
4974 Expected MAC address is of the format XX:XX:XX:XX:XX:XX
4975 where X is the hexa decimal digit character and separated by ':'
4976 This algorithm works even if MAC address is not separated by ':'
4977
4978 This code checks given input string mac contains exactly 12 hexadecimal digits.
4979 and a separator colon : appears in the input string only after
4980 an even number of hex digits.
4981
4982 \param - pMacAddr pointer to the input MAC address
4983 \return - 1 for valid and 0 for invalid
4984
4985 --------------------------------------------------------------------------*/
4986
4987v_BOOL_t hdd_is_valid_mac_address(const tANI_U8 *pMacAddr)
4988{
4989 int xdigit = 0;
4990 int separator = 0;
4991 while (*pMacAddr)
4992 {
4993 if (isxdigit(*pMacAddr))
4994 {
4995 xdigit++;
4996 }
4997 else if (':' == *pMacAddr)
4998 {
4999 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
5000 break;
5001
5002 ++separator;
5003 }
5004 else
5005 {
5006 separator = -1;
5007 /* Invalid MAC found */
5008 return 0;
5009 }
5010 ++pMacAddr;
5011 }
5012 return (xdigit == 12 && (separator == 5 || separator == 0));
5013}
5014
5015/**---------------------------------------------------------------------------
5016
Jeff Johnson295189b2012-06-20 16:38:30 -07005017 \brief hdd_open() - HDD Open function
5018
5019 This is called in response to ifconfig up
5020
5021 \param - dev Pointer to net_device structure
5022
5023 \return - 0 for success non-zero for failure
5024
5025 --------------------------------------------------------------------------*/
5026int hdd_open (struct net_device *dev)
5027{
5028 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5029 hdd_context_t *pHddCtx;
5030 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5031 VOS_STATUS status;
5032 v_BOOL_t in_standby = TRUE;
5033
5034 if (NULL == pAdapter)
5035 {
5036 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Agarwal Ashish971c2882013-10-30 20:11:12 +05305037 "%s: pAdapter is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005038 return -ENODEV;
5039 }
5040
5041 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05305042 MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_OPEN_REQUEST,
5043 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson295189b2012-06-20 16:38:30 -07005044 if (NULL == pHddCtx)
5045 {
5046 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005047 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005048 return -ENODEV;
5049 }
5050
5051 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5052 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
5053 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07005054 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
5055 {
5056 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305057 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07005058 in_standby = FALSE;
5059 break;
5060 }
5061 else
5062 {
5063 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5064 pAdapterNode = pNext;
5065 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005066 }
5067
5068 if (TRUE == in_standby)
5069 {
5070 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
5071 {
5072 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
5073 "wlan out of power save", __func__);
5074 return -EINVAL;
5075 }
5076 }
5077
Jeff Johnson6a81ca42013-04-05 10:37:08 -07005078 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07005079 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
5080 {
5081 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005082 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005083 /* Enable TX queues only when we are connected */
5084 netif_tx_start_all_queues(dev);
5085 }
5086
5087 return 0;
5088}
5089
5090int hdd_mon_open (struct net_device *dev)
5091{
5092 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5093
5094 if(pAdapter == NULL) {
5095 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005096 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005097 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005098 }
5099
5100 netif_start_queue(dev);
5101
5102 return 0;
5103}
5104/**---------------------------------------------------------------------------
5105
5106 \brief hdd_stop() - HDD stop function
5107
5108 This is called in response to ifconfig down
5109
5110 \param - dev Pointer to net_device structure
5111
5112 \return - 0 for success non-zero for failure
5113
5114 --------------------------------------------------------------------------*/
5115
5116int hdd_stop (struct net_device *dev)
5117{
5118 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5119 hdd_context_t *pHddCtx;
5120 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5121 VOS_STATUS status;
5122 v_BOOL_t enter_standby = TRUE;
5123
5124 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005125 if (NULL == pAdapter)
5126 {
5127 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Agarwal Ashish971c2882013-10-30 20:11:12 +05305128 "%s: pAdapter is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005129 return -ENODEV;
5130 }
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05305131 MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_OPEN_REQUEST,
5132 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson295189b2012-06-20 16:38:30 -07005133 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
5134 if (NULL == pHddCtx)
5135 {
5136 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005137 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005138 return -ENODEV;
5139 }
5140
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05305141 /* Nothing to be done if the interface is not opened */
5142 if (VOS_FALSE == test_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags))
5143 {
5144 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5145 "%s: NETDEV Interface is not OPENED", __func__);
5146 return -ENODEV;
5147 }
5148
5149 /* Make sure the interface is marked as closed */
Jeff Johnson6a81ca42013-04-05 10:37:08 -07005150 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07005151 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05305152
5153 /* Disable TX on the interface, after this hard_start_xmit() will not
5154 * be called on that interface
5155 */
Jeff Johnson295189b2012-06-20 16:38:30 -07005156 netif_tx_disable(pAdapter->dev);
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05305157
5158 /* Mark the interface status as "down" for outside world */
Jeff Johnson295189b2012-06-20 16:38:30 -07005159 netif_carrier_off(pAdapter->dev);
5160
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05305161 /* The interface is marked as down for outside world (aka kernel)
5162 * But the driver is pretty much alive inside. The driver needs to
5163 * tear down the existing connection on the netdev (session)
5164 * cleanup the data pipes and wait until the control plane is stabilized
5165 * for this interface. The call also needs to wait until the above
5166 * mentioned actions are completed before returning to the caller.
5167 * Notice that the hdd_stop_adapter is requested not to close the session
5168 * That is intentional to be able to scan if it is a STA/P2P interface
5169 */
5170 hdd_stop_adapter(pHddCtx, pAdapter, VOS_FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -07005171
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05305172 /* DeInit the adapter. This ensures datapath cleanup as well */
5173 hdd_deinit_adapter(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005174 /* SoftAP ifaces should never go in power save mode
5175 making sure same here. */
5176 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
5177 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07005178 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07005179 )
5180 {
5181 /* SoftAP mode, so return from here */
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305182 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5183 "%s: In SAP MODE", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005184 EXIT();
5185 return 0;
5186 }
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05305187 /* Find if any iface is up. If any iface is up then can't put device to
5188 * sleep/power save mode
5189 */
Jeff Johnson295189b2012-06-20 16:38:30 -07005190 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5191 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
5192 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07005193 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
5194 {
5195 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305196 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07005197 enter_standby = FALSE;
5198 break;
5199 }
5200 else
5201 {
5202 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5203 pAdapterNode = pNext;
5204 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005205 }
5206
5207 if (TRUE == enter_standby)
5208 {
5209 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
5210 "entering standby", __func__);
5211 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
5212 {
5213 /*log and return success*/
5214 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
5215 "wlan in power save", __func__);
5216 }
5217 }
5218
5219 EXIT();
5220 return 0;
5221}
5222
5223/**---------------------------------------------------------------------------
5224
5225 \brief hdd_uninit() - HDD uninit function
5226
5227 This is called during the netdev unregister to uninitialize all data
5228associated with the device
5229
5230 \param - dev Pointer to net_device structure
5231
5232 \return - void
5233
5234 --------------------------------------------------------------------------*/
5235static void hdd_uninit (struct net_device *dev)
5236{
5237 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5238
5239 ENTER();
5240
5241 do
5242 {
5243 if (NULL == pAdapter)
5244 {
5245 hddLog(VOS_TRACE_LEVEL_FATAL,
5246 "%s: NULL pAdapter", __func__);
5247 break;
5248 }
5249
5250 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
5251 {
5252 hddLog(VOS_TRACE_LEVEL_FATAL,
5253 "%s: Invalid magic", __func__);
5254 break;
5255 }
5256
5257 if (NULL == pAdapter->pHddCtx)
5258 {
5259 hddLog(VOS_TRACE_LEVEL_FATAL,
5260 "%s: NULL pHddCtx", __func__);
5261 break;
5262 }
5263
5264 if (dev != pAdapter->dev)
5265 {
5266 hddLog(VOS_TRACE_LEVEL_FATAL,
5267 "%s: Invalid device reference", __func__);
5268 /* we haven't validated all cases so let this go for now */
5269 }
5270
5271 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
5272
5273 /* after uninit our adapter structure will no longer be valid */
5274 pAdapter->dev = NULL;
5275 pAdapter->magic = 0;
5276 } while (0);
5277
5278 EXIT();
5279}
5280
5281/**---------------------------------------------------------------------------
5282
5283 \brief hdd_release_firmware() -
5284
5285 This function calls the release firmware API to free the firmware buffer.
5286
5287 \param - pFileName Pointer to the File Name.
5288 pCtx - Pointer to the adapter .
5289
5290
5291 \return - 0 for success, non zero for failure
5292
5293 --------------------------------------------------------------------------*/
5294
5295VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
5296{
5297 VOS_STATUS status = VOS_STATUS_SUCCESS;
5298 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
5299 ENTER();
5300
5301
5302 if (!strcmp(WLAN_FW_FILE, pFileName)) {
5303
5304 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
5305
5306 if(pHddCtx->fw) {
5307 release_firmware(pHddCtx->fw);
5308 pHddCtx->fw = NULL;
5309 }
5310 else
5311 status = VOS_STATUS_E_FAILURE;
5312 }
5313 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
5314 if(pHddCtx->nv) {
5315 release_firmware(pHddCtx->nv);
5316 pHddCtx->nv = NULL;
5317 }
5318 else
5319 status = VOS_STATUS_E_FAILURE;
5320
5321 }
5322
5323 EXIT();
5324 return status;
5325}
5326
5327/**---------------------------------------------------------------------------
5328
5329 \brief hdd_request_firmware() -
5330
5331 This function reads the firmware file using the request firmware
5332 API and returns the the firmware data and the firmware file size.
5333
5334 \param - pfileName - Pointer to the file name.
5335 - pCtx - Pointer to the adapter .
5336 - ppfw_data - Pointer to the pointer of the firmware data.
5337 - pSize - Pointer to the file size.
5338
5339 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
5340
5341 --------------------------------------------------------------------------*/
5342
5343
5344VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
5345{
5346 int status;
5347 VOS_STATUS retval = VOS_STATUS_SUCCESS;
5348 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
5349 ENTER();
5350
5351 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
5352
5353 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
5354
5355 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
5356 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
5357 __func__, pfileName);
5358 retval = VOS_STATUS_E_FAILURE;
5359 }
5360
5361 else {
5362 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
5363 *pSize = pHddCtx->fw->size;
5364 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
5365 __func__, *pSize);
5366 }
5367 }
5368 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
5369
5370 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
5371
5372 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
5373 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
5374 __func__, pfileName);
5375 retval = VOS_STATUS_E_FAILURE;
5376 }
5377
5378 else {
5379 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
5380 *pSize = pHddCtx->nv->size;
5381 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
5382 __func__, *pSize);
5383 }
5384 }
5385
5386 EXIT();
5387 return retval;
5388}
5389/**---------------------------------------------------------------------------
5390 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
5391
5392 This is the function invoked by SME to inform the result of a full power
5393 request issued by HDD
5394
5395 \param - callbackcontext - Pointer to cookie
5396 status - result of request
5397
5398 \return - None
5399
5400--------------------------------------------------------------------------*/
5401void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
5402{
5403 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
5404
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07005405 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07005406 if(&pHddCtx->full_pwr_comp_var)
5407 {
5408 complete(&pHddCtx->full_pwr_comp_var);
5409 }
5410}
5411
5412/**---------------------------------------------------------------------------
5413
5414 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
5415
5416 This is the function invoked by SME to inform the result of BMPS
5417 request issued by HDD
5418
5419 \param - callbackcontext - Pointer to cookie
5420 status - result of request
5421
5422 \return - None
5423
5424--------------------------------------------------------------------------*/
5425void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
5426{
5427
5428 struct completion *completion_var = (struct completion*) callbackContext;
5429
Arif Hussain6d2a3322013-11-17 19:50:10 -08005430 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07005431 if(completion_var != NULL)
5432 {
5433 complete(completion_var);
5434 }
5435}
5436
5437/**---------------------------------------------------------------------------
5438
5439 \brief hdd_get_cfg_file_size() -
5440
5441 This function reads the configuration file using the request firmware
5442 API and returns the configuration file size.
5443
5444 \param - pCtx - Pointer to the adapter .
5445 - pFileName - Pointer to the file name.
5446 - pBufSize - Pointer to the buffer size.
5447
5448 \return - 0 for success, non zero for failure
5449
5450 --------------------------------------------------------------------------*/
5451
5452VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
5453{
5454 int status;
5455 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
5456
5457 ENTER();
5458
5459 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
5460
5461 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
5462 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
5463 status = VOS_STATUS_E_FAILURE;
5464 }
5465 else {
5466 *pBufSize = pHddCtx->fw->size;
5467 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
5468 release_firmware(pHddCtx->fw);
5469 pHddCtx->fw = NULL;
5470 }
5471
5472 EXIT();
5473 return VOS_STATUS_SUCCESS;
5474}
5475
5476/**---------------------------------------------------------------------------
5477
5478 \brief hdd_read_cfg_file() -
5479
5480 This function reads the configuration file using the request firmware
5481 API and returns the cfg data and the buffer size of the configuration file.
5482
5483 \param - pCtx - Pointer to the adapter .
5484 - pFileName - Pointer to the file name.
5485 - pBuffer - Pointer to the data buffer.
5486 - pBufSize - Pointer to the buffer size.
5487
5488 \return - 0 for success, non zero for failure
5489
5490 --------------------------------------------------------------------------*/
5491
5492VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
5493 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
5494{
5495 int status;
5496 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
5497
5498 ENTER();
5499
5500 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
5501
5502 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
5503 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
5504 return VOS_STATUS_E_FAILURE;
5505 }
5506 else {
5507 if(*pBufSize != pHddCtx->fw->size) {
5508 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
5509 "file size", __func__);
5510 release_firmware(pHddCtx->fw);
5511 pHddCtx->fw = NULL;
5512 return VOS_STATUS_E_FAILURE;
5513 }
5514 else {
5515 if(pBuffer) {
5516 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
5517 }
5518 release_firmware(pHddCtx->fw);
5519 pHddCtx->fw = NULL;
5520 }
5521 }
5522
5523 EXIT();
5524
5525 return VOS_STATUS_SUCCESS;
5526}
5527
5528/**---------------------------------------------------------------------------
5529
Jeff Johnson295189b2012-06-20 16:38:30 -07005530 \brief hdd_set_mac_address() -
5531
5532 This function sets the user specified mac address using
5533 the command ifconfig wlanX hw ether <mac adress>.
5534
5535 \param - dev - Pointer to the net device.
5536 - addr - Pointer to the sockaddr.
5537 \return - 0 for success, non zero for failure
5538
5539 --------------------------------------------------------------------------*/
5540
5541static int hdd_set_mac_address(struct net_device *dev, void *addr)
5542{
5543 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5544 struct sockaddr *psta_mac_addr = addr;
5545 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5546
5547 ENTER();
5548
5549 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
Jeff Johnson295189b2012-06-20 16:38:30 -07005550 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
5551
5552 EXIT();
5553 return halStatus;
5554}
5555
5556tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
5557{
5558 int i;
5559 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5560 {
Abhishek Singheb183782014-02-06 13:37:21 +05305561 if( 0 == ((pHddCtx->cfg_ini->intfAddrMask) & (1 << i)) )
Jeff Johnson295189b2012-06-20 16:38:30 -07005562 break;
5563 }
5564
5565 if( VOS_MAX_CONCURRENCY_PERSONA == i)
5566 return NULL;
5567
5568 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
5569 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
5570}
5571
5572void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
5573{
5574 int i;
5575 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5576 {
5577 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
5578 {
5579 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
5580 break;
5581 }
5582 }
5583 return;
5584}
5585
5586#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
5587 static struct net_device_ops wlan_drv_ops = {
5588 .ndo_open = hdd_open,
5589 .ndo_stop = hdd_stop,
5590 .ndo_uninit = hdd_uninit,
5591 .ndo_start_xmit = hdd_hard_start_xmit,
5592 .ndo_tx_timeout = hdd_tx_timeout,
5593 .ndo_get_stats = hdd_stats,
5594 .ndo_do_ioctl = hdd_ioctl,
5595 .ndo_set_mac_address = hdd_set_mac_address,
5596 .ndo_select_queue = hdd_select_queue,
5597#ifdef WLAN_FEATURE_PACKET_FILTERING
5598#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
5599 .ndo_set_rx_mode = hdd_set_multicast_list,
5600#else
5601 .ndo_set_multicast_list = hdd_set_multicast_list,
5602#endif //LINUX_VERSION_CODE
5603#endif
5604 };
Jeff Johnson295189b2012-06-20 16:38:30 -07005605 static struct net_device_ops wlan_mon_drv_ops = {
5606 .ndo_open = hdd_mon_open,
5607 .ndo_stop = hdd_stop,
5608 .ndo_uninit = hdd_uninit,
5609 .ndo_start_xmit = hdd_mon_hard_start_xmit,
5610 .ndo_tx_timeout = hdd_tx_timeout,
5611 .ndo_get_stats = hdd_stats,
5612 .ndo_do_ioctl = hdd_ioctl,
5613 .ndo_set_mac_address = hdd_set_mac_address,
5614 };
Jeff Johnson295189b2012-06-20 16:38:30 -07005615
5616#endif
5617
5618void hdd_set_station_ops( struct net_device *pWlanDev )
5619{
5620#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
Jeff Johnson295189b2012-06-20 16:38:30 -07005621 pWlanDev->netdev_ops = &wlan_drv_ops;
5622#else
5623 pWlanDev->open = hdd_open;
5624 pWlanDev->stop = hdd_stop;
5625 pWlanDev->uninit = hdd_uninit;
5626 pWlanDev->hard_start_xmit = NULL;
5627 pWlanDev->tx_timeout = hdd_tx_timeout;
5628 pWlanDev->get_stats = hdd_stats;
5629 pWlanDev->do_ioctl = hdd_ioctl;
Jeff Johnson295189b2012-06-20 16:38:30 -07005630 pWlanDev->set_mac_address = hdd_set_mac_address;
5631#endif
5632}
5633
Jeff Johnsoneed415b2013-01-18 16:11:20 -08005634static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07005635{
5636 struct net_device *pWlanDev = NULL;
5637 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005638 /*
5639 * cfg80211 initialization and registration....
5640 */
5641 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
5642
Jeff Johnson295189b2012-06-20 16:38:30 -07005643 if(pWlanDev != NULL)
5644 {
5645
5646 //Save the pointer to the net_device in the HDD adapter
5647 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
5648
Jeff Johnson295189b2012-06-20 16:38:30 -07005649 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
5650
5651 pAdapter->dev = pWlanDev;
5652 pAdapter->pHddCtx = pHddCtx;
5653 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
5654
5655 init_completion(&pAdapter->session_open_comp_var);
5656 init_completion(&pAdapter->session_close_comp_var);
5657 init_completion(&pAdapter->disconnect_comp_var);
5658 init_completion(&pAdapter->linkup_event_var);
5659 init_completion(&pAdapter->cancel_rem_on_chan_var);
5660 init_completion(&pAdapter->rem_on_chan_ready_event);
Vinay Krishna Erannaf0e523b2014-03-01 21:00:16 +05305661 init_completion(&pAdapter->pno_comp_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07005662#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
5663 init_completion(&pAdapter->offchannel_tx_event);
5664#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005665 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005666#ifdef FEATURE_WLAN_TDLS
5667 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07005668 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08005669 init_completion(&pAdapter->tdls_mgmt_comp);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05305670 init_completion(&pAdapter->tdls_link_establish_req_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005671#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005672 init_completion(&pHddCtx->mc_sus_event_var);
5673 init_completion(&pHddCtx->tx_sus_event_var);
Gopichand Nakkala05621412013-06-19 19:37:38 +05305674 init_completion(&pHddCtx->rx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07005675 init_completion(&pAdapter->ula_complete);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07005676 init_completion(&pAdapter->change_country_code);
Jeff Johnson295189b2012-06-20 16:38:30 -07005677
Rajeev79dbe4c2013-10-05 11:03:42 +05305678#ifdef FEATURE_WLAN_BATCH_SCAN
5679 init_completion(&pAdapter->hdd_set_batch_scan_req_var);
5680 init_completion(&pAdapter->hdd_get_batch_scan_req_var);
5681 pAdapter->pBatchScanRsp = NULL;
5682 pAdapter->numScanList = 0;
Rajeev Kumar20140c12013-10-21 19:39:02 -07005683 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
Kiet Lamaa8e15a2014-02-11 23:30:06 -08005684 pAdapter->prev_batch_id = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05305685 mutex_init(&pAdapter->hdd_batch_scan_lock);
5686#endif
5687
Jeff Johnson295189b2012-06-20 16:38:30 -07005688 pAdapter->isLinkUpSvcNeeded = FALSE;
5689 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
5690 //Init the net_device structure
5691 strlcpy(pWlanDev->name, name, IFNAMSIZ);
5692
5693 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
5694 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
5695 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
5696 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
5697
5698 hdd_set_station_ops( pAdapter->dev );
5699
5700 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07005701 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
5702 pAdapter->wdev.wiphy = pHddCtx->wiphy;
5703 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07005704 /* set pWlanDev's parent to underlying device */
5705 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
Kumar Anand82c009f2014-05-29 00:29:42 -07005706
5707 hdd_wmm_init( pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07005708 }
5709
5710 return pAdapter;
5711}
5712
5713VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
5714{
5715 struct net_device *pWlanDev = pAdapter->dev;
5716 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
5717 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
5718 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5719
5720 if( rtnl_lock_held )
5721 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08005722 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07005723 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
5724 {
5725 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
5726 return VOS_STATUS_E_FAILURE;
5727 }
5728 }
5729 if (register_netdevice(pWlanDev))
5730 {
5731 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
5732 return VOS_STATUS_E_FAILURE;
5733 }
5734 }
5735 else
5736 {
5737 if(register_netdev(pWlanDev))
5738 {
5739 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
5740 return VOS_STATUS_E_FAILURE;
5741 }
5742 }
5743 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
5744
5745 return VOS_STATUS_SUCCESS;
5746}
5747
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005748static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07005749{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005750 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07005751
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005752 if (NULL == pAdapter)
5753 {
5754 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
5755 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07005756 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005757
5758 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
5759 {
5760 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
5761 return eHAL_STATUS_NOT_INITIALIZED;
5762 }
5763
5764 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
5765
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005766#ifndef WLAN_OPEN_SOURCE
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005767 /* need to make sure all of our scheduled work has completed.
5768 * This callback is called from MC thread context, so it is safe to
5769 * to call below flush workqueue API from here.
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005770 *
5771 * Even though this is called from MC thread context, if there is a faulty
5772 * work item in the system, that can hang this call forever. So flushing
5773 * this global work queue is not safe; and now we make sure that
5774 * individual work queues are stopped correctly. But the cancel work queue
5775 * is a GPL only API, so the proprietary version of the driver would still
5776 * rely on the global work queue flush.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005777 */
5778 flush_scheduled_work();
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005779#endif
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005780
5781 /* We can be blocked while waiting for scheduled work to be
5782 * flushed, and the adapter structure can potentially be freed, in
5783 * which case the magic will have been reset. So make sure the
5784 * magic is still good, and hence the adapter structure is still
5785 * valid, before signaling completion */
5786 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
5787 {
5788 complete(&pAdapter->session_close_comp_var);
5789 }
5790
Jeff Johnson295189b2012-06-20 16:38:30 -07005791 return eHAL_STATUS_SUCCESS;
5792}
5793
5794VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
5795{
5796 struct net_device *pWlanDev = pAdapter->dev;
5797 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
5798 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
5799 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5800 VOS_STATUS status = VOS_STATUS_E_FAILURE;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305801 long rc = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07005802
5803 INIT_COMPLETION(pAdapter->session_open_comp_var);
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07005804 sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07005805 //Open a SME session for future operation
5806 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07005807 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07005808 if ( !HAL_STATUS_SUCCESS( halStatus ) )
5809 {
5810 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005811 "sme_OpenSession() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005812 halStatus, halStatus );
5813 status = VOS_STATUS_E_FAILURE;
5814 goto error_sme_open;
5815 }
5816
5817 //Block on a completion variable. Can't wait forever though.
Vinay Krishna Eranna0fe2e7c2014-04-09 21:32:08 +05305818 rc = wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07005819 &pAdapter->session_open_comp_var,
5820 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305821 if (rc <= 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07005822 {
5823 hddLog(VOS_TRACE_LEVEL_FATAL,
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305824 "Session is not opened within timeout period code %ld", rc );
Jeff Johnson295189b2012-06-20 16:38:30 -07005825 status = VOS_STATUS_E_FAILURE;
5826 goto error_sme_open;
5827 }
5828
5829 // Register wireless extensions
5830 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
5831 {
5832 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005833 "hdd_register_wext() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005834 halStatus, halStatus );
5835 status = VOS_STATUS_E_FAILURE;
5836 goto error_register_wext;
5837 }
5838 //Safe to register the hard_start_xmit function again
5839#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
5840 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
5841#else
5842 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
5843#endif
5844
5845 //Set the Connection State to Not Connected
Abhishek Singhf4669da2014-05-26 15:07:49 +05305846 hddLog(VOS_TRACE_LEVEL_INFO,
5847 "%s: Set HDD connState to eConnectionState_NotConnected",
5848 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005849 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
5850
5851 //Set the default operation channel
5852 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
5853
5854 /* Make the default Auth Type as OPEN*/
5855 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
5856
5857 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
5858 {
5859 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005860 "hdd_init_tx_rx() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005861 status, status );
5862 goto error_init_txrx;
5863 }
5864
5865 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5866
5867 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
5868 {
5869 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005870 "hdd_wmm_adapter_init() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005871 status, status );
5872 goto error_wmm_init;
5873 }
5874
5875 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5876
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005877#ifdef FEATURE_WLAN_TDLS
Agarwal Ashish4b87f922014-06-18 03:03:21 +05305878 if(0 != wlan_hdd_sta_tdls_init(pAdapter))
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005879 {
5880 status = VOS_STATUS_E_FAILURE;
Agarwal Ashish4b87f922014-06-18 03:03:21 +05305881 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_sta_tdls_init failed",__func__);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005882 goto error_tdls_init;
5883 }
5884 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
5885#endif
5886
Jeff Johnson295189b2012-06-20 16:38:30 -07005887 return VOS_STATUS_SUCCESS;
5888
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005889#ifdef FEATURE_WLAN_TDLS
5890error_tdls_init:
5891 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5892 hdd_wmm_adapter_close(pAdapter);
5893#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005894error_wmm_init:
5895 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5896 hdd_deinit_tx_rx(pAdapter);
5897error_init_txrx:
5898 hdd_UnregisterWext(pWlanDev);
5899error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005900 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07005901 {
5902 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005903 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07005904 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005905 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07005906 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305907 unsigned long rc;
5908
Jeff Johnson295189b2012-06-20 16:38:30 -07005909 //Block on a completion variable. Can't wait forever though.
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305910 rc = wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07005911 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005912 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305913 if (rc <= 0)
5914 hddLog(VOS_TRACE_LEVEL_ERROR,
5915 FL("Session is not opened within timeout period code %ld"), rc);
Jeff Johnson295189b2012-06-20 16:38:30 -07005916 }
5917}
5918error_sme_open:
5919 return status;
5920}
5921
Jeff Johnson295189b2012-06-20 16:38:30 -07005922void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5923{
5924 hdd_cfg80211_state_t *cfgState;
5925
5926 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
5927
5928 if( NULL != cfgState->buf )
5929 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305930 long rc;
Jeff Johnson295189b2012-06-20 16:38:30 -07005931 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
5932 rc = wait_for_completion_interruptible_timeout(
5933 &pAdapter->tx_action_cnf_event,
5934 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305935 if (rc <= 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07005936 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08005937 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305938 "%s ERROR: HDD Wait for Action Confirmation Failed!! %ld"
5939 , __func__, rc);
Jeff Johnson295189b2012-06-20 16:38:30 -07005940 }
5941 }
5942 return;
5943}
Jeff Johnson295189b2012-06-20 16:38:30 -07005944
5945void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5946{
5947 ENTER();
5948 switch ( pAdapter->device_mode )
5949 {
5950 case WLAN_HDD_INFRA_STATION:
5951 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005952 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005953 {
5954 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
5955 {
5956 hdd_deinit_tx_rx( pAdapter );
5957 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5958 }
5959
5960 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
5961 {
5962 hdd_wmm_adapter_close( pAdapter );
5963 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5964 }
5965
Jeff Johnson295189b2012-06-20 16:38:30 -07005966 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005967#ifdef FEATURE_WLAN_TDLS
5968 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
5969 {
5970 wlan_hdd_tdls_exit(pAdapter);
5971 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
5972 }
5973#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005974
5975 break;
5976 }
5977
5978 case WLAN_HDD_SOFTAP:
5979 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005980 {
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05305981
5982 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
5983 {
5984 hdd_wmm_adapter_close( pAdapter );
5985 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5986 }
5987
Jeff Johnson295189b2012-06-20 16:38:30 -07005988 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005989
5990 hdd_unregister_hostapd(pAdapter);
5991 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07005992 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07005993 break;
5994 }
5995
5996 case WLAN_HDD_MONITOR:
5997 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005998 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07005999 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
6000 {
6001 hdd_deinit_tx_rx( pAdapter );
6002 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
6003 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006004 if(NULL != pAdapterforTx)
6005 {
6006 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
6007 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006008 break;
6009 }
6010
6011
6012 default:
6013 break;
6014 }
6015
6016 EXIT();
6017}
6018
6019void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
6020{
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -08006021 struct net_device *pWlanDev = NULL;
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05306022
6023 ENTER();
6024 if (NULL == pAdapter)
6025 {
6026 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6027 "%s: HDD adapter is Null", __func__);
6028 return;
6029 }
6030
6031 pWlanDev = pAdapter->dev;
Jeff Johnson295189b2012-06-20 16:38:30 -07006032
Rajeev79dbe4c2013-10-05 11:03:42 +05306033#ifdef FEATURE_WLAN_BATCH_SCAN
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05306034 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
6035 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Rajeev Kumarf999e582014-01-09 17:33:29 -08006036 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05306037 || (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)
6038 )
6039 {
Rajeev Kumarf999e582014-01-09 17:33:29 -08006040 if (pAdapter)
Rajeev79dbe4c2013-10-05 11:03:42 +05306041 {
Rajeev Kumarf999e582014-01-09 17:33:29 -08006042 if (eHDD_BATCH_SCAN_STATE_STARTED == pAdapter->batchScanState)
6043 {
6044 hdd_deinit_batch_scan(pAdapter);
6045 }
Rajeev79dbe4c2013-10-05 11:03:42 +05306046 }
Rajeev Kumarf999e582014-01-09 17:33:29 -08006047 }
Rajeev79dbe4c2013-10-05 11:03:42 +05306048#endif
6049
Jeff Johnson295189b2012-06-20 16:38:30 -07006050 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
6051 if( rtnl_held )
6052 {
6053 unregister_netdevice(pWlanDev);
6054 }
6055 else
6056 {
6057 unregister_netdev(pWlanDev);
6058 }
6059 // note that the pAdapter is no longer valid at this point
6060 // since the memory has been reclaimed
6061 }
6062
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05306063 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07006064}
6065
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006066void hdd_set_pwrparams(hdd_context_t *pHddCtx)
6067{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306068 VOS_STATUS status;
6069 hdd_adapter_t *pAdapter = NULL;
6070 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006071
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306072 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006073
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306074 /*loop through all adapters.*/
6075 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006076 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306077 pAdapter = pAdapterNode->pAdapter;
6078 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
6079 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006080
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306081 { // we skip this registration for modes other than STA and P2P client modes.
6082 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6083 pAdapterNode = pNext;
6084 continue;
6085 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006086
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306087 //Apply Dynamic DTIM For P2P
6088 //Only if ignoreDynamicDtimInP2pMode is not set in ini
6089 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
6090 pHddCtx->cfg_ini->enableModulatedDTIM) &&
6091 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
6092 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
6093 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
6094 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
6095 (eConnectionState_Associated ==
6096 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
6097 (pHddCtx->cfg_ini->fIsBmpsEnabled))
6098 {
6099 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006100
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306101 powerRequest.uIgnoreDTIM = 1;
6102 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
6103
6104 if (pHddCtx->cfg_ini->enableModulatedDTIM)
6105 {
6106 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
6107 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
6108 }
6109 else
6110 {
6111 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
6112 }
6113
6114 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
6115 * specified during Enter/Exit BMPS when LCD off*/
6116 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
6117 NULL, eANI_BOOLEAN_FALSE);
6118 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
6119 NULL, eANI_BOOLEAN_FALSE);
6120
6121 /* switch to the DTIM specified in cfg.ini */
6122 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6123 "Switch to DTIM %d", powerRequest.uListenInterval);
6124 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
6125 break;
6126
6127 }
6128
6129 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6130 pAdapterNode = pNext;
6131 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006132}
6133
6134void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
6135{
6136 /*Switch back to DTIM 1*/
6137 tSirSetPowerParamsReq powerRequest = { 0 };
6138
6139 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
6140 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07006141 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006142
6143 /* Update ignoreDTIM and ListedInterval in CFG with default values */
6144 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
6145 NULL, eANI_BOOLEAN_FALSE);
6146 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
6147 NULL, eANI_BOOLEAN_FALSE);
6148
6149 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6150 "Switch to DTIM%d",powerRequest.uListenInterval);
6151 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
6152
6153}
6154
Jeff Johnson295189b2012-06-20 16:38:30 -07006155VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
6156{
6157 VOS_STATUS status = VOS_STATUS_SUCCESS;
6158
6159 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
6160 {
6161 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
6162 }
6163
6164 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
6165 {
6166 sme_StartAutoBmpsTimer(pHddCtx->hHal);
6167 }
6168
6169 if (pHddCtx->cfg_ini->fIsImpsEnabled)
6170 {
6171 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
6172 }
6173
6174 return status;
6175}
6176
6177VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
6178{
6179 hdd_adapter_t *pAdapter = NULL;
6180 eHalStatus halStatus;
6181 VOS_STATUS status = VOS_STATUS_E_INVAL;
6182 v_BOOL_t disableBmps = FALSE;
6183 v_BOOL_t disableImps = FALSE;
6184
6185 switch(session_type)
6186 {
6187 case WLAN_HDD_INFRA_STATION:
6188 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07006189 case WLAN_HDD_P2P_CLIENT:
6190 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07006191 //Exit BMPS -> Is Sta/P2P Client is already connected
6192 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
6193 if((NULL != pAdapter)&&
6194 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
6195 {
6196 disableBmps = TRUE;
6197 }
6198
6199 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
6200 if((NULL != pAdapter)&&
6201 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
6202 {
6203 disableBmps = TRUE;
6204 }
6205
6206 //Exit both Bmps and Imps incase of Go/SAP Mode
6207 if((WLAN_HDD_SOFTAP == session_type) ||
6208 (WLAN_HDD_P2P_GO == session_type))
6209 {
6210 disableBmps = TRUE;
6211 disableImps = TRUE;
6212 }
6213
6214 if(TRUE == disableImps)
6215 {
6216 if (pHddCtx->cfg_ini->fIsImpsEnabled)
6217 {
6218 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
6219 }
6220 }
6221
6222 if(TRUE == disableBmps)
6223 {
6224 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
6225 {
6226 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
6227
6228 if(eHAL_STATUS_SUCCESS != halStatus)
6229 {
6230 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08006231 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006232 VOS_ASSERT(0);
6233 return status;
6234 }
6235 }
6236
6237 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
6238 {
6239 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
6240
6241 if(eHAL_STATUS_SUCCESS != halStatus)
6242 {
6243 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08006244 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006245 VOS_ASSERT(0);
6246 return status;
6247 }
6248 }
6249 }
6250
6251 if((TRUE == disableBmps) ||
6252 (TRUE == disableImps))
6253 {
6254 /* Now, get the chip into Full Power now */
6255 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
6256 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
6257 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
6258
6259 if(halStatus != eHAL_STATUS_SUCCESS)
6260 {
6261 if(halStatus == eHAL_STATUS_PMC_PENDING)
6262 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306263 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07006264 //Block on a completion variable. Can't wait forever though
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306265 ret = wait_for_completion_interruptible_timeout(
6266 &pHddCtx->full_pwr_comp_var,
6267 msecs_to_jiffies(1000));
6268 if (ret <= 0)
6269 {
6270 hddLog(VOS_TRACE_LEVEL_ERROR,
6271 "%s: wait on full_pwr_comp_var failed %ld",
6272 __func__, ret);
6273 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006274 }
6275 else
6276 {
6277 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08006278 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006279 VOS_ASSERT(0);
6280 return status;
6281 }
6282 }
6283
6284 status = VOS_STATUS_SUCCESS;
6285 }
6286
6287 break;
6288 }
6289 return status;
6290}
6291
6292hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08006293 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07006294 tANI_U8 rtnl_held )
6295{
6296 hdd_adapter_t *pAdapter = NULL;
6297 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
6298 VOS_STATUS status = VOS_STATUS_E_FAILURE;
6299 VOS_STATUS exitbmpsStatus;
6300
Arif Hussain6d2a3322013-11-17 19:50:10 -08006301 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d",__func__,iface_name,session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006302
Nirav Shah436658f2014-02-28 17:05:45 +05306303 if(macAddr == NULL)
6304 {
6305 /* Not received valid macAddr */
6306 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6307 "%s:Unable to add virtual intf: Not able to get"
6308 "valid mac address",__func__);
6309 return NULL;
6310 }
6311
Jeff Johnson295189b2012-06-20 16:38:30 -07006312 //Disable BMPS incase of Concurrency
6313 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
6314
6315 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
6316 {
6317 //Fail to Exit BMPS
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306318 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Exit BMPS", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006319 VOS_ASSERT(0);
6320 return NULL;
6321 }
6322
6323 switch(session_type)
6324 {
6325 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07006326 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006327 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07006328 {
6329 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
6330
6331 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306332 {
6333 hddLog(VOS_TRACE_LEVEL_FATAL,
6334 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006335 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306336 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006337
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306338#ifdef FEATURE_WLAN_TDLS
6339 /* A Mutex Lock is introduced while changing/initializing the mode to
6340 * protect the concurrent access for the Adapters by TDLS module.
6341 */
Rajesh Chauhana34c6e62014-03-25 16:37:58 +05306342 mutex_lock(&pHddCtx->tdls_lock);
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306343#endif
6344
Jeff Johnsone7245742012-09-05 17:12:55 -07006345 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
6346 NL80211_IFTYPE_P2P_CLIENT:
6347 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07006348
Jeff Johnson295189b2012-06-20 16:38:30 -07006349 pAdapter->device_mode = session_type;
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306350#ifdef FEATURE_WLAN_TDLS
6351 mutex_unlock(&pHddCtx->tdls_lock);
6352#endif
Sunil Dutt66485cb2013-12-19 19:05:03 +05306353
6354 status = hdd_init_station_mode( pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07006355 if( VOS_STATUS_SUCCESS != status )
6356 goto err_free_netdev;
6357
6358 status = hdd_register_interface( pAdapter, rtnl_held );
6359 if( VOS_STATUS_SUCCESS != status )
6360 {
6361 hdd_deinit_adapter(pHddCtx, pAdapter);
6362 goto err_free_netdev;
6363 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306364
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05306365 // Workqueue which gets scheduled in IPv4 notification callback.
6366 INIT_WORK(&pAdapter->ipv4NotifierWorkQueue, hdd_ipv4_notifier_work_queue);
6367
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306368#ifdef WLAN_NS_OFFLOAD
6369 // Workqueue which gets scheduled in IPv6 notification callback.
6370 INIT_WORK(&pAdapter->ipv6NotifierWorkQueue, hdd_ipv6_notifier_work_queue);
6371#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006372 //Stop the Interface TX queue.
6373 netif_tx_disable(pAdapter->dev);
6374 //netif_tx_disable(pWlanDev);
6375 netif_carrier_off(pAdapter->dev);
6376
6377 break;
6378 }
6379
Jeff Johnson295189b2012-06-20 16:38:30 -07006380 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07006381 case WLAN_HDD_SOFTAP:
6382 {
6383 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
6384 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306385 {
6386 hddLog(VOS_TRACE_LEVEL_FATAL,
6387 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006388 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306389 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006390
Jeff Johnson295189b2012-06-20 16:38:30 -07006391 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
6392 NL80211_IFTYPE_AP:
6393 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07006394 pAdapter->device_mode = session_type;
6395
6396 status = hdd_init_ap_mode(pAdapter);
6397 if( VOS_STATUS_SUCCESS != status )
6398 goto err_free_netdev;
6399
6400 status = hdd_register_hostapd( pAdapter, rtnl_held );
6401 if( VOS_STATUS_SUCCESS != status )
6402 {
6403 hdd_deinit_adapter(pHddCtx, pAdapter);
6404 goto err_free_netdev;
6405 }
6406
6407 netif_tx_disable(pAdapter->dev);
6408 netif_carrier_off(pAdapter->dev);
6409
6410 hdd_set_conparam( 1 );
6411 break;
6412 }
6413 case WLAN_HDD_MONITOR:
6414 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006415 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
6416 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306417 {
6418 hddLog(VOS_TRACE_LEVEL_FATAL,
6419 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006420 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306421 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006422
6423 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
6424 pAdapter->device_mode = session_type;
6425 status = hdd_register_interface( pAdapter, rtnl_held );
6426#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
6427 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
6428#else
6429 pAdapter->dev->open = hdd_mon_open;
6430 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
6431#endif
6432 hdd_init_tx_rx( pAdapter );
6433 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
6434 //Set adapter to be used for data tx. It will use either GO or softap.
6435 pAdapter->sessionCtx.monitor.pAdapterForTx =
6436 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07006437 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
6438 {
6439 pAdapter->sessionCtx.monitor.pAdapterForTx =
6440 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
6441 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006442 /* This workqueue will be used to transmit management packet over
6443 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07006444 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
6445 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
6446 return NULL;
6447 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07006448
Jeff Johnson295189b2012-06-20 16:38:30 -07006449 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
6450 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07006451 }
6452 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07006453 case WLAN_HDD_FTM:
6454 {
6455 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
6456
6457 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306458 {
6459 hddLog(VOS_TRACE_LEVEL_FATAL,
6460 FL("failed to allocate adapter for session %d"), session_type);
6461 return NULL;
6462 }
6463
Jeff Johnson295189b2012-06-20 16:38:30 -07006464 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
6465 * message while loading driver in FTM mode. */
6466 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
6467 pAdapter->device_mode = session_type;
6468 status = hdd_register_interface( pAdapter, rtnl_held );
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05306469
6470 hdd_init_tx_rx( pAdapter );
6471
6472 //Stop the Interface TX queue.
6473 netif_tx_disable(pAdapter->dev);
6474 netif_carrier_off(pAdapter->dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07006475 }
6476 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07006477 default:
6478 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306479 hddLog(VOS_TRACE_LEVEL_FATAL,"%s Invalid session type %d",
6480 __func__, session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006481 VOS_ASSERT(0);
6482 return NULL;
6483 }
6484 }
6485
Jeff Johnson295189b2012-06-20 16:38:30 -07006486 if( VOS_STATUS_SUCCESS == status )
6487 {
6488 //Add it to the hdd's session list.
6489 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
6490 if( NULL == pHddAdapterNode )
6491 {
6492 status = VOS_STATUS_E_NOMEM;
6493 }
6494 else
6495 {
6496 pHddAdapterNode->pAdapter = pAdapter;
6497 status = hdd_add_adapter_back ( pHddCtx,
6498 pHddAdapterNode );
6499 }
6500 }
6501
6502 if( VOS_STATUS_SUCCESS != status )
6503 {
6504 if( NULL != pAdapter )
6505 {
6506 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
6507 pAdapter = NULL;
6508 }
6509 if( NULL != pHddAdapterNode )
6510 {
6511 vos_mem_free( pHddAdapterNode );
6512 }
6513
6514 goto resume_bmps;
6515 }
6516
6517 if(VOS_STATUS_SUCCESS == status)
6518 {
6519 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
6520
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07006521 //Initialize the WoWL service
6522 if(!hdd_init_wowl(pAdapter))
6523 {
6524 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
6525 goto err_free_netdev;
6526 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006527 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006528 return pAdapter;
6529
6530err_free_netdev:
6531 free_netdev(pAdapter->dev);
6532 wlan_hdd_release_intf_addr( pHddCtx,
6533 pAdapter->macAddressCurrent.bytes );
6534
6535resume_bmps:
6536 //If bmps disabled enable it
6537 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
6538 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306539 if (pHddCtx->hdd_wlan_suspended)
6540 {
6541 hdd_set_pwrparams(pHddCtx);
6542 }
6543 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07006544 }
6545 return NULL;
6546}
6547
6548VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
6549 tANI_U8 rtnl_held )
6550{
6551 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
6552 VOS_STATUS status;
6553
6554 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
6555 if( VOS_STATUS_SUCCESS != status )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306556 {
6557 hddLog(VOS_TRACE_LEVEL_WARN,"%s: adapter list empty %d",
6558 __func__, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07006559 return status;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306560 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006561
6562 while ( pCurrent->pAdapter != pAdapter )
6563 {
6564 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
6565 if( VOS_STATUS_SUCCESS != status )
6566 break;
6567
6568 pCurrent = pNext;
6569 }
6570 pAdapterNode = pCurrent;
6571 if( VOS_STATUS_SUCCESS == status )
6572 {
6573 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
6574 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306575
6576#ifdef FEATURE_WLAN_TDLS
6577
6578 /* A Mutex Lock is introduced while changing/initializing the mode to
6579 * protect the concurrent access for the Adapters by TDLS module.
6580 */
Rajesh Chauhana34c6e62014-03-25 16:37:58 +05306581 mutex_lock(&pHddCtx->tdls_lock);
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306582#endif
6583
Jeff Johnson295189b2012-06-20 16:38:30 -07006584 hdd_remove_adapter( pHddCtx, pAdapterNode );
6585 vos_mem_free( pAdapterNode );
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08006586 pAdapterNode = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006587
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306588#ifdef FEATURE_WLAN_TDLS
6589 mutex_unlock(&pHddCtx->tdls_lock);
6590#endif
6591
Jeff Johnson295189b2012-06-20 16:38:30 -07006592
6593 /* If there is a single session of STA/P2P client, re-enable BMPS */
Agarwal Ashish51325b52014-06-16 16:50:49 +05306594 if ((!vos_concurrent_open_sessions_running()) &&
6595 ((pHddCtx->no_of_open_sessions[VOS_STA_MODE] >= 1) ||
6596 (pHddCtx->no_of_open_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
Jeff Johnson295189b2012-06-20 16:38:30 -07006597 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306598 if (pHddCtx->hdd_wlan_suspended)
6599 {
6600 hdd_set_pwrparams(pHddCtx);
6601 }
6602 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07006603 }
6604
6605 return VOS_STATUS_SUCCESS;
6606 }
6607
6608 return VOS_STATUS_E_FAILURE;
6609}
6610
6611VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
6612{
6613 hdd_adapter_list_node_t *pHddAdapterNode;
6614 VOS_STATUS status;
6615
6616 ENTER();
6617
6618 do
6619 {
6620 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
6621 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
6622 {
6623 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
6624 vos_mem_free( pHddAdapterNode );
6625 }
6626 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
6627
6628 EXIT();
6629
6630 return VOS_STATUS_SUCCESS;
6631}
6632
6633void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
6634{
6635 v_U8_t addIE[1] = {0};
6636
6637 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6638 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
6639 eANI_BOOLEAN_FALSE) )
6640 {
6641 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006642 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006643 }
6644
6645 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6646 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
6647 eANI_BOOLEAN_FALSE) )
6648 {
6649 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006650 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006651 }
6652
6653 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6654 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
6655 eANI_BOOLEAN_FALSE) )
6656 {
6657 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006658 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006659 }
6660}
6661
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05306662VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
6663 const v_BOOL_t bCloseSession )
Jeff Johnson295189b2012-06-20 16:38:30 -07006664{
6665 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
6666 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6667 union iwreq_data wrqu;
Kaushik, Sushant7005e372014-04-08 11:36:54 +05306668 v_U8_t retry = 0;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306669 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07006670
6671 ENTER();
6672
6673 switch(pAdapter->device_mode)
6674 {
6675 case WLAN_HDD_INFRA_STATION:
6676 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006677 case WLAN_HDD_P2P_DEVICE:
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05306678 {
6679 hdd_station_ctx_t *pstation = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6680 if( hdd_connIsConnected(pstation) ||
6681 (pstation->conn_info.connState == eConnectionState_Connecting) )
Jeff Johnson295189b2012-06-20 16:38:30 -07006682 {
6683 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
6684 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
6685 pAdapter->sessionId,
6686 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
6687 else
6688 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
6689 pAdapter->sessionId,
6690 eCSR_DISCONNECT_REASON_UNSPECIFIED);
6691 //success implies disconnect command got queued up successfully
6692 if(halStatus == eHAL_STATUS_SUCCESS)
6693 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306694 ret = wait_for_completion_interruptible_timeout(
6695 &pAdapter->disconnect_comp_var,
6696 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6697 if (ret <= 0)
6698 {
6699 hddLog(VOS_TRACE_LEVEL_ERROR,
6700 "%s: wait on disconnect_comp_var failed %ld",
6701 __func__, ret);
6702 }
6703 }
6704 else
6705 {
6706 hddLog(LOGE, "%s: failed to post disconnect event to SME",
6707 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006708 }
6709 memset(&wrqu, '\0', sizeof(wrqu));
6710 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
6711 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
6712 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
6713 }
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05306714 else if(pstation->conn_info.connState ==
6715 eConnectionState_Disconnecting)
6716 {
6717 ret = wait_for_completion_interruptible_timeout(
6718 &pAdapter->disconnect_comp_var,
6719 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6720 if (ret <= 0)
6721 {
6722 hddLog(VOS_TRACE_LEVEL_ERROR,
6723 FL("wait on disconnect_comp_var failed %ld"), ret);
6724 }
6725 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006726 else
6727 {
Srinivas, Dasari138af4f2014-02-07 11:13:45 +05306728 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
6729 eCSR_SCAN_ABORT_DEFAULT);
Jeff Johnson295189b2012-06-20 16:38:30 -07006730 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +05306731 if (pAdapter->device_mode != WLAN_HDD_INFRA_STATION)
6732 {
6733 while (pAdapter->is_roc_inprogress)
6734 {
6735 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6736 "%s: ROC in progress for session %d!!!",
6737 __func__, pAdapter->sessionId);
6738 // waiting for ROC to expire
6739 msleep(500);
6740 /* In GO present case , if retry exceeds 3,
6741 it means something went wrong. */
6742 if ( retry++ > MAX_WAIT_FOR_ROC_COMPLETION )
6743 {
6744 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6745 "%s: ROC completion is not received.!!!", __func__);
6746 sme_CancelRemainOnChannel(WLAN_HDD_GET_HAL_CTX(pAdapter),
6747 pAdapter->sessionId);
6748 wait_for_completion_interruptible_timeout(
6749 &pAdapter->cancel_rem_on_chan_var,
6750 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
6751 break;
6752 }
6753 }
6754 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306755#ifdef WLAN_NS_OFFLOAD
Vinay Krishna Eranna941360f2014-01-16 15:38:22 +05306756#ifdef WLAN_OPEN_SOURCE
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306757 cancel_work_sync(&pAdapter->ipv6NotifierWorkQueue);
6758#endif
Vinay Krishna Eranna941360f2014-01-16 15:38:22 +05306759 if (pAdapter->ipv6_notifier_registered)
6760 {
6761 hddLog(LOG1, FL("Unregistered IPv6 notifier"));
6762 unregister_inet6addr_notifier(&pAdapter->ipv6_notifier);
6763 pAdapter->ipv6_notifier_registered = false;
6764 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306765#endif
Vinay Krishna Erannad9cbdb32014-01-16 12:59:10 +05306766 if (pAdapter->ipv4_notifier_registered)
6767 {
6768 hddLog(LOG1, FL("Unregistered IPv4 notifier"));
6769 unregister_inetaddr_notifier(&pAdapter->ipv4_notifier);
6770 pAdapter->ipv4_notifier_registered = false;
6771 }
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05306772#ifdef WLAN_OPEN_SOURCE
6773 cancel_work_sync(&pAdapter->ipv4NotifierWorkQueue);
6774#endif
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05306775 /* It is possible that the caller of this function does not
6776 * wish to close the session
6777 */
6778 if (VOS_TRUE == bCloseSession &&
6779 test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07006780 {
6781 INIT_COMPLETION(pAdapter->session_close_comp_var);
6782 if (eHAL_STATUS_SUCCESS ==
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05306783 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
6784 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07006785 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306786 unsigned long ret;
6787
Jeff Johnson295189b2012-06-20 16:38:30 -07006788 //Block on a completion variable. Can't wait forever though.
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306789 ret = wait_for_completion_timeout(
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05306790 &pAdapter->session_close_comp_var,
6791 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306792 if ( 0 >= ret)
6793 {
6794 hddLog(LOGE, "%s: failure waiting for session_close_comp_var %ld",
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05306795 __func__, ret);
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306796 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006797 }
6798 }
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05306799 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006800 break;
6801
6802 case WLAN_HDD_SOFTAP:
6803 case WLAN_HDD_P2P_GO:
6804 //Any softap specific cleanup here...
Kaushik, Sushant7005e372014-04-08 11:36:54 +05306805 if (pAdapter->device_mode == WLAN_HDD_P2P_GO) {
6806 while (pAdapter->is_roc_inprogress) {
6807 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6808 "%s: ROC in progress for session %d!!!",
6809 __func__, pAdapter->sessionId);
6810 msleep(500);
6811 if ( retry++ > MAX_WAIT_FOR_ROC_COMPLETION ) {
6812 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6813 "%s: ROC completion is not received.!!!", __func__);
6814 WLANSAP_CancelRemainOnChannel(
6815 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
6816 wait_for_completion_interruptible_timeout(
6817 &pAdapter->cancel_rem_on_chan_var,
6818 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
6819 break;
6820 }
6821 }
6822 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006823 mutex_lock(&pHddCtx->sap_lock);
6824 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
6825 {
6826 VOS_STATUS status;
6827 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6828
6829 //Stop Bss.
6830 status = WLANSAP_StopBss(pHddCtx->pvosContext);
6831 if (VOS_IS_STATUS_SUCCESS(status))
6832 {
6833 hdd_hostapd_state_t *pHostapdState =
6834 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6835
6836 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
6837
6838 if (!VOS_IS_STATUS_SUCCESS(status))
6839 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306840 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss %d",
6841 __func__, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07006842 }
6843 }
6844 else
6845 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006846 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006847 }
6848 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
Agarwal Ashish51325b52014-06-16 16:50:49 +05306849 wlan_hdd_decr_active_session(pHddCtx, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07006850
6851 if (eHAL_STATUS_FAILURE ==
6852 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
6853 0, NULL, eANI_BOOLEAN_FALSE))
6854 {
6855 hddLog(LOGE,
6856 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006857 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006858 }
6859
6860 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
6861 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
6862 eANI_BOOLEAN_FALSE) )
6863 {
6864 hddLog(LOGE,
6865 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
6866 }
6867
6868 // Reset WNI_CFG_PROBE_RSP Flags
6869 wlan_hdd_reset_prob_rspies(pAdapter);
6870 kfree(pAdapter->sessionCtx.ap.beacon);
6871 pAdapter->sessionCtx.ap.beacon = NULL;
6872 }
6873 mutex_unlock(&pHddCtx->sap_lock);
6874 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006875
Jeff Johnson295189b2012-06-20 16:38:30 -07006876 case WLAN_HDD_MONITOR:
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006877#ifdef WLAN_OPEN_SOURCE
6878 cancel_work_sync(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue);
6879#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006880 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006881
Jeff Johnson295189b2012-06-20 16:38:30 -07006882 default:
6883 break;
6884 }
6885
6886 EXIT();
6887 return VOS_STATUS_SUCCESS;
6888}
6889
6890VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
6891{
6892 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6893 VOS_STATUS status;
6894 hdd_adapter_t *pAdapter;
6895
6896 ENTER();
6897
6898 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6899
6900 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6901 {
6902 pAdapter = pAdapterNode->pAdapter;
6903 netif_tx_disable(pAdapter->dev);
6904 netif_carrier_off(pAdapter->dev);
6905
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05306906 hdd_stop_adapter( pHddCtx, pAdapter, VOS_TRUE );
Jeff Johnson295189b2012-06-20 16:38:30 -07006907
6908 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6909 pAdapterNode = pNext;
6910 }
6911
6912 EXIT();
6913
6914 return VOS_STATUS_SUCCESS;
6915}
6916
Rajeev Kumarf999e582014-01-09 17:33:29 -08006917
6918#ifdef FEATURE_WLAN_BATCH_SCAN
6919/**---------------------------------------------------------------------------
6920
6921 \brief hdd_deinit_batch_scan () - This function cleans up batch scan data
6922 structures
6923
6924 \param - pAdapter Pointer to HDD adapter
6925
6926 \return - None
6927
6928 --------------------------------------------------------------------------*/
6929void hdd_deinit_batch_scan(hdd_adapter_t *pAdapter)
6930{
6931 tHddBatchScanRsp *pNode;
6932 tHddBatchScanRsp *pPrev;
6933
Siddharth Bhalb3e9b792014-02-24 15:14:16 +05306934 if (NULL == pAdapter)
Rajeev Kumarf999e582014-01-09 17:33:29 -08006935 {
Siddharth Bhalb3e9b792014-02-24 15:14:16 +05306936 hddLog(VOS_TRACE_LEVEL_ERROR,
6937 "%s: Adapter context is Null", __func__);
6938 return;
6939 }
6940
6941 pNode = pAdapter->pBatchScanRsp;
6942 while (pNode)
6943 {
6944 pPrev = pNode;
6945 pNode = pNode->pNext;
6946 vos_mem_free((v_VOID_t * )pPrev);
Rajeev Kumarf999e582014-01-09 17:33:29 -08006947 }
6948
6949 pAdapter->pBatchScanRsp = NULL;
6950 pAdapter->numScanList = 0;
6951 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
6952 pAdapter->prev_batch_id = 0;
6953
6954 return;
6955}
6956#endif
6957
6958
Jeff Johnson295189b2012-06-20 16:38:30 -07006959VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
6960{
6961 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6962 VOS_STATUS status;
6963 hdd_adapter_t *pAdapter;
6964
6965 ENTER();
6966
6967 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6968
6969 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6970 {
6971 pAdapter = pAdapterNode->pAdapter;
6972 netif_tx_disable(pAdapter->dev);
6973 netif_carrier_off(pAdapter->dev);
6974
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07006975 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
6976
Jeff Johnson295189b2012-06-20 16:38:30 -07006977 hdd_deinit_tx_rx(pAdapter);
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05306978 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
6979 {
6980 hdd_wmm_adapter_close( pAdapter );
6981 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
6982 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006983
Rajeev Kumarf999e582014-01-09 17:33:29 -08006984#ifdef FEATURE_WLAN_BATCH_SCAN
6985 if (eHDD_BATCH_SCAN_STATE_STARTED == pAdapter->batchScanState)
6986 {
6987 hdd_deinit_batch_scan(pAdapter);
6988 }
6989#endif
6990
Jeff Johnson295189b2012-06-20 16:38:30 -07006991 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6992 pAdapterNode = pNext;
6993 }
6994
6995 EXIT();
6996
6997 return VOS_STATUS_SUCCESS;
6998}
6999
7000VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
7001{
7002 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7003 VOS_STATUS status;
7004 hdd_adapter_t *pAdapter;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05307005 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -07007006
7007 ENTER();
7008
7009 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7010
7011 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7012 {
7013 pAdapter = pAdapterNode->pAdapter;
7014
Kumar Anand82c009f2014-05-29 00:29:42 -07007015 hdd_wmm_init( pAdapter );
7016
Jeff Johnson295189b2012-06-20 16:38:30 -07007017 switch(pAdapter->device_mode)
7018 {
7019 case WLAN_HDD_INFRA_STATION:
7020 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07007021 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05307022
7023 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
7024
Jeff Johnson295189b2012-06-20 16:38:30 -07007025 hdd_init_station_mode(pAdapter);
7026 /* Open the gates for HDD to receive Wext commands */
7027 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07007028 pHddCtx->scan_info.mScanPending = FALSE;
7029 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07007030
7031 //Trigger the initial scan
7032 hdd_wlan_initial_scan(pAdapter);
7033
7034 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05307035 if (eConnectionState_Associated == connState ||
7036 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -07007037 {
7038 union iwreq_data wrqu;
7039 memset(&wrqu, '\0', sizeof(wrqu));
7040 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
7041 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
7042 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07007043 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07007044
Jeff Johnson295189b2012-06-20 16:38:30 -07007045 /* indicate disconnected event to nl80211 */
7046 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
7047 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07007048 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05307049 else if (eConnectionState_Connecting == connState)
7050 {
7051 /*
7052 * Indicate connect failure to supplicant if we were in the
7053 * process of connecting
7054 */
7055 cfg80211_connect_result(pAdapter->dev, NULL,
7056 NULL, 0, NULL, 0,
7057 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
7058 GFP_KERNEL);
7059 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007060 break;
7061
7062 case WLAN_HDD_SOFTAP:
7063 /* softAP can handle SSR */
7064 break;
7065
7066 case WLAN_HDD_P2P_GO:
Sameer Thalappiledf0d792013-08-09 14:31:03 -07007067 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send stop ap to supplicant",
Jeff Johnson295189b2012-06-20 16:38:30 -07007068 __func__);
Sameer Thalappiledf0d792013-08-09 14:31:03 -07007069 cfg80211_ap_stopped(pAdapter->dev, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07007070 break;
7071
7072 case WLAN_HDD_MONITOR:
7073 /* monitor interface start */
7074 break;
7075 default:
7076 break;
7077 }
7078
7079 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7080 pAdapterNode = pNext;
7081 }
7082
7083 EXIT();
7084
7085 return VOS_STATUS_SUCCESS;
7086}
7087
7088VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
7089{
7090 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7091 hdd_adapter_t *pAdapter;
7092 VOS_STATUS status;
7093 v_U32_t roamId;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307094 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07007095
7096 ENTER();
7097
7098 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7099
7100 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7101 {
7102 pAdapter = pAdapterNode->pAdapter;
7103
7104 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
7105 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
7106 {
7107 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7108 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
7109
Abhishek Singhf4669da2014-05-26 15:07:49 +05307110 hddLog(VOS_TRACE_LEVEL_INFO,
7111 "%s: Set HDD connState to eConnectionState_NotConnected",
7112 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007113 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
7114 init_completion(&pAdapter->disconnect_comp_var);
7115 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
7116 eCSR_DISCONNECT_REASON_UNSPECIFIED);
7117
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307118 ret = wait_for_completion_interruptible_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07007119 &pAdapter->disconnect_comp_var,
7120 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307121 if (0 >= ret)
7122 hddLog(LOGE, "%s: failure waiting for disconnect_comp_var %ld",
7123 __func__, ret);
Jeff Johnson295189b2012-06-20 16:38:30 -07007124
7125 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
7126 pHddCtx->isAmpAllowed = VOS_FALSE;
7127 sme_RoamConnect(pHddCtx->hHal,
7128 pAdapter->sessionId, &(pWextState->roamProfile),
7129 &roamId);
7130 }
7131
7132 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7133 pAdapterNode = pNext;
7134 }
7135
7136 EXIT();
7137
7138 return VOS_STATUS_SUCCESS;
7139}
7140
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07007141void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
7142{
7143 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7144 VOS_STATUS status;
7145 hdd_adapter_t *pAdapter;
7146 hdd_station_ctx_t *pHddStaCtx;
7147 hdd_ap_ctx_t *pHddApCtx;
7148 hdd_hostapd_state_t * pHostapdState;
7149 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
7150 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
7151 const char *p2pMode = "DEV";
7152 const char *ccMode = "Standalone";
7153 int n;
7154
7155 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7156 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7157 {
7158 pAdapter = pAdapterNode->pAdapter;
7159 switch (pAdapter->device_mode) {
7160 case WLAN_HDD_INFRA_STATION:
7161 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7162 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
7163 staChannel = pHddStaCtx->conn_info.operationChannel;
7164 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
7165 }
7166 break;
7167 case WLAN_HDD_P2P_CLIENT:
7168 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7169 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
7170 p2pChannel = pHddStaCtx->conn_info.operationChannel;
7171 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
7172 p2pMode = "CLI";
7173 }
7174 break;
7175 case WLAN_HDD_P2P_GO:
7176 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
7177 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
7178 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
7179 p2pChannel = pHddApCtx->operatingChannel;
7180 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
7181 }
7182 p2pMode = "GO";
7183 break;
7184 case WLAN_HDD_SOFTAP:
7185 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
7186 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
7187 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
7188 apChannel = pHddApCtx->operatingChannel;
7189 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
7190 }
7191 break;
7192 default:
7193 break;
7194 }
7195 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7196 pAdapterNode = pNext;
7197 }
7198 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
7199 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
7200 }
7201 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
7202 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
7203 if (p2pChannel > 0) {
7204 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
7205 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
7206 }
7207 if (apChannel > 0) {
7208 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
7209 apChannel, MAC_ADDR_ARRAY(apBssid));
7210 }
7211
7212 if (p2pChannel > 0 && apChannel > 0) {
7213 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
7214 }
7215}
7216
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07007217bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07007218{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07007219 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07007220}
7221
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07007222/* Once SSR is disabled then it cannot be set. */
7223void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07007224{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07007225 if (HDD_SSR_DISABLED == isSsrRequired)
7226 return;
7227
Jeff Johnson295189b2012-06-20 16:38:30 -07007228 isSsrRequired = value;
7229}
7230
7231VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
7232 hdd_adapter_list_node_t** ppAdapterNode)
7233{
7234 VOS_STATUS status;
7235 spin_lock(&pHddCtx->hddAdapters.lock);
7236 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
7237 (hdd_list_node_t**) ppAdapterNode );
7238 spin_unlock(&pHddCtx->hddAdapters.lock);
7239 return status;
7240}
7241
7242VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
7243 hdd_adapter_list_node_t* pAdapterNode,
7244 hdd_adapter_list_node_t** pNextAdapterNode)
7245{
7246 VOS_STATUS status;
7247 spin_lock(&pHddCtx->hddAdapters.lock);
7248 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
7249 (hdd_list_node_t*) pAdapterNode,
7250 (hdd_list_node_t**)pNextAdapterNode );
7251
7252 spin_unlock(&pHddCtx->hddAdapters.lock);
7253 return status;
7254}
7255
7256VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
7257 hdd_adapter_list_node_t* pAdapterNode)
7258{
7259 VOS_STATUS status;
7260 spin_lock(&pHddCtx->hddAdapters.lock);
7261 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
7262 &pAdapterNode->node );
7263 spin_unlock(&pHddCtx->hddAdapters.lock);
7264 return status;
7265}
7266
7267VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
7268 hdd_adapter_list_node_t** ppAdapterNode)
7269{
7270 VOS_STATUS status;
7271 spin_lock(&pHddCtx->hddAdapters.lock);
7272 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
7273 (hdd_list_node_t**) ppAdapterNode );
7274 spin_unlock(&pHddCtx->hddAdapters.lock);
7275 return status;
7276}
7277
7278VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
7279 hdd_adapter_list_node_t* pAdapterNode)
7280{
7281 VOS_STATUS status;
7282 spin_lock(&pHddCtx->hddAdapters.lock);
7283 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
7284 (hdd_list_node_t*) pAdapterNode );
7285 spin_unlock(&pHddCtx->hddAdapters.lock);
7286 return status;
7287}
7288
7289VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
7290 hdd_adapter_list_node_t* pAdapterNode)
7291{
7292 VOS_STATUS status;
7293 spin_lock(&pHddCtx->hddAdapters.lock);
7294 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
7295 (hdd_list_node_t*) pAdapterNode );
7296 spin_unlock(&pHddCtx->hddAdapters.lock);
7297 return status;
7298}
7299
7300hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
7301 tSirMacAddr macAddr )
7302{
7303 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7304 hdd_adapter_t *pAdapter;
7305 VOS_STATUS status;
7306
7307 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7308
7309 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7310 {
7311 pAdapter = pAdapterNode->pAdapter;
7312
7313 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
7314 macAddr, sizeof(tSirMacAddr) ) )
7315 {
7316 return pAdapter;
7317 }
7318 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7319 pAdapterNode = pNext;
7320 }
7321
7322 return NULL;
7323
7324}
7325
7326hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
7327{
7328 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7329 hdd_adapter_t *pAdapter;
7330 VOS_STATUS status;
7331
7332 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7333
7334 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7335 {
7336 pAdapter = pAdapterNode->pAdapter;
7337
7338 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
7339 IFNAMSIZ ) )
7340 {
7341 return pAdapter;
7342 }
7343 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7344 pAdapterNode = pNext;
7345 }
7346
7347 return NULL;
7348
7349}
7350
7351hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
7352{
7353 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7354 hdd_adapter_t *pAdapter;
7355 VOS_STATUS status;
7356
7357 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7358
7359 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7360 {
7361 pAdapter = pAdapterNode->pAdapter;
7362
7363 if( pAdapter && (mode == pAdapter->device_mode) )
7364 {
7365 return pAdapter;
7366 }
7367 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7368 pAdapterNode = pNext;
7369 }
7370
7371 return NULL;
7372
7373}
7374
7375//Remove this function later
7376hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
7377{
7378 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7379 hdd_adapter_t *pAdapter;
7380 VOS_STATUS status;
7381
7382 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7383
7384 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7385 {
7386 pAdapter = pAdapterNode->pAdapter;
7387
7388 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
7389 {
7390 return pAdapter;
7391 }
7392
7393 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7394 pAdapterNode = pNext;
7395 }
7396
7397 return NULL;
7398
7399}
7400
Jeff Johnson295189b2012-06-20 16:38:30 -07007401/**---------------------------------------------------------------------------
7402
7403 \brief hdd_set_monitor_tx_adapter() -
7404
7405 This API initializes the adapter to be used while transmitting on monitor
7406 adapter.
7407
7408 \param - pHddCtx - Pointer to the HDD context.
7409 pAdapter - Adapter that will used for TX. This can be NULL.
7410 \return - None.
7411 --------------------------------------------------------------------------*/
7412void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
7413{
7414 hdd_adapter_t *pMonAdapter;
7415
7416 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
7417
7418 if( NULL != pMonAdapter )
7419 {
7420 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
7421 }
7422}
Jeff Johnson295189b2012-06-20 16:38:30 -07007423/**---------------------------------------------------------------------------
7424
7425 \brief hdd_select_queue() -
7426
7427 This API returns the operating channel of the requested device mode
7428
7429 \param - pHddCtx - Pointer to the HDD context.
7430 - mode - Device mode for which operating channel is required
7431 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
7432 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
7433 \return - channel number. "0" id the requested device is not found OR it is not connected.
7434 --------------------------------------------------------------------------*/
7435v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
7436{
7437 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7438 VOS_STATUS status;
7439 hdd_adapter_t *pAdapter;
7440 v_U8_t operatingChannel = 0;
7441
7442 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7443
7444 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7445 {
7446 pAdapter = pAdapterNode->pAdapter;
7447
7448 if( mode == pAdapter->device_mode )
7449 {
7450 switch(pAdapter->device_mode)
7451 {
7452 case WLAN_HDD_INFRA_STATION:
7453 case WLAN_HDD_P2P_CLIENT:
7454 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
7455 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
7456 break;
7457 case WLAN_HDD_SOFTAP:
7458 case WLAN_HDD_P2P_GO:
7459 /*softap connection info */
7460 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
7461 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
7462 break;
7463 default:
7464 break;
7465 }
7466
7467 break; //Found the device of interest. break the loop
7468 }
7469
7470 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7471 pAdapterNode = pNext;
7472 }
7473 return operatingChannel;
7474}
7475
7476#ifdef WLAN_FEATURE_PACKET_FILTERING
7477/**---------------------------------------------------------------------------
7478
7479 \brief hdd_set_multicast_list() -
7480
7481 This used to set the multicast address list.
7482
7483 \param - dev - Pointer to the WLAN device.
7484 - skb - Pointer to OS packet (sk_buff).
7485 \return - success/fail
7486
7487 --------------------------------------------------------------------------*/
7488static void hdd_set_multicast_list(struct net_device *dev)
7489{
7490 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07007491 int mc_count;
7492 int i = 0;
7493 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307494
7495 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07007496 {
7497 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307498 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007499 return;
7500 }
7501
7502 if (dev->flags & IFF_ALLMULTI)
7503 {
7504 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007505 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307506 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07007507 }
7508 else
7509 {
7510 mc_count = netdev_mc_count(dev);
7511 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007512 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07007513 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
7514 {
7515 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007516 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307517 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07007518 return;
7519 }
7520
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307521 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07007522
7523 netdev_for_each_mc_addr(ha, dev) {
7524 if (i == mc_count)
7525 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307526 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
7527 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
Arif Hussain6d2a3322013-11-17 19:50:10 -08007528 hddLog(VOS_TRACE_LEVEL_INFO, "%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07007529 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307530 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07007531 i++;
7532 }
7533 }
7534 return;
7535}
7536#endif
7537
7538/**---------------------------------------------------------------------------
7539
7540 \brief hdd_select_queue() -
7541
7542 This function is registered with the Linux OS for network
7543 core to decide which queue to use first.
7544
7545 \param - dev - Pointer to the WLAN device.
7546 - skb - Pointer to OS packet (sk_buff).
7547 \return - ac, Queue Index/access category corresponding to UP in IP header
7548
7549 --------------------------------------------------------------------------*/
7550v_U16_t hdd_select_queue(struct net_device *dev,
7551 struct sk_buff *skb)
7552{
7553 return hdd_wmm_select_queue(dev, skb);
7554}
7555
7556
7557/**---------------------------------------------------------------------------
7558
7559 \brief hdd_wlan_initial_scan() -
7560
7561 This function triggers the initial scan
7562
7563 \param - pAdapter - Pointer to the HDD adapter.
7564
7565 --------------------------------------------------------------------------*/
7566void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
7567{
7568 tCsrScanRequest scanReq;
7569 tCsrChannelInfo channelInfo;
7570 eHalStatus halStatus;
Jeff Johnson02797792013-10-26 19:17:13 -07007571 tANI_U32 scanId;
Jeff Johnson295189b2012-06-20 16:38:30 -07007572 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7573
7574 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
7575 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
7576 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
7577
7578 if(sme_Is11dSupported(pHddCtx->hHal))
7579 {
7580 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
7581 if ( HAL_STATUS_SUCCESS( halStatus ) )
7582 {
7583 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
7584 if( !scanReq.ChannelInfo.ChannelList )
7585 {
7586 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
7587 vos_mem_free(channelInfo.ChannelList);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08007588 channelInfo.ChannelList = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007589 return;
7590 }
7591 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
7592 channelInfo.numOfChannels);
7593 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
7594 vos_mem_free(channelInfo.ChannelList);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08007595 channelInfo.ChannelList = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007596 }
7597
7598 scanReq.scanType = eSIR_PASSIVE_SCAN;
7599 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
7600 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
7601 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
7602 }
7603 else
7604 {
7605 scanReq.scanType = eSIR_ACTIVE_SCAN;
7606 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
7607 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
7608 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
7609 }
7610
7611 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
7612 if ( !HAL_STATUS_SUCCESS( halStatus ) )
7613 {
7614 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
7615 __func__, halStatus );
7616 }
7617
7618 if(sme_Is11dSupported(pHddCtx->hHal))
7619 vos_mem_free(scanReq.ChannelInfo.ChannelList);
7620}
7621
Jeff Johnson295189b2012-06-20 16:38:30 -07007622/**---------------------------------------------------------------------------
7623
7624 \brief hdd_full_power_callback() - HDD full power callback function
7625
7626 This is the function invoked by SME to inform the result of a full power
7627 request issued by HDD
7628
7629 \param - callbackcontext - Pointer to cookie
7630 \param - status - result of request
7631
7632 \return - None
7633
7634 --------------------------------------------------------------------------*/
7635static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
7636{
Jeff Johnson72a40512013-12-19 10:14:15 -08007637 struct statsContext *pContext = callbackContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07007638
7639 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307640 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07007641
7642 if (NULL == callbackContext)
7643 {
7644 hddLog(VOS_TRACE_LEVEL_ERROR,
7645 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007646 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07007647 return;
7648 }
7649
Jeff Johnson72a40512013-12-19 10:14:15 -08007650 /* there is a race condition that exists between this callback
7651 function and the caller since the caller could time out either
7652 before or while this code is executing. we use a spinlock to
7653 serialize these actions */
7654 spin_lock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07007655
7656 if (POWER_CONTEXT_MAGIC != pContext->magic)
7657 {
7658 /* the caller presumably timed out so there is nothing we can do */
Jeff Johnson72a40512013-12-19 10:14:15 -08007659 spin_unlock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07007660 hddLog(VOS_TRACE_LEVEL_WARN,
7661 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007662 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07007663 return;
7664 }
7665
Jeff Johnson72a40512013-12-19 10:14:15 -08007666 /* context is valid so caller is still waiting */
7667
7668 /* paranoia: invalidate the magic */
7669 pContext->magic = 0;
7670
7671 /* notify the caller */
Jeff Johnson295189b2012-06-20 16:38:30 -07007672 complete(&pContext->completion);
Jeff Johnson72a40512013-12-19 10:14:15 -08007673
7674 /* serialization is complete */
7675 spin_unlock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07007676}
7677
7678/**---------------------------------------------------------------------------
7679
7680 \brief hdd_wlan_exit() - HDD WLAN exit function
7681
7682 This is the driver exit point (invoked during rmmod)
7683
7684 \param - pHddCtx - Pointer to the HDD Context
7685
7686 \return - None
7687
7688 --------------------------------------------------------------------------*/
7689void hdd_wlan_exit(hdd_context_t *pHddCtx)
7690{
7691 eHalStatus halStatus;
7692 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
7693 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05307694 struct wiphy *wiphy = pHddCtx->wiphy;
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -08007695 hdd_adapter_t* pAdapter = NULL;
Jeff Johnson72a40512013-12-19 10:14:15 -08007696 struct statsContext powerContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07007697 long lrc;
c_hpothu5ab05e92014-06-13 17:34:05 +05307698 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007699
7700 ENTER();
7701
Jeff Johnson88ba7742013-02-27 14:36:02 -08007702 if (VOS_FTM_MODE != hdd_get_conparam())
7703 {
7704 // Unloading, restart logic is no more required.
7705 wlan_hdd_restart_deinit(pHddCtx);
Jeff Johnsone7245742012-09-05 17:12:55 -07007706
c_hpothu5ab05e92014-06-13 17:34:05 +05307707 vosStatus = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7708 while (NULL != pAdapterNode && VOS_STATUS_E_EMPTY != vosStatus)
Jeff Johnson295189b2012-06-20 16:38:30 -07007709 {
c_hpothu5ab05e92014-06-13 17:34:05 +05307710 pAdapter = pAdapterNode->pAdapter;
7711 if (NULL != pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07007712 {
c_hpothu5ab05e92014-06-13 17:34:05 +05307713 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode ||
7714 WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)
7715 {
7716 wlan_hdd_cfg80211_deregister_frames(pAdapter);
7717 hdd_UnregisterWext(pAdapter->dev);
7718 }
7719 // Cancel any outstanding scan requests. We are about to close all
7720 // of our adapters, but an adapter structure is what SME passes back
7721 // to our callback function. Hence if there are any outstanding scan
7722 // requests then there is a race condition between when the adapter
7723 // is closed and when the callback is invoked.We try to resolve that
7724 // race condition here by canceling any outstanding scans before we
7725 // close the adapters.
7726 // Note that the scans may be cancelled in an asynchronous manner,
7727 // so ideally there needs to be some kind of synchronization. Rather
7728 // than introduce a new synchronization here, we will utilize the
7729 // fact that we are about to Request Full Power, and since that is
7730 // synchronized, the expectation is that by the time Request Full
7731 // Power has completed all scans will be cancelled.
7732 if (pHddCtx->scan_info.mScanPending)
7733 {
7734 hddLog(VOS_TRACE_LEVEL_INFO,
7735 FL("abort scan mode: %d sessionId: %d"),
7736 pAdapter->device_mode,
7737 pAdapter->sessionId);
7738 hdd_abort_mac_scan(pHddCtx,
7739 pAdapter->sessionId,
7740 eCSR_SCAN_ABORT_DEFAULT);
7741 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007742 }
c_hpothu5ab05e92014-06-13 17:34:05 +05307743 vosStatus = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7744 pAdapterNode = pNext;
Jeff Johnson295189b2012-06-20 16:38:30 -07007745 }
7746 }
c_hpothu5ab05e92014-06-13 17:34:05 +05307747 else
Jeff Johnson88ba7742013-02-27 14:36:02 -08007748 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307749 hddLog(VOS_TRACE_LEVEL_INFO,"%s: FTM MODE",__func__);
Jeff Johnson88ba7742013-02-27 14:36:02 -08007750 wlan_hdd_ftm_close(pHddCtx);
7751 goto free_hdd_ctx;
7752 }
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307753
Jeff Johnson295189b2012-06-20 16:38:30 -07007754 /* DeRegister with platform driver as client for Suspend/Resume */
7755 vosStatus = hddDeregisterPmOps(pHddCtx);
7756 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
7757 {
7758 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
7759 VOS_ASSERT(0);
7760 }
7761
7762 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
7763 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
7764 {
7765 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
7766 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007767
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07007768 //Stop the traffic monitor timer
7769 if ( VOS_TIMER_STATE_RUNNING ==
7770 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr))
7771 {
7772 vos_timer_stop(&pHddCtx->tx_rx_trafficTmr);
7773 }
7774
7775 // Destroy the traffic monitor timer
7776 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
7777 &pHddCtx->tx_rx_trafficTmr)))
7778 {
7779 hddLog(VOS_TRACE_LEVEL_ERROR,
7780 "%s: Cannot deallocate Traffic monitor timer", __func__);
7781 }
7782
Jeff Johnson295189b2012-06-20 16:38:30 -07007783 //Disable IMPS/BMPS as we do not want the device to enter any power
7784 //save mode during shutdown
7785 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
7786 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
7787 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
7788
7789 //Ensure that device is in full power as we will touch H/W during vos_Stop
7790 init_completion(&powerContext.completion);
7791 powerContext.magic = POWER_CONTEXT_MAGIC;
7792
7793 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
7794 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
7795
7796 if (eHAL_STATUS_SUCCESS != halStatus)
7797 {
7798 if (eHAL_STATUS_PMC_PENDING == halStatus)
7799 {
7800 /* request was sent -- wait for the response */
7801 lrc = wait_for_completion_interruptible_timeout(
7802 &powerContext.completion,
7803 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
Jeff Johnson295189b2012-06-20 16:38:30 -07007804 if (lrc <= 0)
7805 {
7806 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007807 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07007808 }
7809 }
7810 else
7811 {
7812 hddLog(VOS_TRACE_LEVEL_ERROR,
7813 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007814 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07007815 /* continue -- need to clean up as much as possible */
7816 }
7817 }
7818
Jeff Johnson72a40512013-12-19 10:14:15 -08007819 /* either we never sent a request, we sent a request and received a
7820 response or we sent a request and timed out. if we never sent a
7821 request or if we sent a request and got a response, we want to
7822 clear the magic out of paranoia. if we timed out there is a
7823 race condition such that the callback function could be
7824 executing at the same time we are. of primary concern is if the
7825 callback function had already verified the "magic" but had not
7826 yet set the completion variable when a timeout occurred. we
7827 serialize these activities by invalidating the magic while
7828 holding a shared spinlock which will cause us to block if the
7829 callback is currently executing */
7830 spin_lock(&hdd_context_lock);
7831 powerContext.magic = 0;
7832 spin_unlock(&hdd_context_lock);
7833
Yue Ma0d4891e2013-08-06 17:01:45 -07007834 hdd_debugfs_exit(pHddCtx);
7835
Jeff Johnson295189b2012-06-20 16:38:30 -07007836 // Unregister the Net Device Notifier
7837 unregister_netdevice_notifier(&hdd_netdev_notifier);
7838
Jeff Johnson295189b2012-06-20 16:38:30 -07007839 hdd_stop_all_adapters( pHddCtx );
7840
Jeff Johnson295189b2012-06-20 16:38:30 -07007841#ifdef WLAN_BTAMP_FEATURE
7842 vosStatus = WLANBAP_Stop(pVosContext);
7843 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
7844 {
7845 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7846 "%s: Failed to stop BAP",__func__);
7847 }
7848#endif //WLAN_BTAMP_FEATURE
7849
7850 //Stop all the modules
7851 vosStatus = vos_stop( pVosContext );
7852 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
7853 {
7854 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7855 "%s: Failed to stop VOSS",__func__);
7856 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7857 }
7858
Jeff Johnson295189b2012-06-20 16:38:30 -07007859 //Assert Deep sleep signal now to put Libra HW in lowest power state
7860 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
7861 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7862
7863 //Vote off any PMIC voltage supplies
7864 vos_chipPowerDown(NULL, NULL, NULL);
7865
7866 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
7867
Leo Chang59cdc7e2013-07-10 10:08:21 -07007868
Jeff Johnson295189b2012-06-20 16:38:30 -07007869 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07007870 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07007871
7872 //Close the scheduler before calling vos_close to make sure no thread is
7873 // scheduled after the each module close is called i.e after all the data
7874 // structures are freed.
7875 vosStatus = vos_sched_close( pVosContext );
7876 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
7877 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
7878 "%s: Failed to close VOSS Scheduler",__func__);
7879 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7880 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007881#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07007882#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
7883 /* Destroy the wake lock */
7884 wake_lock_destroy(&pHddCtx->rx_wake_lock);
7885#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08007886 /* Destroy the wake lock */
7887 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007888#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007889
Mihir Shete7a24b5f2013-12-21 12:18:31 +05307890#ifdef CONFIG_ENABLE_LINUX_REG
7891 vosStatus = vos_nv_close();
7892 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
7893 {
7894 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7895 "%s: Failed to close NV", __func__);
7896 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7897 }
7898#endif
7899
Jeff Johnson295189b2012-06-20 16:38:30 -07007900 //Close VOSS
7901 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
7902 vos_close(pVosContext);
7903
Jeff Johnson295189b2012-06-20 16:38:30 -07007904 //Close Watchdog
7905 if(pHddCtx->cfg_ini->fIsLogpEnabled)
7906 vos_watchdog_close(pVosContext);
7907
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05307908 //Clean up HDD Nlink Service
7909 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Leo Chang59cdc7e2013-07-10 10:08:21 -07007910#ifdef WLAN_KD_READY_NOTIFIER
7911 nl_srv_exit(pHddCtx->ptt_pid);
7912#else
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05307913 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07007914#endif /* WLAN_KD_READY_NOTIFIER */
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05307915
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05307916#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05307917 if (pHddCtx->cfg_ini->wlanLoggingEnable)
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05307918 {
7919 wlan_logging_sock_deactivate_svc();
7920 }
7921#endif
7922
Jeff Johnson295189b2012-06-20 16:38:30 -07007923 /* Cancel the vote for XO Core ON.
7924 * This is done here to ensure there is no race condition since MC, TX and WD threads have
7925 * exited at this point
7926 */
7927 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
Arif Hussain6d2a3322013-11-17 19:50:10 -08007928 " when WLAN is turned OFF");
Jeff Johnson295189b2012-06-20 16:38:30 -07007929 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
7930 {
7931 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
7932 " Not returning failure."
Arif Hussain6d2a3322013-11-17 19:50:10 -08007933 " Power consumed will be high");
Jeff Johnson295189b2012-06-20 16:38:30 -07007934 }
7935
7936 hdd_close_all_adapters( pHddCtx );
7937
Jeff Johnson295189b2012-06-20 16:38:30 -07007938 /* free the power on lock from platform driver */
7939 if (free_riva_power_on_lock("wlan"))
7940 {
7941 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
7942 __func__);
7943 }
7944
Jeff Johnson88ba7742013-02-27 14:36:02 -08007945free_hdd_ctx:
c_hpothu78c7b602014-05-17 17:35:49 +05307946
7947 //Free up dynamically allocated members inside HDD Adapter
7948 if (pHddCtx->cfg_ini)
7949 {
7950 kfree(pHddCtx->cfg_ini);
7951 pHddCtx->cfg_ini= NULL;
7952 }
7953
Leo Changf04ddad2013-09-18 13:46:38 -07007954 /* FTM mode, WIPHY did not registered
7955 If un-register here, system crash will happen */
7956 if (VOS_FTM_MODE != hdd_get_conparam())
7957 {
7958 wiphy_unregister(wiphy) ;
7959 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007960 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07007961 if (hdd_is_ssr_required())
7962 {
7963 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07007964 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07007965 msleep(5000);
7966 }
7967 hdd_set_ssr_required (VOS_FALSE);
7968}
7969
7970
7971/**---------------------------------------------------------------------------
7972
7973 \brief hdd_update_config_from_nv() - Function to update the contents of
7974 the running configuration with parameters taken from NV storage
7975
7976 \param - pHddCtx - Pointer to the HDD global context
7977
7978 \return - VOS_STATUS_SUCCESS if successful
7979
7980 --------------------------------------------------------------------------*/
7981static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
7982{
Jeff Johnson295189b2012-06-20 16:38:30 -07007983 v_BOOL_t itemIsValid = VOS_FALSE;
7984 VOS_STATUS status;
7985 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
7986 v_U8_t macLoop;
7987
7988 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
7989 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
7990 if(status != VOS_STATUS_SUCCESS)
7991 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08007992 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed");
Jeff Johnson295189b2012-06-20 16:38:30 -07007993 return VOS_STATUS_E_FAILURE;
7994 }
7995
7996 if (itemIsValid == VOS_TRUE)
7997 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08007998 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV");
Jeff Johnson295189b2012-06-20 16:38:30 -07007999 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
8000 VOS_MAX_CONCURRENCY_PERSONA);
8001 if(status != VOS_STATUS_SUCCESS)
8002 {
8003 /* Get MAC from NV fail, not update CFG info
8004 * INI MAC value will be used for MAC setting */
Arif Hussain6d2a3322013-11-17 19:50:10 -08008005 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed");
Jeff Johnson295189b2012-06-20 16:38:30 -07008006 return VOS_STATUS_E_FAILURE;
8007 }
8008
8009 /* If first MAC is not valid, treat all others are not valid
8010 * Then all MACs will be got from ini file */
8011 if(vos_is_macaddr_zero(&macFromNV[0]))
8012 {
8013 /* MAC address in NV file is not configured yet */
8014 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
8015 return VOS_STATUS_E_INVAL;
8016 }
8017
8018 /* Get MAC address from NV, update CFG info */
8019 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
8020 {
8021 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
8022 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308023 hddLog(VOS_TRACE_LEVEL_ERROR,"not valid MAC from NV for %d", macLoop);
Jeff Johnson295189b2012-06-20 16:38:30 -07008024 /* This MAC is not valid, skip it
8025 * This MAC will be got from ini file */
8026 }
8027 else
8028 {
8029 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
8030 (v_U8_t *)&macFromNV[macLoop].bytes[0],
8031 VOS_MAC_ADDR_SIZE);
8032 }
8033 }
8034 }
8035 else
8036 {
8037 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
8038 return VOS_STATUS_E_FAILURE;
8039 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008040
Jeff Johnson295189b2012-06-20 16:38:30 -07008041
8042 return VOS_STATUS_SUCCESS;
8043}
8044
8045/**---------------------------------------------------------------------------
8046
8047 \brief hdd_post_voss_start_config() - HDD post voss start config helper
8048
8049 \param - pAdapter - Pointer to the HDD
8050
8051 \return - None
8052
8053 --------------------------------------------------------------------------*/
8054VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
8055{
8056 eHalStatus halStatus;
8057 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308058 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -07008059
Jeff Johnson295189b2012-06-20 16:38:30 -07008060
8061 // Send ready indication to the HDD. This will kick off the MAC
8062 // into a 'running' state and should kick off an initial scan.
8063 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
8064 if ( !HAL_STATUS_SUCCESS( halStatus ) )
8065 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308066 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07008067 "code %08d [x%08x]",__func__, halStatus, halStatus );
8068 return VOS_STATUS_E_FAILURE;
8069 }
8070
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308071 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -07008072 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
8073 // And RIVA will crash
8074 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
8075 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308076 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
8077 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
8078
8079
Jeff Johnson295189b2012-06-20 16:38:30 -07008080 return VOS_STATUS_SUCCESS;
8081}
8082
Jeff Johnson295189b2012-06-20 16:38:30 -07008083/* wake lock APIs for HDD */
8084void hdd_prevent_suspend(void)
8085{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008086#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008087 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008088#else
8089 wcnss_prevent_suspend();
8090#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008091}
8092
8093void hdd_allow_suspend(void)
8094{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008095#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008096 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008097#else
8098 wcnss_allow_suspend();
8099#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008100}
8101
Mahesh A Saptasagarb9c50402014-01-16 15:49:22 +05308102void hdd_prevent_suspend_timeout(v_U32_t timeout)
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07008103{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008104#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07008105 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07008106#else
8107 /* Do nothing as there is no API in wcnss for timeout*/
8108#endif
8109}
8110
Jeff Johnson295189b2012-06-20 16:38:30 -07008111/**---------------------------------------------------------------------------
8112
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008113 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
8114 information between Host and Riva
8115
8116 This function gets reported version of FW
8117 It also finds the version of Riva headers used to compile the host
8118 It compares the above two and prints a warning if they are different
8119 It gets the SW and HW version string
8120 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
8121 indicating the features they support through a bitmap
8122
8123 \param - pHddCtx - Pointer to HDD context
8124
8125 \return - void
8126
8127 --------------------------------------------------------------------------*/
8128
8129void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
8130{
8131
8132 tSirVersionType versionCompiled;
8133 tSirVersionType versionReported;
8134 tSirVersionString versionString;
8135 tANI_U8 fwFeatCapsMsgSupported = 0;
8136 VOS_STATUS vstatus;
8137
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -08008138 memset(&versionCompiled, 0, sizeof(versionCompiled));
8139 memset(&versionReported, 0, sizeof(versionReported));
8140
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008141 /* retrieve and display WCNSS version information */
8142 do {
8143
8144 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
8145 &versionCompiled);
8146 if (!VOS_IS_STATUS_SUCCESS(vstatus))
8147 {
8148 hddLog(VOS_TRACE_LEVEL_FATAL,
8149 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008150 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008151 break;
8152 }
8153
8154 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
8155 &versionReported);
8156 if (!VOS_IS_STATUS_SUCCESS(vstatus))
8157 {
8158 hddLog(VOS_TRACE_LEVEL_FATAL,
8159 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008160 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008161 break;
8162 }
8163
8164 if ((versionCompiled.major != versionReported.major) ||
8165 (versionCompiled.minor != versionReported.minor) ||
8166 (versionCompiled.version != versionReported.version) ||
8167 (versionCompiled.revision != versionReported.revision))
8168 {
8169 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
8170 "Host expected %u.%u.%u.%u\n",
8171 WLAN_MODULE_NAME,
8172 (int)versionReported.major,
8173 (int)versionReported.minor,
8174 (int)versionReported.version,
8175 (int)versionReported.revision,
8176 (int)versionCompiled.major,
8177 (int)versionCompiled.minor,
8178 (int)versionCompiled.version,
8179 (int)versionCompiled.revision);
8180 }
8181 else
8182 {
8183 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
8184 WLAN_MODULE_NAME,
8185 (int)versionReported.major,
8186 (int)versionReported.minor,
8187 (int)versionReported.version,
8188 (int)versionReported.revision);
8189 }
8190
8191 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
8192 versionString,
8193 sizeof(versionString));
8194 if (!VOS_IS_STATUS_SUCCESS(vstatus))
8195 {
8196 hddLog(VOS_TRACE_LEVEL_FATAL,
8197 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008198 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008199 break;
8200 }
8201
8202 pr_info("%s: WCNSS software version %s\n",
8203 WLAN_MODULE_NAME, versionString);
8204
8205 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
8206 versionString,
8207 sizeof(versionString));
8208 if (!VOS_IS_STATUS_SUCCESS(vstatus))
8209 {
8210 hddLog(VOS_TRACE_LEVEL_FATAL,
8211 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008212 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008213 break;
8214 }
8215
8216 pr_info("%s: WCNSS hardware version %s\n",
8217 WLAN_MODULE_NAME, versionString);
8218
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07008219 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
8220 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008221 send the message only if it the riva is 1.1
8222 minor numbers for different riva branches:
8223 0 -> (1.0)Mainline Build
8224 1 -> (1.1)Mainline Build
8225 2->(1.04) Stability Build
8226 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07008227 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008228 ((versionReported.minor>=1) && (versionReported.version>=1)))
8229 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
8230 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07008231
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008232 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08008233 {
8234#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
8235 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
8236 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
8237#endif
Ravi Joshid2ca7c42013-07-23 08:37:49 -07008238 /* Indicate if IBSS heartbeat monitoring needs to be offloaded */
8239 if (!pHddCtx->cfg_ini->enableIbssHeartBeatOffload)
8240 {
8241 sme_disableFeatureCapablity(IBSS_HEARTBEAT_OFFLOAD);
8242 }
8243
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008244 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08008245 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008246
8247 } while (0);
8248
8249}
8250
8251/**---------------------------------------------------------------------------
8252
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308253 \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
8254
8255 \param - pHddCtx - Pointer to the hdd context
8256
8257 \return - true if hardware supports 5GHz
8258
8259 --------------------------------------------------------------------------*/
Vinay Krishna Erannafacf5e22014-02-24 13:16:25 +05308260boolean hdd_is_5g_supported(hdd_context_t * pHddCtx)
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308261{
8262 /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
8263 * then hardware support 5Ghz.
8264 */
8265 if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode())
8266 {
Agarwal Ashish971c2882013-10-30 20:11:12 +05308267 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Hardware supports 5Ghz", __func__);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308268 return true;
8269 }
8270 else
8271 {
Agarwal Ashish971c2882013-10-30 20:11:12 +05308272 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Hardware doesn't supports 5Ghz",
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308273 __func__);
8274 return false;
8275 }
8276}
8277
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308278/**---------------------------------------------------------------------------
8279
8280 \brief hdd_generate_iface_mac_addr_auto() - HDD Mac Interface Auto
8281 generate function
8282
8283 This is generate the random mac address for WLAN interface
8284
8285 \param - pHddCtx - Pointer to HDD context
8286 idx - Start interface index to get auto
8287 generated mac addr.
8288 mac_addr - Mac address
8289
8290 \return - 0 for success, < 0 for failure
8291
8292 --------------------------------------------------------------------------*/
8293
8294static int hdd_generate_iface_mac_addr_auto(hdd_context_t *pHddCtx,
8295 int idx, v_MACADDR_t mac_addr)
8296{
8297 int i;
8298 unsigned int serialno;
8299 serialno = wcnss_get_serial_number();
8300
8301 if (0 != serialno)
8302 {
8303 /* MAC address has 3 bytes of OUI so we have a maximum of 3
8304 bytes of the serial number that can be used to generate
8305 the other 3 bytes of the MAC address. Mask off all but
8306 the lower 3 bytes (this will also make sure we don't
8307 overflow in the next step) */
8308 serialno &= 0x00FFFFFF;
8309
8310 /* we need a unique address for each session */
8311 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
8312
8313 /* autogen other Mac addresses */
8314 for (i = idx; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
8315 {
8316 /* start with the entire default address */
8317 pHddCtx->cfg_ini->intfMacAddr[i] = mac_addr;
8318 /* then replace the lower 3 bytes */
8319 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
8320 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
8321 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
8322
8323 serialno++;
8324 hddLog(VOS_TRACE_LEVEL_ERROR,
8325 "%s: Derived Mac Addr: "
8326 MAC_ADDRESS_STR, __func__,
8327 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[i].bytes));
8328 }
8329
8330 }
8331 else
8332 {
8333 hddLog(LOGE, FL("Failed to Get Serial NO"));
8334 return -1;
8335 }
8336 return 0;
8337}
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308338
8339/**---------------------------------------------------------------------------
8340
Mihir Shetefc7ff5b2014-01-27 11:30:05 +05308341 \brief hdd_11d_scan_done - callback to be executed when 11d scan is
8342 completed to flush out the scan results
8343
8344 11d scan is done during driver load and is a passive scan on all
8345 channels supported by the device, 11d scans may find some APs on
8346 frequencies which are forbidden to be used in the regulatory domain
8347 the device is operating in. If these APs are notified to the supplicant
8348 it may try to connect to these APs, thus flush out all the scan results
8349 which are present in SME after 11d scan is done.
8350
8351 \return - eHalStatus
8352
8353 --------------------------------------------------------------------------*/
8354static eHalStatus hdd_11d_scan_done(tHalHandle halHandle, void *pContext,
8355 tANI_U32 scanId, eCsrScanStatus status)
8356{
8357 ENTER();
8358
8359 sme_ScanFlushResult(halHandle, 0);
8360
8361 EXIT();
8362
8363 return eHAL_STATUS_SUCCESS;
8364}
8365
8366/**---------------------------------------------------------------------------
8367
Jeff Johnson295189b2012-06-20 16:38:30 -07008368 \brief hdd_wlan_startup() - HDD init function
8369
8370 This is the driver startup code executed once a WLAN device has been detected
8371
8372 \param - dev - Pointer to the underlying device
8373
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08008374 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07008375
8376 --------------------------------------------------------------------------*/
8377
8378int hdd_wlan_startup(struct device *dev )
8379{
8380 VOS_STATUS status;
8381 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07008382 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07008383 hdd_context_t *pHddCtx = NULL;
8384 v_CONTEXT_t pVosContext= NULL;
8385#ifdef WLAN_BTAMP_FEATURE
8386 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
8387 WLANBAP_ConfigType btAmpConfig;
8388 hdd_config_t *pConfig;
8389#endif
8390 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07008391 struct wiphy *wiphy;
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308392 v_MACADDR_t mac_addr;
Jeff Johnson295189b2012-06-20 16:38:30 -07008393
8394 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07008395 /*
8396 * cfg80211: wiphy allocation
8397 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308398 wiphy = wlan_hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t)) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07008399
8400 if(wiphy == NULL)
8401 {
8402 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08008403 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07008404 }
8405
8406 pHddCtx = wiphy_priv(wiphy);
8407
Jeff Johnson295189b2012-06-20 16:38:30 -07008408 //Initialize the adapter context to zeros.
8409 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
8410
Jeff Johnson295189b2012-06-20 16:38:30 -07008411 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07008412 hdd_prevent_suspend();
Mihir Shete18156292014-03-11 15:38:30 +05308413 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_LOAD_IN_PROGRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -07008414
8415 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
8416
8417 /*Get vos context here bcoz vos_open requires it*/
8418 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
8419
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08008420 if(pVosContext == NULL)
8421 {
8422 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
8423 goto err_free_hdd_context;
8424 }
8425
Jeff Johnson295189b2012-06-20 16:38:30 -07008426 //Save the Global VOSS context in adapter context for future.
8427 pHddCtx->pvosContext = pVosContext;
8428
8429 //Save the adapter context in global context for future.
8430 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
8431
Jeff Johnson295189b2012-06-20 16:38:30 -07008432 pHddCtx->parent_dev = dev;
8433
8434 init_completion(&pHddCtx->full_pwr_comp_var);
8435 init_completion(&pHddCtx->standby_comp_var);
8436 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07008437 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08008438 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Kiet Lam46b8e4e2013-11-06 21:49:53 +05308439 init_completion(&pHddCtx->wiphy_channel_update_event);
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +05308440 init_completion(&pHddCtx->ssr_comp_var);
Amar Singhala49cbc52013-10-08 18:37:44 -07008441
8442#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhalfddc28c2013-09-05 13:03:40 -07008443 init_completion(&pHddCtx->linux_reg_req);
Amar Singhala49cbc52013-10-08 18:37:44 -07008444#else
8445 init_completion(&pHddCtx->driver_crda_req);
8446#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008447
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05308448 spin_lock_init(&pHddCtx->schedScan_lock);
8449
Jeff Johnson295189b2012-06-20 16:38:30 -07008450 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
8451
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05308452#ifdef FEATURE_WLAN_TDLS
8453 /* tdls_lock is initialized before an hdd_open_adapter ( which is
8454 * invoked by other instances also) to protect the concurrent
8455 * access for the Adapters by TDLS module.
8456 */
8457 mutex_init(&pHddCtx->tdls_lock);
8458#endif
Agarwal Ashish1f422872014-07-22 00:11:55 +05308459 /* By default Strict Regulatory For FCC should be false */
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05308460
Agarwal Ashish1f422872014-07-22 00:11:55 +05308461 pHddCtx->nEnableStrictRegulatoryForFCC = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07008462 // Load all config first as TL config is needed during vos_open
8463 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
8464 if(pHddCtx->cfg_ini == NULL)
8465 {
8466 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
8467 goto err_free_hdd_context;
8468 }
8469
8470 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
8471
8472 // Read and parse the qcom_cfg.ini file
8473 status = hdd_parse_config_ini( pHddCtx );
8474 if ( VOS_STATUS_SUCCESS != status )
8475 {
8476 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
8477 __func__, WLAN_INI_FILE);
8478 goto err_config;
8479 }
Arif Hussaind5218912013-12-05 01:10:55 -08008480#ifdef MEMORY_DEBUG
8481 if (pHddCtx->cfg_ini->IsMemoryDebugSupportEnabled)
8482 vos_mem_init();
8483
8484 hddLog(VOS_TRACE_LEVEL_INFO, "%s: gEnableMemoryDebug=%d",
8485 __func__, pHddCtx->cfg_ini->IsMemoryDebugSupportEnabled);
8486#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008487
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05308488 /* INI has been read, initialise the configuredMcastBcastFilter with
8489 * INI value as this will serve as the default value
8490 */
8491 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
8492 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
8493 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308494
8495 if (false == hdd_is_5g_supported(pHddCtx))
8496 {
8497 //5Ghz is not supported.
8498 if (1 != pHddCtx->cfg_ini->nBandCapability)
8499 {
8500 hddLog(VOS_TRACE_LEVEL_INFO,
8501 "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__);
8502 pHddCtx->cfg_ini->nBandCapability = 1;
8503 }
8504 }
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05308505
8506 /* If SNR Monitoring is enabled, FW has to parse all beacons
8507 * for calcaluting and storing the average SNR, so set Nth beacon
8508 * filter to 1 to enable FW to parse all the beaocons
8509 */
8510 if (1 == pHddCtx->cfg_ini->fEnableSNRMonitoring)
8511 {
8512 /* The log level is deliberately set to WARN as overriding
8513 * nthBeaconFilter to 1 will increase power cosumption and this
8514 * might just prove helpful to detect the power issue.
8515 */
8516 hddLog(VOS_TRACE_LEVEL_WARN,
8517 "%s: Setting pHddCtx->cfg_ini->nthBeaconFilter = 1", __func__);
8518 pHddCtx->cfg_ini->nthBeaconFilter = 1;
8519 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008520 /*
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308521 * cfg80211: Initialization ...
Jeff Johnson295189b2012-06-20 16:38:30 -07008522 */
Manjunathappa Prakasheec4ddf2014-01-13 18:23:51 -08008523 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07008524 {
Manjunathappa Prakasheec4ddf2014-01-13 18:23:51 -08008525 if (0 < wlan_hdd_cfg80211_init(dev, wiphy, pHddCtx->cfg_ini))
8526 {
8527 hddLog(VOS_TRACE_LEVEL_FATAL,
8528 "%s: wlan_hdd_cfg80211_init return failure", __func__);
8529 goto err_config;
8530 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008531 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008532
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08008533 // Update VOS trace levels based upon the cfg.ini
8534 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
8535 pHddCtx->cfg_ini->vosTraceEnableBAP);
8536 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
8537 pHddCtx->cfg_ini->vosTraceEnableTL);
8538 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
8539 pHddCtx->cfg_ini->vosTraceEnableWDI);
8540 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
8541 pHddCtx->cfg_ini->vosTraceEnableHDD);
8542 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
8543 pHddCtx->cfg_ini->vosTraceEnableSME);
8544 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
8545 pHddCtx->cfg_ini->vosTraceEnablePE);
Katya Nigam70d68332013-09-16 16:49:45 +05308546 hdd_vos_trace_enable(VOS_MODULE_ID_PMC,
8547 pHddCtx->cfg_ini->vosTraceEnablePMC);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08008548 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
8549 pHddCtx->cfg_ini->vosTraceEnableWDA);
8550 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
8551 pHddCtx->cfg_ini->vosTraceEnableSYS);
8552 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
8553 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08008554 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
8555 pHddCtx->cfg_ini->vosTraceEnableSAP);
8556 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
8557 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08008558
Jeff Johnson295189b2012-06-20 16:38:30 -07008559 // Update WDI trace levels based upon the cfg.ini
8560 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
8561 pHddCtx->cfg_ini->wdiTraceEnableDAL);
8562 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
8563 pHddCtx->cfg_ini->wdiTraceEnableCTL);
8564 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
8565 pHddCtx->cfg_ini->wdiTraceEnableDAT);
8566 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
8567 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07008568
Jeff Johnson88ba7742013-02-27 14:36:02 -08008569 if (VOS_FTM_MODE == hdd_get_conparam())
8570 {
Jeff Johnson295189b2012-06-20 16:38:30 -07008571 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
8572 {
8573 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
8574 goto err_free_hdd_context;
8575 }
8576 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
c_hpothu2de0ef62014-04-15 16:16:15 +05308577
8578 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -07008579 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08008580 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008581
Jeff Johnson88ba7742013-02-27 14:36:02 -08008582 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07008583 if(pHddCtx->cfg_ini->fIsLogpEnabled)
8584 {
8585 status = vos_watchdog_open(pVosContext,
8586 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
8587
8588 if(!VOS_IS_STATUS_SUCCESS( status ))
8589 {
8590 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308591 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07008592 }
8593 }
8594
8595 pHddCtx->isLogpInProgress = FALSE;
8596 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
8597
Jeff Johnson295189b2012-06-20 16:38:30 -07008598 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
8599 if(!VOS_IS_STATUS_SUCCESS(status))
8600 {
8601 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008602 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07008603 }
8604
Amar Singhala49cbc52013-10-08 18:37:44 -07008605#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -07008606 /* initialize the NV module. This is required so that
8607 we can initialize the channel information in wiphy
8608 from the NV.bin data. The channel information in
8609 wiphy needs to be initialized before wiphy registration */
8610
8611 status = vos_nv_open();
8612 if (!VOS_IS_STATUS_SUCCESS(status))
8613 {
8614 /* NV module cannot be initialized */
8615 hddLog( VOS_TRACE_LEVEL_FATAL,
8616 "%s: vos_nv_open failed", __func__);
8617 goto err_clkvote;
8618 }
8619
8620 status = vos_init_wiphy_from_nv_bin();
8621 if (!VOS_IS_STATUS_SUCCESS(status))
8622 {
8623 /* NV module cannot be initialized */
8624 hddLog( VOS_TRACE_LEVEL_FATAL,
8625 "%s: vos_init_wiphy failed", __func__);
8626 goto err_vos_nv_close;
8627 }
8628
Amar Singhala49cbc52013-10-08 18:37:44 -07008629#endif
8630
Arun Kumar Khandavalliebb19482014-03-25 13:56:53 +05308631 status = vos_open( &pVosContext, pHddCtx->parent_dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07008632 if ( !VOS_IS_STATUS_SUCCESS( status ))
8633 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008634 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
Mihir Shetee1093ba2014-01-21 20:13:32 +05308635 goto err_vos_nv_close;
Jeff Johnson295189b2012-06-20 16:38:30 -07008636 }
8637
Jeff Johnson295189b2012-06-20 16:38:30 -07008638 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
8639
8640 if ( NULL == pHddCtx->hHal )
8641 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008642 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008643 goto err_vosclose;
8644 }
8645
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008646 status = vos_preStart( pHddCtx->pvosContext );
8647 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8648 {
8649 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05308650 goto err_vosclose;
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008651 }
Jeff Johnsone7245742012-09-05 17:12:55 -07008652
Arif Hussaineaf68602013-12-30 23:10:44 -08008653 if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan)
8654 {
8655 pHddCtx->cfg_ini->enableDFSChnlScan = enable_dfs_chan_scan;
8656 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_dfs_chan_scan set to %d",
8657 __func__, enable_dfs_chan_scan);
8658 }
8659 if (0 == enable_11d || 1 == enable_11d)
8660 {
8661 pHddCtx->cfg_ini->Is11dSupportEnabled = enable_11d;
8662 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_11d set to %d",
8663 __func__, enable_11d);
8664 }
8665
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008666 /* Note that the vos_preStart() sequence triggers the cfg download.
8667 The cfg download must occur before we update the SME config
8668 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07008669 status = hdd_set_sme_config( pHddCtx );
8670
8671 if ( VOS_STATUS_SUCCESS != status )
8672 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008673 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05308674 goto err_vosclose;
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008675 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008676
Jeff Johnson295189b2012-06-20 16:38:30 -07008677 /* In the integrated architecture we update the configuration from
8678 the INI file and from NV before vOSS has been started so that
8679 the final contents are available to send down to the cCPU */
8680
8681 // Apply the cfg.ini to cfg.dat
8682 if (FALSE == hdd_update_config_dat(pHddCtx))
8683 {
8684 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05308685 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07008686 }
8687
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308688 // Get mac addr from platform driver
8689 ret = wcnss_get_wlan_mac_address((char*)&mac_addr.bytes);
8690
8691 if ((0 == ret) && (!vos_is_macaddr_zero(&mac_addr)))
Jeff Johnson295189b2012-06-20 16:38:30 -07008692 {
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308693 /* Store the mac addr for first interface */
8694 pHddCtx->cfg_ini->intfMacAddr[0] = mac_addr;
8695
8696 hddLog(VOS_TRACE_LEVEL_ERROR,
8697 "%s: WLAN Mac Addr: "
8698 MAC_ADDRESS_STR, __func__,
8699 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
8700
8701 /* Here, passing Arg2 as 1 because we do not want to change the
8702 last 3 bytes (means non OUI bytes) of first interface mac
8703 addr.
8704 */
8705 if (0 != hdd_generate_iface_mac_addr_auto(pHddCtx, 1, mac_addr))
8706 {
8707 hddLog(VOS_TRACE_LEVEL_ERROR,
8708 "%s: Failed to generate wlan interface mac addr "
8709 "using MAC from ini file ", __func__);
8710 }
8711 }
8712 else if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
8713 {
8714 // Apply the NV to cfg.dat
8715 /* Prima Update MAC address only at here */
Jeff Johnson295189b2012-06-20 16:38:30 -07008716#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
8717 /* There was not a valid set of MAC Addresses in NV. See if the
8718 default addresses were modified by the cfg.ini settings. If so,
8719 we'll use them, but if not, we'll autogenerate a set of MAC
8720 addresses based upon the device serial number */
8721
8722 static const v_MACADDR_t default_address =
8723 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
Jeff Johnson295189b2012-06-20 16:38:30 -07008724
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308725 if (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
8726 sizeof(default_address)))
Jeff Johnson295189b2012-06-20 16:38:30 -07008727 {
8728 /* cfg.ini has the default address, invoke autogen logic */
8729
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308730 /* Here, passing Arg2 as 0 because we want to change the
8731 last 3 bytes (means non OUI bytes) of all the interfaces
8732 mac addr.
8733 */
8734 if (0 != hdd_generate_iface_mac_addr_auto(pHddCtx, 0,
8735 default_address))
Jeff Johnson295189b2012-06-20 16:38:30 -07008736 {
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308737 hddLog(VOS_TRACE_LEVEL_ERROR,
8738 "%s: Failed to generate wlan interface mac addr "
8739 "using MAC from ini file " MAC_ADDRESS_STR, __func__,
8740 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
Jeff Johnson295189b2012-06-20 16:38:30 -07008741 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008742 }
8743 else
8744#endif //WLAN_AUTOGEN_MACADDR_FEATURE
8745 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008746 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07008747 "%s: Invalid MAC address in NV, using MAC from ini file "
8748 MAC_ADDRESS_STR, __func__,
8749 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
8750 }
8751 }
8752 {
8753 eHalStatus halStatus;
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308754
8755 /* Set the MAC Address Currently this is used by HAL to
8756 * add self sta. Remove this once self sta is added as
8757 * part of session open.
8758 */
Jeff Johnson295189b2012-06-20 16:38:30 -07008759 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
8760 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
8761 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308762
Jeff Johnson295189b2012-06-20 16:38:30 -07008763 if (!HAL_STATUS_SUCCESS( halStatus ))
8764 {
8765 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
8766 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05308767 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07008768 }
8769 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008770
8771 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
8772 Note: Firmware image will be read and downloaded inside vos_start API */
8773 status = vos_start( pHddCtx->pvosContext );
8774 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8775 {
8776 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05308777 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07008778 }
8779
Leo Chang6cec3e22014-01-21 15:33:49 -08008780#ifdef FEATURE_WLAN_CH_AVOID
8781 /* Plug in avoid channel notification callback
8782 * This should happen before ADD_SELF_STA
8783 * FW will send first IND with ADD_SELF_STA REQ from host */
Pradeep Reddy POTTETI5c2e16d2014-06-27 16:47:38 +05308784
8785 /* check the Channel Avoidance is enabled */
8786 if (TRUE == pHddCtx->cfg_ini->fenableCHAvoidance)
8787 {
8788 sme_AddChAvoidCallback(pHddCtx->hHal,
8789 hdd_hostapd_ch_avoid_cb);
8790 }
Leo Chang6cec3e22014-01-21 15:33:49 -08008791#endif /* FEATURE_WLAN_CH_AVOID */
8792
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008793 /* Exchange capability info between Host and FW and also get versioning info from FW */
8794 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07008795
Agarwal Ashishad9281b2014-06-10 14:57:30 +05308796#ifdef CONFIG_ENABLE_LINUX_REG
8797 status = wlan_hdd_init_channels(pHddCtx);
8798 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8799 {
8800 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: wlan_hdd_init_channels failed",
8801 __func__);
8802 goto err_vosstop;
8803 }
8804#endif
8805
Jeff Johnson295189b2012-06-20 16:38:30 -07008806 status = hdd_post_voss_start_config( pHddCtx );
8807 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8808 {
8809 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
8810 __func__);
8811 goto err_vosstop;
8812 }
Amar Singhala49cbc52013-10-08 18:37:44 -07008813
8814#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308815 wlan_hdd_cfg80211_update_reg_info( wiphy );
8816
8817 /* registration of wiphy dev with cfg80211 */
8818 if (0 > wlan_hdd_cfg80211_register(wiphy))
8819 {
8820 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
8821 goto err_vosstop;
8822 }
Amar Singhala49cbc52013-10-08 18:37:44 -07008823#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008824
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05308825#ifdef CONFIG_ENABLE_LINUX_REG
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05308826 /* registration of wiphy dev with cfg80211 */
8827 if (0 > wlan_hdd_cfg80211_register(wiphy))
8828 {
8829 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
8830 goto err_vosstop;
8831 }
8832
8833 status = wlan_hdd_init_channels_for_cc(pHddCtx);
8834 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8835 {
8836 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: wlan_hdd_init_channels_for_cc failed",
8837 __func__);
8838 goto err_unregister_wiphy;
8839 }
8840#endif
8841
Jeff Johnson295189b2012-06-20 16:38:30 -07008842 if (VOS_STA_SAP_MODE == hdd_get_conparam())
8843 {
8844 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
8845 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
8846 }
8847 else
8848 {
Jeff Johnson295189b2012-06-20 16:38:30 -07008849 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
8850 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
8851 if (pAdapter != NULL)
8852 {
kaidde69982014-06-18 13:23:21 +08008853 if (pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated && !(pHddCtx->cfg_ini->intfMacAddr[0].bytes[0] &= 0x02))
Jeff Johnson295189b2012-06-20 16:38:30 -07008854 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05308855 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
8856 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
8857 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07008858
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05308859 /* Generate the P2P Device Address. This consists of the device's
8860 * primary MAC address with the locally administered bit set.
8861 */
8862 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07008863 }
8864 else
8865 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05308866 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
8867 if (p2p_dev_addr != NULL)
8868 {
8869 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
8870 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
8871 }
8872 else
8873 {
8874 hddLog(VOS_TRACE_LEVEL_FATAL,
8875 "%s: Failed to allocate mac_address for p2p_device",
8876 __func__);
8877 goto err_close_adapter;
8878 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008879 }
Jeff Johnsone7245742012-09-05 17:12:55 -07008880
8881 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
8882 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
8883 if ( NULL == pP2pAdapter )
8884 {
8885 hddLog(VOS_TRACE_LEVEL_FATAL,
8886 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008887 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07008888 goto err_close_adapter;
8889 }
Jeff Johnsone7245742012-09-05 17:12:55 -07008890 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008891 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008892
8893 if( pAdapter == NULL )
8894 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008895 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
8896 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07008897 }
Jeff Johnsone7245742012-09-05 17:12:55 -07008898
Arif Hussain66559122013-11-21 10:11:40 -08008899 if (country_code)
8900 {
8901 eHalStatus ret;
Arif Hussaincb607082013-12-20 11:57:42 -08008902 INIT_COMPLETION(pAdapter->change_country_code);
Arif Hussain66559122013-11-21 10:11:40 -08008903 hdd_checkandupdate_dfssetting(pAdapter, country_code);
8904#ifndef CONFIG_ENABLE_LINUX_REG
8905 hdd_checkandupdate_phymode(pAdapter, country_code);
8906#endif
Arif Hussaineaf68602013-12-30 23:10:44 -08008907 ret = sme_ChangeCountryCode(pHddCtx->hHal,
8908 (void *)(tSmeChangeCountryCallback)
8909 wlan_hdd_change_country_code_callback,
Arif Hussain66559122013-11-21 10:11:40 -08008910 country_code,
8911 pAdapter, pHddCtx->pvosContext,
Abhishek Singha306a442013-11-07 18:39:01 +05308912 eSIR_TRUE, eSIR_TRUE);
Arif Hussain66559122013-11-21 10:11:40 -08008913 if (eHAL_STATUS_SUCCESS == ret)
8914 {
Arif Hussaincb607082013-12-20 11:57:42 -08008915 ret = wait_for_completion_interruptible_timeout(
8916 &pAdapter->change_country_code,
8917 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
8918
8919 if (0 >= ret)
8920 {
8921 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8922 "%s: SME while setting country code timed out", __func__);
8923 }
Arif Hussain66559122013-11-21 10:11:40 -08008924 }
8925 else
8926 {
Arif Hussaincb607082013-12-20 11:57:42 -08008927 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8928 "%s: SME Change Country code from module param fail ret=%d",
8929 __func__, ret);
Arif Hussain66559122013-11-21 10:11:40 -08008930 }
8931 }
8932
Jeff Johnson295189b2012-06-20 16:38:30 -07008933#ifdef WLAN_BTAMP_FEATURE
8934 vStatus = WLANBAP_Open(pVosContext);
8935 if(!VOS_IS_STATUS_SUCCESS(vStatus))
8936 {
8937 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8938 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07008939 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07008940 }
8941
8942 vStatus = BSL_Init(pVosContext);
8943 if(!VOS_IS_STATUS_SUCCESS(vStatus))
8944 {
8945 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8946 "%s: Failed to Init BSL",__func__);
8947 goto err_bap_close;
8948 }
8949 vStatus = WLANBAP_Start(pVosContext);
8950 if (!VOS_IS_STATUS_SUCCESS(vStatus))
8951 {
8952 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8953 "%s: Failed to start TL",__func__);
8954 goto err_bap_close;
8955 }
8956
8957 pConfig = pHddCtx->cfg_ini;
8958 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
8959 status = WLANBAP_SetConfig(&btAmpConfig);
8960
8961#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07008962
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07008963#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
8964 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
8965 {
8966 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
8967 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
8968 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
8969 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
8970 }
8971#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008972
Agarwal Ashish4b87f922014-06-18 03:03:21 +05308973 wlan_hdd_tdls_init(pHddCtx);
8974
Mihir Shetefc7ff5b2014-01-27 11:30:05 +05308975 sme_Register11dScanDoneCallback(pHddCtx->hHal, hdd_11d_scan_done);
8976
Jeff Johnson295189b2012-06-20 16:38:30 -07008977 /* Register with platform driver as client for Suspend/Resume */
8978 status = hddRegisterPmOps(pHddCtx);
8979 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8980 {
8981 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
8982#ifdef WLAN_BTAMP_FEATURE
8983 goto err_bap_stop;
8984#else
Jeff Johnsone7245742012-09-05 17:12:55 -07008985 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07008986#endif //WLAN_BTAMP_FEATURE
8987 }
8988
Yue Ma0d4891e2013-08-06 17:01:45 -07008989 /* Open debugfs interface */
8990 if (VOS_STATUS_SUCCESS != hdd_debugfs_init(pAdapter))
8991 {
8992 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8993 "%s: hdd_debugfs_init failed!", __func__);
Yue Ma0d4891e2013-08-06 17:01:45 -07008994 }
8995
Jeff Johnson295189b2012-06-20 16:38:30 -07008996 /* Register TM level change handler function to the platform */
8997 status = hddDevTmRegisterNotifyCallback(pHddCtx);
8998 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8999 {
9000 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
9001 goto err_unregister_pmops;
9002 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009003
9004 /* register for riva power on lock to platform driver */
9005 if (req_riva_power_on_lock("wlan"))
9006 {
9007 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
9008 __func__);
9009 goto err_unregister_pmops;
9010 }
9011
Jeff Johnson295189b2012-06-20 16:38:30 -07009012 // register net device notifier for device change notification
9013 ret = register_netdevice_notifier(&hdd_netdev_notifier);
9014
9015 if(ret < 0)
9016 {
9017 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
9018 goto err_free_power_on_lock;
9019 }
9020
9021 //Initialize the nlink service
9022 if(nl_srv_init() != 0)
9023 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05309024 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009025 goto err_reg_netdev;
9026 }
9027
Leo Chang4ce1cc52013-10-21 18:27:15 -07009028#ifdef WLAN_KD_READY_NOTIFIER
9029 pHddCtx->kd_nl_init = 1;
9030#endif /* WLAN_KD_READY_NOTIFIER */
9031
Jeff Johnson295189b2012-06-20 16:38:30 -07009032 //Initialize the BTC service
9033 if(btc_activate_service(pHddCtx) != 0)
9034 {
9035 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
9036 goto err_nl_srv;
9037 }
9038
9039#ifdef PTT_SOCK_SVC_ENABLE
9040 //Initialize the PTT service
9041 if(ptt_sock_activate_svc(pHddCtx) != 0)
9042 {
9043 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
9044 goto err_nl_srv;
9045 }
9046#endif
9047
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05309048#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9049 if(pHddCtx->cfg_ini && pHddCtx->cfg_ini->wlanLoggingEnable)
9050 {
9051 if(wlan_logging_sock_activate_svc(
9052 pHddCtx->cfg_ini->wlanLoggingFEToConsole,
9053 pHddCtx->cfg_ini->wlanLoggingNumBuf))
9054 {
9055 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wlan_logging_sock_activate_svc"
9056 " failed", __func__);
9057 goto err_nl_srv;
9058 }
9059 }
9060#endif
9061
Jeff Johnson295189b2012-06-20 16:38:30 -07009062 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07009063 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07009064 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07009065 /* Action frame registered in one adapter which will
9066 * applicable to all interfaces
9067 */
Agarwal Ashish8fa0e9a2014-05-23 00:40:12 +05309068 wlan_hdd_cfg80211_register_frames(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07009069 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009070
9071 mutex_init(&pHddCtx->sap_lock);
9072
Jeff Johnson295189b2012-06-20 16:38:30 -07009073
Sameer Thalappil50dc0092013-02-19 17:23:33 -08009074#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07009075#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
9076 /* Initialize the wake lcok */
9077 wake_lock_init(&pHddCtx->rx_wake_lock,
9078 WAKE_LOCK_SUSPEND,
9079 "qcom_rx_wakelock");
9080#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08009081 /* Initialize the wake lcok */
9082 wake_lock_init(&pHddCtx->sap_wake_lock,
9083 WAKE_LOCK_SUSPEND,
9084 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08009085#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07009086
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07009087 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
9088 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07009089
Katya Nigam5c306ea2014-06-19 15:39:54 +05309090 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_NO_LOAD_UNLOAD_IN_PROGRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -07009091 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
9092 hdd_allow_suspend();
Katya Nigam5c306ea2014-06-19 15:39:54 +05309093
9094#ifdef FEATURE_WLAN_SCAN_PNO
9095 /*SME must send channel update configuration to RIVA*/
9096 sme_UpdateChannelConfig(pHddCtx->hHal);
9097#endif
9098
Abhishek Singha306a442013-11-07 18:39:01 +05309099#ifndef CONFIG_ENABLE_LINUX_REG
9100 /*updating wiphy so that regulatory user hints can be processed*/
9101 if (wiphy)
9102 {
9103 regulatory_hint(wiphy, "00");
9104 }
9105#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07009106 // Initialize the restart logic
9107 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05309108
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07009109 //Register the traffic monitor timer now
9110 if ( pHddCtx->cfg_ini->dynSplitscan)
9111 {
9112 vos_timer_init(&pHddCtx->tx_rx_trafficTmr,
9113 VOS_TIMER_TYPE_SW,
9114 hdd_tx_rx_pkt_cnt_stat_timer_handler,
9115 (void *)pHddCtx);
9116 }
Dino Mycle6fb96c12014-06-10 11:52:40 +05309117#ifdef WLAN_FEATURE_EXTSCAN
9118 sme_EXTScanRegisterCallback(pHddCtx->hHal,
9119 wlan_hdd_cfg80211_extscan_callback,
9120 pHddCtx);
9121#endif /* WLAN_FEATURE_EXTSCAN */
Jeff Johnson295189b2012-06-20 16:38:30 -07009122 goto success;
9123
9124err_nl_srv:
Leo Chang59cdc7e2013-07-10 10:08:21 -07009125#ifdef WLAN_KD_READY_NOTIFIER
9126 nl_srv_exit(pHddCtx->ptt_pid);
9127#else
Jeff Johnson295189b2012-06-20 16:38:30 -07009128 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07009129#endif /* WLAN_KD_READY_NOTIFIER */
Jeff Johnson295189b2012-06-20 16:38:30 -07009130err_reg_netdev:
9131 unregister_netdevice_notifier(&hdd_netdev_notifier);
9132
9133err_free_power_on_lock:
9134 free_riva_power_on_lock("wlan");
9135
9136err_unregister_pmops:
9137 hddDevTmUnregisterNotifyCallback(pHddCtx);
9138 hddDeregisterPmOps(pHddCtx);
9139
Yue Ma0d4891e2013-08-06 17:01:45 -07009140 hdd_debugfs_exit(pHddCtx);
9141
Jeff Johnson295189b2012-06-20 16:38:30 -07009142#ifdef WLAN_BTAMP_FEATURE
9143err_bap_stop:
9144 WLANBAP_Stop(pVosContext);
9145#endif
9146
9147#ifdef WLAN_BTAMP_FEATURE
9148err_bap_close:
9149 WLANBAP_Close(pVosContext);
9150#endif
9151
Jeff Johnson295189b2012-06-20 16:38:30 -07009152err_close_adapter:
9153 hdd_close_all_adapters( pHddCtx );
Mahesh A Saptasagar9ecefe42014-07-15 18:43:49 +05309154#ifdef CONFIG_ENABLE_LINUX_REG
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05309155err_unregister_wiphy:
Mahesh A Saptasagar9ecefe42014-07-15 18:43:49 +05309156#endif
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05309157 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07009158err_vosstop:
9159 vos_stop(pVosContext);
9160
Amar Singhala49cbc52013-10-08 18:37:44 -07009161err_vosclose:
Jeff Johnson295189b2012-06-20 16:38:30 -07009162 status = vos_sched_close( pVosContext );
9163 if (!VOS_IS_STATUS_SUCCESS(status)) {
9164 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
9165 "%s: Failed to close VOSS Scheduler", __func__);
9166 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
9167 }
Amar Singhala49cbc52013-10-08 18:37:44 -07009168 vos_close(pVosContext );
9169
Amar Singhal0a402232013-10-11 20:57:16 -07009170err_vos_nv_close:
9171
c_hpothue6a36282014-03-19 12:27:38 +05309172#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -07009173 vos_nv_close();
9174
Jeff Johnson295189b2012-06-20 16:38:30 -07009175err_clkvote:
c_hpothu70f8d812014-03-22 22:59:23 +05309176#endif
Jeff Johnsonbc676b42013-02-14 16:04:08 -08009177 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07009178
9179err_wdclose:
9180 if(pHddCtx->cfg_ini->fIsLogpEnabled)
9181 vos_watchdog_close(pVosContext);
9182
Jeff Johnson295189b2012-06-20 16:38:30 -07009183err_config:
9184 kfree(pHddCtx->cfg_ini);
9185 pHddCtx->cfg_ini= NULL;
9186
9187err_free_hdd_context:
9188 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07009189 wiphy_free(wiphy) ;
9190 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07009191 VOS_BUG(1);
9192
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08009193 if (hdd_is_ssr_required())
9194 {
9195 /* WDI timeout had happened during load, so SSR is needed here */
9196 subsystem_restart("wcnss");
9197 msleep(5000);
9198 }
9199 hdd_set_ssr_required (VOS_FALSE);
9200
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08009201 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07009202
9203success:
9204 EXIT();
9205 return 0;
9206}
9207
9208/**---------------------------------------------------------------------------
9209
Jeff Johnson32d95a32012-09-10 13:15:23 -07009210 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07009211
Jeff Johnson32d95a32012-09-10 13:15:23 -07009212 This is the driver entry point - called in different timeline depending
9213 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07009214
9215 \param - None
9216
9217 \return - 0 for success, non zero for failure
9218
9219 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07009220static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07009221{
9222 VOS_STATUS status;
9223 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07009224 struct device *dev = NULL;
9225 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07009226#ifdef HAVE_WCNSS_CAL_DOWNLOAD
9227 int max_retries = 0;
9228#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009229
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05309230#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9231 wlan_logging_sock_init_svc();
9232#endif
9233
Jeff Johnson295189b2012-06-20 16:38:30 -07009234 ENTER();
9235
Sameer Thalappil50dc0092013-02-19 17:23:33 -08009236#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07009237 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07009238#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009239
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05309240 hddTraceInit();
Jeff Johnson295189b2012-06-20 16:38:30 -07009241 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
9242 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
9243
9244 //Power Up Libra WLAN card first if not already powered up
9245 status = vos_chipPowerUp(NULL,NULL,NULL);
9246 if (!VOS_IS_STATUS_SUCCESS(status))
9247 {
9248 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
9249 "exiting", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05309250#ifdef WLAN_OPEN_SOURCE
9251 wake_lock_destroy(&wlan_wake_lock);
9252#endif
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05309253
9254#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9255 wlan_logging_sock_deinit_svc();
9256#endif
9257
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08009258 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07009259 }
9260
Jeff Johnson295189b2012-06-20 16:38:30 -07009261#ifdef ANI_BUS_TYPE_PCI
9262
9263 dev = wcnss_wlan_get_device();
9264
9265#endif // ANI_BUS_TYPE_PCI
9266
9267#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07009268
9269#ifdef HAVE_WCNSS_CAL_DOWNLOAD
9270 /* wait until WCNSS driver downloads NV */
9271 while (!wcnss_device_ready() && 5 >= ++max_retries) {
9272 msleep(1000);
9273 }
9274 if (max_retries >= 5) {
9275 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05309276#ifdef WLAN_OPEN_SOURCE
9277 wake_lock_destroy(&wlan_wake_lock);
9278#endif
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05309279
9280#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9281 wlan_logging_sock_deinit_svc();
9282#endif
9283
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07009284 return -ENODEV;
9285 }
9286#endif
9287
Jeff Johnson295189b2012-06-20 16:38:30 -07009288 dev = wcnss_wlan_get_device();
9289#endif // ANI_BUS_TYPE_PLATFORM
9290
9291
9292 do {
9293 if (NULL == dev) {
9294 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
9295 ret_status = -1;
9296 break;
9297 }
9298
Jeff Johnson295189b2012-06-20 16:38:30 -07009299#ifdef TIMER_MANAGER
9300 vos_timer_manager_init();
9301#endif
9302
9303 /* Preopen VOSS so that it is ready to start at least SAL */
9304 status = vos_preOpen(&pVosContext);
9305
9306 if (!VOS_IS_STATUS_SUCCESS(status))
9307 {
9308 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
9309 ret_status = -1;
9310 break;
9311 }
9312
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009313#ifndef MODULE
9314 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
9315 */
9316 hdd_set_conparam((v_UINT_t)con_mode);
9317#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009318
9319 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08009320 if (hdd_wlan_startup(dev))
9321 {
Jeff Johnson295189b2012-06-20 16:38:30 -07009322 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08009323 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009324 vos_preClose( &pVosContext );
9325 ret_status = -1;
9326 break;
9327 }
9328
9329 /* Cancel the vote for XO Core ON
9330 * This is done here for safety purposes in case we re-initialize without turning
9331 * it OFF in any error scenario.
9332 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07009333 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07009334 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07009335 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07009336 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
9337 {
9338 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
Arif Hussain6d2a3322013-11-17 19:50:10 -08009339 " Power consumed will be high");
Jeff Johnson295189b2012-06-20 16:38:30 -07009340 }
9341 } while (0);
9342
9343 if (0 != ret_status)
9344 {
9345 //Assert Deep sleep signal now to put Libra HW in lowest power state
9346 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
9347 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
9348
9349 //Vote off any PMIC voltage supplies
9350 vos_chipPowerDown(NULL, NULL, NULL);
9351#ifdef TIMER_MANAGER
9352 vos_timer_exit();
9353#endif
9354#ifdef MEMORY_DEBUG
9355 vos_mem_exit();
9356#endif
9357
Sameer Thalappil50dc0092013-02-19 17:23:33 -08009358#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07009359 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07009360#endif
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05309361
9362#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9363 wlan_logging_sock_deinit_svc();
9364#endif
9365
Jeff Johnson295189b2012-06-20 16:38:30 -07009366 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
9367 }
9368 else
9369 {
9370 //Send WLAN UP indication to Nlink Service
9371 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
9372
9373 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Jeff Johnson295189b2012-06-20 16:38:30 -07009374 }
9375
9376 EXIT();
9377
9378 return ret_status;
9379}
9380
Jeff Johnson32d95a32012-09-10 13:15:23 -07009381/**---------------------------------------------------------------------------
9382
9383 \brief hdd_module_init() - Init Function
9384
9385 This is the driver entry point (invoked when module is loaded using insmod)
9386
9387 \param - None
9388
9389 \return - 0 for success, non zero for failure
9390
9391 --------------------------------------------------------------------------*/
9392#ifdef MODULE
9393static int __init hdd_module_init ( void)
9394{
9395 return hdd_driver_init();
9396}
Jeff Johnson32d95a32012-09-10 13:15:23 -07009397#else /* #ifdef MODULE */
9398static int __init hdd_module_init ( void)
9399{
9400 /* Driver initialization is delayed to fwpath_changed_handler */
9401 return 0;
9402}
Jeff Johnson32d95a32012-09-10 13:15:23 -07009403#endif /* #ifdef MODULE */
9404
Jeff Johnson295189b2012-06-20 16:38:30 -07009405
9406/**---------------------------------------------------------------------------
9407
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009408 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07009409
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009410 This is the driver exit point (invoked when module is unloaded using rmmod
9411 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07009412
9413 \param - None
9414
9415 \return - None
9416
9417 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009418static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07009419{
9420 hdd_context_t *pHddCtx = NULL;
9421 v_CONTEXT_t pVosContext = NULL;
Agarwal Ashish5e414792014-06-08 15:25:23 +05309422 v_REGDOMAIN_t regId;
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +05309423 unsigned long rc = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07009424
9425 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
9426
9427 //Get the global vos context
9428 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
9429
9430 if(!pVosContext)
9431 {
9432 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
9433 goto done;
9434 }
9435
9436 //Get the HDD context.
9437 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
9438
9439 if(!pHddCtx)
9440 {
9441 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
9442 }
9443 else
9444 {
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +05309445 INIT_COMPLETION(pHddCtx->ssr_comp_var);
9446
9447 if (pHddCtx->isLogpInProgress)
9448 {
Sameer Thalappil451ebb92013-06-28 15:49:58 -07009449 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +05309450 "%s:SSR in Progress; block rmmod !!!", __func__);
9451 rc = wait_for_completion_timeout(&pHddCtx->ssr_comp_var,
9452 msecs_to_jiffies(30000));
9453 if(!rc)
9454 {
9455 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
9456 "%s:SSR timedout, fatal error", __func__);
9457 VOS_BUG(0);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07009458 }
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +05309459 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009460
Mihir Shete18156292014-03-11 15:38:30 +05309461 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_UNLOAD_IN_PROGRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -07009462 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
9463
Agarwal Ashish5e414792014-06-08 15:25:23 +05309464 if (eANI_BOOLEAN_TRUE == sme_Is11dCountrycode(pHddCtx->hHal) &&
9465 pHddCtx->cfg_ini->fSupplicantCountryCodeHasPriority )
9466 {
9467 vos_nv_getRegDomainFromCountryCode(&regId , "00", COUNTRY_USER);
9468 }
9469
Jeff Johnson295189b2012-06-20 16:38:30 -07009470 //Do all the cleanup before deregistering the driver
9471 hdd_wlan_exit(pHddCtx);
9472 }
9473
Jeff Johnson295189b2012-06-20 16:38:30 -07009474 vos_preClose( &pVosContext );
9475
9476#ifdef TIMER_MANAGER
9477 vos_timer_exit();
9478#endif
9479#ifdef MEMORY_DEBUG
9480 vos_mem_exit();
9481#endif
9482
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05309483#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9484 wlan_logging_sock_deinit_svc();
9485#endif
9486
Jeff Johnson295189b2012-06-20 16:38:30 -07009487done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08009488#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07009489 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07009490#endif
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05309491
Jeff Johnson295189b2012-06-20 16:38:30 -07009492 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
9493}
9494
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009495/**---------------------------------------------------------------------------
9496
9497 \brief hdd_module_exit() - Exit function
9498
9499 This is the driver exit point (invoked when module is unloaded using rmmod)
9500
9501 \param - None
9502
9503 \return - None
9504
9505 --------------------------------------------------------------------------*/
9506static void __exit hdd_module_exit(void)
9507{
9508 hdd_driver_exit();
9509}
9510
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009511#ifdef MODULE
9512static int fwpath_changed_handler(const char *kmessage,
9513 struct kernel_param *kp)
9514{
Jeff Johnson76052702013-04-16 13:55:05 -07009515 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009516}
9517
9518static int con_mode_handler(const char *kmessage,
9519 struct kernel_param *kp)
9520{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07009521 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009522}
9523#else /* #ifdef MODULE */
9524/**---------------------------------------------------------------------------
9525
Jeff Johnson76052702013-04-16 13:55:05 -07009526 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009527
Jeff Johnson76052702013-04-16 13:55:05 -07009528 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009529 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07009530 - invoked when module parameter fwpath is modified from userspace to signal
9531 initializing the WLAN driver or when con_mode is modified from userspace
9532 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009533
9534 \return - 0 for success, non zero for failure
9535
9536 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07009537static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009538{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07009539 int ret_status;
9540
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009541 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07009542 ret_status = hdd_driver_init();
9543 wlan_hdd_inited = ret_status ? 0 : 1;
9544 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009545 }
9546
9547 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07009548
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009549 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07009550
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07009551 ret_status = hdd_driver_init();
9552 wlan_hdd_inited = ret_status ? 0 : 1;
9553 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009554}
9555
Jeff Johnson295189b2012-06-20 16:38:30 -07009556/**---------------------------------------------------------------------------
9557
Jeff Johnson76052702013-04-16 13:55:05 -07009558 \brief fwpath_changed_handler() - Handler Function
9559
9560 Handle changes to the fwpath parameter
9561
9562 \return - 0 for success, non zero for failure
9563
9564 --------------------------------------------------------------------------*/
9565static int fwpath_changed_handler(const char *kmessage,
9566 struct kernel_param *kp)
9567{
9568 int ret;
9569
9570 ret = param_set_copystring(kmessage, kp);
9571 if (0 == ret)
9572 ret = kickstart_driver();
9573 return ret;
9574}
9575
9576/**---------------------------------------------------------------------------
9577
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009578 \brief con_mode_handler() -
9579
9580 Handler function for module param con_mode when it is changed by userspace
9581 Dynamically linked - do nothing
9582 Statically linked - exit and init driver, as in rmmod and insmod
9583
Jeff Johnson76052702013-04-16 13:55:05 -07009584 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009585
Jeff Johnson76052702013-04-16 13:55:05 -07009586 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009587
9588 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07009589static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009590{
Jeff Johnson76052702013-04-16 13:55:05 -07009591 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009592
Jeff Johnson76052702013-04-16 13:55:05 -07009593 ret = param_set_int(kmessage, kp);
9594 if (0 == ret)
9595 ret = kickstart_driver();
9596 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009597}
9598#endif /* #ifdef MODULE */
9599
9600/**---------------------------------------------------------------------------
9601
Jeff Johnson295189b2012-06-20 16:38:30 -07009602 \brief hdd_get_conparam() -
9603
9604 This is the driver exit point (invoked when module is unloaded using rmmod)
9605
9606 \param - None
9607
9608 \return - tVOS_CON_MODE
9609
9610 --------------------------------------------------------------------------*/
9611tVOS_CON_MODE hdd_get_conparam ( void )
9612{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009613#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07009614 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009615#else
9616 return (tVOS_CON_MODE)curr_con_mode;
9617#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009618}
9619void hdd_set_conparam ( v_UINT_t newParam )
9620{
9621 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009622#ifndef MODULE
9623 curr_con_mode = con_mode;
9624#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009625}
9626/**---------------------------------------------------------------------------
9627
9628 \brief hdd_softap_sta_deauth() - function
9629
9630 This to take counter measure to handle deauth req from HDD
9631
9632 \param - pAdapter - Pointer to the HDD
9633
9634 \param - enable - boolean value
9635
9636 \return - None
9637
9638 --------------------------------------------------------------------------*/
9639
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009640VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07009641{
Jeff Johnson295189b2012-06-20 16:38:30 -07009642 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009643 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07009644
9645 ENTER();
9646
Rajesh Chauhan18488fc2013-08-22 10:15:03 -07009647 hddLog(LOG1, "hdd_softap_sta_deauth:(%p, false)",
9648 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07009649
9650 //Ignore request to deauth bcmc station
9651 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009652 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07009653
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009654 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07009655
9656 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009657 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07009658}
9659
9660/**---------------------------------------------------------------------------
9661
9662 \brief hdd_softap_sta_disassoc() - function
9663
9664 This to take counter measure to handle deauth req from HDD
9665
9666 \param - pAdapter - Pointer to the HDD
9667
9668 \param - enable - boolean value
9669
9670 \return - None
9671
9672 --------------------------------------------------------------------------*/
9673
9674void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
9675{
9676 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
9677
9678 ENTER();
9679
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05309680 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07009681
9682 //Ignore request to disassoc bcmc station
9683 if( pDestMacAddress[0] & 0x1 )
9684 return;
9685
9686 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
9687}
9688
9689void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
9690{
9691 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
9692
9693 ENTER();
9694
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05309695 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07009696
9697 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
9698}
9699
Jeff Johnson295189b2012-06-20 16:38:30 -07009700/**---------------------------------------------------------------------------
9701 *
9702 * \brief hdd_get__concurrency_mode() -
9703 *
9704 *
9705 * \param - None
9706 *
9707 * \return - CONCURRENCY MODE
9708 *
9709 * --------------------------------------------------------------------------*/
9710tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
9711{
9712 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
9713 hdd_context_t *pHddCtx;
9714
9715 if (NULL != pVosContext)
9716 {
9717 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
9718 if (NULL != pHddCtx)
9719 {
9720 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
9721 }
9722 }
9723
9724 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07009725 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009726 return VOS_STA;
9727}
Sushant Kaushikabb7ee62014-07-18 16:20:12 +05309728v_BOOL_t
9729wlan_hdd_is_GO_power_collapse_allowed (hdd_context_t* pHddCtx)
9730{
9731 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07009732
Sushant Kaushikabb7ee62014-07-18 16:20:12 +05309733 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_GO);
9734 if (pAdapter == NULL)
9735 {
9736 hddLog(VOS_TRACE_LEVEL_INFO,
9737 FL("GO doesn't exist"));
9738 return TRUE;
9739 }
9740 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
9741 {
9742 hddLog(VOS_TRACE_LEVEL_INFO,
9743 FL("GO started"));
9744 return TRUE;
9745 }
9746 else
9747 /* wait till GO changes its interface to p2p device */
9748 hddLog(VOS_TRACE_LEVEL_INFO,
9749 FL("Del_bss called, avoid apps suspend"));
9750 return FALSE;
9751
9752}
Jeff Johnson295189b2012-06-20 16:38:30 -07009753/* Decide whether to allow/not the apps power collapse.
9754 * Allow apps power collapse if we are in connected state.
9755 * if not, allow only if we are in IMPS */
9756v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
9757{
9758 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08009759 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08009760 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07009761 hdd_config_t *pConfig = pHddCtx->cfg_ini;
9762 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
9763 hdd_adapter_t *pAdapter = NULL;
9764 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08009765 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07009766
Jeff Johnson295189b2012-06-20 16:38:30 -07009767 if (VOS_STA_SAP_MODE == hdd_get_conparam())
9768 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07009769
Yathish9f22e662012-12-10 14:21:35 -08009770 concurrent_state = hdd_get_concurrency_mode();
9771
Sushant Kaushikabb7ee62014-07-18 16:20:12 +05309772 if ((concurrent_state == (VOS_STA | VOS_P2P_GO)) &&
9773 !(wlan_hdd_is_GO_power_collapse_allowed(pHddCtx)))
9774 return FALSE;
Yathish9f22e662012-12-10 14:21:35 -08009775#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
Sushant Kaushikabb7ee62014-07-18 16:20:12 +05309776
Yathish9f22e662012-12-10 14:21:35 -08009777 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
Sushant Kaushikabb7ee62014-07-18 16:20:12 +05309778 (concurrent_state == (VOS_STA | VOS_P2P_GO)))&&
Yathish9f22e662012-12-10 14:21:35 -08009779 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
9780 return TRUE;
9781#endif
9782
Jeff Johnson295189b2012-06-20 16:38:30 -07009783 /*loop through all adapters. TBD fix for Concurrency */
9784 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
9785 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
9786 {
9787 pAdapter = pAdapterNode->pAdapter;
9788 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
9789 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
9790 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08009791 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
c_hpothu4e8faac2014-05-16 17:38:44 +05309792 && (pmcState != IMPS && pmcState != BMPS && pmcState != UAPSD
Srikant Kuppafef66a72013-01-30 17:32:44 -08009793 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08009794 (eANI_BOOLEAN_TRUE == scanRspPending) ||
9795 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07009796 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08009797 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08009798 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
9799 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07009800 return FALSE;
9801 }
9802 }
9803 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
9804 pAdapterNode = pNext;
9805 }
9806 return TRUE;
9807}
9808
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08009809/* Decides whether to send suspend notification to Riva
9810 * if any adapter is in BMPS; then it is required */
9811v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
9812{
9813 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
9814 hdd_config_t *pConfig = pHddCtx->cfg_ini;
9815
9816 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
9817 {
9818 return TRUE;
9819 }
9820 return FALSE;
9821}
9822
Jeff Johnson295189b2012-06-20 16:38:30 -07009823void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
9824{
9825 switch(mode)
9826 {
Chilam Ngc4244af2013-04-01 15:37:32 -07009827 case VOS_STA_MODE:
9828 case VOS_P2P_CLIENT_MODE:
9829 case VOS_P2P_GO_MODE:
9830 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07009831 pHddCtx->concurrency_mode |= (1 << mode);
Agarwal Ashish51325b52014-06-16 16:50:49 +05309832 pHddCtx->no_of_open_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07009833 break;
9834 default:
9835 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07009836 }
Agarwal Ashish51325b52014-06-16 16:50:49 +05309837 hddLog(VOS_TRACE_LEVEL_INFO, FL("concurrency_mode = 0x%x "
9838 "Number of open sessions for mode %d = %d"),
9839 pHddCtx->concurrency_mode, mode,
9840 pHddCtx->no_of_open_sessions[mode]);
Jeff Johnson295189b2012-06-20 16:38:30 -07009841}
9842
9843
9844void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
9845{
9846 switch(mode)
9847 {
Chilam Ngc4244af2013-04-01 15:37:32 -07009848 case VOS_STA_MODE:
9849 case VOS_P2P_CLIENT_MODE:
9850 case VOS_P2P_GO_MODE:
9851 case VOS_STA_SAP_MODE:
Agarwal Ashish51325b52014-06-16 16:50:49 +05309852 pHddCtx->no_of_open_sessions[mode]--;
9853 if (!(pHddCtx->no_of_open_sessions[mode]))
9854 pHddCtx->concurrency_mode &= (~(1 << mode));
Jeff Johnson295189b2012-06-20 16:38:30 -07009855 break;
9856 default:
9857 break;
9858 }
Agarwal Ashish51325b52014-06-16 16:50:49 +05309859 hddLog(VOS_TRACE_LEVEL_INFO, FL("concurrency_mode = 0x%x "
9860 "Number of open sessions for mode %d = %d"),
9861 pHddCtx->concurrency_mode, mode, pHddCtx->no_of_open_sessions[mode]);
9862
9863}
9864/**---------------------------------------------------------------------------
9865 *
9866 * \brief wlan_hdd_incr_active_session()
9867 *
9868 * This function increments the number of active sessions
9869 * maintained per device mode
9870 * Incase of STA/P2P CLI/IBSS upon connection indication it is incremented
9871 * Incase of SAP/P2P GO upon bss start it is incremented
9872 *
9873 * \param pHddCtx - HDD Context
9874 * \param mode - device mode
9875 *
9876 * \return - None
9877 *
9878 * --------------------------------------------------------------------------*/
9879void wlan_hdd_incr_active_session(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
9880{
9881 switch (mode) {
9882 case VOS_STA_MODE:
9883 case VOS_P2P_CLIENT_MODE:
9884 case VOS_P2P_GO_MODE:
9885 case VOS_STA_SAP_MODE:
9886 pHddCtx->no_of_active_sessions[mode]++;
9887 break;
9888 default:
9889 hddLog(VOS_TRACE_LEVEL_INFO, FL("Not Expected Mode %d"), mode);
9890 break;
9891 }
9892 hddLog(VOS_TRACE_LEVEL_INFO, FL("No.# of active sessions for mode %d = %d"),
9893 mode,
9894 pHddCtx->no_of_active_sessions[mode]);
9895}
9896
9897/**---------------------------------------------------------------------------
9898 *
9899 * \brief wlan_hdd_decr_active_session()
9900 *
9901 * This function decrements the number of active sessions
9902 * maintained per device mode
9903 * Incase of STA/P2P CLI/IBSS upon disconnection it is decremented
9904 * Incase of SAP/P2P GO upon bss stop it is decremented
9905 *
9906 * \param pHddCtx - HDD Context
9907 * \param mode - device mode
9908 *
9909 * \return - None
9910 *
9911 * --------------------------------------------------------------------------*/
9912void wlan_hdd_decr_active_session(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
9913{
9914 switch (mode) {
9915 case VOS_STA_MODE:
9916 case VOS_P2P_CLIENT_MODE:
9917 case VOS_P2P_GO_MODE:
9918 case VOS_STA_SAP_MODE:
9919 pHddCtx->no_of_active_sessions[mode]--;
9920 break;
9921 default:
9922 hddLog(VOS_TRACE_LEVEL_INFO, FL("Not Expected Mode %d"), mode);
9923 break;
9924 }
9925 hddLog(VOS_TRACE_LEVEL_INFO, FL("No.# of active sessions for mode %d = %d"),
9926 mode,
9927 pHddCtx->no_of_active_sessions[mode]);
Jeff Johnson295189b2012-06-20 16:38:30 -07009928}
9929
Jeff Johnsone7245742012-09-05 17:12:55 -07009930/**---------------------------------------------------------------------------
9931 *
9932 * \brief wlan_hdd_restart_init
9933 *
9934 * This function initalizes restart timer/flag. An internal function.
9935 *
9936 * \param - pHddCtx
9937 *
9938 * \return - None
9939 *
9940 * --------------------------------------------------------------------------*/
9941
9942static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
9943{
9944 /* Initialize */
9945 pHddCtx->hdd_restart_retries = 0;
9946 atomic_set(&pHddCtx->isRestartInProgress, 0);
9947 vos_timer_init(&pHddCtx->hdd_restart_timer,
9948 VOS_TIMER_TYPE_SW,
9949 wlan_hdd_restart_timer_cb,
9950 pHddCtx);
9951}
9952/**---------------------------------------------------------------------------
9953 *
9954 * \brief wlan_hdd_restart_deinit
9955 *
9956 * This function cleans up the resources used. An internal function.
9957 *
9958 * \param - pHddCtx
9959 *
9960 * \return - None
9961 *
9962 * --------------------------------------------------------------------------*/
9963
9964static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
9965{
9966
9967 VOS_STATUS vos_status;
9968 /* Block any further calls */
9969 atomic_set(&pHddCtx->isRestartInProgress, 1);
9970 /* Cleanup */
9971 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
9972 if (!VOS_IS_STATUS_SUCCESS(vos_status))
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309973 hddLog(LOGE, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07009974 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
9975 if (!VOS_IS_STATUS_SUCCESS(vos_status))
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309976 hddLog(LOGE, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07009977
9978}
9979
9980/**---------------------------------------------------------------------------
9981 *
9982 * \brief wlan_hdd_framework_restart
9983 *
9984 * This function uses a cfg80211 API to start a framework initiated WLAN
9985 * driver module unload/load.
9986 *
9987 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
9988 *
9989 *
9990 * \param - pHddCtx
9991 *
9992 * \return - VOS_STATUS_SUCCESS: Success
9993 * VOS_STATUS_E_EMPTY: Adapter is Empty
9994 * VOS_STATUS_E_NOMEM: No memory
9995
9996 * --------------------------------------------------------------------------*/
9997
9998static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
9999{
10000 VOS_STATUS status = VOS_STATUS_SUCCESS;
10001 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -070010002 int len = (sizeof (struct ieee80211_mgmt));
10003 struct ieee80211_mgmt *mgmt = NULL;
10004
10005 /* Prepare the DEAUTH managment frame with reason code */
10006 mgmt = kzalloc(len, GFP_KERNEL);
10007 if(mgmt == NULL)
10008 {
10009 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
10010 "%s: memory allocation failed (%d bytes)", __func__, len);
10011 return VOS_STATUS_E_NOMEM;
10012 }
10013 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -070010014
10015 /* Iterate over all adapters/devices */
10016 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10017 do
10018 {
10019 if( (status == VOS_STATUS_SUCCESS) &&
10020 pAdapterNode &&
10021 pAdapterNode->pAdapter)
10022 {
10023 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
10024 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
10025 pAdapterNode->pAdapter->dev->name,
10026 pAdapterNode->pAdapter->device_mode,
10027 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -070010028 /*
10029 * CFG80211 event to restart the driver
10030 *
10031 * 'cfg80211_send_unprot_deauth' sends a
10032 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
10033 * of SME(Linux Kernel) state machine.
10034 *
10035 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
10036 * the driver.
10037 *
10038 */
10039
10040 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -070010041 }
10042 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10043 pAdapterNode = pNext;
10044 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
10045
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -070010046
10047 /* Free the allocated management frame */
10048 kfree(mgmt);
10049
Jeff Johnsone7245742012-09-05 17:12:55 -070010050 /* Retry until we unload or reach max count */
10051 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
10052 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
10053
10054 return status;
10055
10056}
10057/**---------------------------------------------------------------------------
10058 *
10059 * \brief wlan_hdd_restart_timer_cb
10060 *
10061 * Restart timer callback. An internal function.
10062 *
10063 * \param - User data:
10064 *
10065 * \return - None
10066 *
10067 * --------------------------------------------------------------------------*/
10068
10069void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
10070{
10071 hdd_context_t *pHddCtx = usrDataForCallback;
10072 wlan_hdd_framework_restart(pHddCtx);
10073 return;
10074
10075}
10076
10077
10078/**---------------------------------------------------------------------------
10079 *
10080 * \brief wlan_hdd_restart_driver
10081 *
10082 * This function sends an event to supplicant to restart the WLAN driver.
10083 *
10084 * This function is called from vos_wlanRestart.
10085 *
10086 * \param - pHddCtx
10087 *
10088 * \return - VOS_STATUS_SUCCESS: Success
10089 * VOS_STATUS_E_EMPTY: Adapter is Empty
10090 * VOS_STATUS_E_ALREADY: Request already in progress
10091
10092 * --------------------------------------------------------------------------*/
10093VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
10094{
10095 VOS_STATUS status = VOS_STATUS_SUCCESS;
10096
10097 /* A tight check to make sure reentrancy */
10098 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
10099 {
Mihir Shetefd528652014-06-23 19:07:50 +053010100 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnsone7245742012-09-05 17:12:55 -070010101 "%s: WLAN restart is already in progress", __func__);
10102
10103 return VOS_STATUS_E_ALREADY;
10104 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -070010105 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -080010106#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -070010107 wcnss_reset_intr();
10108#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -070010109
Jeff Johnsone7245742012-09-05 17:12:55 -070010110 return status;
10111}
10112
Mihir Shetee1093ba2014-01-21 20:13:32 +053010113/**---------------------------------------------------------------------------
10114 *
10115 * \brief wlan_hdd_init_channels
10116 *
10117 * This function is used to initialize the channel list in CSR
10118 *
10119 * This function is called from hdd_wlan_startup
10120 *
10121 * \param - pHddCtx: HDD context
10122 *
10123 * \return - VOS_STATUS_SUCCESS: Success
10124 * VOS_STATUS_E_FAULT: Failure reported by SME
10125
10126 * --------------------------------------------------------------------------*/
10127static VOS_STATUS wlan_hdd_init_channels(hdd_context_t *pHddCtx)
10128{
10129 eHalStatus status;
10130
10131 status = sme_InitChannels(pHddCtx->hHal);
10132 if (HAL_STATUS_SUCCESS(status))
10133 {
10134 return VOS_STATUS_SUCCESS;
10135 }
10136 else
10137 {
10138 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Channel initialization failed(%d)",
10139 __func__, status);
10140 return VOS_STATUS_E_FAULT;
10141 }
10142}
10143
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053010144static VOS_STATUS wlan_hdd_init_channels_for_cc(hdd_context_t *pHddCtx)
10145{
10146 eHalStatus status;
10147
10148 status = sme_InitChannelsForCC(pHddCtx->hHal);
10149 if (HAL_STATUS_SUCCESS(status))
10150 {
10151 return VOS_STATUS_SUCCESS;
10152 }
10153 else
10154 {
10155 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Issue reg hint failed(%d)",
10156 __func__, status);
10157 return VOS_STATUS_E_FAULT;
10158 }
10159}
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -070010160/*
10161 * API to find if there is any STA or P2P-Client is connected
10162 */
10163VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
10164{
10165 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
10166}
Jeff Johnsone7245742012-09-05 17:12:55 -070010167
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053010168int wlan_hdd_scan_abort(hdd_adapter_t *pAdapter)
10169{
10170 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10171 hdd_scaninfo_t *pScanInfo = NULL;
Girish Gowli4bf7a632014-06-12 13:42:11 +053010172 long status = 0;
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053010173
10174 pScanInfo = &pHddCtx->scan_info;
10175 if (pScanInfo->mScanPending)
10176 {
10177 INIT_COMPLETION(pScanInfo->abortscan_event_var);
10178 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
10179 eCSR_SCAN_ABORT_DEFAULT);
10180
10181 status = wait_for_completion_interruptible_timeout(
10182 &pScanInfo->abortscan_event_var,
10183 msecs_to_jiffies(5000));
Girish Gowli4bf7a632014-06-12 13:42:11 +053010184 if (0 >= status)
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053010185 {
10186 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Girish Gowli4bf7a632014-06-12 13:42:11 +053010187 "%s: Timeout or Interrupt occurred while waiting for abort"
10188 "scan, status- %ld", __func__, status);
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053010189 return -ETIMEDOUT;
10190 }
10191 }
Girish Gowli4bf7a632014-06-12 13:42:11 +053010192 return 0;
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053010193}
10194
Jeff Johnson295189b2012-06-20 16:38:30 -070010195//Register the module init/exit functions
10196module_init(hdd_module_init);
10197module_exit(hdd_module_exit);
10198
10199MODULE_LICENSE("Dual BSD/GPL");
10200MODULE_AUTHOR("Qualcomm Atheros, Inc.");
10201MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
10202
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070010203module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
10204 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -070010205
Jeff Johnson76052702013-04-16 13:55:05 -070010206module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -070010207 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Arif Hussain66559122013-11-21 10:11:40 -080010208
10209module_param(enable_dfs_chan_scan, int,
10210 S_IRUSR | S_IRGRP | S_IROTH);
10211
10212module_param(enable_11d, int,
10213 S_IRUSR | S_IRGRP | S_IROTH);
10214
10215module_param(country_code, charp,
10216 S_IRUSR | S_IRGRP | S_IROTH);