blob: 3a7478a12e78e26f2de70adf17b7c4774abcbacc [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Kiet Lam842dad02014-02-18 18:44:02 -08002 * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved.
3 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
Kiet Lama7f454d2014-07-24 12:04:06 -070023 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
Gopichand Nakkala92f07d82013-01-08 21:16:34 -080026 */
Kiet Lam842dad02014-02-18 18:44:02 -080027
28
Kiet Lama7f454d2014-07-24 12:04:06 -070029
30
Jeff Johnson295189b2012-06-20 16:38:30 -070031/*========================================================================
32
33 \file wlan_hdd_main.c
34
35 \brief WLAN Host Device Driver implementation
36
Jeff Johnson295189b2012-06-20 16:38:30 -070037
38 ========================================================================*/
39
40/**=========================================================================
41
42 EDIT HISTORY FOR FILE
43
44
45 This section contains comments describing changes made to the module.
46 Notice that changes are listed in reverse chronological order.
47
48
49 $Header:$ $DateTime: $ $Author: $
50
51
52 when who what, where, why
53 -------- --- --------------------------------------------------------
54 04/5/09 Shailender Created module.
55 02/24/10 Sudhir.S.Kohalli Added to support param for SoftAP module
56 06/03/10 js - Added support to hostapd driven deauth/disassoc/mic failure
57 ==========================================================================*/
58
59/*--------------------------------------------------------------------------
60 Include Files
61 ------------------------------------------------------------------------*/
62//#include <wlan_qct_driver.h>
63#include <wlan_hdd_includes.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070064#include <vos_api.h>
65#include <vos_sched.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070066#include <linux/etherdevice.h>
67#include <linux/firmware.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070068#ifdef ANI_BUS_TYPE_PLATFORM
69#include <linux/wcnss_wlan.h>
70#endif //ANI_BUS_TYPE_PLATFORM
71#ifdef ANI_BUS_TYPE_PCI
72#include "wcnss_wlan.h"
73#endif /* ANI_BUS_TYPE_PCI */
74#include <wlan_hdd_tx_rx.h>
75#include <palTimer.h>
76#include <wniApi.h>
77#include <wlan_nlink_srv.h>
78#include <wlan_btc_svc.h>
79#include <wlan_hdd_cfg.h>
80#include <wlan_ptt_sock_svc.h>
Vinay Krishna Erannad938c422014-03-10 17:14:21 +053081#include <wlan_logging_sock_svc.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070082#include <wlan_hdd_wowl.h>
83#include <wlan_hdd_misc.h>
84#include <wlan_hdd_wext.h>
85#ifdef WLAN_BTAMP_FEATURE
86#include <bap_hdd_main.h>
87#include <bapInternal.h>
88#endif // WLAN_BTAMP_FEATURE
Sushant Kaushik4b7cb302014-01-06 17:45:01 +053089#include "wlan_hdd_trace.h"
90#include "vos_types.h"
91#include "vos_trace.h"
Jeff Johnson295189b2012-06-20 16:38:30 -070092#include <linux/wireless.h>
93#include <net/cfg80211.h>
Vinay Krishna Erannad9cbdb32014-01-16 12:59:10 +053094#include <linux/inetdevice.h>
95#include <net/addrconf.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070096#include "wlan_hdd_cfg80211.h"
97#include "wlan_hdd_p2p.h"
Jeff Johnson295189b2012-06-20 16:38:30 -070098#include <linux/rtnetlink.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070099int wlan_hdd_ftm_start(hdd_context_t *pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700100#include "sapApi.h"
101#include <linux/semaphore.h>
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -0700102#include <linux/ctype.h>
Arun Kumar Khandavalli74fe3032014-03-17 20:35:34 +0530103#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0))
104#include <soc/qcom/subsystem_restart.h>
105#else
Jeff Johnson295189b2012-06-20 16:38:30 -0700106#include <mach/subsystem_restart.h>
Arun Kumar Khandavalli74fe3032014-03-17 20:35:34 +0530107#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700108#include <wlan_hdd_hostapd.h>
109#include <wlan_hdd_softap_tx_rx.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700110#include "cfgApi.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700111#include "wlan_hdd_dev_pwr.h"
112#ifdef WLAN_BTAMP_FEATURE
113#include "bap_hdd_misc.h"
114#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700115#include "wlan_qct_pal_trace.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700116#include "qwlan_version.h"
Yathish9f22e662012-12-10 14:21:35 -0800117#include "wlan_qct_wda.h"
Chilam NG571c65a2013-01-19 12:27:36 +0530118#ifdef FEATURE_WLAN_TDLS
119#include "wlan_hdd_tdls.h"
120#endif
Yue Ma0d4891e2013-08-06 17:01:45 -0700121#include "wlan_hdd_debugfs.h"
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +0530122#include "sapInternal.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700123
124#ifdef MODULE
125#define WLAN_MODULE_NAME module_name(THIS_MODULE)
126#else
127#define WLAN_MODULE_NAME "wlan"
128#endif
129
130#ifdef TIMER_MANAGER
131#define TIMER_MANAGER_STR " +TIMER_MANAGER"
132#else
133#define TIMER_MANAGER_STR ""
134#endif
135
136#ifdef MEMORY_DEBUG
137#define MEMORY_DEBUG_STR " +MEMORY_DEBUG"
138#else
139#define MEMORY_DEBUG_STR ""
140#endif
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530141#define MAX_WAIT_FOR_ROC_COMPLETION 3
Jeff Johnson295189b2012-06-20 16:38:30 -0700142/* the Android framework expects this param even though we don't use it */
143#define BUF_LEN 20
Jeff Johnson76052702013-04-16 13:55:05 -0700144static char fwpath_buffer[BUF_LEN];
145static struct kparam_string fwpath = {
146 .string = fwpath_buffer,
147 .maxlen = BUF_LEN,
148};
Arif Hussain66559122013-11-21 10:11:40 -0800149
150static char *country_code;
151static int enable_11d = -1;
152static int enable_dfs_chan_scan = -1;
c_hpothu92367912014-05-01 15:18:17 +0530153static int gbcnMissRate = -1;
Arif Hussain66559122013-11-21 10:11:40 -0800154
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700155#ifndef MODULE
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700156static int wlan_hdd_inited;
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700157#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700158
Jeff Johnsone7245742012-09-05 17:12:55 -0700159/*
Jeff Johnson72a40512013-12-19 10:14:15 -0800160 * spinlock for synchronizing asynchronous request/response
161 * (full description of use in wlan_hdd_main.h)
162 */
163DEFINE_SPINLOCK(hdd_context_lock);
164
165/*
Jeff Johnsone7245742012-09-05 17:12:55 -0700166 * The rate at which the driver sends RESTART event to supplicant
167 * once the function 'vos_wlanRestart()' is called
168 *
169 */
170#define WLAN_HDD_RESTART_RETRY_DELAY_MS 5000 /* 5 second */
171#define WLAN_HDD_RESTART_RETRY_MAX_CNT 5 /* 5 retries */
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -0700172
173/*
174 * Size of Driver command strings from upper layer
175 */
176#define SIZE_OF_SETROAMMODE 11 /* size of SETROAMMODE */
177#define SIZE_OF_GETROAMMODE 11 /* size of GETROAMMODE */
178
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -0800179#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda5cecb202013-10-08 09:13:25 -0700180#define TID_MIN_VALUE 0
181#define TID_MAX_VALUE 15
182static VOS_STATUS hdd_get_tsm_stats(hdd_adapter_t *pAdapter, const tANI_U8 tid,
183 tAniTrafStrmMetrics* pTsmMetrics);
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -0800184static VOS_STATUS hdd_parse_ese_beacon_req(tANI_U8 *pValue,
185 tCsrEseBeaconReq *pEseBcnReq);
186#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -0700187
Atul Mittal1d722422014-03-19 11:15:07 +0530188/*
189 * Maximum buffer size used for returning the data back to user space
190 */
191#define WLAN_MAX_BUF_SIZE 1024
192#define WLAN_PRIV_DATA_MAX_LEN 8192
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -0700193
c_hpothu92367912014-05-01 15:18:17 +0530194//wait time for beacon miss rate.
195#define BCN_MISS_RATE_TIME 500
196
Sameer Thalappil50dc0092013-02-19 17:23:33 -0800197#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -0700198static struct wake_lock wlan_wake_lock;
Jeff Johnsone7245742012-09-05 17:12:55 -0700199#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700200/* set when SSR is needed after unload */
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -0700201static e_hdd_ssr_required isSsrRequired = HDD_SSR_NOT_REQUIRED;
Jeff Johnson295189b2012-06-20 16:38:30 -0700202
203//internal function declaration
Jeff Johnsone7245742012-09-05 17:12:55 -0700204static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx);
205static void wlan_hdd_restart_init(hdd_context_t *pHddCtx);
206static void wlan_hdd_restart_deinit(hdd_context_t *pHddCtx);
207void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback);
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800208void hdd_set_wlan_suspend_mode(bool suspend);
Jeff Johnsone7245742012-09-05 17:12:55 -0700209
Jeff Johnson295189b2012-06-20 16:38:30 -0700210v_U16_t hdd_select_queue(struct net_device *dev,
211 struct sk_buff *skb);
212
213#ifdef WLAN_FEATURE_PACKET_FILTERING
214static void hdd_set_multicast_list(struct net_device *dev);
215#endif
216
217void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter);
218
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -0800219#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -0800220void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand);
221static VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels);
Srinivas Girigowda100eb322013-03-15 16:48:20 -0700222static VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid,
223 tANI_U8 *pChannel, tANI_U8 *pDwellTime,
224 tANI_U8 **pBuf, tANI_U8 *pBufLen);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -0700225static VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue,
226 tANI_U8 *pTargetApBssid,
227 tANI_U8 *pChannel);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800228#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -0800229#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda5cecb202013-10-08 09:13:25 -0700230VOS_STATUS hdd_parse_get_cckm_ie(tANI_U8 *pValue, tANI_U8 **pCckmIe, tANI_U8 *pCckmIeLen);
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -0800231#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -0700232
Mihir Shetee1093ba2014-01-21 20:13:32 +0530233static VOS_STATUS wlan_hdd_init_channels(hdd_context_t *pHddCtx);
Sushant Kaushik8bc7df22014-04-09 17:55:29 +0530234const char * hdd_device_modetoString(v_U8_t device_mode)
235{
236 switch(device_mode)
237 {
238 CASE_RETURN_STRING( WLAN_HDD_INFRA_STATION );
239 CASE_RETURN_STRING( WLAN_HDD_SOFTAP );
240 CASE_RETURN_STRING( WLAN_HDD_P2P_CLIENT );
241 CASE_RETURN_STRING( WLAN_HDD_P2P_GO );
242 CASE_RETURN_STRING( WLAN_HDD_MONITOR);
243 CASE_RETURN_STRING( WLAN_HDD_FTM );
244 CASE_RETURN_STRING( WLAN_HDD_IBSS );
245 CASE_RETURN_STRING( WLAN_HDD_P2P_DEVICE );
246 default:
247 return "device_mode Unknown";
248 }
249}
Mihir Shetee1093ba2014-01-21 20:13:32 +0530250
Jeff Johnson295189b2012-06-20 16:38:30 -0700251static int hdd_netdev_notifier_call(struct notifier_block * nb,
252 unsigned long state,
253 void *ndev)
254{
255 struct net_device *dev = ndev;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700256 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson27cee452013-03-27 11:10:24 -0700257 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700258#ifdef WLAN_BTAMP_FEATURE
259 VOS_STATUS status;
Jeff Johnson295189b2012-06-20 16:38:30 -0700260#endif
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +0530261 long result;
Jeff Johnson295189b2012-06-20 16:38:30 -0700262
263 //Make sure that this callback corresponds to our device.
Jeff Johnson27cee452013-03-27 11:10:24 -0700264 if ((strncmp(dev->name, "wlan", 4)) &&
Amar Singhal4c723bd2013-03-25 18:14:15 -0700265 (strncmp(dev->name, "p2p", 3)))
266 return NOTIFY_DONE;
267
Jeff Johnson295189b2012-06-20 16:38:30 -0700268 if (!dev->ieee80211_ptr)
Jeff Johnson27cee452013-03-27 11:10:24 -0700269 return NOTIFY_DONE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700270
Jeff Johnson27cee452013-03-27 11:10:24 -0700271 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -0700272 {
Jeff Johnsona8a1a482012-12-12 16:49:33 -0800273 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Adapter Null Pointer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700274 VOS_ASSERT(0);
275 return NOTIFY_DONE;
276 }
277
Jeff Johnson27cee452013-03-27 11:10:24 -0700278 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
279 if (NULL == pHddCtx)
280 {
281 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Context Null Pointer", __func__);
282 VOS_ASSERT(0);
283 return NOTIFY_DONE;
284 }
Sameer Thalappil14067972014-01-23 14:54:54 -0800285 if (pHddCtx->isLogpInProgress)
286 return NOTIFY_DONE;
287
Jeff Johnson27cee452013-03-27 11:10:24 -0700288
289 hddLog(VOS_TRACE_LEVEL_INFO, "%s: %s New Net Device State = %lu",
290 __func__, dev->name, state);
Jeff Johnson295189b2012-06-20 16:38:30 -0700291
292 switch (state) {
293 case NETDEV_REGISTER:
294 break;
295
296 case NETDEV_UNREGISTER:
297 break;
298
299 case NETDEV_UP:
300 break;
301
302 case NETDEV_DOWN:
303 break;
304
305 case NETDEV_CHANGE:
Jeff Johnsone7245742012-09-05 17:12:55 -0700306 if(TRUE == pAdapter->isLinkUpSvcNeeded)
307 complete(&pAdapter->linkup_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700308 break;
309
310 case NETDEV_GOING_DOWN:
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +0530311 result = wlan_hdd_scan_abort(pAdapter);
Girish Gowli4bf7a632014-06-12 13:42:11 +0530312 if (result < 0)
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +0530313 {
314 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
315 "%s: Timeout occurred while waiting for abortscan %ld",
316 __func__, result);
Jeff Johnson295189b2012-06-20 16:38:30 -0700317 }
318 else
319 {
320 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +0530321 "%s: Scan Abort Successful" , __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700322 }
323#ifdef WLAN_BTAMP_FEATURE
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700324 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: disabling AMP", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700325 status = WLANBAP_StopAmp();
326 if(VOS_STATUS_SUCCESS != status )
327 {
328 pHddCtx->isAmpAllowed = VOS_TRUE;
329 hddLog(VOS_TRACE_LEVEL_FATAL,
330 "%s: Failed to stop AMP", __func__);
331 }
332 else
333 {
334 //a state m/c implementation in PAL is TBD to avoid this delay
335 msleep(500);
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700336 if ( pHddCtx->isAmpAllowed )
337 {
338 WLANBAP_DeregisterFromHCI();
339 pHddCtx->isAmpAllowed = VOS_FALSE;
340 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700341 }
342#endif //WLAN_BTAMP_FEATURE
343 break;
344
345 default:
346 break;
347 }
348
349 return NOTIFY_DONE;
350}
351
352struct notifier_block hdd_netdev_notifier = {
353 .notifier_call = hdd_netdev_notifier_call,
354};
355
356/*---------------------------------------------------------------------------
357 * Function definitions
358 *-------------------------------------------------------------------------*/
Jeff Johnson295189b2012-06-20 16:38:30 -0700359void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx);
360void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -0700361//variable to hold the insmod parameters
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700362static int con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -0700363#ifndef MODULE
364/* current con_mode - used only for statically linked driver
365 * con_mode is changed by userspace to indicate a mode change which will
366 * result in calling the module exit and init functions. The module
367 * exit function will clean up based on the value of con_mode prior to it
368 * being changed by userspace. So curr_con_mode records the current con_mode
369 * for exit when con_mode becomes the next mode for init
370 */
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700371static int curr_con_mode;
Jeff Johnson295189b2012-06-20 16:38:30 -0700372#endif
373
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -0800374/**---------------------------------------------------------------------------
375
376 \brief hdd_vos_trace_enable() - Configure initial VOS Trace enable
377
378 Called immediately after the cfg.ini is read in order to configure
379 the desired trace levels.
380
381 \param - moduleId - module whose trace level is being configured
382 \param - bitmask - bitmask of log levels to be enabled
383
384 \return - void
385
386 --------------------------------------------------------------------------*/
387static void hdd_vos_trace_enable(VOS_MODULE_ID moduleId, v_U32_t bitmask)
388{
389 wpt_tracelevel level;
390
391 /* if the bitmask is the default value, then a bitmask was not
392 specified in cfg.ini, so leave the logging level alone (it
393 will remain at the "compiled in" default value) */
394 if (CFG_VOS_TRACE_ENABLE_DEFAULT == bitmask)
395 {
396 return;
397 }
398
399 /* a mask was specified. start by disabling all logging */
400 vos_trace_setValue(moduleId, VOS_TRACE_LEVEL_NONE, 0);
401
402 /* now cycle through the bitmask until all "set" bits are serviced */
403 level = VOS_TRACE_LEVEL_FATAL;
404 while (0 != bitmask)
405 {
406 if (bitmask & 1)
407 {
408 vos_trace_setValue(moduleId, level, 1);
409 }
410 level++;
411 bitmask >>= 1;
412 }
413}
414
415
Jeff Johnson295189b2012-06-20 16:38:30 -0700416/**---------------------------------------------------------------------------
417
418 \brief hdd_wdi_trace_enable() - Configure initial WDI Trace enable
419
420 Called immediately after the cfg.ini is read in order to configure
421 the desired trace levels in the WDI.
422
423 \param - moduleId - module whose trace level is being configured
424 \param - bitmask - bitmask of log levels to be enabled
425
426 \return - void
427
428 --------------------------------------------------------------------------*/
429static void hdd_wdi_trace_enable(wpt_moduleid moduleId, v_U32_t bitmask)
430{
431 wpt_tracelevel level;
432
433 /* if the bitmask is the default value, then a bitmask was not
434 specified in cfg.ini, so leave the logging level alone (it
435 will remain at the "compiled in" default value) */
436 if (CFG_WDI_TRACE_ENABLE_DEFAULT == bitmask)
437 {
438 return;
439 }
440
441 /* a mask was specified. start by disabling all logging */
442 wpalTraceSetLevel(moduleId, eWLAN_PAL_TRACE_LEVEL_NONE, 0);
443
444 /* now cycle through the bitmask until all "set" bits are serviced */
445 level = eWLAN_PAL_TRACE_LEVEL_FATAL;
446 while (0 != bitmask)
447 {
448 if (bitmask & 1)
449 {
450 wpalTraceSetLevel(moduleId, level, 1);
451 }
452 level++;
453 bitmask >>= 1;
454 }
455}
Jeff Johnson295189b2012-06-20 16:38:30 -0700456
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530457/*
458 * FUNCTION: wlan_hdd_validate_context
459 * This function is used to check the HDD context
460 */
461int wlan_hdd_validate_context(hdd_context_t *pHddCtx)
462{
463 ENTER();
464
465 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
466 {
467 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
468 "%s: HDD context is Null", __func__);
469 return -ENODEV;
470 }
471
472 if (pHddCtx->isLogpInProgress)
473 {
474 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
c_hpothu8adb97b2014-12-08 19:38:20 +0530475 "%s: LOGP %s. Ignore!!", __func__,
476 vos_is_wlan_in_badState(VOS_MODULE_ID_HDD, NULL)
477 ?"failed":"in Progress");
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530478 return -EAGAIN;
479 }
480
Mihir Shete18156292014-03-11 15:38:30 +0530481 if (WLAN_HDD_IS_LOAD_UNLOAD_IN_PROGRESS(pHddCtx))
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530482 {
483 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
484 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
485 return -EAGAIN;
486 }
487 return 0;
488}
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700489#ifdef CONFIG_ENABLE_LINUX_REG
490void hdd_checkandupdate_phymode( hdd_context_t *pHddCtx)
491{
492 hdd_adapter_t *pAdapter = NULL;
493 hdd_station_ctx_t *pHddStaCtx = NULL;
494 eCsrPhyMode phyMode;
495 hdd_config_t *cfg_param = NULL;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530496
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700497 if (NULL == pHddCtx)
498 {
499 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
500 "HDD Context is null !!");
501 return ;
502 }
503
504 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
505 if (NULL == pAdapter)
506 {
507 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
508 "pAdapter is null !!");
509 return ;
510 }
511
512 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
513 if (NULL == pHddStaCtx)
514 {
515 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
516 "pHddStaCtx is null !!");
517 return ;
518 }
519
520 cfg_param = pHddCtx->cfg_ini;
521 if (NULL == cfg_param)
522 {
523 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
524 "cfg_params not available !!");
525 return ;
526 }
527
528 phyMode = sme_GetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter));
529
530 if (!pHddCtx->isVHT80Allowed)
531 {
532 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
533 (eCSR_DOT11_MODE_11ac == phyMode) ||
534 (eCSR_DOT11_MODE_11ac_ONLY == phyMode))
535 {
536 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
537 "Setting phymode to 11n!!");
538 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter), eCSR_DOT11_MODE_11n);
539 }
540 }
541 else
542 {
543 /*New country Supports 11ac as well resetting value back from .ini*/
544 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter),
545 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->dot11Mode));
546 return ;
547 }
548
549 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
550 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode) ||
551 (eCSR_CFG_DOT11_MODE_11AC == pHddStaCtx->conn_info.dot11Mode)))
552 {
553 VOS_STATUS vosStatus;
554
555 // need to issue a disconnect to CSR.
556 INIT_COMPLETION(pAdapter->disconnect_comp_var);
557 vosStatus = sme_RoamDisconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
558 pAdapter->sessionId,
559 eCSR_DISCONNECT_REASON_UNSPECIFIED );
560
561 if (VOS_STATUS_SUCCESS == vosStatus)
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530562 {
563 long ret;
564
565 ret = wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700566 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530567 if (0 >= ret)
568 hddLog(LOGE, FL("failure waiting for disconnect_comp_var %ld"),
569 ret);
570 }
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700571
572 }
573}
574#else
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530575void hdd_checkandupdate_phymode( hdd_adapter_t *pAdapter, char *country_code)
576{
577 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
578 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
579 hdd_config_t *cfg_param;
580 eCsrPhyMode phyMode;
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530581 long ret;
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530582
583 if (NULL == pHddCtx)
584 {
585 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
586 "HDD Context is null !!");
587 return ;
588 }
589
590 cfg_param = pHddCtx->cfg_ini;
591
592 if (NULL == cfg_param)
593 {
594 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
595 "cfg_params not available !!");
596 return ;
597 }
598
599 phyMode = sme_GetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter));
600
601 if (NULL != strstr(cfg_param->listOfNon11acCountryCode, country_code))
602 {
603 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
604 (eCSR_DOT11_MODE_11ac == phyMode) ||
605 (eCSR_DOT11_MODE_11ac_ONLY == phyMode))
606 {
607 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
608 "Setting phymode to 11n!!");
609 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter), eCSR_DOT11_MODE_11n);
610 }
611 }
612 else
613 {
614 /*New country Supports 11ac as well resetting value back from .ini*/
615 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter),
616 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->dot11Mode));
617 return ;
618 }
619
620 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
621 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode) ||
622 (eCSR_CFG_DOT11_MODE_11AC == pHddStaCtx->conn_info.dot11Mode)))
623 {
624 VOS_STATUS vosStatus;
625
626 // need to issue a disconnect to CSR.
627 INIT_COMPLETION(pAdapter->disconnect_comp_var);
628 vosStatus = sme_RoamDisconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
629 pAdapter->sessionId,
630 eCSR_DISCONNECT_REASON_UNSPECIFIED );
631
632 if (VOS_STATUS_SUCCESS == vosStatus)
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530633 {
634 ret = wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530635 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530636 if (ret <= 0)
637 {
638 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
639 "wait on disconnect_comp_var is failed %ld", ret);
640 }
641 }
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530642
643 }
644}
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700645#endif //CONFIG_ENABLE_LINUX_REG
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530646
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700647void hdd_checkandupdate_dfssetting( hdd_adapter_t *pAdapter, char *country_code)
648{
649 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
650 hdd_config_t *cfg_param;
651
652 if (NULL == pHddCtx)
653 {
654 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
655 "HDD Context is null !!");
656 return ;
657 }
658
659 cfg_param = pHddCtx->cfg_ini;
660
661 if (NULL == cfg_param)
662 {
663 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
664 "cfg_params not available !!");
665 return ;
666 }
667
Agarwal Ashish738843c2014-09-25 12:27:56 +0530668 if (NULL != strstr(cfg_param->listOfNonDfsCountryCode, country_code) ||
669 pHddCtx->disable_dfs_flag == TRUE)
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700670 {
671 /*New country doesn't support DFS */
672 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), 0);
673 }
674 else
675 {
676 /*New country Supports DFS as well resetting value back from .ini*/
677 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), cfg_param->enableDFSChnlScan);
678 }
679
680}
681
Rajeev79dbe4c2013-10-05 11:03:42 +0530682#ifdef FEATURE_WLAN_BATCH_SCAN
683
684/**---------------------------------------------------------------------------
685
686 \brief hdd_extract_assigned_int_from_str() - Extracts assigned integer from
687 input string
688
689 This function extracts assigned integer from string in below format:
690 "STRING=10" : extracts integer 10 from this string
691
692 \param - pInPtr Pointer to input string
693 \param - base Base for string to int conversion(10 for decimal 16 for hex)
694 \param - pOutPtr Pointer to variable in which extracted integer needs to be
695 assigned
696 \param - pLastArg to tell whether it is last arguement in input string or
697 not
698
699 \return - NULL for failure cases
700 pointer to next arguement in input string for success cases
701 --------------------------------------------------------------------------*/
702static tANI_U8 *
703hdd_extract_assigned_int_from_str
704(
705 tANI_U8 *pInPtr,
706 tANI_U8 base,
707 tANI_U32 *pOutPtr,
708 tANI_U8 *pLastArg
709)
710{
711 int tempInt;
712 int v = 0;
713 char buf[32];
714 int val = 0;
715 *pLastArg = FALSE;
716
717 pInPtr = strnchr(pInPtr, strlen(pInPtr), EQUALS_TO_ASCII_VALUE);
718 if (NULL == pInPtr)
719 {
720 return NULL;
721 }
722
723 pInPtr++;
724
725 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
726
727 val = sscanf(pInPtr, "%32s ", buf);
728 if (val < 0 && val > strlen(pInPtr))
729 {
730 return NULL;
731 }
732 pInPtr += val;
733 v = kstrtos32(buf, base, &tempInt);
734 if (v < 0)
735 {
736 return NULL;
737 }
Rajeev Kumar4d93d842014-01-02 18:31:21 -0800738 if (tempInt < 0)
739 {
740 tempInt = 0;
741 }
Rajeev79dbe4c2013-10-05 11:03:42 +0530742 *pOutPtr = tempInt;
743
744 pInPtr = strnchr(pInPtr, strlen(pInPtr), SPACE_ASCII_VALUE);
745 if (NULL == pInPtr)
746 {
747 *pLastArg = TRUE;
748 return NULL;
749 }
750 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
751
752 return pInPtr;
753}
754
755/**---------------------------------------------------------------------------
756
757 \brief hdd_extract_assigned_char_from_str() - Extracts assigned char from
758 input string
759
760 This function extracts assigned character from string in below format:
761 "STRING=A" : extracts char 'A' from this string
762
763 \param - pInPtr Pointer to input string
764 \param - pOutPtr Pointer to variable in which extracted char needs to be
765 assigned
766 \param - pLastArg to tell whether it is last arguement in input string or
767 not
768
769 \return - NULL for failure cases
770 pointer to next arguement in input string for success cases
771 --------------------------------------------------------------------------*/
772static tANI_U8 *
773hdd_extract_assigned_char_from_str
774(
775 tANI_U8 *pInPtr,
776 tANI_U8 *pOutPtr,
777 tANI_U8 *pLastArg
778)
779{
780 *pLastArg = FALSE;
781
782 pInPtr = strnchr(pInPtr, strlen(pInPtr), EQUALS_TO_ASCII_VALUE);
783 if (NULL == pInPtr)
784 {
785 return NULL;
786 }
787
788 pInPtr++;
789
790 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
791
792 *pOutPtr = *pInPtr;
793
794 pInPtr = strnchr(pInPtr, strlen(pInPtr), SPACE_ASCII_VALUE);
795 if (NULL == pInPtr)
796 {
797 *pLastArg = TRUE;
798 return NULL;
799 }
800 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
801
802 return pInPtr;
803}
804
805
806/**---------------------------------------------------------------------------
807
808 \brief hdd_parse_set_batchscan_command () - HDD parse set batch scan command
809
810 This function parses set batch scan command in below format:
811 WLS_BATCHING_SET <space> followed by below arguements
812 "SCANFREQ=XX" : Optional defaults to 30 sec
813 "MSCAN=XX" : Required number of scans to attempt to batch
814 "BESTN=XX" : Best Network (RSSI) defaults to 16
815 "CHANNEL=<X,Y>" : optional defaults to all channels, can list 'A'or` B.
816 A. implies only 5 GHz , B. implies only 2.4GHz
817 "RTT=X" : optional defaults to 0
818 returns the MIN of MSCAN or the max # of scans firmware can cache or -1 on
819 error
820
821 For example input commands:
822 1) WLS_BATCHING_SET SCANFREQ=60 MSCAN=10 BESTN=20 CHANNEL=A RTT=0 -> This is
823 translated into set batch scan with following parameters:
824 a) Frequence 60 seconds
825 b) Batch 10 scans together
826 c) Best RSSI to be 20
827 d) 5GHz band only
828 e) RTT is equal to 0
829
830 \param - pValue Pointer to input channel list
831 \param - pHddSetBatchScanReq Pointer to HDD batch scan request structure
832
833 \return - 0 for success non-zero for failure
834
835 --------------------------------------------------------------------------*/
836static int
837hdd_parse_set_batchscan_command
838(
839 tANI_U8 *pValue,
840 tSirSetBatchScanReq *pHddSetBatchScanReq
841)
842{
843 tANI_U8 *inPtr = pValue;
844 tANI_U8 val = 0;
845 tANI_U8 lastArg = 0;
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800846 tANI_U32 nScanFreq;
847 tANI_U32 nMscan;
848 tANI_U32 nBestN;
849 tANI_U8 ucRfBand;
850 tANI_U32 nRtt;
Rajeev Kumarc933d982013-11-18 20:04:20 -0800851 tANI_U32 temp;
Rajeev79dbe4c2013-10-05 11:03:42 +0530852
853 /*initialize default values*/
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800854 nScanFreq = HDD_SET_BATCH_SCAN_DEFAULT_FREQ;
855 ucRfBand = HDD_SET_BATCH_SCAN_DEFAULT_BAND;
856 nRtt = 0;
857 nBestN = HDD_SET_BATCH_SCAN_BEST_NETWORK;
Rajeev79dbe4c2013-10-05 11:03:42 +0530858
859 /*go to space after WLS_BATCHING_SET command*/
860 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
861 /*no argument after the command*/
862 if (NULL == inPtr)
863 {
864 return -EINVAL;
865 }
866
867 /*no space after the command*/
868 else if (SPACE_ASCII_VALUE != *inPtr)
869 {
870 return -EINVAL;
871 }
872
873 /*removing empty spaces*/
874 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
875
876 /*no argument followed by spaces*/
877 if ('\0' == *inPtr)
878 {
879 return -EINVAL;
880 }
881
882 /*check and parse SCANFREQ*/
883 if ((strncmp(inPtr, "SCANFREQ", 8) == 0))
884 {
885 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumarc933d982013-11-18 20:04:20 -0800886 &temp, &lastArg);
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800887
Rajeev Kumarc933d982013-11-18 20:04:20 -0800888 if (0 != temp)
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800889 {
Rajeev Kumarc933d982013-11-18 20:04:20 -0800890 nScanFreq = temp;
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800891 }
892
Rajeev79dbe4c2013-10-05 11:03:42 +0530893 if ( (NULL == inPtr) || (TRUE == lastArg))
894 {
895 return -EINVAL;
896 }
897 }
898
899 /*check and parse MSCAN*/
900 if ((strncmp(inPtr, "MSCAN", 5) == 0))
901 {
902 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800903 &nMscan, &lastArg);
904
905 if (0 == nMscan)
906 {
907 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
908 "invalid MSCAN=%d", nMscan);
909 return -EINVAL;
910 }
911
Rajeev79dbe4c2013-10-05 11:03:42 +0530912 if (TRUE == lastArg)
913 {
914 goto done;
915 }
916 else if (NULL == inPtr)
917 {
918 return -EINVAL;
919 }
920 }
921 else
922 {
923 return -EINVAL;
924 }
925
926 /*check and parse BESTN*/
927 if ((strncmp(inPtr, "BESTN", 5) == 0))
928 {
929 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumarc933d982013-11-18 20:04:20 -0800930 &temp, &lastArg);
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800931
Rajeev Kumarc933d982013-11-18 20:04:20 -0800932 if (0 != temp)
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800933 {
Rajeev Kumarc933d982013-11-18 20:04:20 -0800934 nBestN = temp;
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800935 }
936
Rajeev79dbe4c2013-10-05 11:03:42 +0530937 if (TRUE == lastArg)
938 {
939 goto done;
940 }
941 else if (NULL == inPtr)
942 {
943 return -EINVAL;
944 }
945 }
946
947 /*check and parse CHANNEL*/
948 if ((strncmp(inPtr, "CHANNEL", 7) == 0))
949 {
950 inPtr = hdd_extract_assigned_char_from_str(inPtr, &val, &lastArg);
Rajeev Kumarc933d982013-11-18 20:04:20 -0800951
Rajeev79dbe4c2013-10-05 11:03:42 +0530952 if (('A' == val) || ('a' == val))
953 {
c_hpothuebf89732014-02-25 13:00:24 +0530954 ucRfBand = HDD_SET_BATCH_SCAN_5GHz_BAND_ONLY;
Rajeev79dbe4c2013-10-05 11:03:42 +0530955 }
956 else if (('B' == val) || ('b' == val))
957 {
c_hpothuebf89732014-02-25 13:00:24 +0530958 ucRfBand = HDD_SET_BATCH_SCAN_24GHz_BAND_ONLY;
Rajeev79dbe4c2013-10-05 11:03:42 +0530959 }
960 else
961 {
Rajeev Kumarc933d982013-11-18 20:04:20 -0800962 ucRfBand = HDD_SET_BATCH_SCAN_DEFAULT_BAND;
963 }
964
965 if (TRUE == lastArg)
966 {
967 goto done;
968 }
969 else if (NULL == inPtr)
970 {
Rajeev79dbe4c2013-10-05 11:03:42 +0530971 return -EINVAL;
972 }
973 }
974
975 /*check and parse RTT*/
976 if ((strncmp(inPtr, "RTT", 3) == 0))
977 {
978 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800979 &nRtt, &lastArg);
Rajeev79dbe4c2013-10-05 11:03:42 +0530980 if (TRUE == lastArg)
981 {
982 goto done;
983 }
984 if (NULL == inPtr)
985 {
986 return -EINVAL;
987 }
988 }
989
990
991done:
992
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800993 pHddSetBatchScanReq->scanFrequency = nScanFreq;
994 pHddSetBatchScanReq->numberOfScansToBatch = nMscan;
995 pHddSetBatchScanReq->bestNetwork = nBestN;
996 pHddSetBatchScanReq->rfBand = ucRfBand;
997 pHddSetBatchScanReq->rtt = nRtt;
998
Rajeev79dbe4c2013-10-05 11:03:42 +0530999 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1000 "Received WLS_BATCHING_SET with SCANFREQ=%d "
1001 "MSCAN=%d BESTN=%d CHANNEL=%d RTT=%d",
1002 pHddSetBatchScanReq->scanFrequency,
1003 pHddSetBatchScanReq->numberOfScansToBatch,
1004 pHddSetBatchScanReq->bestNetwork,
1005 pHddSetBatchScanReq->rfBand,
1006 pHddSetBatchScanReq->rtt);
1007
1008 return 0;
1009}/*End of hdd_parse_set_batchscan_command*/
1010
1011/**---------------------------------------------------------------------------
1012
1013 \brief hdd_set_batch_scan_req_callback () - This function is called after
1014 receiving set batch scan response from FW and it saves set batch scan
1015 response data FW to HDD context and sets the completion event on
1016 which hdd_ioctl is waiting
1017
1018 \param - callbackContext Pointer to HDD adapter
1019 \param - pRsp Pointer to set batch scan response data received from FW
1020
1021 \return - nothing
1022
1023 --------------------------------------------------------------------------*/
1024static void hdd_set_batch_scan_req_callback
1025(
1026 void *callbackContext,
1027 tSirSetBatchScanRsp *pRsp
1028)
1029{
1030 hdd_adapter_t* pAdapter = (hdd_adapter_t*)callbackContext;
1031 tSirSetBatchScanRsp *pHddSetBatchScanRsp;
1032
1033 /*sanity check*/
1034 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
1035 {
1036 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1037 "%s: Invalid pAdapter magic", __func__);
1038 VOS_ASSERT(0);
1039 return;
1040 }
1041 pHddSetBatchScanRsp = &pAdapter->hddSetBatchScanRsp;
1042
1043 /*save set batch scan response*/
1044 pHddSetBatchScanRsp->nScansToBatch = pRsp->nScansToBatch;
1045
1046 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1047 "Received set batch scan rsp from FW with nScansToBatch=%d",
1048 pHddSetBatchScanRsp->nScansToBatch);
1049
1050 pAdapter->hdd_wait_for_set_batch_scan_rsp = FALSE;
1051 complete(&pAdapter->hdd_set_batch_scan_req_var);
1052
1053 return;
1054}/*End of hdd_set_batch_scan_req_callback*/
1055
1056
1057/**---------------------------------------------------------------------------
1058
1059 \brief hdd_populate_batch_scan_rsp_queue () - This function stores AP meta
1060 info in hdd batch scan response queue
1061
1062 \param - pAdapter Pointer to hdd adapter
1063 \param - pAPMetaInfo Pointer to access point meta info
1064 \param - scanId scan ID of batch scan response
1065 \param - isLastAp tells whether AP is last AP in batch scan response or not
1066
1067 \return - nothing
1068
1069 --------------------------------------------------------------------------*/
1070static void hdd_populate_batch_scan_rsp_queue( hdd_adapter_t* pAdapter,
1071 tpSirBatchScanNetworkInfo pApMetaInfo, tANI_U32 scanId, v_BOOL_t isLastAp)
1072{
1073 tHddBatchScanRsp *pHead;
1074 tHddBatchScanRsp *pNode;
1075 tHddBatchScanRsp *pPrev;
1076 tHddBatchScanRsp *pTemp;
1077 tANI_U8 ssidLen;
1078
1079 /*head of hdd batch scan response queue*/
1080 pHead = pAdapter->pBatchScanRsp;
1081
1082 pNode = (tHddBatchScanRsp *)vos_mem_malloc(sizeof(tHddBatchScanRsp));
1083 if (NULL == pNode)
1084 {
1085 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1086 "%s: Could not allocate memory", __func__);
1087 VOS_ASSERT(0);
1088 return;
1089 }
1090
1091 vos_mem_copy(pNode->ApInfo.bssid, pApMetaInfo->bssid,
1092 sizeof(pNode->ApInfo.bssid));
1093 ssidLen = strlen(pApMetaInfo->ssid);
1094 if (SIR_MAX_SSID_SIZE < ssidLen)
1095 {
1096 /*invalid scan result*/
1097 vos_mem_free(pNode);
1098 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1099 "%s: Invalid AP meta info ssidlen %d", __func__, ssidLen);
1100 return;
1101 }
1102 vos_mem_copy(pNode->ApInfo.ssid, pApMetaInfo->ssid, ssidLen);
1103 /*null terminate ssid*/
1104 pNode->ApInfo.ssid[ssidLen] = '\0';
1105 pNode->ApInfo.ch = pApMetaInfo->ch;
1106 pNode->ApInfo.rssi = pApMetaInfo->rssi;
1107 pNode->ApInfo.age = pApMetaInfo->timestamp;
1108 pNode->ApInfo.batchId = scanId;
1109 pNode->ApInfo.isLastAp = isLastAp;
1110
1111 pNode->pNext = NULL;
1112 if (NULL == pHead)
1113 {
1114 pAdapter->pBatchScanRsp = pNode;
1115 }
1116 else
1117 {
1118 pTemp = pHead;
1119 while (NULL != pTemp)
1120 {
1121 pPrev = pTemp;
1122 pTemp = pTemp->pNext;
1123 }
1124 pPrev->pNext = pNode;
1125 }
1126
1127 return;
1128}/*End of hdd_populate_batch_scan_rsp_queue*/
1129
1130/**---------------------------------------------------------------------------
1131
1132 \brief hdd_batch_scan_result_ind_callback () - This function is called after
1133 receiving batch scan response indication from FW. It saves get batch scan
1134 response data in HDD batch scan response queue. This callback sets the
1135 completion event on which hdd_ioctl is waiting only after getting complete
1136 batch scan response data from FW
1137
1138 \param - callbackContext Pointer to HDD adapter
1139 \param - pRsp Pointer to get batch scan response data received from FW
1140
1141 \return - nothing
1142
1143 --------------------------------------------------------------------------*/
1144static void hdd_batch_scan_result_ind_callback
1145(
1146 void *callbackContext,
1147 void *pRsp
1148)
1149{
1150 v_BOOL_t isLastAp;
1151 tANI_U32 numApMetaInfo;
Rajeev Kumarce651e42013-10-21 18:57:15 -07001152 tANI_U32 numNetworkInScanList;
Rajeev79dbe4c2013-10-05 11:03:42 +05301153 tANI_U32 numberScanList;
1154 tANI_U32 nextScanListOffset;
1155 tANI_U32 nextApMetaInfoOffset;
1156 hdd_adapter_t* pAdapter;
1157 tpSirBatchScanList pScanList;
1158 tpSirBatchScanNetworkInfo pApMetaInfo;
1159 tpSirBatchScanResultIndParam pBatchScanRsp;/*batch scan rsp data from FW*/
1160 tSirSetBatchScanReq *pReq;
1161
1162 pAdapter = (hdd_adapter_t *)callbackContext;
1163 /*sanity check*/
Rajeev Kumar5286bb92013-12-05 11:52:10 -08001164 if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
Rajeev79dbe4c2013-10-05 11:03:42 +05301165 {
1166 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1167 "%s: Invalid pAdapter magic", __func__);
1168 VOS_ASSERT(0);
1169 return;
1170 }
1171
1172 /*initialize locals*/
1173 pReq = &pAdapter->hddSetBatchScanReq;
1174 pBatchScanRsp = (tpSirBatchScanResultIndParam)pRsp;
1175 isLastAp = FALSE;
1176 numApMetaInfo = 0;
Rajeev Kumarce651e42013-10-21 18:57:15 -07001177 numNetworkInScanList = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05301178 numberScanList = 0;
1179 nextScanListOffset = 0;
1180 nextApMetaInfoOffset = 0;
1181 pScanList = NULL;
1182 pApMetaInfo = NULL;
1183
1184 if ((NULL == pBatchScanRsp) || (NULL == pReq))
1185 {
1186 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1187 "%s: pBatchScanRsp is %p pReq %p", __func__, pBatchScanRsp, pReq);
1188 isLastAp = TRUE;
1189 goto done;
1190 }
1191
1192 pAdapter->numScanList = numberScanList = pBatchScanRsp->numScanLists;
1193 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1194 "Batch scan rsp: numberScalList %d", numberScanList);
1195
1196 if ((!numberScanList) || (numberScanList > pReq->numberOfScansToBatch))
1197 {
1198 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1199 "%s: numberScanList %d", __func__, numberScanList);
1200 isLastAp = TRUE;
1201 goto done;
1202 }
1203
1204 while (numberScanList)
1205 {
Rajeev Kumarce651e42013-10-21 18:57:15 -07001206 pScanList = (tpSirBatchScanList)((tANI_U8 *)pBatchScanRsp->scanResults +
Rajeev79dbe4c2013-10-05 11:03:42 +05301207 nextScanListOffset);
1208 if (NULL == pScanList)
1209 {
1210 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1211 "%s: pScanList is %p", __func__, pScanList);
1212 isLastAp = TRUE;
1213 goto done;
1214 }
Rajeev Kumarce651e42013-10-21 18:57:15 -07001215 numNetworkInScanList = numApMetaInfo = pScanList->numNetworksInScanList;
Rajeev79dbe4c2013-10-05 11:03:42 +05301216 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumarce651e42013-10-21 18:57:15 -07001217 "Batch scan rsp: numApMetaInfo %d scanId %d",
1218 numApMetaInfo, pScanList->scanId);
Rajeev79dbe4c2013-10-05 11:03:42 +05301219
1220 if ((!numApMetaInfo) || (numApMetaInfo > pReq->bestNetwork))
1221 {
1222 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1223 "%s: numApMetaInfo %d", __func__, numApMetaInfo);
1224 isLastAp = TRUE;
1225 goto done;
1226 }
1227
Rajeev Kumarce651e42013-10-21 18:57:15 -07001228 /*Initialize next AP meta info offset for next scan list*/
1229 nextApMetaInfoOffset = 0;
1230
Rajeev79dbe4c2013-10-05 11:03:42 +05301231 while (numApMetaInfo)
1232 {
1233 pApMetaInfo = (tpSirBatchScanNetworkInfo)(pScanList->scanList +
1234 nextApMetaInfoOffset);
1235 if (NULL == pApMetaInfo)
1236 {
1237 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1238 "%s: pApMetaInfo is %p", __func__, pApMetaInfo);
1239 isLastAp = TRUE;
1240 goto done;
1241 }
1242 /*calculate AP age*/
1243 pApMetaInfo->timestamp =
1244 pBatchScanRsp->timestamp - pApMetaInfo->timestamp;
1245
1246 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
Arif Hussaina7c8e412013-11-20 11:06:42 -08001247 "%s: bssId "MAC_ADDRESS_STR
1248 " ch %d rssi %d timestamp %d", __func__,
1249 MAC_ADDR_ARRAY(pApMetaInfo->bssid),
1250 pApMetaInfo->ch, pApMetaInfo->rssi,
1251 pApMetaInfo->timestamp);
Rajeev79dbe4c2013-10-05 11:03:42 +05301252
1253 /*mark last AP in batch scan response*/
1254 if ((TRUE == pBatchScanRsp->isLastResult) &&
1255 (1 == numberScanList) && (1 == numApMetaInfo))
1256 {
1257 isLastAp = TRUE;
1258 }
1259
1260 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1261 /*store batch scan repsonse in hdd queue*/
1262 hdd_populate_batch_scan_rsp_queue(pAdapter, pApMetaInfo,
1263 pScanList->scanId, isLastAp);
1264 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1265
1266 nextApMetaInfoOffset += sizeof(tSirBatchScanNetworkInfo);
1267 numApMetaInfo--;
1268 }
1269
Rajeev Kumarce651e42013-10-21 18:57:15 -07001270 nextScanListOffset += ((sizeof(tSirBatchScanList) - sizeof(tANI_U8))
1271 + (sizeof(tSirBatchScanNetworkInfo)
1272 * numNetworkInScanList));
Rajeev79dbe4c2013-10-05 11:03:42 +05301273 numberScanList--;
1274 }
1275
1276done:
1277
1278 /*notify hdd_ioctl only if complete batch scan rsp is received and it was
1279 requested from hdd_ioctl*/
1280 if ((TRUE == pAdapter->hdd_wait_for_get_batch_scan_rsp) &&
1281 (TRUE == isLastAp))
1282 {
1283 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
1284 complete(&pAdapter->hdd_get_batch_scan_req_var);
1285 }
1286
1287 return;
1288}/*End of hdd_batch_scan_result_ind_callback*/
1289
1290/**---------------------------------------------------------------------------
1291
1292 \brief hdd_format_batch_scan_rsp () - This function formats batch scan
1293 response as per batch scan FR request format by putting proper markers
1294
1295 \param - pDest pointer to destination buffer
1296 \param - cur_len current length
1297 \param - tot_len total remaining size which can be written to user space
1298 \param - pApMetaInfo Pointer to get batch scan response AP meta info
1299 \param - pAdapter Pointer to HDD adapter
1300
1301 \return - ret no of characters written
1302
1303 --------------------------------------------------------------------------*/
1304static tANI_U32
1305hdd_format_batch_scan_rsp
1306(
1307 tANI_U8 *pDest,
1308 tANI_U32 cur_len,
1309 tANI_U32 tot_len,
1310 tHddBatchScanRsp *pApMetaInfo,
1311 hdd_adapter_t* pAdapter
1312)
1313{
1314 tANI_U32 ret = 0;
1315 tANI_U32 rem_len = 0;
1316 tANI_U8 temp_len = 0;
1317 tANI_U8 temp_total_len = 0;
1318 tANI_U8 temp[HDD_BATCH_SCAN_AP_META_INFO_SIZE];
1319 tANI_U8 *pTemp = temp;
1320
1321 /*Batch scan reponse needs to be returned to user space in
1322 following format:
1323 "scancount=X\n" where X is the number of scans in current batch
1324 batch
1325 "trunc\n" optional present if current scan truncated
1326 "bssid=XX:XX:XX:XX:XX:XX\n"
1327 "ssid=XXXX\n"
1328 "freq=X\n" frequency in Mhz
1329 "level=XX\n"
1330 "age=X\n" ms
1331 "dist=X\n" cm (-1 if not available)
1332 "errror=X\n" (-1if not available)
1333 "====\n" (end of ap marker)
1334 "####\n" (end of scan marker)
1335 "----\n" (end of results)*/
1336 /*send scan result in above format to user space based on
1337 available length*/
1338 /*The GET response may have more data than the driver can return in its
1339 buffer. In that case the buffer should be filled to the nearest complete
1340 scan, ending with "%%%%".Subsequent callsshould return the remaining data
1341 starting with the next scan (optional .trunc\n., .apcount=X\n., etc).
1342 The final buffer should end with "----\n"*/
1343
1344 /*sanity*/
1345 if (cur_len > tot_len)
1346 {
1347 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1348 "%s: invaid cur_len %d tot_len %d", __func__, cur_len, tot_len);
1349 return 0;
1350 }
1351 else
1352 {
1353 rem_len = (tot_len - cur_len);
1354 }
1355
1356 /*end scan marker*/
1357 if (pApMetaInfo->ApInfo.batchId != pAdapter->prev_batch_id)
1358 {
1359 temp_len = snprintf(pTemp, sizeof(temp), "####\n");
1360 pTemp += temp_len;
1361 temp_total_len += temp_len;
1362 }
1363
1364 /*bssid*/
1365 temp_len = snprintf(pTemp, sizeof(temp),
1366 "bssid=0x%x:0x%x:0x%x:0x%x:0x%x:0x%x\n",
1367 pApMetaInfo->ApInfo.bssid[0], pApMetaInfo->ApInfo.bssid[1],
1368 pApMetaInfo->ApInfo.bssid[2], pApMetaInfo->ApInfo.bssid[3],
1369 pApMetaInfo->ApInfo.bssid[4], pApMetaInfo->ApInfo.bssid[5]);
1370 pTemp += temp_len;
1371 temp_total_len += temp_len;
1372
1373 /*ssid*/
1374 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "ssid=%s\n",
1375 pApMetaInfo->ApInfo.ssid);
1376 pTemp += temp_len;
1377 temp_total_len += temp_len;
1378
1379 /*freq*/
1380 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "freq=%d\n",
Rajeev Kumarc40f7512013-11-04 14:13:23 -08001381 sme_ChnToFreq(pApMetaInfo->ApInfo.ch));
Rajeev79dbe4c2013-10-05 11:03:42 +05301382 pTemp += temp_len;
1383 temp_total_len += temp_len;
1384
1385 /*level*/
1386 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "level=%d\n",
1387 pApMetaInfo->ApInfo.rssi);
1388 pTemp += temp_len;
1389 temp_total_len += temp_len;
1390
1391 /*age*/
Jeff Johnson02797792013-10-26 19:17:13 -07001392 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "age=%d\n",
Rajeev79dbe4c2013-10-05 11:03:42 +05301393 pApMetaInfo->ApInfo.age);
1394 pTemp += temp_len;
1395 temp_total_len += temp_len;
1396
1397 /*dist*/
1398 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "dist=-1\n");
1399 pTemp += temp_len;
1400 temp_total_len += temp_len;
1401
1402 /*error*/
1403 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "error=-1\n");
1404 pTemp += temp_len;
1405 temp_total_len += temp_len;
1406
1407 /*end AP marker*/
1408 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "====\n");
1409 pTemp += temp_len;
1410 temp_total_len += temp_len;
1411
1412 /*last AP in batch scan response*/
1413 if(TRUE == pApMetaInfo->ApInfo.isLastAp)
1414 {
1415 /*end scan marker*/
1416 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "####\n");
1417 pTemp += temp_len;
1418 temp_total_len += temp_len;
1419
1420 /*end batch scan result marker*/
1421 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "----\n");
1422 pTemp += temp_len;
1423 temp_total_len += temp_len;
Kiet Lamaa8e15a2014-02-11 23:30:06 -08001424
Rajeev79dbe4c2013-10-05 11:03:42 +05301425 }
1426
1427 if (temp_total_len < rem_len)
1428 {
1429 ret = temp_total_len + 1;
1430 strlcpy(pDest, temp, ret);
1431 pAdapter->isTruncated = FALSE;
1432 }
1433 else
1434 {
1435 pAdapter->isTruncated = TRUE;
1436 if (rem_len >= strlen("%%%%"))
1437 {
Rajeev Kumarc933d982013-11-18 20:04:20 -08001438 ret = snprintf(pDest, sizeof(temp), "%%%%");
Rajeev79dbe4c2013-10-05 11:03:42 +05301439 }
Rajeev Kumarc933d982013-11-18 20:04:20 -08001440 else
Rajeev79dbe4c2013-10-05 11:03:42 +05301441 {
1442 ret = 0;
1443 }
1444 }
1445
1446 return ret;
1447
1448}/*End of hdd_format_batch_scan_rsp*/
1449
1450/**---------------------------------------------------------------------------
1451
1452 \brief hdd_populate_user_batch_scan_rsp() - This function populates user data
1453 buffer starting with head of hdd batch scan response queue
1454
1455 \param - pAdapter Pointer to HDD adapter
1456 \param - pDest Pointer to user data buffer
1457 \param - cur_len current offset in user buffer
1458 \param - rem_len remaining no of bytes in user buffer
1459
1460 \return - number of bytes written in user buffer
1461
1462 --------------------------------------------------------------------------*/
1463
1464tANI_U32 hdd_populate_user_batch_scan_rsp
1465(
1466 hdd_adapter_t* pAdapter,
1467 tANI_U8 *pDest,
1468 tANI_U32 cur_len,
1469 tANI_U32 rem_len
1470)
1471{
1472 tHddBatchScanRsp *pHead;
1473 tHddBatchScanRsp *pPrev;
1474 tANI_U32 len;
1475
Rajeev79dbe4c2013-10-05 11:03:42 +05301476 pAdapter->isTruncated = FALSE;
1477
1478 /*head of hdd batch scan response queue*/
1479 pHead = pAdapter->pBatchScanRsp;
1480 while (pHead)
1481 {
1482 len = hdd_format_batch_scan_rsp(pDest, cur_len, rem_len, pHead,
1483 pAdapter);
1484 pDest += len;
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07001485 pDest--;
Rajeev79dbe4c2013-10-05 11:03:42 +05301486 cur_len += len;
1487 if(TRUE == pAdapter->isTruncated)
1488 {
1489 /*result is truncated return rest of scan rsp in next req*/
1490 cur_len = rem_len;
1491 break;
1492 }
1493 pPrev = pHead;
1494 pHead = pHead->pNext;
1495 pAdapter->pBatchScanRsp = pHead;
Rajeev Kumarbe17d8b2014-01-10 15:39:45 -08001496 if (TRUE == pPrev->ApInfo.isLastAp)
1497 {
1498 pAdapter->prev_batch_id = 0;
1499 }
1500 else
1501 {
1502 pAdapter->prev_batch_id = pPrev->ApInfo.batchId;
1503 }
Rajeev79dbe4c2013-10-05 11:03:42 +05301504 vos_mem_free(pPrev);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08001505 pPrev = NULL;
Rajeev79dbe4c2013-10-05 11:03:42 +05301506 }
1507
1508 return cur_len;
1509}/*End of hdd_populate_user_batch_scan_rsp*/
1510
1511/**---------------------------------------------------------------------------
1512
1513 \brief hdd_return_batch_scan_rsp_to_user () - This function returns batch
1514 scan response data from HDD queue to user space
1515 It does following in detail:
1516 a) if HDD has enough data in its queue then it 1st copies data to user
1517 space and then send get batch scan indication message to FW. In this
1518 case it does not wait on any event and batch scan response data will
1519 be populated in HDD response queue in MC thread context after receiving
1520 indication from FW
1521 b) else send get batch scan indication message to FW and wait on an event
1522 which will be set once HDD receives complete batch scan response from
1523 FW and then this function returns batch scan response to user space
1524
1525 \param - pAdapter Pointer to HDD adapter
1526 \param - pPrivData Pointer to priv_data
1527
1528 \return - 0 for success -EFAULT for failure
1529
1530 --------------------------------------------------------------------------*/
1531
1532int hdd_return_batch_scan_rsp_to_user
1533(
1534 hdd_adapter_t* pAdapter,
1535 hdd_priv_data_t *pPrivData,
1536 tANI_U8 *command
1537)
1538{
1539 tANI_U8 *pDest;
1540 tANI_U32 count = 0;
1541 tANI_U32 len = 0;
1542 tANI_U32 cur_len = 0;
1543 tANI_U32 rem_len = 0;
1544 eHalStatus halStatus;
1545 unsigned long rc;
1546 tSirTriggerBatchScanResultInd *pReq;
1547
1548 pReq = &pAdapter->hddTriggerBatchScanResultInd;
1549 pReq->param = 0;/*batch scan client*/
1550 pDest = (tANI_U8 *)(command + pPrivData->used_len);
1551 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
1552
1553 cur_len = pPrivData->used_len;
1554 if (pPrivData->total_len > pPrivData->used_len)
1555 {
1556 rem_len = pPrivData->total_len - pPrivData->used_len;
1557 }
1558 else
1559 {
1560 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1561 "%s: Invalid user data buffer total_len %d used_len %d",
1562 __func__, pPrivData->total_len, pPrivData->used_len);
1563 return -EFAULT;
1564 }
1565
1566 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1567 len = hdd_populate_user_batch_scan_rsp(pAdapter, pDest,
1568 cur_len, rem_len);
1569 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1570
1571 /*enough scan result available in cache to return to user space or
1572 scan result needs to be fetched 1st from fw and then return*/
Rajeev Kumar99db6262013-11-11 15:23:36 -08001573 if (len == cur_len)
Rajeev79dbe4c2013-10-05 11:03:42 +05301574 {
1575 pAdapter->hdd_wait_for_get_batch_scan_rsp = TRUE;
1576 halStatus = sme_TriggerBatchScanResultInd(
1577 WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
1578 pAdapter->sessionId, hdd_batch_scan_result_ind_callback,
1579 pAdapter);
1580 if ( eHAL_STATUS_SUCCESS == halStatus )
1581 {
1582 if (TRUE == pAdapter->hdd_wait_for_get_batch_scan_rsp)
1583 {
1584 INIT_COMPLETION(pAdapter->hdd_get_batch_scan_req_var);
1585 rc = wait_for_completion_timeout(
1586 &pAdapter->hdd_get_batch_scan_req_var,
1587 msecs_to_jiffies(HDD_GET_BATCH_SCAN_RSP_TIME_OUT));
1588 if (0 == rc)
1589 {
1590 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1591 "%s: Timeout waiting to fetch batch scan rsp from fw",
1592 __func__);
1593 return -EFAULT;
1594 }
1595 }
1596
1597 len = snprintf(pDest, HDD_BATCH_SCAN_AP_META_INFO_SIZE,
Jeff Johnson02797792013-10-26 19:17:13 -07001598 "scancount=%u\n", pAdapter->numScanList);
Rajeev79dbe4c2013-10-05 11:03:42 +05301599 pDest += len;
1600 cur_len += len;
1601
1602 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1603 len = hdd_populate_user_batch_scan_rsp(pAdapter, pDest,
1604 cur_len, rem_len);
1605 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1606
1607 count = 0;
1608 len = (len - pPrivData->used_len);
1609 pDest = (command + pPrivData->used_len);
1610 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar99db6262013-11-11 15:23:36 -08001611 "NEW BATCH SCAN RESULT:");
Rajeev79dbe4c2013-10-05 11:03:42 +05301612 while(count < len)
1613 {
1614 printk("%c", *(pDest + count));
1615 count++;
1616 }
1617 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1618 "%s: copy %d data to user buffer", __func__, len);
1619 if (copy_to_user(pPrivData->buf, pDest, len))
1620 {
1621 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1622 "%s: failed to copy data to user buffer", __func__);
1623 return -EFAULT;
1624 }
1625 }
1626 else
1627 {
1628 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1629 "sme_GetBatchScanScan returned failure halStatus %d",
1630 halStatus);
1631 return -EINVAL;
1632 }
1633 }
1634 else
1635 {
Rajeev79dbe4c2013-10-05 11:03:42 +05301636 count = 0;
1637 len = (len - pPrivData->used_len);
1638 pDest = (command + pPrivData->used_len);
1639 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar99db6262013-11-11 15:23:36 -08001640 "REMAINING TRUNCATED BATCH SCAN RESULT:");
Rajeev79dbe4c2013-10-05 11:03:42 +05301641 while(count < len)
1642 {
1643 printk("%c", *(pDest + count));
1644 count++;
1645 }
Rajeev Kumar99db6262013-11-11 15:23:36 -08001646 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1647 "%s: copy %d data to user buffer", __func__, len);
Rajeev79dbe4c2013-10-05 11:03:42 +05301648 if (copy_to_user(pPrivData->buf, pDest, len))
1649 {
1650 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1651 "%s: failed to copy data to user buffer", __func__);
1652 return -EFAULT;
1653 }
Rajeev79dbe4c2013-10-05 11:03:42 +05301654 }
1655
1656 return 0;
1657} /*End of hdd_return_batch_scan_rsp_to_user*/
1658
Rajeev Kumar8b373292014-01-08 20:36:55 -08001659
1660/**---------------------------------------------------------------------------
1661
1662 \brief hdd_handle_batch_scan_ioctl () - This function handles WLS_BATCHING
1663 IOCTLs from user space. Following BATCH SCAN DEV IOCTs are handled:
1664 WLS_BATCHING VERSION
1665 WLS_BATCHING SET
1666 WLS_BATCHING GET
1667 WLS_BATCHING STOP
1668
1669 \param - pAdapter Pointer to HDD adapter
1670 \param - pPrivdata Pointer to priv_data
1671 \param - command Pointer to command
1672
1673 \return - 0 for success -EFAULT for failure
1674
1675 --------------------------------------------------------------------------*/
1676
1677int hdd_handle_batch_scan_ioctl
1678(
1679 hdd_adapter_t *pAdapter,
1680 hdd_priv_data_t *pPrivdata,
1681 tANI_U8 *command
1682)
1683{
1684 int ret = 0;
Yue Mae36e3552014-03-05 17:06:20 -08001685 hdd_context_t *pHddCtx;
1686
1687 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
1688 ret = wlan_hdd_validate_context(pHddCtx);
1689 if (ret)
1690 {
1691 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1692 "%s: HDD context is not valid!", __func__);
1693 goto exit;
1694 }
Rajeev Kumar8b373292014-01-08 20:36:55 -08001695
1696 if (strncmp(command, "WLS_BATCHING VERSION", 20) == 0)
1697 {
1698 char extra[32];
1699 tANI_U8 len = 0;
1700 tANI_U8 version = HDD_BATCH_SCAN_VERSION;
1701
1702 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
1703 {
1704 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1705 "%s: Batch scan feature is not supported by FW", __func__);
1706 ret = -EINVAL;
1707 goto exit;
1708 }
1709
1710 len = scnprintf(extra, sizeof(extra), "WLS_BATCHING_VERSION %d",
1711 version);
1712 if (copy_to_user(pPrivdata->buf, &extra, len + 1))
1713 {
1714 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1715 "%s: failed to copy data to user buffer", __func__);
1716 ret = -EFAULT;
1717 goto exit;
1718 }
1719 ret = HDD_BATCH_SCAN_VERSION;
1720 }
1721 else if (strncmp(command, "WLS_BATCHING SET", 16) == 0)
1722 {
1723 int status;
1724 tANI_U8 *value = (command + 16);
1725 eHalStatus halStatus;
1726 unsigned long rc;
1727 tSirSetBatchScanReq *pReq = &pAdapter->hddSetBatchScanReq;
1728 tSirSetBatchScanRsp *pRsp = &pAdapter->hddSetBatchScanRsp;
1729
1730 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
1731 {
1732 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1733 "%s: Batch scan feature is not supported by FW", __func__);
1734 ret = -EINVAL;
1735 goto exit;
1736 }
1737
1738 if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) &&
1739 (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) &&
1740 (WLAN_HDD_P2P_GO != pAdapter->device_mode) &&
1741 (WLAN_HDD_P2P_DEVICE != pAdapter->device_mode))
1742 {
1743 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Sushant Kaushik8bc7df22014-04-09 17:55:29 +05301744 "Received WLS_BATCHING SET command in invalid mode %s (%d) "
Rajeev Kumar8b373292014-01-08 20:36:55 -08001745 "WLS_BATCHING_SET is only allowed in infra STA/P2P client mode",
Sushant Kaushik8bc7df22014-04-09 17:55:29 +05301746 hdd_device_modetoString(pAdapter->device_mode),
1747 pAdapter->device_mode);
Rajeev Kumar8b373292014-01-08 20:36:55 -08001748 ret = -EINVAL;
1749 goto exit;
1750 }
1751
1752 status = hdd_parse_set_batchscan_command(value, pReq);
1753 if (status)
1754 {
1755 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1756 "Invalid WLS_BATCHING SET command");
1757 ret = -EINVAL;
1758 goto exit;
1759 }
1760
1761
1762 pAdapter->hdd_wait_for_set_batch_scan_rsp = TRUE;
1763 halStatus = sme_SetBatchScanReq(WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
1764 pAdapter->sessionId, hdd_set_batch_scan_req_callback,
1765 pAdapter);
1766
1767 if ( eHAL_STATUS_SUCCESS == halStatus )
1768 {
Mahesh A Saptasagar5f568172014-05-14 17:02:33 +05301769 char extra[32];
1770 tANI_U8 len = 0;
1771 tANI_U8 mScan = 0;
1772
Rajeev Kumar8b373292014-01-08 20:36:55 -08001773 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1774 "sme_SetBatchScanReq returned success halStatus %d",
1775 halStatus);
1776 if (TRUE == pAdapter->hdd_wait_for_set_batch_scan_rsp)
1777 {
1778 INIT_COMPLETION(pAdapter->hdd_set_batch_scan_req_var);
1779 rc = wait_for_completion_timeout(
1780 &pAdapter->hdd_set_batch_scan_req_var,
1781 msecs_to_jiffies(HDD_SET_BATCH_SCAN_REQ_TIME_OUT));
1782 if (0 == rc)
1783 {
1784 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1785 "%s: Timeout waiting for set batch scan to complete",
1786 __func__);
1787 ret = -EINVAL;
1788 goto exit;
1789 }
1790 }
1791 if ( !pRsp->nScansToBatch )
1792 {
1793 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1794 "%s: Received set batch scan failure response from FW",
1795 __func__);
1796 ret = -EINVAL;
1797 goto exit;
1798 }
1799 /*As per the Batch Scan Framework API we should return the MIN of
1800 either MSCAN or the max # of scans firmware can cache*/
Mahesh A Saptasagar5f568172014-05-14 17:02:33 +05301801 mScan = MIN(pReq->numberOfScansToBatch , pRsp->nScansToBatch);
Rajeev Kumar8b373292014-01-08 20:36:55 -08001802
1803 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STARTED;
1804
1805 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1806 "%s: request MSCAN %d response MSCAN %d ret %d",
Mahesh A Saptasagar5f568172014-05-14 17:02:33 +05301807 __func__, pReq->numberOfScansToBatch, pRsp->nScansToBatch, mScan);
1808 len = scnprintf(extra, sizeof(extra), "%d", mScan);
1809 if (copy_to_user(pPrivdata->buf, &extra, len + 1))
1810 {
1811 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1812 "%s: failed to copy MSCAN value to user buffer", __func__);
1813 ret = -EFAULT;
1814 goto exit;
1815 }
Rajeev Kumar8b373292014-01-08 20:36:55 -08001816 }
1817 else
1818 {
1819 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1820 "sme_SetBatchScanReq returned failure halStatus %d",
1821 halStatus);
1822 ret = -EINVAL;
1823 goto exit;
1824 }
1825 }
1826 else if (strncmp(command, "WLS_BATCHING STOP", 17) == 0)
1827 {
1828 eHalStatus halStatus;
1829 tSirStopBatchScanInd *pInd = &pAdapter->hddStopBatchScanInd;
1830 pInd->param = 0;
1831
1832 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
1833 {
1834 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1835 "%s: Batch scan feature is not supported by FW", __func__);
1836 ret = -EINVAL;
1837 goto exit;
1838 }
1839
1840 if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState)
1841 {
Deepthi Gowribfd17132014-11-14 17:59:04 +05301842 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Rajeev Kumar8b373292014-01-08 20:36:55 -08001843 "Batch scan is not yet enabled batch scan state %d",
1844 pAdapter->batchScanState);
1845 ret = -EINVAL;
1846 goto exit;
1847 }
1848
Kiet Lamaa8e15a2014-02-11 23:30:06 -08001849 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1850 hdd_deinit_batch_scan(pAdapter);
1851 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1852
Rajeev Kumar8b373292014-01-08 20:36:55 -08001853 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
1854
1855 halStatus = sme_StopBatchScanInd(WLAN_HDD_GET_HAL_CTX(pAdapter), pInd,
1856 pAdapter->sessionId);
1857 if ( eHAL_STATUS_SUCCESS == halStatus )
1858 {
1859 ret = 0;
1860 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1861 "sme_StopBatchScanInd returned success halStatus %d",
1862 halStatus);
1863 }
1864 else
1865 {
1866 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1867 "sme_StopBatchScanInd returned failure halStatus %d",
1868 halStatus);
1869 ret = -EINVAL;
1870 goto exit;
1871 }
1872 }
1873 else if (strncmp(command, "WLS_BATCHING GET", 16) == 0)
1874 {
1875 tANI_U32 remain_len;
1876
1877 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
1878 {
1879 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1880 "%s: Batch scan feature is not supported by FW", __func__);
1881 ret = -EINVAL;
1882 goto exit;
1883 }
1884
1885 if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState)
1886 {
Deepthi Gowribfd17132014-11-14 17:59:04 +05301887 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Rajeev Kumar8b373292014-01-08 20:36:55 -08001888 "Batch scan is not yet enabled could not return results"
1889 "Batch Scan state %d",
1890 pAdapter->batchScanState);
1891 ret = -EINVAL;
1892 goto exit;
1893 }
1894
1895 pPrivdata->used_len = 16;
1896 remain_len = pPrivdata->total_len - pPrivdata->used_len;
1897 if (remain_len < pPrivdata->total_len)
1898 {
1899 /*Clear previous batch scan response data if any*/
1900 vos_mem_zero((tANI_U8 *)(command + pPrivdata->used_len), remain_len);
1901 }
1902 else
1903 {
1904 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1905 "Invalid total length from user space can't fetch batch"
1906 " scan response total_len %d used_len %d remain len %d",
1907 pPrivdata->total_len, pPrivdata->used_len, remain_len);
1908 ret = -EINVAL;
1909 goto exit;
1910 }
1911 ret = hdd_return_batch_scan_rsp_to_user(pAdapter, pPrivdata, command);
1912 }
1913
1914exit:
1915
1916 return ret;
1917}
1918
1919
Rajeev79dbe4c2013-10-05 11:03:42 +05301920#endif/*End of FEATURE_WLAN_BATCH_SCAN*/
1921
c_hpothu92367912014-05-01 15:18:17 +05301922static void getBcnMissRateCB(VOS_STATUS status, int bcnMissRate, void *data)
1923{
c_hpothu39eb1e32014-06-26 16:31:50 +05301924 bcnMissRateContext_t *pCBCtx;
1925
1926 if (NULL == data)
1927 {
1928 hddLog(VOS_TRACE_LEVEL_ERROR, FL("argument data is NULL"));
1929 return;
1930 }
c_hpothu92367912014-05-01 15:18:17 +05301931
1932 /* there is a race condition that exists between this callback
1933 function and the caller since the caller could time out either
1934 before or while this code is executing. we use a spinlock to
1935 serialize these actions */
1936 spin_lock(&hdd_context_lock);
1937
c_hpothu39eb1e32014-06-26 16:31:50 +05301938 pCBCtx = (bcnMissRateContext_t *)data;
c_hpothu92367912014-05-01 15:18:17 +05301939 gbcnMissRate = -1;
1940
c_hpothu39eb1e32014-06-26 16:31:50 +05301941 if (pCBCtx->magic != BCN_MISS_RATE_CONTEXT_MAGIC)
c_hpothu92367912014-05-01 15:18:17 +05301942 {
1943 hddLog(VOS_TRACE_LEVEL_ERROR,
c_hpothu39eb1e32014-06-26 16:31:50 +05301944 FL("invalid context magic: %08x"), pCBCtx->magic);
c_hpothu92367912014-05-01 15:18:17 +05301945 spin_unlock(&hdd_context_lock);
1946 return ;
1947 }
1948
1949 if (VOS_STATUS_SUCCESS == status)
1950 {
c_hpothu39eb1e32014-06-26 16:31:50 +05301951 gbcnMissRate = bcnMissRate;
c_hpothu92367912014-05-01 15:18:17 +05301952 }
c_hpothu39eb1e32014-06-26 16:31:50 +05301953 else
1954 {
1955 hddLog(VOS_TRACE_LEVEL_ERROR, FL("failed to get bcnMissRate"));
1956 }
1957
c_hpothu92367912014-05-01 15:18:17 +05301958 complete(&(pCBCtx->completion));
1959 spin_unlock(&hdd_context_lock);
1960
1961 return;
1962}
1963
Abhishek Singh08aa7762014-12-16 13:59:03 +05301964void hdd_FWStatisCB( VOS_STATUS status,
1965 tSirFwStatsResult *fwStatsResult, void *pContext )
Satyanarayana Dash72806012014-12-02 14:30:08 +05301966{
1967 fwStatsContext_t *fwStatsCtx;
Satyanarayana Dash72806012014-12-02 14:30:08 +05301968 hdd_adapter_t *pAdapter;
1969
1970 hddLog(VOS_TRACE_LEVEL_INFO, FL(" with status = %d"),status);
1971
Abhishek Singh08aa7762014-12-16 13:59:03 +05301972 if (NULL == pContext)
Satyanarayana Dash72806012014-12-02 14:30:08 +05301973 {
1974 hddLog(VOS_TRACE_LEVEL_ERROR, FL("argument data is NULL"));
1975 return;
1976 }
1977 /* there is a race condition that exists between this callback
1978 function and the caller since the caller could time out either
1979 before or while this code is executing. we use a spinlock to
1980 serialize these actions */
1981 spin_lock(&hdd_context_lock);
Abhishek Singh08aa7762014-12-16 13:59:03 +05301982 fwStatsCtx = (fwStatsContext_t *) pContext;
Satyanarayana Dash72806012014-12-02 14:30:08 +05301983 if (fwStatsCtx->magic != FW_STATS_CONTEXT_MAGIC)
1984 {
1985 hddLog(VOS_TRACE_LEVEL_ERROR,
1986 FL("invalid context magic: %08x"), fwStatsCtx->magic);
1987 spin_unlock(&hdd_context_lock);
1988 return;
1989 }
1990 pAdapter = fwStatsCtx->pAdapter;
1991 if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
1992 {
1993 hddLog(VOS_TRACE_LEVEL_ERROR,
1994 FL("pAdapter returned is NULL or invalid"));
1995 spin_unlock(&hdd_context_lock);
1996 return;
1997 }
1998 pAdapter->fwStatsRsp.type = 0;
Abhishek Singh08aa7762014-12-16 13:59:03 +05301999 if ((VOS_STATUS_SUCCESS == status) && (NULL != fwStatsResult))
Satyanarayana Dash72806012014-12-02 14:30:08 +05302000 {
Satyanarayana Dash72806012014-12-02 14:30:08 +05302001 switch( fwStatsResult->type )
2002 {
2003 case FW_UBSP_STATS:
2004 {
Abhishek Singh08aa7762014-12-16 13:59:03 +05302005 memcpy(&pAdapter->fwStatsRsp,fwStatsResult,sizeof(tSirFwStatsResult));
Satyanarayana Dash72806012014-12-02 14:30:08 +05302006 hddLog(VOS_TRACE_LEVEL_INFO,
2007 FL("ubsp_enter_cnt = %d ubsp_jump_ddr_cnt = %d"),
Abhishek Singh08aa7762014-12-16 13:59:03 +05302008 pAdapter->fwStatsRsp.fwStatsData.ubspStats.ubsp_enter_cnt,
2009 pAdapter->fwStatsRsp.fwStatsData.ubspStats.ubsp_jump_ddr_cnt);
Satyanarayana Dash72806012014-12-02 14:30:08 +05302010 }
2011 break;
2012 default:
2013 {
2014 hddLog(VOS_TRACE_LEVEL_ERROR,
2015 FL(" No handling for stats type %d"),fwStatsResult->type);
2016 }
2017 }
2018 }
2019 complete(&(fwStatsCtx->completion));
2020 spin_unlock(&hdd_context_lock);
2021 return;
2022}
2023
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302024static int hdd_get_dwell_time(hdd_config_t *pCfg, tANI_U8 *command, char *extra, tANI_U8 n, tANI_U8 *len)
2025{
2026 int ret = 0;
2027
2028 if (!pCfg || !command || !extra || !len)
2029 {
2030 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2031 "%s: argument passsed for GETDWELLTIME is incorrect", __func__);
2032 ret = -EINVAL;
2033 return ret;
2034 }
2035
2036 if (strncmp(command, "GETDWELLTIME ACTIVE MAX", 23) == 0)
2037 {
2038 *len = scnprintf(extra, n, "GETDWELLTIME ACTIVE MAX %u\n",
2039 (int)pCfg->nActiveMaxChnTime);
2040 return ret;
2041 }
2042 else if (strncmp(command, "GETDWELLTIME ACTIVE MIN", 23) == 0)
2043 {
2044 *len = scnprintf(extra, n, "GETDWELLTIME ACTIVE MIN %u\n",
2045 (int)pCfg->nActiveMinChnTime);
2046 return ret;
2047 }
2048 else if (strncmp(command, "GETDWELLTIME PASSIVE MAX", 24) == 0)
2049 {
2050 *len = scnprintf(extra, n, "GETDWELLTIME PASSIVE MAX %u\n",
2051 (int)pCfg->nPassiveMaxChnTime);
2052 return ret;
2053 }
2054 else if (strncmp(command, "GETDWELLTIME PASSIVE MIN", 24) == 0)
2055 {
2056 *len = scnprintf(extra, n, "GETDWELLTIME PASSIVE MIN %u\n",
2057 (int)pCfg->nPassiveMinChnTime);
2058 return ret;
2059 }
Rajesh Babu Prathipati0fd227e2014-07-05 12:50:00 +05302060 else if (strncmp(command, "GETDWELLTIME", 12) == 0)
2061 {
2062 *len = scnprintf(extra, n, "GETDWELLTIME %u \n",
2063 (int)pCfg->nActiveMaxChnTime);
2064 return ret;
2065 }
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302066 else
2067 {
2068 ret = -EINVAL;
2069 }
2070
2071 return ret;
2072}
2073
2074static int hdd_set_dwell_time(hdd_adapter_t *pAdapter, tANI_U8 *command)
2075{
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302076 tHalHandle hHal;
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302077 hdd_config_t *pCfg;
2078 tANI_U8 *value = command;
2079 int val = 0, ret = 0, temp = 0;
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302080 tSmeConfigParams smeConfig;
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302081
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302082 if (!pAdapter || !command || !(pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini)
2083 || !(hHal = (WLAN_HDD_GET_HAL_CTX(pAdapter))))
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302084 {
2085 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2086 "%s: argument passed for SETDWELLTIME is incorrect", __func__);
2087 ret = -EINVAL;
2088 return ret;
2089 }
2090
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302091 vos_mem_zero(&smeConfig, sizeof(smeConfig));
2092 sme_GetConfigParam(hHal, &smeConfig);
2093
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302094 if (strncmp(command, "SETDWELLTIME ACTIVE MAX", 23) == 0 )
2095 {
2096 value = value + 24;
2097 temp = kstrtou32(value, 10, &val);
2098 if (temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_MIN ||
2099 val > CFG_ACTIVE_MAX_CHANNEL_TIME_MAX )
2100 {
2101 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2102 "%s: argument passed for SETDWELLTIME ACTIVE MAX is incorrect", __func__);
2103 ret = -EFAULT;
2104 return ret;
2105 }
2106 pCfg->nActiveMaxChnTime = val;
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302107 smeConfig.csrConfig.nActiveMaxChnTime = val;
2108 sme_UpdateConfig(hHal, &smeConfig);
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302109 }
2110 else if (strncmp(command, "SETDWELLTIME ACTIVE MIN", 23) == 0)
2111 {
2112 value = value + 24;
2113 temp = kstrtou32(value, 10, &val);
2114 if (temp !=0 || val < CFG_ACTIVE_MIN_CHANNEL_TIME_MIN ||
2115 val > CFG_ACTIVE_MIN_CHANNEL_TIME_MAX )
2116 {
2117 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2118 "%s: argument passsed for SETDWELLTIME ACTIVE MIN is incorrect", __func__);
2119 ret = -EFAULT;
2120 return ret;
2121 }
2122 pCfg->nActiveMinChnTime = val;
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302123 smeConfig.csrConfig.nActiveMinChnTime = val;
2124 sme_UpdateConfig(hHal, &smeConfig);
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302125 }
2126 else if (strncmp(command, "SETDWELLTIME PASSIVE MAX", 24) == 0)
2127 {
2128 value = value + 25;
2129 temp = kstrtou32(value, 10, &val);
2130 if (temp != 0 || val < CFG_PASSIVE_MAX_CHANNEL_TIME_MIN ||
2131 val > CFG_PASSIVE_MAX_CHANNEL_TIME_MAX )
2132 {
2133 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2134 "%s: argument passed for SETDWELLTIME PASSIVE MAX is incorrect", __func__);
2135 ret = -EFAULT;
2136 return ret;
2137 }
2138 pCfg->nPassiveMaxChnTime = val;
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302139 smeConfig.csrConfig.nPassiveMaxChnTime = val;
2140 sme_UpdateConfig(hHal, &smeConfig);
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302141 }
2142 else if (strncmp(command, "SETDWELLTIME PASSIVE MIN", 24) == 0)
2143 {
2144 value = value + 25;
2145 temp = kstrtou32(value, 10, &val);
2146 if (temp != 0 || val < CFG_PASSIVE_MIN_CHANNEL_TIME_MIN ||
2147 val > CFG_PASSIVE_MIN_CHANNEL_TIME_MAX )
2148 {
2149 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2150 "%s: argument passed for SETDWELLTIME PASSIVE MIN is incorrect", __func__);
2151 ret = -EFAULT;
2152 return ret;
2153 }
2154 pCfg->nPassiveMinChnTime = val;
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302155 smeConfig.csrConfig.nPassiveMinChnTime = val;
2156 sme_UpdateConfig(hHal, &smeConfig);
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302157 }
Rajesh Babu Prathipati0fd227e2014-07-05 12:50:00 +05302158 else if (strncmp(command, "SETDWELLTIME", 12) == 0)
2159 {
2160 value = value + 13;
2161 temp = kstrtou32(value, 10, &val);
2162 if (temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_MIN ||
2163 val > CFG_ACTIVE_MAX_CHANNEL_TIME_MAX )
2164 {
2165 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2166 "%s: argument passed for SETDWELLTIME is incorrect", __func__);
2167 ret = -EFAULT;
2168 return ret;
2169 }
2170 pCfg->nActiveMaxChnTime = val;
2171 smeConfig.csrConfig.nActiveMaxChnTime = val;
2172 sme_UpdateConfig(hHal, &smeConfig);
2173 }
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302174 else
2175 {
2176 ret = -EINVAL;
2177 }
2178
2179 return ret;
2180}
2181
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002182static int hdd_driver_command(hdd_adapter_t *pAdapter,
2183 hdd_priv_data_t *ppriv_data)
Jeff Johnson295189b2012-06-20 16:38:30 -07002184{
Jeff Johnson295189b2012-06-20 16:38:30 -07002185 hdd_priv_data_t priv_data;
2186 tANI_U8 *command = NULL;
Kaushik, Sushant96122442014-10-21 16:40:18 +05302187 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2188 hdd_scaninfo_t *pScanInfo = NULL;
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002189 int ret = 0;
Kaushik, Sushant96122442014-10-21 16:40:18 +05302190 int status;
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002191 /*
2192 * Note that valid pointers are provided by caller
2193 */
Jeff Johnson295189b2012-06-20 16:38:30 -07002194
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002195 /* copy to local struct to avoid numerous changes to legacy code */
2196 priv_data = *ppriv_data;
Jeff Johnson295189b2012-06-20 16:38:30 -07002197
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002198 if (priv_data.total_len <= 0 ||
2199 priv_data.total_len > WLAN_PRIV_DATA_MAX_LEN)
Sameer Thalappil8ef3a0e2013-04-05 14:36:04 -07002200 {
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002201 hddLog(VOS_TRACE_LEVEL_WARN,
2202 "%s:invalid priv_data.total_len(%d)!!!", __func__,
2203 priv_data.total_len);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07002204 ret = -EINVAL;
2205 goto exit;
2206 }
Kaushik, Sushant96122442014-10-21 16:40:18 +05302207 status = wlan_hdd_validate_context(pHddCtx);
2208 if (0 != status)
2209 {
2210 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2211 "%s: HDD context is not valid", __func__);
2212 return status;
2213 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07002214 /* Allocate +1 for '\0' */
2215 command = kmalloc(priv_data.total_len + 1, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07002216 if (!command)
2217 {
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002218 hddLog(VOS_TRACE_LEVEL_ERROR,
2219 "%s: failed to allocate memory", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002220 ret = -ENOMEM;
2221 goto exit;
2222 }
2223
2224 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
2225 {
2226 ret = -EFAULT;
2227 goto exit;
2228 }
2229
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002230 /* Make sure the command is NUL-terminated */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07002231 command[priv_data.total_len] = '\0';
2232
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002233 /* at one time the following block of code was conditional. braces
2234 * have been retained to avoid re-indenting the legacy code
2235 */
Jeff Johnson295189b2012-06-20 16:38:30 -07002236 {
2237 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2238
2239 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07002240 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -07002241
2242 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
2243 {
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302244 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2245 TRACE_CODE_HDD_P2P_DEV_ADDR_IOCTL,
2246 pAdapter->sessionId, (unsigned)
2247 (*(pHddCtx->p2pDeviceAddress.bytes+2)<<24 |
2248 *(pHddCtx->p2pDeviceAddress.bytes+3)<<16 |
2249 *(pHddCtx->p2pDeviceAddress.bytes+4)<<8 |
2250 *(pHddCtx->p2pDeviceAddress.bytes+5))));
Jeff Johnson295189b2012-06-20 16:38:30 -07002251 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
2252 sizeof(tSirMacAddr)))
2253 {
2254 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Arif Hussain6d2a3322013-11-17 19:50:10 -08002255 "%s: failed to copy data to user buffer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002256 ret = -EFAULT;
2257 }
2258 }
Amar Singhal0974e402013-02-12 14:27:46 -08002259 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07002260 {
Amar Singhal0974e402013-02-12 14:27:46 -08002261 tANI_U8 *ptr = command ;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002262
Jeff Johnson295189b2012-06-20 16:38:30 -07002263 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -08002264
2265 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -07002266 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07002267 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -08002268 "%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 -07002269 /* Change band request received */
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002270 ret = hdd_setBand_helper(pAdapter->dev, ptr);
Abhishek Singh2ec36ab2014-08-07 16:14:25 +05302271 if(ret < 0)
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302272 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002273 "%s: failed to set band ret=%d", __func__, ret);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002274 }
Kiet Lamf040f472013-11-20 21:15:23 +05302275 else if(strncmp(command, "SETWMMPS", 8) == 0)
2276 {
2277 tANI_U8 *ptr = command;
2278 ret = hdd_wmmps_helper(pAdapter, ptr);
2279 }
Agarwal Ashishef54a182014-12-16 15:07:31 +05302280
2281 else if(strncmp(command, "TDLSSCAN", 8) == 0)
2282 {
2283 tANI_U8 *ptr = command;
2284 ret = hdd_set_tdls_scan_type(pAdapter, ptr);
2285 }
2286
Jeff Johnson32d95a32012-09-10 13:15:23 -07002287 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
2288 {
2289 char *country_code;
2290
2291 country_code = command + 8;
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07002292
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002293 INIT_COMPLETION(pAdapter->change_country_code);
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07002294 hdd_checkandupdate_dfssetting(pAdapter, country_code);
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -07002295#ifndef CONFIG_ENABLE_LINUX_REG
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +05302296 hdd_checkandupdate_phymode(pAdapter, country_code);
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -07002297#endif
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002298 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal,
2299 (void *)(tSmeChangeCountryCallback)
2300 wlan_hdd_change_country_code_callback,
Abhishek Singha306a442013-11-07 18:39:01 +05302301 country_code, pAdapter, pHddCtx->pvosContext, eSIR_TRUE, eSIR_TRUE);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002302 if (eHAL_STATUS_SUCCESS == ret)
2303 {
2304 ret = wait_for_completion_interruptible_timeout(
2305 &pAdapter->change_country_code,
2306 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
2307 if (0 >= ret)
2308 {
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002309 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: SME while setting country code timed out %d",
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302310 __func__, ret);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002311 }
2312 }
2313 else
Jeff Johnson32d95a32012-09-10 13:15:23 -07002314 {
2315 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002316 "%s: SME Change Country code fail ret=%d", __func__, ret);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002317 ret = -EINVAL;
Jeff Johnson32d95a32012-09-10 13:15:23 -07002318 }
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002319
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07002320 }
2321 /*
2322 command should be a string having format
2323 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
2324 */
Amar Singhal0974e402013-02-12 14:27:46 -08002325 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07002326 {
Amar Singhal0974e402013-02-12 14:27:46 -08002327 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07002328
2329 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002330 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07002331
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -08002332 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -07002333 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -08002334 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
2335 {
2336 int suspend = 0;
2337 tANI_U8 *ptr = (tANI_U8*)command + 15;
2338
2339 suspend = *ptr - '0';
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302340 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2341 TRACE_CODE_HDD_SETSUSPENDMODE_IOCTL,
2342 pAdapter->sessionId, suspend));
Sameer Thalappil45931fb2013-02-01 11:18:05 -08002343 hdd_set_wlan_suspend_mode(suspend);
2344 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002345#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
2346 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
2347 {
2348 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002349 tANI_S8 rssi = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002350 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
2351 eHalStatus status = eHAL_STATUS_SUCCESS;
2352
2353 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
2354 value = value + 15;
2355
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002356 /* Convert the value from ascii to integer */
2357 ret = kstrtos8(value, 10, &rssi);
2358 if (ret < 0)
2359 {
2360 /* If the input value is greater than max value of datatype, then also
2361 kstrtou8 fails */
2362 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2363 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdafa7157d2013-10-31 10:14:22 -07002364 __func__,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002365 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
2366 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
2367 ret = -EINVAL;
2368 goto exit;
2369 }
2370
Srinivas Girigowdade697412013-02-14 16:31:48 -08002371 lookUpThreshold = abs(rssi);
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002372
Srinivas Girigowdade697412013-02-14 16:31:48 -08002373 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
2374 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
2375 {
2376 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2377 "Neighbor lookup threshold value %d is out of range"
2378 " (Min: %d Max: %d)", lookUpThreshold,
2379 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
2380 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
2381 ret = -EINVAL;
2382 goto exit;
2383 }
2384
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302385 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2386 TRACE_CODE_HDD_SETROAMTRIGGER_IOCTL,
2387 pAdapter->sessionId, lookUpThreshold));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002388 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2389 "%s: Received Command to Set Roam trigger"
2390 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
2391
2392 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
2393 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
2394 if (eHAL_STATUS_SUCCESS != status)
2395 {
2396 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2397 "%s: Failed to set roam trigger, try again", __func__);
2398 ret = -EPERM;
2399 goto exit;
2400 }
2401
2402 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
mukul sharmad6e1fdd2014-06-23 19:19:09 +05302403 pHddCtx->cfg_ini->nNeighborReassocRssiThreshold = lookUpThreshold + 5;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002404 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
2405 }
2406 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
2407 {
2408 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
2409 int rssi = (-1) * lookUpThreshold;
2410 char extra[32];
2411 tANI_U8 len = 0;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302412 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2413 TRACE_CODE_HDD_GETROAMTRIGGER_IOCTL,
2414 pAdapter->sessionId, lookUpThreshold));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002415 len = scnprintf(extra, sizeof(extra), "%s %d", command, rssi);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002416 if (copy_to_user(priv_data.buf, &extra, len + 1))
2417 {
2418 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2419 "%s: failed to copy data to user buffer", __func__);
2420 ret = -EFAULT;
2421 goto exit;
2422 }
2423 }
2424 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
2425 {
2426 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002427 tANI_U8 roamScanPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002428 tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002429
Srinivas Girigowdade697412013-02-14 16:31:48 -08002430 /* input refresh period is in terms of seconds */
2431 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
2432 value = value + 18;
2433 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002434 ret = kstrtou8(value, 10, &roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002435 if (ret < 0)
2436 {
2437 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002438 kstrtou8 fails */
Srinivas Girigowdade697412013-02-14 16:31:48 -08002439 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002440 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdade697412013-02-14 16:31:48 -08002441 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07002442 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
2443 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002444 ret = -EINVAL;
2445 goto exit;
2446 }
2447
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002448 if ((roamScanPeriod < (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000)) ||
2449 (roamScanPeriod > (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000)))
Srinivas Girigowdade697412013-02-14 16:31:48 -08002450 {
2451 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002452 "Roam scan period value %d is out of range"
2453 " (Min: %d Max: %d)", roamScanPeriod,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07002454 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
2455 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002456 ret = -EINVAL;
2457 goto exit;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302458 }
2459 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2460 TRACE_CODE_HDD_SETROAMSCANPERIOD_IOCTL,
2461 pAdapter->sessionId, roamScanPeriod));
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002462 neighborEmptyScanRefreshPeriod = roamScanPeriod * 1000;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002463
2464 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2465 "%s: Received Command to Set roam scan period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002466 " (Empty Scan refresh period) = %d", __func__, roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002467
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002468 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod;
2469 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002470 }
2471 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
2472 {
2473 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
2474 char extra[32];
2475 tANI_U8 len = 0;
2476
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302477 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2478 TRACE_CODE_HDD_GETROAMSCANPERIOD_IOCTL,
2479 pAdapter->sessionId, nEmptyScanRefreshPeriod));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002480 len = scnprintf(extra, sizeof(extra), "%s %d",
2481 "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002482 /* Returned value is in units of seconds */
2483 if (copy_to_user(priv_data.buf, &extra, len + 1))
2484 {
2485 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2486 "%s: failed to copy data to user buffer", __func__);
2487 ret = -EFAULT;
2488 goto exit;
2489 }
2490 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002491 else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0)
2492 {
2493 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002494 tANI_U8 roamScanRefreshPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002495 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002496
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002497 /* input refresh period is in terms of seconds */
2498 /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */
2499 value = value + 25;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002500
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002501 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002502 ret = kstrtou8(value, 10, &roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002503 if (ret < 0)
2504 {
2505 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002506 kstrtou8 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002507 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002508 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002509 __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002510 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
2511 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
2512 ret = -EINVAL;
2513 goto exit;
2514 }
2515
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002516 if ((roamScanRefreshPeriod < (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000)) ||
2517 (roamScanRefreshPeriod > (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000)))
2518 {
2519 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2520 "Neighbor scan results refresh period value %d is out of range"
2521 " (Min: %d Max: %d)", roamScanRefreshPeriod,
2522 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
2523 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
2524 ret = -EINVAL;
2525 goto exit;
2526 }
2527 neighborScanRefreshPeriod = roamScanRefreshPeriod * 1000;
2528
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002529 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2530 "%s: Received Command to Set roam scan refresh period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002531 " (Scan refresh period) = %d", __func__, roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002532
2533 pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod;
2534 sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
2535 }
2536 else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0)
2537 {
2538 tANI_U16 value = sme_getNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
2539 char extra[32];
2540 tANI_U8 len = 0;
2541
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002542 len = scnprintf(extra, sizeof(extra), "%s %d",
2543 "GETROAMSCANREFRESHPERIOD", (value/1000));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002544 /* Returned value is in units of seconds */
2545 if (copy_to_user(priv_data.buf, &extra, len + 1))
2546 {
2547 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2548 "%s: failed to copy data to user buffer", __func__);
2549 ret = -EFAULT;
2550 goto exit;
2551 }
2552 }
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07002553#ifdef FEATURE_WLAN_LFR
2554 /* SETROAMMODE */
2555 else if (strncmp(command, "SETROAMMODE", SIZE_OF_SETROAMMODE) == 0)
2556 {
2557 tANI_U8 *value = command;
2558 tANI_BOOLEAN roamMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
2559
2560 /* Move pointer to ahead of SETROAMMODE<delimiter> */
2561 value = value + SIZE_OF_SETROAMMODE + 1;
2562
2563 /* Convert the value from ascii to integer */
2564 ret = kstrtou8(value, SIZE_OF_SETROAMMODE, &roamMode);
2565 if (ret < 0)
2566 {
2567 /* If the input value is greater than max value of datatype, then also
2568 kstrtou8 fails */
2569 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2570 "%s: kstrtou8 failed range [%d - %d]", __func__,
2571 CFG_LFR_FEATURE_ENABLED_MIN,
2572 CFG_LFR_FEATURE_ENABLED_MAX);
2573 ret = -EINVAL;
2574 goto exit;
2575 }
2576 if ((roamMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
2577 (roamMode > CFG_LFR_FEATURE_ENABLED_MAX))
2578 {
2579 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2580 "Roam Mode value %d is out of range"
2581 " (Min: %d Max: %d)", roamMode,
2582 CFG_LFR_FEATURE_ENABLED_MIN,
2583 CFG_LFR_FEATURE_ENABLED_MAX);
2584 ret = -EINVAL;
2585 goto exit;
2586 }
2587
2588 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2589 "%s: Received Command to Set Roam Mode = %d", __func__, roamMode);
2590 /*
2591 * Note that
2592 * SETROAMMODE 0 is to enable LFR while
2593 * SETROAMMODE 1 is to disable LFR, but
2594 * NotifyIsFastRoamIniFeatureEnabled 0/1 is to enable/disable.
2595 * So, we have to invert the value to call sme_UpdateIsFastRoamIniFeatureEnabled.
2596 */
2597 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
2598 roamMode = CFG_LFR_FEATURE_ENABLED_MAX; /* Roam enable */
2599 else
2600 roamMode = CFG_LFR_FEATURE_ENABLED_MIN; /* Roam disable */
2601
2602 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = roamMode;
2603 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), roamMode);
2604 }
2605 /* GETROAMMODE */
2606 else if (strncmp(priv_data.buf, "GETROAMMODE", SIZE_OF_GETROAMMODE) == 0)
2607 {
2608 tANI_BOOLEAN roamMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2609 char extra[32];
2610 tANI_U8 len = 0;
2611
2612 /*
2613 * roamMode value shall be inverted because the sementics is different.
2614 */
2615 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
2616 roamMode = CFG_LFR_FEATURE_ENABLED_MAX;
2617 else
2618 roamMode = CFG_LFR_FEATURE_ENABLED_MIN;
2619
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002620 len = scnprintf(extra, sizeof(extra), "%s %d", command, roamMode);
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07002621 if (copy_to_user(priv_data.buf, &extra, len + 1))
2622 {
2623 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2624 "%s: failed to copy data to user buffer", __func__);
2625 ret = -EFAULT;
2626 goto exit;
2627 }
2628 }
2629#endif
Srinivas Girigowdade697412013-02-14 16:31:48 -08002630#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002631#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -08002632 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
2633 {
2634 tANI_U8 *value = command;
2635 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
2636
2637 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
2638 value = value + 13;
2639 /* Convert the value from ascii to integer */
2640 ret = kstrtou8(value, 10, &roamRssiDiff);
2641 if (ret < 0)
2642 {
2643 /* If the input value is greater than max value of datatype, then also
2644 kstrtou8 fails */
2645 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2646 "%s: kstrtou8 failed range [%d - %d]", __func__,
2647 CFG_ROAM_RSSI_DIFF_MIN,
2648 CFG_ROAM_RSSI_DIFF_MAX);
2649 ret = -EINVAL;
2650 goto exit;
2651 }
2652
2653 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
2654 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
2655 {
2656 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2657 "Roam rssi diff value %d is out of range"
2658 " (Min: %d Max: %d)", roamRssiDiff,
2659 CFG_ROAM_RSSI_DIFF_MIN,
2660 CFG_ROAM_RSSI_DIFF_MAX);
2661 ret = -EINVAL;
2662 goto exit;
2663 }
2664
2665 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2666 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
2667
2668 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
2669 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
2670 }
2671 else if (strncmp(priv_data.buf, "GETROAMDELTA", 12) == 0)
2672 {
2673 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
2674 char extra[32];
2675 tANI_U8 len = 0;
2676
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302677 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2678 TRACE_CODE_HDD_GETROAMDELTA_IOCTL,
2679 pAdapter->sessionId, roamRssiDiff));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002680 len = scnprintf(extra, sizeof(extra), "%s %d",
2681 command, roamRssiDiff);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002682 if (copy_to_user(priv_data.buf, &extra, len + 1))
2683 {
2684 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2685 "%s: failed to copy data to user buffer", __func__);
2686 ret = -EFAULT;
2687 goto exit;
2688 }
2689 }
2690#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002691#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -08002692 else if (strncmp(command, "GETBAND", 7) == 0)
2693 {
2694 int band = -1;
2695 char extra[32];
2696 tANI_U8 len = 0;
2697 hdd_getBand_helper(pHddCtx, &band);
2698
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302699 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2700 TRACE_CODE_HDD_GETBAND_IOCTL,
2701 pAdapter->sessionId, band));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002702 len = scnprintf(extra, sizeof(extra), "%s %d", command, band);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002703 if (copy_to_user(priv_data.buf, &extra, len + 1))
2704 {
2705 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2706 "%s: failed to copy data to user buffer", __func__);
2707 ret = -EFAULT;
2708 goto exit;
2709 }
2710 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002711 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
2712 {
2713 tANI_U8 *value = command;
2714 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2715 tANI_U8 numChannels = 0;
2716 eHalStatus status = eHAL_STATUS_SUCCESS;
2717
2718 status = hdd_parse_channellist(value, ChannelList, &numChannels);
2719 if (eHAL_STATUS_SUCCESS != status)
2720 {
2721 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2722 "%s: Failed to parse channel list information", __func__);
2723 ret = -EINVAL;
2724 goto exit;
2725 }
2726
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302727 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2728 TRACE_CODE_HDD_SETROAMSCANCHANNELS_IOCTL,
2729 pAdapter->sessionId, numChannels));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002730 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
2731 {
2732 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2733 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
2734 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
2735 ret = -EINVAL;
2736 goto exit;
2737 }
2738 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
2739 numChannels);
2740 if (eHAL_STATUS_SUCCESS != status)
2741 {
2742 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2743 "%s: Failed to update channel list information", __func__);
2744 ret = -EINVAL;
2745 goto exit;
2746 }
2747 }
2748 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
2749 {
2750 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2751 tANI_U8 numChannels = 0;
Jeff Johnson51b67782013-04-05 12:35:41 -07002752 tANI_U8 j = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002753 char extra[128] = {0};
Jeff Johnson51b67782013-04-05 12:35:41 -07002754 int len;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002755
2756 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
2757 ChannelList, &numChannels ))
2758 {
2759 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2760 "%s: failed to get roam scan channel list", __func__);
2761 ret = -EFAULT;
2762 goto exit;
2763 }
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302764 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2765 TRACE_CODE_HDD_GETROAMSCANCHANNELS_IOCTL,
2766 pAdapter->sessionId, numChannels));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002767 /* output channel list is of the format
2768 [Number of roam scan channels][Channel1][Channel2]... */
2769 /* copy the number of channels in the 0th index */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002770 len = scnprintf(extra, sizeof(extra), "%s %d", command, numChannels);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002771 for (j = 0; (j < numChannels); j++)
2772 {
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002773 len += scnprintf(extra + len, sizeof(extra) - len, " %d",
2774 ChannelList[j]);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002775 }
2776
2777 if (copy_to_user(priv_data.buf, &extra, len + 1))
2778 {
2779 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2780 "%s: failed to copy data to user buffer", __func__);
2781 ret = -EFAULT;
2782 goto exit;
2783 }
2784 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002785 else if (strncmp(command, "GETCCXMODE", 10) == 0)
2786 {
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002787 tANI_BOOLEAN eseMode = sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002788 char extra[32];
2789 tANI_U8 len = 0;
2790
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002791 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002792 then this operation is not permitted (return FAILURE) */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002793 if (eseMode &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002794 hdd_is_okc_mode_enabled(pHddCtx) &&
2795 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2796 {
2797 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002798 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002799 " hence this operation is not permitted!", __func__);
2800 ret = -EPERM;
2801 goto exit;
2802 }
2803
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002804 len = scnprintf(extra, sizeof(extra), "%s %d",
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002805 "GETCCXMODE", eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002806 if (copy_to_user(priv_data.buf, &extra, len + 1))
2807 {
2808 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2809 "%s: failed to copy data to user buffer", __func__);
2810 ret = -EFAULT;
2811 goto exit;
2812 }
2813 }
2814 else if (strncmp(command, "GETOKCMODE", 10) == 0)
2815 {
2816 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
2817 char extra[32];
2818 tANI_U8 len = 0;
2819
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002820 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002821 then this operation is not permitted (return FAILURE) */
2822 if (okcMode &&
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002823 sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002824 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2825 {
2826 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002827 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002828 " hence this operation is not permitted!", __func__);
2829 ret = -EPERM;
2830 goto exit;
2831 }
2832
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002833 len = scnprintf(extra, sizeof(extra), "%s %d",
2834 "GETOKCMODE", okcMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002835 if (copy_to_user(priv_data.buf, &extra, len + 1))
2836 {
2837 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2838 "%s: failed to copy data to user buffer", __func__);
2839 ret = -EFAULT;
2840 goto exit;
2841 }
2842 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002843 else if (strncmp(command, "GETFASTROAM", 11) == 0)
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002844 {
2845 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2846 char extra[32];
2847 tANI_U8 len = 0;
2848
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002849 len = scnprintf(extra, sizeof(extra), "%s %d",
2850 "GETFASTROAM", lfrMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002851 if (copy_to_user(priv_data.buf, &extra, len + 1))
2852 {
2853 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2854 "%s: failed to copy data to user buffer", __func__);
2855 ret = -EFAULT;
2856 goto exit;
2857 }
2858 }
2859 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
2860 {
2861 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2862 char extra[32];
2863 tANI_U8 len = 0;
2864
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002865 len = scnprintf(extra, sizeof(extra), "%s %d",
2866 "GETFASTTRANSITION", ft);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002867 if (copy_to_user(priv_data.buf, &extra, len + 1))
2868 {
2869 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2870 "%s: failed to copy data to user buffer", __func__);
2871 ret = -EFAULT;
2872 goto exit;
2873 }
2874 }
2875 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
2876 {
2877 tANI_U8 *value = command;
2878 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
2879
2880 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
2881 value = value + 26;
2882 /* Convert the value from ascii to integer */
2883 ret = kstrtou8(value, 10, &minTime);
2884 if (ret < 0)
2885 {
2886 /* If the input value is greater than max value of datatype, then also
2887 kstrtou8 fails */
2888 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2889 "%s: kstrtou8 failed range [%d - %d]", __func__,
2890 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
2891 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
2892 ret = -EINVAL;
2893 goto exit;
2894 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002895 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
2896 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
2897 {
2898 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2899 "scan min channel time value %d is out of range"
2900 " (Min: %d Max: %d)", minTime,
2901 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
2902 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
2903 ret = -EINVAL;
2904 goto exit;
2905 }
2906
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302907 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2908 TRACE_CODE_HDD_SETROAMSCANCHANNELMINTIME_IOCTL,
2909 pAdapter->sessionId, minTime));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002910 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2911 "%s: Received Command to change channel min time = %d", __func__, minTime);
2912
2913 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
2914 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
2915 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002916 else if (strncmp(command, "SENDACTIONFRAME", 15) == 0)
2917 {
2918 tANI_U8 *value = command;
2919 tANI_U8 channel = 0;
2920 tANI_U8 dwellTime = 0;
2921 tANI_U8 bufLen = 0;
2922 tANI_U8 *buf = NULL;
2923 tSirMacAddr targetApBssid;
2924 eHalStatus status = eHAL_STATUS_SUCCESS;
2925 struct ieee80211_channel chan;
2926 tANI_U8 finalLen = 0;
2927 tANI_U8 *finalBuf = NULL;
2928 tANI_U8 temp = 0;
2929 u64 cookie;
2930 hdd_station_ctx_t *pHddStaCtx = NULL;
2931 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2932
2933 /* if not associated, no need to send action frame */
2934 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2935 {
2936 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2937 ret = -EINVAL;
2938 goto exit;
2939 }
2940
2941 status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel,
2942 &dwellTime, &buf, &bufLen);
2943 if (eHAL_STATUS_SUCCESS != status)
2944 {
2945 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2946 "%s: Failed to parse send action frame data", __func__);
2947 ret = -EINVAL;
2948 goto exit;
2949 }
2950
2951 /* if the target bssid is different from currently associated AP,
2952 then no need to send action frame */
2953 if (VOS_TRUE != vos_mem_compare(targetApBssid,
2954 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2955 {
2956 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__);
2957 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002958 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002959 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002960 goto exit;
2961 }
2962
2963 /* if the channel number is different from operating channel then
2964 no need to send action frame */
2965 if (channel != pHddStaCtx->conn_info.operationChannel)
2966 {
2967 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2968 "%s: channel(%d) is different from operating channel(%d)",
2969 __func__, channel, pHddStaCtx->conn_info.operationChannel);
2970 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002971 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002972 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002973 goto exit;
2974 }
2975 chan.center_freq = sme_ChnToFreq(channel);
2976
2977 finalLen = bufLen + 24;
2978 finalBuf = vos_mem_malloc(finalLen);
2979 if (NULL == finalBuf)
2980 {
2981 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__);
2982 ret = -ENOMEM;
Jeff Johnson11c33152013-04-16 17:52:40 -07002983 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002984 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002985 goto exit;
2986 }
2987 vos_mem_zero(finalBuf, finalLen);
2988
2989 /* Fill subtype */
2990 temp = SIR_MAC_MGMT_ACTION << 4;
2991 vos_mem_copy(finalBuf + 0, &temp, sizeof(temp));
2992
2993 /* Fill type */
2994 temp = SIR_MAC_MGMT_FRAME;
2995 vos_mem_copy(finalBuf + 2, &temp, sizeof(temp));
2996
2997 /* Fill destination address (bssid of the AP) */
2998 vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid));
2999
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07003000 /* Fill source address (STA mac address) */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003001 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
3002
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07003003 /* Fill BSSID (AP mac address) */
3004 vos_mem_copy(finalBuf + 16, targetApBssid, sizeof(targetApBssid));
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003005
3006 /* Fill received buffer from 24th address */
3007 vos_mem_copy(finalBuf + 24, buf, bufLen);
3008
Jeff Johnson11c33152013-04-16 17:52:40 -07003009 /* done with the parsed buffer */
3010 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08003011 buf = NULL;
Jeff Johnson11c33152013-04-16 17:52:40 -07003012
DARAM SUDHA39eede62014-02-12 11:16:40 +05303013 wlan_hdd_mgmt_tx( NULL,
Yue Maf49ba872013-08-19 12:04:25 -07003014#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
3015 &(pAdapter->wdev),
3016#else
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003017 pAdapter->dev,
Yue Maf49ba872013-08-19 12:04:25 -07003018#endif
3019 &chan, 0,
3020#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
3021 NL80211_CHAN_HT20, 1,
3022#endif
3023 dwellTime, finalBuf, finalLen, 1,
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003024 1, &cookie );
3025 vos_mem_free(finalBuf);
3026 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003027 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
3028 {
3029 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
3030 char extra[32];
3031 tANI_U8 len = 0;
3032
3033 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003034 len = scnprintf(extra, sizeof(extra), "%s %d",
3035 "GETROAMSCANCHANNELMINTIME", val);
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303036 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3037 TRACE_CODE_HDD_GETROAMSCANCHANNELMINTIME_IOCTL,
3038 pAdapter->sessionId, val));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003039 if (copy_to_user(priv_data.buf, &extra, len + 1))
3040 {
3041 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3042 "%s: failed to copy data to user buffer", __func__);
3043 ret = -EFAULT;
3044 goto exit;
3045 }
3046 }
3047 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
3048 {
3049 tANI_U8 *value = command;
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07003050 tANI_U16 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003051
3052 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
3053 value = value + 19;
3054 /* Convert the value from ascii to integer */
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07003055 ret = kstrtou16(value, 10, &maxTime);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003056 if (ret < 0)
3057 {
3058 /* If the input value is greater than max value of datatype, then also
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07003059 kstrtou16 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003060 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07003061 "%s: kstrtou16 failed range [%d - %d]", __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003062 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
3063 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
3064 ret = -EINVAL;
3065 goto exit;
3066 }
3067
3068 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
3069 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
3070 {
3071 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3072 "lfr mode value %d is out of range"
3073 " (Min: %d Max: %d)", maxTime,
3074 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
3075 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
3076 ret = -EINVAL;
3077 goto exit;
3078 }
3079
3080 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3081 "%s: Received Command to change channel max time = %d", __func__, maxTime);
3082
3083 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
3084 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
3085 }
3086 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
3087 {
3088 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
3089 char extra[32];
3090 tANI_U8 len = 0;
3091
3092 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003093 len = scnprintf(extra, sizeof(extra), "%s %d",
3094 "GETSCANCHANNELTIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003095 if (copy_to_user(priv_data.buf, &extra, len + 1))
3096 {
3097 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3098 "%s: failed to copy data to user buffer", __func__);
3099 ret = -EFAULT;
3100 goto exit;
3101 }
3102 }
3103 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
3104 {
3105 tANI_U8 *value = command;
3106 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
3107
3108 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
3109 value = value + 16;
3110 /* Convert the value from ascii to integer */
3111 ret = kstrtou16(value, 10, &val);
3112 if (ret < 0)
3113 {
3114 /* If the input value is greater than max value of datatype, then also
3115 kstrtou16 fails */
3116 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3117 "%s: kstrtou16 failed range [%d - %d]", __func__,
3118 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
3119 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
3120 ret = -EINVAL;
3121 goto exit;
3122 }
3123
3124 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
3125 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
3126 {
3127 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3128 "scan home time value %d is out of range"
3129 " (Min: %d Max: %d)", val,
3130 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
3131 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
3132 ret = -EINVAL;
3133 goto exit;
3134 }
3135
3136 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3137 "%s: Received Command to change scan home time = %d", __func__, val);
3138
3139 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
3140 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
3141 }
3142 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
3143 {
3144 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
3145 char extra[32];
3146 tANI_U8 len = 0;
3147
3148 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003149 len = scnprintf(extra, sizeof(extra), "%s %d",
3150 "GETSCANHOMETIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003151 if (copy_to_user(priv_data.buf, &extra, len + 1))
3152 {
3153 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3154 "%s: failed to copy data to user buffer", __func__);
3155 ret = -EFAULT;
3156 goto exit;
3157 }
3158 }
3159 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
3160 {
3161 tANI_U8 *value = command;
3162 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
3163
3164 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
3165 value = value + 17;
3166 /* Convert the value from ascii to integer */
3167 ret = kstrtou8(value, 10, &val);
3168 if (ret < 0)
3169 {
3170 /* If the input value is greater than max value of datatype, then also
3171 kstrtou8 fails */
3172 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3173 "%s: kstrtou8 failed range [%d - %d]", __func__,
3174 CFG_ROAM_INTRA_BAND_MIN,
3175 CFG_ROAM_INTRA_BAND_MAX);
3176 ret = -EINVAL;
3177 goto exit;
3178 }
3179
3180 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
3181 (val > CFG_ROAM_INTRA_BAND_MAX))
3182 {
3183 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3184 "intra band mode value %d is out of range"
3185 " (Min: %d Max: %d)", val,
3186 CFG_ROAM_INTRA_BAND_MIN,
3187 CFG_ROAM_INTRA_BAND_MAX);
3188 ret = -EINVAL;
3189 goto exit;
3190 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003191 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3192 "%s: Received Command to change intra band = %d", __func__, val);
3193
3194 pHddCtx->cfg_ini->nRoamIntraBand = val;
3195 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
3196 }
3197 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
3198 {
3199 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
3200 char extra[32];
3201 tANI_U8 len = 0;
3202
3203 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003204 len = scnprintf(extra, sizeof(extra), "%s %d",
3205 "GETROAMINTRABAND", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003206 if (copy_to_user(priv_data.buf, &extra, len + 1))
3207 {
3208 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3209 "%s: failed to copy data to user buffer", __func__);
3210 ret = -EFAULT;
3211 goto exit;
3212 }
3213 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003214 else if (strncmp(command, "SETSCANNPROBES", 14) == 0)
3215 {
3216 tANI_U8 *value = command;
3217 tANI_U8 nProbes = CFG_ROAM_SCAN_N_PROBES_DEFAULT;
3218
3219 /* Move pointer to ahead of SETSCANNPROBES<delimiter> */
3220 value = value + 15;
3221 /* Convert the value from ascii to integer */
3222 ret = kstrtou8(value, 10, &nProbes);
3223 if (ret < 0)
3224 {
3225 /* If the input value is greater than max value of datatype, then also
3226 kstrtou8 fails */
3227 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3228 "%s: kstrtou8 failed range [%d - %d]", __func__,
3229 CFG_ROAM_SCAN_N_PROBES_MIN,
3230 CFG_ROAM_SCAN_N_PROBES_MAX);
3231 ret = -EINVAL;
3232 goto exit;
3233 }
3234
3235 if ((nProbes < CFG_ROAM_SCAN_N_PROBES_MIN) ||
3236 (nProbes > CFG_ROAM_SCAN_N_PROBES_MAX))
3237 {
3238 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3239 "NProbes value %d is out of range"
3240 " (Min: %d Max: %d)", nProbes,
3241 CFG_ROAM_SCAN_N_PROBES_MIN,
3242 CFG_ROAM_SCAN_N_PROBES_MAX);
3243 ret = -EINVAL;
3244 goto exit;
3245 }
3246
3247 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3248 "%s: Received Command to Set nProbes = %d", __func__, nProbes);
3249
3250 pHddCtx->cfg_ini->nProbes = nProbes;
3251 sme_UpdateRoamScanNProbes((tHalHandle)(pHddCtx->hHal), nProbes);
3252 }
3253 else if (strncmp(priv_data.buf, "GETSCANNPROBES", 14) == 0)
3254 {
3255 tANI_U8 val = sme_getRoamScanNProbes((tHalHandle)(pHddCtx->hHal));
3256 char extra[32];
3257 tANI_U8 len = 0;
3258
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003259 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003260 if (copy_to_user(priv_data.buf, &extra, len + 1))
3261 {
3262 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3263 "%s: failed to copy data to user buffer", __func__);
3264 ret = -EFAULT;
3265 goto exit;
3266 }
3267 }
3268 else if (strncmp(command, "SETSCANHOMEAWAYTIME", 19) == 0)
3269 {
3270 tANI_U8 *value = command;
3271 tANI_U16 homeAwayTime = CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT;
3272
3273 /* Move pointer to ahead of SETSCANHOMEAWAYTIME<delimiter> */
3274 /* input value is in units of msec */
3275 value = value + 20;
3276 /* Convert the value from ascii to integer */
3277 ret = kstrtou16(value, 10, &homeAwayTime);
3278 if (ret < 0)
3279 {
3280 /* If the input value is greater than max value of datatype, then also
3281 kstrtou8 fails */
3282 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3283 "%s: kstrtou8 failed range [%d - %d]", __func__,
3284 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
3285 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
3286 ret = -EINVAL;
3287 goto exit;
3288 }
3289
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003290 if ((homeAwayTime < CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN) ||
3291 (homeAwayTime > CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX))
3292 {
3293 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3294 "homeAwayTime value %d is out of range"
3295 " (Min: %d Max: %d)", homeAwayTime,
3296 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
3297 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
3298 ret = -EINVAL;
3299 goto exit;
3300 }
3301
3302 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3303 "%s: Received Command to Set scan away time = %d", __func__, homeAwayTime);
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07003304 if (pHddCtx->cfg_ini->nRoamScanHomeAwayTime != homeAwayTime)
3305 {
3306 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
3307 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_TRUE);
3308 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003309 }
3310 else if (strncmp(priv_data.buf, "GETSCANHOMEAWAYTIME", 19) == 0)
3311 {
3312 tANI_U16 val = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
3313 char extra[32];
3314 tANI_U8 len = 0;
3315
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003316 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003317 if (copy_to_user(priv_data.buf, &extra, len + 1))
3318 {
3319 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3320 "%s: failed to copy data to user buffer", __func__);
3321 ret = -EFAULT;
3322 goto exit;
3323 }
3324 }
3325 else if (strncmp(command, "REASSOC", 7) == 0)
3326 {
3327 tANI_U8 *value = command;
3328 tANI_U8 channel = 0;
3329 tSirMacAddr targetApBssid;
3330 eHalStatus status = eHAL_STATUS_SUCCESS;
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07003331#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
3332 tCsrHandoffRequest handoffInfo;
3333#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003334 hdd_station_ctx_t *pHddStaCtx = NULL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003335 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3336
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003337 /* if not associated, no need to proceed with reassoc */
3338 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3339 {
3340 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
3341 ret = -EINVAL;
3342 goto exit;
3343 }
3344
3345 status = hdd_parse_reassoc_command_data(value, targetApBssid, &channel);
3346 if (eHAL_STATUS_SUCCESS != status)
3347 {
3348 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3349 "%s: Failed to parse reassoc command data", __func__);
3350 ret = -EINVAL;
3351 goto exit;
3352 }
3353
3354 /* if the target bssid is same as currently associated AP,
3355 then no need to proceed with reassoc */
3356 if (VOS_TRUE == vos_mem_compare(targetApBssid,
3357 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
3358 {
3359 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Reassoc BSSID is same as currently associated AP bssid",__func__);
3360 ret = -EINVAL;
3361 goto exit;
3362 }
3363
3364 /* Check channel number is a valid channel number */
3365 if(VOS_STATUS_SUCCESS !=
3366 wlan_hdd_validate_operation_channel(pAdapter, channel))
3367 {
3368 hddLog(VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08003369 "%s: Invalid Channel [%d]", __func__, channel);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003370 return -EINVAL;
3371 }
3372
3373 /* Proceed with reassoc */
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07003374#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
3375 handoffInfo.channel = channel;
3376 vos_mem_copy(handoffInfo.bssid, targetApBssid, sizeof(tSirMacAddr));
3377 sme_HandoffRequest(pHddCtx->hHal, &handoffInfo);
3378#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003379 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07003380 else if (strncmp(command, "SETWESMODE", 10) == 0)
3381 {
3382 tANI_U8 *value = command;
3383 tANI_BOOLEAN wesMode = CFG_ENABLE_WES_MODE_NAME_DEFAULT;
3384
3385 /* Move pointer to ahead of SETWESMODE<delimiter> */
3386 value = value + 11;
3387 /* Convert the value from ascii to integer */
3388 ret = kstrtou8(value, 10, &wesMode);
3389 if (ret < 0)
3390 {
3391 /* If the input value is greater than max value of datatype, then also
3392 kstrtou8 fails */
3393 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3394 "%s: kstrtou8 failed range [%d - %d]", __func__,
3395 CFG_ENABLE_WES_MODE_NAME_MIN,
3396 CFG_ENABLE_WES_MODE_NAME_MAX);
3397 ret = -EINVAL;
3398 goto exit;
3399 }
3400
3401 if ((wesMode < CFG_ENABLE_WES_MODE_NAME_MIN) ||
3402 (wesMode > CFG_ENABLE_WES_MODE_NAME_MAX))
3403 {
3404 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3405 "WES Mode value %d is out of range"
3406 " (Min: %d Max: %d)", wesMode,
3407 CFG_ENABLE_WES_MODE_NAME_MIN,
3408 CFG_ENABLE_WES_MODE_NAME_MAX);
3409 ret = -EINVAL;
3410 goto exit;
3411 }
3412 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3413 "%s: Received Command to Set WES Mode rssi diff = %d", __func__, wesMode);
3414
3415 pHddCtx->cfg_ini->isWESModeEnabled = wesMode;
3416 sme_UpdateWESMode((tHalHandle)(pHddCtx->hHal), wesMode);
3417 }
3418 else if (strncmp(priv_data.buf, "GETWESMODE", 10) == 0)
3419 {
3420 tANI_BOOLEAN wesMode = sme_GetWESMode((tHalHandle)(pHddCtx->hHal));
3421 char extra[32];
3422 tANI_U8 len = 0;
3423
Arif Hussain826d9412013-11-12 16:44:54 -08003424 len = scnprintf(extra, sizeof(extra), "%s %d", command, wesMode);
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07003425 if (copy_to_user(priv_data.buf, &extra, len + 1))
3426 {
3427 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3428 "%s: failed to copy data to user buffer", __func__);
3429 ret = -EFAULT;
3430 goto exit;
3431 }
3432 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003433#endif /* WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_ESE || FEATURE_WLAN_LFR */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003434#ifdef FEATURE_WLAN_LFR
3435 else if (strncmp(command, "SETFASTROAM", 11) == 0)
3436 {
3437 tANI_U8 *value = command;
3438 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
3439
3440 /* Move pointer to ahead of SETFASTROAM<delimiter> */
3441 value = value + 12;
3442 /* Convert the value from ascii to integer */
3443 ret = kstrtou8(value, 10, &lfrMode);
3444 if (ret < 0)
3445 {
3446 /* If the input value is greater than max value of datatype, then also
3447 kstrtou8 fails */
3448 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3449 "%s: kstrtou8 failed range [%d - %d]", __func__,
3450 CFG_LFR_FEATURE_ENABLED_MIN,
3451 CFG_LFR_FEATURE_ENABLED_MAX);
3452 ret = -EINVAL;
3453 goto exit;
3454 }
3455
3456 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
3457 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
3458 {
3459 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3460 "lfr mode value %d is out of range"
3461 " (Min: %d Max: %d)", lfrMode,
3462 CFG_LFR_FEATURE_ENABLED_MIN,
3463 CFG_LFR_FEATURE_ENABLED_MAX);
3464 ret = -EINVAL;
3465 goto exit;
3466 }
3467
3468 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3469 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
3470
3471 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
3472 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
3473 }
3474#endif
3475#ifdef WLAN_FEATURE_VOWIFI_11R
3476 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
3477 {
3478 tANI_U8 *value = command;
3479 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
3480
3481 /* Move pointer to ahead of SETFASTROAM<delimiter> */
3482 value = value + 18;
3483 /* Convert the value from ascii to integer */
3484 ret = kstrtou8(value, 10, &ft);
3485 if (ret < 0)
3486 {
3487 /* If the input value is greater than max value of datatype, then also
3488 kstrtou8 fails */
3489 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3490 "%s: kstrtou8 failed range [%d - %d]", __func__,
3491 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
3492 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
3493 ret = -EINVAL;
3494 goto exit;
3495 }
3496
3497 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
3498 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
3499 {
3500 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3501 "ft mode value %d is out of range"
3502 " (Min: %d Max: %d)", ft,
3503 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
3504 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
3505 ret = -EINVAL;
3506 goto exit;
3507 }
3508
3509 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3510 "%s: Received Command to change ft mode = %d", __func__, ft);
3511
3512 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
3513 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
3514 }
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05303515
3516 else if (strncmp(command, "FASTREASSOC", 11) == 0)
3517 {
3518 tANI_U8 *value = command;
Padma, Santhosh Kumarf4582d32014-11-06 19:24:51 +05303519 tANI_U8 channel = 0;
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05303520 tSirMacAddr targetApBssid;
3521 tANI_U8 trigger = 0;
3522 eHalStatus status = eHAL_STATUS_SUCCESS;
Padma, Santhosh Kumarb980a6f2014-11-06 19:07:24 +05303523 tHalHandle hHal;
3524 v_U32_t roamId = 0;
3525 tCsrRoamModifyProfileFields modProfileFields;
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05303526 hdd_station_ctx_t *pHddStaCtx = NULL;
3527 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Padma, Santhosh Kumarb980a6f2014-11-06 19:07:24 +05303528 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05303529
3530 /* if not associated, no need to proceed with reassoc */
3531 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3532 {
3533 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
3534 ret = -EINVAL;
3535 goto exit;
3536 }
3537
Padma, Santhosh Kumarf4582d32014-11-06 19:24:51 +05303538 status = hdd_parse_reassoc_command_data(value, targetApBssid, &channel);
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05303539 if (eHAL_STATUS_SUCCESS != status)
3540 {
3541 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3542 "%s: Failed to parse reassoc command data", __func__);
3543 ret = -EINVAL;
3544 goto exit;
3545 }
3546
3547 /* if the target bssid is same as currently associated AP,
Padma, Santhosh Kumarb980a6f2014-11-06 19:07:24 +05303548 issue reassoc to same AP */
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05303549 if (VOS_TRUE == vos_mem_compare(targetApBssid,
3550 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
3551 {
3552 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3553 "%s:11r Reassoc BSSID is same as currently associated AP bssid",
3554 __func__);
Padma, Santhosh Kumarb980a6f2014-11-06 19:07:24 +05303555 sme_GetModifyProfileFields(hHal, pAdapter->sessionId,
3556 &modProfileFields);
3557 sme_RoamReassoc(hHal, pAdapter->sessionId,
3558 NULL, modProfileFields, &roamId, 1);
3559 return 0;
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05303560 }
Padma, Santhosh Kumar0fa809b2014-11-13 14:56:56 +05303561
3562 /* Check channel number is a valid channel number */
3563 if(VOS_STATUS_SUCCESS !=
3564 wlan_hdd_validate_operation_channel(pAdapter, channel))
3565 {
3566 hddLog(VOS_TRACE_LEVEL_ERROR,
3567 "%s: Invalid Channel [%d]", __func__, channel);
3568 return -EINVAL;
3569 }
3570
Padma, Santhosh Kumarf4582d32014-11-06 19:24:51 +05303571 trigger = eSME_ROAM_TRIGGER_SCAN;
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05303572
3573 /* Proceed with scan/roam */
3574 smeIssueFastRoamNeighborAPEvent(WLAN_HDD_GET_HAL_CTX(pAdapter),
3575 &targetApBssid[0],
Mukul Sharma9e4e0f92015-02-13 18:45:20 +05303576 (tSmeFastRoamTrigger)(trigger),
3577 channel);
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05303578 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003579#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003580#ifdef FEATURE_WLAN_ESE
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003581 else if (strncmp(command, "SETCCXMODE", 10) == 0)
3582 {
3583 tANI_U8 *value = command;
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003584 tANI_U8 eseMode = CFG_ESE_FEATURE_ENABLED_DEFAULT;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003585
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003586 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003587 then this operation is not permitted (return FAILURE) */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003588 if (sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003589 hdd_is_okc_mode_enabled(pHddCtx) &&
3590 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
3591 {
3592 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003593 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003594 " hence this operation is not permitted!", __func__);
3595 ret = -EPERM;
3596 goto exit;
3597 }
3598
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003599 /* Move pointer to ahead of SETCCXMODE<delimiter> */
3600 value = value + 11;
3601 /* Convert the value from ascii to integer */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003602 ret = kstrtou8(value, 10, &eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003603 if (ret < 0)
3604 {
3605 /* If the input value is greater than max value of datatype, then also
3606 kstrtou8 fails */
3607 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3608 "%s: kstrtou8 failed range [%d - %d]", __func__,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003609 CFG_ESE_FEATURE_ENABLED_MIN,
3610 CFG_ESE_FEATURE_ENABLED_MAX);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003611 ret = -EINVAL;
3612 goto exit;
3613 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003614 if ((eseMode < CFG_ESE_FEATURE_ENABLED_MIN) ||
3615 (eseMode > CFG_ESE_FEATURE_ENABLED_MAX))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003616 {
3617 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003618 "Ese mode value %d is out of range"
3619 " (Min: %d Max: %d)", eseMode,
3620 CFG_ESE_FEATURE_ENABLED_MIN,
3621 CFG_ESE_FEATURE_ENABLED_MAX);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003622 ret = -EINVAL;
3623 goto exit;
3624 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003625 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003626 "%s: Received Command to change ese mode = %d", __func__, eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003627
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003628 pHddCtx->cfg_ini->isEseIniFeatureEnabled = eseMode;
3629 sme_UpdateIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal), eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003630 }
3631#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003632 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
3633 {
3634 tANI_U8 *value = command;
3635 tANI_BOOLEAN roamScanControl = 0;
3636
3637 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
3638 value = value + 19;
3639 /* Convert the value from ascii to integer */
3640 ret = kstrtou8(value, 10, &roamScanControl);
3641 if (ret < 0)
3642 {
3643 /* If the input value is greater than max value of datatype, then also
3644 kstrtou8 fails */
3645 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3646 "%s: kstrtou8 failed ", __func__);
3647 ret = -EINVAL;
3648 goto exit;
3649 }
3650
3651 if (0 != roamScanControl)
3652 {
3653 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3654 "roam scan control invalid value = %d",
3655 roamScanControl);
3656 ret = -EINVAL;
3657 goto exit;
3658 }
3659 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3660 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
3661
3662 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
3663 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003664#ifdef FEATURE_WLAN_OKC
3665 else if (strncmp(command, "SETOKCMODE", 10) == 0)
3666 {
3667 tANI_U8 *value = command;
3668 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
3669
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003670 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003671 then this operation is not permitted (return FAILURE) */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003672 if (sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003673 hdd_is_okc_mode_enabled(pHddCtx) &&
3674 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
3675 {
3676 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003677 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003678 " hence this operation is not permitted!", __func__);
3679 ret = -EPERM;
3680 goto exit;
3681 }
3682
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003683 /* Move pointer to ahead of SETOKCMODE<delimiter> */
3684 value = value + 11;
3685 /* Convert the value from ascii to integer */
3686 ret = kstrtou8(value, 10, &okcMode);
3687 if (ret < 0)
3688 {
3689 /* If the input value is greater than max value of datatype, then also
3690 kstrtou8 fails */
3691 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3692 "%s: kstrtou8 failed range [%d - %d]", __func__,
3693 CFG_OKC_FEATURE_ENABLED_MIN,
3694 CFG_OKC_FEATURE_ENABLED_MAX);
3695 ret = -EINVAL;
3696 goto exit;
3697 }
3698
3699 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
3700 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
3701 {
3702 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3703 "Okc mode value %d is out of range"
3704 " (Min: %d Max: %d)", okcMode,
3705 CFG_OKC_FEATURE_ENABLED_MIN,
3706 CFG_OKC_FEATURE_ENABLED_MAX);
3707 ret = -EINVAL;
3708 goto exit;
3709 }
3710
3711 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3712 "%s: Received Command to change okc mode = %d", __func__, okcMode);
3713
3714 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
3715 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07003716#endif /* FEATURE_WLAN_OKC */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003717 else if (strncmp(priv_data.buf, "GETROAMSCANCONTROL", 18) == 0)
3718 {
3719 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
3720 char extra[32];
3721 tANI_U8 len = 0;
3722
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003723 len = scnprintf(extra, sizeof(extra), "%s %d",
3724 command, roamScanControl);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003725 if (copy_to_user(priv_data.buf, &extra, len + 1))
3726 {
3727 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3728 "%s: failed to copy data to user buffer", __func__);
3729 ret = -EFAULT;
3730 goto exit;
3731 }
3732 }
Gopichand Nakkala227c7f32013-06-26 22:44:57 +05303733#ifdef WLAN_FEATURE_PACKET_FILTERING
3734 else if (strncmp(command, "ENABLE_PKTFILTER_IPV6", 21) == 0)
3735 {
3736 tANI_U8 filterType = 0;
3737 tANI_U8 *value = command;
3738
3739 /* Move pointer to ahead of ENABLE_PKTFILTER_IPV6<delimiter> */
3740 value = value + 22;
3741
3742 /* Convert the value from ascii to integer */
3743 ret = kstrtou8(value, 10, &filterType);
3744 if (ret < 0)
3745 {
3746 /* If the input value is greater than max value of datatype,
3747 * then also kstrtou8 fails
3748 */
3749 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3750 "%s: kstrtou8 failed range ", __func__);
3751 ret = -EINVAL;
3752 goto exit;
3753 }
3754
3755 if (filterType != 0 && filterType != 1)
3756 {
3757 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3758 "%s: Accepted Values are 0 and 1 ", __func__);
3759 ret = -EINVAL;
3760 goto exit;
3761 }
3762 wlan_hdd_setIPv6Filter(WLAN_HDD_GET_CTX(pAdapter), filterType,
3763 pAdapter->sessionId);
3764 }
3765#endif
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303766 else if (strncmp(command, "BTCOEXMODE", 10) == 0 )
3767 {
Kiet Lamad161252014-07-22 11:23:32 -07003768 char *dhcpPhase;
Satyanarayana Dash1faea4f2014-09-22 16:21:04 +05303769 int ret;
3770
Kiet Lamad161252014-07-22 11:23:32 -07003771 dhcpPhase = command + 11;
3772 if ('1' == *dhcpPhase)
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303773 {
Deepthi Gowribfd17132014-11-14 17:59:04 +05303774 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Kiet Lamad161252014-07-22 11:23:32 -07003775 FL("send DHCP START indication"));
c_hpothu9b781ba2013-12-30 20:57:45 +05303776
3777 pHddCtx->btCoexModeSet = TRUE;
Kiet Lamad161252014-07-22 11:23:32 -07003778
Satyanarayana Dash1faea4f2014-09-22 16:21:04 +05303779 ret = wlan_hdd_scan_abort(pAdapter);
3780 if (ret < 0)
3781 {
3782 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3783 FL("failed to abort existing scan %d"), ret);
3784 }
3785
Kiet Lamad161252014-07-22 11:23:32 -07003786 sme_DHCPStartInd(pHddCtx->hHal, pAdapter->device_mode,
3787 pAdapter->sessionId);
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303788 }
Kiet Lamad161252014-07-22 11:23:32 -07003789 else if ('2' == *dhcpPhase)
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303790 {
Deepthi Gowribfd17132014-11-14 17:59:04 +05303791 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Kiet Lamad161252014-07-22 11:23:32 -07003792 FL("send DHCP STOP indication"));
c_hpothu9b781ba2013-12-30 20:57:45 +05303793
3794 pHddCtx->btCoexModeSet = FALSE;
Kiet Lamad161252014-07-22 11:23:32 -07003795
3796 sme_DHCPStopInd(pHddCtx->hHal, pAdapter->device_mode,
3797 pAdapter->sessionId);
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303798 }
3799 }
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07003800 else if (strncmp(command, "SCAN-ACTIVE", 11) == 0)
3801 {
c_hpothudbefd3e2014-04-28 15:59:47 +05303802 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3803 FL("making default scan to ACTIVE"));
3804 pHddCtx->scan_info.scan_mode = eSIR_ACTIVE_SCAN;
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07003805 }
3806 else if (strncmp(command, "SCAN-PASSIVE", 12) == 0)
3807 {
c_hpothudbefd3e2014-04-28 15:59:47 +05303808 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3809 FL("making default scan to PASSIVE"));
3810 pHddCtx->scan_info.scan_mode = eSIR_PASSIVE_SCAN;
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07003811 }
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303812 else if (strncmp(command, "GETDWELLTIME", 12) == 0)
3813 {
3814 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3815 char extra[32];
3816 tANI_U8 len = 0;
3817
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05303818 memset(extra, 0, sizeof(extra));
3819 ret = hdd_get_dwell_time(pCfg, command, extra, sizeof(extra), &len);
3820 if (ret != 0 || copy_to_user(priv_data.buf, &extra, len + 1))
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303821 {
3822 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3823 "%s: failed to copy data to user buffer", __func__);
3824 ret = -EFAULT;
3825 goto exit;
3826 }
3827 ret = len;
3828 }
3829 else if (strncmp(command, "SETDWELLTIME", 12) == 0)
3830 {
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05303831 ret = hdd_set_dwell_time(pAdapter, command);
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303832 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07003833 else if ( strncasecmp(command, "MIRACAST", 8) == 0 )
3834 {
3835 tANI_U8 filterType = 0;
3836 tANI_U8 *value;
3837 value = command + 9;
3838
3839 /* Convert the value from ascii to integer */
3840 ret = kstrtou8(value, 10, &filterType);
3841 if (ret < 0)
3842 {
3843 /* If the input value is greater than max value of datatype,
3844 * then also kstrtou8 fails
3845 */
3846 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3847 "%s: kstrtou8 failed range ", __func__);
3848 ret = -EINVAL;
3849 goto exit;
3850 }
3851 if ((filterType < WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL ) ||
3852 (filterType > WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL))
3853 {
3854 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3855 "%s: Accepted Values are 0 to 2. 0-Disabled, 1-Source,"
3856 " 2-Sink ", __func__);
3857 ret = -EINVAL;
3858 goto exit;
3859 }
3860 //Filtertype value should be either 0-Disabled, 1-Source, 2-sink
3861 pHddCtx->drvr_miracast = filterType;
Kaushik, Sushant96122442014-10-21 16:40:18 +05303862 pScanInfo = &pHddCtx->scan_info;
3863 if (filterType && pScanInfo != NULL &&
3864 pHddCtx->scan_info.mScanPending)
3865 {
3866 /*Miracast Session started. Abort Scan */
3867 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3868 "%s, Aborting Scan For Miracast",__func__);
3869 hdd_abort_mac_scan(pHddCtx, pScanInfo->sessionId,
3870 eCSR_SCAN_ABORT_DEFAULT);
3871 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07003872 hdd_tx_rx_pkt_cnt_stat_timer_handler(pHddCtx);
Ganesh Kondabattini8f6e3b32014-08-25 16:07:54 +05303873 sme_SetMiracastMode(pHddCtx->hHal, pHddCtx->drvr_miracast);
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07003874 }
Leo Chang614d2072013-08-22 14:59:44 -07003875 else if (strncmp(command, "SETMCRATE", 9) == 0)
3876 {
Leo Chang614d2072013-08-22 14:59:44 -07003877 tANI_U8 *value = command;
3878 int targetRate;
Leo Chang1f98cbd2013-10-17 15:03:52 -07003879 tSirRateUpdateInd *rateUpdate;
3880 eHalStatus status;
Leo Chang614d2072013-08-22 14:59:44 -07003881
3882 /* Only valid for SAP mode */
3883 if (WLAN_HDD_SOFTAP != pAdapter->device_mode)
3884 {
3885 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3886 "%s: SAP mode is not running", __func__);
3887 ret = -EFAULT;
3888 goto exit;
3889 }
3890
3891 /* Move pointer to ahead of SETMCRATE<delimiter> */
3892 /* input value is in units of hundred kbps */
3893 value = value + 10;
3894 /* Convert the value from ascii to integer, decimal base */
3895 ret = kstrtouint(value, 10, &targetRate);
3896
Leo Chang1f98cbd2013-10-17 15:03:52 -07003897 rateUpdate = (tSirRateUpdateInd *)vos_mem_malloc(sizeof(tSirRateUpdateInd));
3898 if (NULL == rateUpdate)
Leo Chang614d2072013-08-22 14:59:44 -07003899 {
Leo Chang1f98cbd2013-10-17 15:03:52 -07003900 hddLog(VOS_TRACE_LEVEL_ERROR,
3901 "%s: SETMCRATE indication alloc fail", __func__);
3902 ret = -EFAULT;
3903 goto exit;
3904 }
3905 vos_mem_zero(rateUpdate, sizeof(tSirRateUpdateInd ));
3906
3907 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3908 "MC Target rate %d", targetRate);
3909 /* Ignore unicast */
3910 rateUpdate->ucastDataRate = -1;
3911 rateUpdate->mcastDataRate24GHz = targetRate;
3912 rateUpdate->mcastDataRate5GHz = targetRate;
3913 rateUpdate->mcastDataRate24GHzTxFlag = 0;
3914 rateUpdate->mcastDataRate5GHzTxFlag = 0;
3915 status = sme_SendRateUpdateInd(pHddCtx->hHal, rateUpdate);
3916 if (eHAL_STATUS_SUCCESS != status)
3917 {
3918 hddLog(VOS_TRACE_LEVEL_ERROR,
3919 "%s: SET_MC_RATE failed", __func__);
3920 vos_mem_free(rateUpdate);
3921 ret = -EFAULT;
3922 goto exit;
Leo Chang614d2072013-08-22 14:59:44 -07003923 }
3924 }
Rajeev79dbe4c2013-10-05 11:03:42 +05303925#ifdef FEATURE_WLAN_BATCH_SCAN
Rajeev Kumar8b373292014-01-08 20:36:55 -08003926 else if (strncmp(command, "WLS_BATCHING", 12) == 0)
Rajeev79dbe4c2013-10-05 11:03:42 +05303927 {
Rajeev Kumar8b373292014-01-08 20:36:55 -08003928 ret = hdd_handle_batch_scan_ioctl(pAdapter, &priv_data, command);
Rajeev79dbe4c2013-10-05 11:03:42 +05303929 }
3930#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003931#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003932 else if (strncmp(command, "SETCCXROAMSCANCHANNELS", 22) == 0)
3933 {
3934 tANI_U8 *value = command;
3935 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
3936 tANI_U8 numChannels = 0;
3937 eHalStatus status = eHAL_STATUS_SUCCESS;
3938
3939 status = hdd_parse_channellist(value, ChannelList, &numChannels);
3940 if (eHAL_STATUS_SUCCESS != status)
3941 {
3942 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3943 "%s: Failed to parse channel list information", __func__);
3944 ret = -EINVAL;
3945 goto exit;
3946 }
3947
3948 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
3949 {
3950 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3951 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
3952 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
3953 ret = -EINVAL;
3954 goto exit;
3955 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003956 status = sme_SetEseRoamScanChannelList((tHalHandle)(pHddCtx->hHal),
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003957 ChannelList,
3958 numChannels);
3959 if (eHAL_STATUS_SUCCESS != status)
3960 {
3961 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3962 "%s: Failed to update channel list information", __func__);
3963 ret = -EINVAL;
3964 goto exit;
3965 }
3966 }
3967 else if (strncmp(command, "GETTSMSTATS", 11) == 0)
3968 {
3969 tANI_U8 *value = command;
3970 char extra[128] = {0};
3971 int len = 0;
3972 tANI_U8 tid = 0;
3973 hdd_station_ctx_t *pHddStaCtx = NULL;
3974 tAniTrafStrmMetrics tsmMetrics;
3975 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3976
3977 /* if not associated, return error */
3978 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3979 {
3980 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:Not associated!",__func__);
3981 ret = -EINVAL;
3982 goto exit;
3983 }
3984
3985 /* Move pointer to ahead of GETTSMSTATS<delimiter> */
3986 value = value + 12;
3987 /* Convert the value from ascii to integer */
3988 ret = kstrtou8(value, 10, &tid);
3989 if (ret < 0)
3990 {
3991 /* If the input value is greater than max value of datatype, then also
3992 kstrtou8 fails */
3993 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3994 "%s: kstrtou8 failed range [%d - %d]", __func__,
3995 TID_MIN_VALUE,
3996 TID_MAX_VALUE);
3997 ret = -EINVAL;
3998 goto exit;
3999 }
4000
4001 if ((tid < TID_MIN_VALUE) || (tid > TID_MAX_VALUE))
4002 {
4003 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4004 "tid value %d is out of range"
4005 " (Min: %d Max: %d)", tid,
4006 TID_MIN_VALUE,
4007 TID_MAX_VALUE);
4008 ret = -EINVAL;
4009 goto exit;
4010 }
4011
4012 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4013 "%s: Received Command to get tsm stats tid = %d", __func__, tid);
4014
4015 if (VOS_STATUS_SUCCESS != hdd_get_tsm_stats(pAdapter, tid, &tsmMetrics))
4016 {
4017 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4018 "%s: failed to get tsm stats", __func__);
4019 ret = -EFAULT;
4020 goto exit;
4021 }
4022
4023 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4024 "UplinkPktQueueDly(%d)\n"
4025 "UplinkPktQueueDlyHist[0](%d)\n"
4026 "UplinkPktQueueDlyHist[1](%d)\n"
4027 "UplinkPktQueueDlyHist[2](%d)\n"
4028 "UplinkPktQueueDlyHist[3](%d)\n"
Arun Kumar Khandavallie8768212014-02-17 16:43:34 +05304029 "UplinkPktTxDly(%u)\n"
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004030 "UplinkPktLoss(%d)\n"
4031 "UplinkPktCount(%d)\n"
4032 "RoamingCount(%d)\n"
4033 "RoamingDly(%d)", tsmMetrics.UplinkPktQueueDly,
4034 tsmMetrics.UplinkPktQueueDlyHist[0],
4035 tsmMetrics.UplinkPktQueueDlyHist[1],
4036 tsmMetrics.UplinkPktQueueDlyHist[2],
4037 tsmMetrics.UplinkPktQueueDlyHist[3],
4038 tsmMetrics.UplinkPktTxDly, tsmMetrics.UplinkPktLoss,
4039 tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount, tsmMetrics.RoamingDly);
4040
4041 /* Output TSM stats is of the format
4042 GETTSMSTATS [PktQueueDly] [PktQueueDlyHist[0]]:[PktQueueDlyHist[1]] ...[RoamingDly]
4043 eg., GETTSMSTATS 10 1:0:0:161 20 1 17 8 39800 */
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004044 len = scnprintf(extra, sizeof(extra), "%s %d %d:%d:%d:%d %u %d %d %d %d", command,
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004045 tsmMetrics.UplinkPktQueueDly, tsmMetrics.UplinkPktQueueDlyHist[0],
4046 tsmMetrics.UplinkPktQueueDlyHist[1], tsmMetrics.UplinkPktQueueDlyHist[2],
4047 tsmMetrics.UplinkPktQueueDlyHist[3], tsmMetrics.UplinkPktTxDly,
4048 tsmMetrics.UplinkPktLoss, tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount,
4049 tsmMetrics.RoamingDly);
4050
4051 if (copy_to_user(priv_data.buf, &extra, len + 1))
4052 {
4053 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4054 "%s: failed to copy data to user buffer", __func__);
4055 ret = -EFAULT;
4056 goto exit;
4057 }
4058 }
4059 else if (strncmp(command, "SETCCKMIE", 9) == 0)
4060 {
4061 tANI_U8 *value = command;
4062 tANI_U8 *cckmIe = NULL;
4063 tANI_U8 cckmIeLen = 0;
4064 eHalStatus status = eHAL_STATUS_SUCCESS;
4065
4066 status = hdd_parse_get_cckm_ie(value, &cckmIe, &cckmIeLen);
4067 if (eHAL_STATUS_SUCCESS != status)
4068 {
4069 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4070 "%s: Failed to parse cckm ie data", __func__);
4071 ret = -EINVAL;
4072 goto exit;
4073 }
4074
4075 if (cckmIeLen > DOT11F_IE_RSN_MAX_LEN)
4076 {
4077 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4078 "%s: CCKM Ie input length is more than max[%d]", __func__,
4079 DOT11F_IE_RSN_MAX_LEN);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08004080 vos_mem_free(cckmIe);
4081 cckmIe = NULL;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004082 ret = -EINVAL;
4083 goto exit;
4084 }
4085 sme_SetCCKMIe((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, cckmIe, cckmIeLen);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08004086 vos_mem_free(cckmIe);
4087 cckmIe = NULL;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004088 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004089 else if (strncmp(command, "CCXBEACONREQ", 12) == 0)
4090 {
4091 tANI_U8 *value = command;
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004092 tCsrEseBeaconReq eseBcnReq;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004093 eHalStatus status = eHAL_STATUS_SUCCESS;
Srinivas Girigowda0c6d7fe2014-05-28 18:18:10 -07004094
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004095 status = hdd_parse_ese_beacon_req(value, &eseBcnReq);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004096 if (eHAL_STATUS_SUCCESS != status)
4097 {
4098 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004099 "%s: Failed to parse ese beacon req", __func__);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004100 ret = -EINVAL;
4101 goto exit;
4102 }
Srinivas Girigowda0c6d7fe2014-05-28 18:18:10 -07004103 if (!hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))) {
4104 hddLog(VOS_TRACE_LEVEL_INFO, FL("Not associated"));
4105 hdd_indicateEseBcnReportNoResults (pAdapter,
4106 eseBcnReq.bcnReq[0].measurementToken,
4107 0x02, //BIT(1) set for measurement done
4108 0); // no BSS
4109 goto exit;
4110 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004111
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004112 status = sme_SetEseBeaconRequest((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, &eseBcnReq);
4113 if (eHAL_STATUS_SUCCESS != status)
4114 {
4115 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4116 "%s: sme_SetEseBeaconRequest failed (%d)", __func__, status);
4117 ret = -EINVAL;
4118 goto exit;
4119 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004120 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004121#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
c_hpothu92367912014-05-01 15:18:17 +05304122 else if (strncmp(command, "GETBCNMISSRATE", 14) == 0)
4123 {
4124 eHalStatus status;
4125 char buf[32], len;
4126 long waitRet;
4127 bcnMissRateContext_t getBcnMissRateCtx;
4128
4129 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4130
4131 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
4132 {
4133 hddLog(VOS_TRACE_LEVEL_WARN,
4134 FL("GETBCNMISSRATE: STA is not in connected state"));
4135 ret = -1;
4136 goto exit;
4137 }
4138
4139 init_completion(&(getBcnMissRateCtx.completion));
4140 getBcnMissRateCtx.magic = BCN_MISS_RATE_CONTEXT_MAGIC;
4141
4142 status = sme_getBcnMissRate((tHalHandle)(pHddCtx->hHal),
4143 pAdapter->sessionId,
4144 (void *)getBcnMissRateCB,
4145 (void *)(&getBcnMissRateCtx));
4146 if( eHAL_STATUS_SUCCESS != status)
4147 {
4148 hddLog(VOS_TRACE_LEVEL_INFO,
4149 FL("GETBCNMISSRATE: fail to post WDA cmd"));
4150 ret = -EINVAL;
4151 goto exit;
4152 }
4153
4154 waitRet = wait_for_completion_interruptible_timeout
4155 (&getBcnMissRateCtx.completion, BCN_MISS_RATE_TIME);
4156 if(waitRet <= 0)
4157 {
4158 hddLog(VOS_TRACE_LEVEL_ERROR,
4159 FL("failed to wait on bcnMissRateComp %d"), ret);
4160
4161 //Make magic number to zero so that callback is not called.
4162 spin_lock(&hdd_context_lock);
4163 getBcnMissRateCtx.magic = 0x0;
4164 spin_unlock(&hdd_context_lock);
4165 ret = -EINVAL;
4166 goto exit;
4167 }
4168
4169 hddLog(VOS_TRACE_LEVEL_INFO,
4170 FL("GETBCNMISSRATE: bcnMissRate: %d"), gbcnMissRate);
4171
4172 len = snprintf(buf, sizeof(buf), "GETBCNMISSRATE %d", gbcnMissRate);
4173 if (copy_to_user(priv_data.buf, &buf, len + 1))
4174 {
4175 hddLog(VOS_TRACE_LEVEL_ERROR,
4176 "%s: failed to copy data to user buffer", __func__);
4177 ret = -EFAULT;
4178 goto exit;
4179 }
4180 ret = len;
4181 }
Atul Mittal87ec2422014-09-24 13:12:50 +05304182#ifdef FEATURE_WLAN_TDLS
4183 else if (strncmp(command, "TDLSSECONDARYCHANNELOFFSET", 26) == 0) {
4184 tANI_U8 *value = command;
4185 int set_value;
4186 /* Move pointer to ahead of TDLSOFFCH*/
4187 value += 26;
4188 sscanf(value, "%d", &set_value);
4189 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4190 "%s: Tdls offchannel offset:%d",
4191 __func__, set_value);
4192 ret = iw_set_tdlssecoffchanneloffset(pHddCtx, set_value);
4193 if (ret < 0)
4194 {
4195 ret = -EINVAL;
4196 goto exit;
4197 }
4198
4199 } else if (strncmp(command, "TDLSOFFCHANNELMODE", 18) == 0) {
4200 tANI_U8 *value = command;
4201 int set_value;
4202 /* Move pointer to ahead of tdlsoffchnmode*/
4203 value += 18;
4204 sscanf(value, "%d", &set_value);
4205 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4206 "%s: Tdls offchannel mode:%d",
4207 __func__, set_value);
4208 ret = iw_set_tdlsoffchannelmode(pAdapter, set_value);
4209 if (ret < 0)
4210 {
4211 ret = -EINVAL;
4212 goto exit;
4213 }
4214 } else if (strncmp(command, "TDLSOFFCHANNEL", 14) == 0) {
4215 tANI_U8 *value = command;
4216 int set_value;
4217 /* Move pointer to ahead of TDLSOFFCH*/
4218 value += 14;
4219 sscanf(value, "%d", &set_value);
4220 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4221 "%s: Tdls offchannel num: %d",
4222 __func__, set_value);
4223 ret = iw_set_tdlsoffchannel(pHddCtx, set_value);
4224 if (ret < 0)
4225 {
4226 ret = -EINVAL;
4227 goto exit;
4228 }
4229 }
4230#endif
Satyanarayana Dash72806012014-12-02 14:30:08 +05304231 else if (strncmp(command, "GETFWSTATS", 10) == 0)
4232 {
4233 eHalStatus status;
4234 char *buf = NULL;
4235 char len;
4236 long waitRet;
4237 fwStatsContext_t fwStatsCtx;
Abhishek Singh08aa7762014-12-16 13:59:03 +05304238 tSirFwStatsResult *fwStatsRsp = &(pAdapter->fwStatsRsp);
Satyanarayana Dash72806012014-12-02 14:30:08 +05304239 tANI_U8 *ptr = command;
4240 int stats = *(ptr + 11) - '0';
4241
4242 hddLog(VOS_TRACE_LEVEL_INFO, FL("stats = %d "),stats);
4243 if (!IS_FEATURE_FW_STATS_ENABLE)
4244 {
4245 hddLog(VOS_TRACE_LEVEL_INFO,
4246 FL("Get Firmware stats feature not supported"));
4247 ret = -EINVAL;
4248 goto exit;
4249 }
4250
4251 if (FW_STATS_MAX <= stats || 0 >= stats)
4252 {
4253 hddLog(VOS_TRACE_LEVEL_INFO,
4254 FL(" stats %d not supported"),stats);
4255 ret = -EINVAL;
4256 goto exit;
4257 }
4258
4259 init_completion(&(fwStatsCtx.completion));
4260 fwStatsCtx.magic = FW_STATS_CONTEXT_MAGIC;
4261 fwStatsCtx.pAdapter = pAdapter;
4262 fwStatsRsp->type = 0;
4263 status = sme_GetFwStats( (tHalHandle)pHddCtx->hHal, stats,
Abhishek Singh08aa7762014-12-16 13:59:03 +05304264 &fwStatsCtx, hdd_FWStatisCB);
Satyanarayana Dash72806012014-12-02 14:30:08 +05304265 if (eHAL_STATUS_SUCCESS != status)
4266 {
4267 hddLog(VOS_TRACE_LEVEL_ERROR,
4268 FL(" fail to post WDA cmd status = %d"), status);
4269 ret = -EINVAL;
4270 goto exit;
4271 }
4272 waitRet = wait_for_completion_timeout
4273 (&(fwStatsCtx.completion), FW_STATE_WAIT_TIME);
4274 if (waitRet <= 0)
4275 {
4276 hddLog(VOS_TRACE_LEVEL_ERROR,
4277 FL("failed to wait on GwtFwstats"));
4278 //Make magic number to zero so that callback is not executed.
4279 spin_lock(&hdd_context_lock);
4280 fwStatsCtx.magic = 0x0;
4281 spin_unlock(&hdd_context_lock);
4282 ret = -EINVAL;
4283 goto exit;
4284 }
4285 if (fwStatsRsp->type)
4286 {
4287 buf = kmalloc(FW_STATE_RSP_LEN, GFP_KERNEL);
4288 if (!buf)
4289 {
4290 hddLog(VOS_TRACE_LEVEL_ERROR,
4291 FL(" failed to allocate memory"));
4292 ret = -ENOMEM;
4293 goto exit;
4294 }
4295 switch( fwStatsRsp->type )
4296 {
4297 case FW_UBSP_STATS:
4298 {
4299 len = snprintf(buf, FW_STATE_RSP_LEN,
4300 "GETFWSTATS: ubsp_enter_cnt %d ubsp_jump_ddr_cnt %d",
Abhishek Singh08aa7762014-12-16 13:59:03 +05304301 fwStatsRsp->fwStatsData.ubspStats.ubsp_enter_cnt,
4302 fwStatsRsp->fwStatsData.ubspStats.ubsp_jump_ddr_cnt);
Satyanarayana Dash72806012014-12-02 14:30:08 +05304303 }
4304 break;
4305 default:
4306 {
4307 hddLog(VOS_TRACE_LEVEL_ERROR, FL( "No handling for stats type %d"),fwStatsRsp->type);
4308 ret = -EFAULT;
4309 kfree(buf);
4310 goto exit;
4311 }
4312 }
4313 if (copy_to_user(priv_data.buf, buf, len + 1))
4314 {
4315 hddLog(VOS_TRACE_LEVEL_ERROR,
4316 FL(" failed to copy data to user buffer"));
4317 ret = -EFAULT;
4318 kfree(buf);
4319 goto exit;
4320 }
4321 ret = len;
4322 kfree(buf);
4323 }
4324 else
4325 {
4326 hddLog(VOS_TRACE_LEVEL_ERROR,
4327 FL("failed to fetch the stats"));
4328 ret = -EFAULT;
4329 goto exit;
4330 }
4331
4332 }
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07004333 else {
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05304334 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
4335 TRACE_CODE_HDD_UNSUPPORTED_IOCTL,
4336 pAdapter->sessionId, 0));
Satyanarayana Dash72806012014-12-02 14:30:08 +05304337 hddLog( VOS_TRACE_LEVEL_WARN, FL("Unsupported GUI command %s"),
4338 command);
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07004339 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004340 }
4341exit:
4342 if (command)
4343 {
4344 kfree(command);
4345 }
4346 return ret;
4347}
4348
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07004349#ifdef CONFIG_COMPAT
4350static int hdd_driver_compat_ioctl(hdd_adapter_t *pAdapter, struct ifreq *ifr)
4351{
4352 struct {
4353 compat_uptr_t buf;
4354 int used_len;
4355 int total_len;
4356 } compat_priv_data;
4357 hdd_priv_data_t priv_data;
4358 int ret = 0;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004359
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07004360 /*
4361 * Note that pAdapter and ifr have already been verified by caller,
4362 * and HDD context has also been validated
4363 */
4364 if (copy_from_user(&compat_priv_data, ifr->ifr_data,
4365 sizeof(compat_priv_data))) {
4366 ret = -EFAULT;
4367 goto exit;
4368 }
4369 priv_data.buf = compat_ptr(compat_priv_data.buf);
4370 priv_data.used_len = compat_priv_data.used_len;
4371 priv_data.total_len = compat_priv_data.total_len;
4372 ret = hdd_driver_command(pAdapter, &priv_data);
4373 exit:
4374 return ret;
4375}
4376#else /* CONFIG_COMPAT */
4377static int hdd_driver_compat_ioctl(hdd_adapter_t *pAdapter, struct ifreq *ifr)
4378{
4379 /* will never be invoked */
4380 return 0;
4381}
4382#endif /* CONFIG_COMPAT */
4383
4384static int hdd_driver_ioctl(hdd_adapter_t *pAdapter, struct ifreq *ifr)
4385{
4386 hdd_priv_data_t priv_data;
4387 int ret = 0;
4388
4389 /*
4390 * Note that pAdapter and ifr have already been verified by caller,
4391 * and HDD context has also been validated
4392 */
4393 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(priv_data))) {
4394 ret = -EFAULT;
4395 } else {
4396 ret = hdd_driver_command(pAdapter, &priv_data);
4397 }
4398 return ret;
4399}
4400
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05304401int __hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07004402{
4403 hdd_adapter_t *pAdapter;
4404 hdd_context_t *pHddCtx;
4405 int ret;
4406
4407 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4408 if (NULL == pAdapter) {
4409 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4410 "%s: HDD adapter context is Null", __func__);
4411 ret = -ENODEV;
4412 goto exit;
4413 }
4414 if (dev != pAdapter->dev) {
4415 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4416 "%s: HDD adapter/dev inconsistency", __func__);
4417 ret = -ENODEV;
4418 goto exit;
4419 }
4420
4421 if ((!ifr) || (!ifr->ifr_data)) {
4422 ret = -EINVAL;
4423 goto exit;
4424 }
4425
4426 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4427 ret = wlan_hdd_validate_context(pHddCtx);
4428 if (ret) {
Mahesh A Saptasagar5b16d0a2014-11-03 17:55:29 +05304429 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07004430 "%s: invalid context", __func__);
4431 ret = -EBUSY;
4432 goto exit;
4433 }
4434
4435 switch (cmd) {
4436 case (SIOCDEVPRIVATE + 1):
4437 if (is_compat_task())
4438 ret = hdd_driver_compat_ioctl(pAdapter, ifr);
4439 else
4440 ret = hdd_driver_ioctl(pAdapter, ifr);
4441 break;
4442 default:
4443 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unknown ioctl %d",
4444 __func__, cmd);
4445 ret = -EINVAL;
4446 break;
4447 }
4448 exit:
4449 return ret;
4450}
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004451
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05304452int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
4453{
4454 int ret;
4455
4456 vos_ssr_protect(__func__);
4457 ret = __hdd_ioctl(dev, ifr, cmd);
4458 vos_ssr_unprotect(__func__);
4459
4460 return ret;
4461}
4462
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004463#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004464/**---------------------------------------------------------------------------
4465
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004466 \brief hdd_parse_ese_beacon_req() - Parse ese beacon request
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004467
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004468 This function parses the ese beacon request passed in the format
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004469 CCXBEACONREQ<space><Number of fields><space><Measurement token>
4470 <space>Channel 1<space>Scan Mode <space>Meas Duration<space>Channel N
4471 <space>Scan Mode N<space>Meas Duration N
4472 if the Number of bcn req fields (N) does not match with the actual number of fields passed
4473 then take N.
4474 <Meas Token><Channel><Scan Mode> and <Meas Duration> are treated as one pair
4475 For example, CCXBEACONREQ 2 1 1 1 30 2 44 0 40.
4476 This function does not take care of removing duplicate channels from the list
4477
4478 \param - pValue Pointer to data
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004479 \param - pEseBcnReq output pointer to store parsed ie information
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004480
4481 \return - 0 for success non-zero for failure
4482
4483 --------------------------------------------------------------------------*/
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004484static VOS_STATUS hdd_parse_ese_beacon_req(tANI_U8 *pValue,
4485 tCsrEseBeaconReq *pEseBcnReq)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004486{
4487 tANI_U8 *inPtr = pValue;
4488 int tempInt = 0;
4489 int j = 0, i = 0, v = 0;
4490 char buf[32];
4491
4492 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4493 /*no argument after the command*/
4494 if (NULL == inPtr)
4495 {
4496 return -EINVAL;
4497 }
4498 /*no space after the command*/
4499 else if (SPACE_ASCII_VALUE != *inPtr)
4500 {
4501 return -EINVAL;
4502 }
4503
4504 /*removing empty spaces*/
4505 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
4506
4507 /*no argument followed by spaces*/
4508 if ('\0' == *inPtr) return -EINVAL;
4509
4510 /*getting the first argument ie measurement token*/
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004511 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004512 if (1 != v) return -EINVAL;
4513
4514 v = kstrtos32(buf, 10, &tempInt);
4515 if ( v < 0) return -EINVAL;
4516
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004517 pEseBcnReq->numBcnReqIe = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004518
4519 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004520 "Number of Bcn Req Ie fields(%d)", pEseBcnReq->numBcnReqIe);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004521
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004522 for (j = 0; j < (pEseBcnReq->numBcnReqIe); j++)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004523 {
4524 for (i = 0; i < 4; i++)
4525 {
4526 /*inPtr pointing to the beginning of first space after number of ie fields*/
4527 inPtr = strpbrk( inPtr, " " );
4528 /*no ie data after the number of ie fields argument*/
4529 if (NULL == inPtr) return -EINVAL;
4530
4531 /*removing empty space*/
4532 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
4533
4534 /*no ie data after the number of ie fields argument and spaces*/
4535 if ( '\0' == *inPtr ) return -EINVAL;
4536
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004537 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004538 if (1 != v) return -EINVAL;
4539
4540 v = kstrtos32(buf, 10, &tempInt);
4541 if (v < 0) return -EINVAL;
4542
4543 switch (i)
4544 {
4545 case 0: /* Measurement token */
4546 if (tempInt <= 0)
4547 {
4548 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4549 "Invalid Measurement Token(%d)", tempInt);
4550 return -EINVAL;
4551 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004552 pEseBcnReq->bcnReq[j].measurementToken = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004553 break;
4554
4555 case 1: /* Channel number */
4556 if ((tempInt <= 0) ||
4557 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4558 {
4559 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4560 "Invalid Channel Number(%d)", tempInt);
4561 return -EINVAL;
4562 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004563 pEseBcnReq->bcnReq[j].channel = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004564 break;
4565
4566 case 2: /* Scan mode */
Varun Reddy Yeturu0b18d5a2013-12-04 11:42:23 -08004567 if ((tempInt < eSIR_PASSIVE_SCAN) || (tempInt > eSIR_BEACON_TABLE))
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004568 {
4569 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4570 "Invalid Scan Mode(%d) Expected{0|1|2}", tempInt);
4571 return -EINVAL;
4572 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004573 pEseBcnReq->bcnReq[j].scanMode= tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004574 break;
4575
4576 case 3: /* Measurement duration */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004577 if (((tempInt <= 0) && (pEseBcnReq->bcnReq[j].scanMode != eSIR_BEACON_TABLE)) ||
4578 ((tempInt < 0) && (pEseBcnReq->bcnReq[j].scanMode == eSIR_BEACON_TABLE)))
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004579 {
4580 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4581 "Invalid Measurement Duration(%d)", tempInt);
4582 return -EINVAL;
4583 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004584 pEseBcnReq->bcnReq[j].measurementDuration = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004585 break;
4586 }
4587 }
4588 }
4589
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004590 for (j = 0; j < pEseBcnReq->numBcnReqIe; j++)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004591 {
4592 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arun Kumar Khandavallie8768212014-02-17 16:43:34 +05304593 "Index(%d) Measurement Token(%u)Channel(%u) Scan Mode(%u) Measurement Duration(%u)\n",
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004594 j,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004595 pEseBcnReq->bcnReq[j].measurementToken,
4596 pEseBcnReq->bcnReq[j].channel,
4597 pEseBcnReq->bcnReq[j].scanMode,
4598 pEseBcnReq->bcnReq[j].measurementDuration);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004599 }
4600
4601 return VOS_STATUS_SUCCESS;
4602}
4603
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004604static void hdd_GetTsmStatsCB( tAniTrafStrmMetrics tsmMetrics, const tANI_U32 staId, void *pContext )
4605{
4606 struct statsContext *pStatsContext = NULL;
4607 hdd_adapter_t *pAdapter = NULL;
4608
4609 if (NULL == pContext)
4610 {
4611 hddLog(VOS_TRACE_LEVEL_ERROR,
4612 "%s: Bad param, pContext [%p]",
4613 __func__, pContext);
4614 return;
4615 }
4616
Jeff Johnson72a40512013-12-19 10:14:15 -08004617 /* there is a race condition that exists between this callback
4618 function and the caller since the caller could time out either
4619 before or while this code is executing. we use a spinlock to
4620 serialize these actions */
4621 spin_lock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004622
4623 pStatsContext = pContext;
4624 pAdapter = pStatsContext->pAdapter;
4625 if ((NULL == pAdapter) || (STATS_CONTEXT_MAGIC != pStatsContext->magic))
4626 {
4627 /* the caller presumably timed out so there is nothing we can do */
Jeff Johnson72a40512013-12-19 10:14:15 -08004628 spin_unlock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004629 hddLog(VOS_TRACE_LEVEL_WARN,
4630 "%s: Invalid context, pAdapter [%p] magic [%08x]",
4631 __func__, pAdapter, pStatsContext->magic);
4632 return;
4633 }
4634
Jeff Johnson72a40512013-12-19 10:14:15 -08004635 /* context is valid so caller is still waiting */
4636
4637 /* paranoia: invalidate the magic */
4638 pStatsContext->magic = 0;
4639
4640 /* copy over the tsm stats */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004641 pAdapter->tsmStats.UplinkPktQueueDly = tsmMetrics.UplinkPktQueueDly;
4642 vos_mem_copy(pAdapter->tsmStats.UplinkPktQueueDlyHist,
4643 tsmMetrics.UplinkPktQueueDlyHist,
4644 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
4645 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
4646 pAdapter->tsmStats.UplinkPktTxDly = tsmMetrics.UplinkPktTxDly;
4647 pAdapter->tsmStats.UplinkPktLoss = tsmMetrics.UplinkPktLoss;
4648 pAdapter->tsmStats.UplinkPktCount = tsmMetrics.UplinkPktCount;
4649 pAdapter->tsmStats.RoamingCount = tsmMetrics.RoamingCount;
4650 pAdapter->tsmStats.RoamingDly = tsmMetrics.RoamingDly;
4651
Jeff Johnson72a40512013-12-19 10:14:15 -08004652 /* notify the caller */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004653 complete(&pStatsContext->completion);
Jeff Johnson72a40512013-12-19 10:14:15 -08004654
4655 /* serialization is complete */
4656 spin_unlock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004657}
4658
4659
4660
4661static VOS_STATUS hdd_get_tsm_stats(hdd_adapter_t *pAdapter, const tANI_U8 tid,
4662 tAniTrafStrmMetrics* pTsmMetrics)
4663{
4664 hdd_station_ctx_t *pHddStaCtx = NULL;
4665 eHalStatus hstatus;
Jeff Johnson72a40512013-12-19 10:14:15 -08004666 VOS_STATUS vstatus = VOS_STATUS_SUCCESS;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004667 long lrc;
4668 struct statsContext context;
4669 hdd_context_t *pHddCtx = NULL;
4670
4671 if (NULL == pAdapter)
4672 {
4673 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: pAdapter is NULL", __func__);
4674 return VOS_STATUS_E_FAULT;
4675 }
4676
4677 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4678 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4679
4680 /* we are connected prepare our callback context */
4681 init_completion(&context.completion);
4682 context.pAdapter = pAdapter;
4683 context.magic = STATS_CONTEXT_MAGIC;
4684
4685 /* query tsm stats */
4686 hstatus = sme_GetTsmStats(pHddCtx->hHal, hdd_GetTsmStatsCB,
4687 pHddStaCtx->conn_info.staId[ 0 ],
4688 pHddStaCtx->conn_info.bssId,
4689 &context, pHddCtx->pvosContext, tid);
4690
4691 if (eHAL_STATUS_SUCCESS != hstatus)
4692 {
Jeff Johnson72a40512013-12-19 10:14:15 -08004693 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unable to retrieve statistics",
4694 __func__);
4695 vstatus = VOS_STATUS_E_FAULT;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004696 }
4697 else
4698 {
4699 /* request was sent -- wait for the response */
4700 lrc = wait_for_completion_interruptible_timeout(&context.completion,
4701 msecs_to_jiffies(WLAN_WAIT_TIME_STATS));
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004702 if (lrc <= 0)
4703 {
4704 hddLog(VOS_TRACE_LEVEL_ERROR,
4705 "%s: SME %s while retrieving statistics",
4706 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson72a40512013-12-19 10:14:15 -08004707 vstatus = VOS_STATUS_E_TIMEOUT;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004708 }
4709 }
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004710
Jeff Johnson72a40512013-12-19 10:14:15 -08004711 /* either we never sent a request, we sent a request and received a
4712 response or we sent a request and timed out. if we never sent a
4713 request or if we sent a request and got a response, we want to
4714 clear the magic out of paranoia. if we timed out there is a
4715 race condition such that the callback function could be
4716 executing at the same time we are. of primary concern is if the
4717 callback function had already verified the "magic" but had not
4718 yet set the completion variable when a timeout occurred. we
4719 serialize these activities by invalidating the magic while
4720 holding a shared spinlock which will cause us to block if the
4721 callback is currently executing */
4722 spin_lock(&hdd_context_lock);
4723 context.magic = 0;
4724 spin_unlock(&hdd_context_lock);
4725
4726 if (VOS_STATUS_SUCCESS == vstatus)
4727 {
4728 pTsmMetrics->UplinkPktQueueDly = pAdapter->tsmStats.UplinkPktQueueDly;
4729 vos_mem_copy(pTsmMetrics->UplinkPktQueueDlyHist,
4730 pAdapter->tsmStats.UplinkPktQueueDlyHist,
4731 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
4732 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
4733 pTsmMetrics->UplinkPktTxDly = pAdapter->tsmStats.UplinkPktTxDly;
4734 pTsmMetrics->UplinkPktLoss = pAdapter->tsmStats.UplinkPktLoss;
4735 pTsmMetrics->UplinkPktCount = pAdapter->tsmStats.UplinkPktCount;
4736 pTsmMetrics->RoamingCount = pAdapter->tsmStats.RoamingCount;
4737 pTsmMetrics->RoamingDly = pAdapter->tsmStats.RoamingDly;
4738 }
4739 return vstatus;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004740}
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004741#endif /*FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004742
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004743#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -08004744void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
4745{
4746 eCsrBand band = -1;
4747 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
4748 switch (band)
4749 {
4750 case eCSR_BAND_ALL:
4751 *pBand = WLAN_HDD_UI_BAND_AUTO;
4752 break;
4753
4754 case eCSR_BAND_24:
4755 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
4756 break;
4757
4758 case eCSR_BAND_5G:
4759 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
4760 break;
4761
4762 default:
4763 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
4764 *pBand = -1;
4765 break;
4766 }
4767}
4768
4769/**---------------------------------------------------------------------------
4770
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004771 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
4772
4773 This function parses the send action frame data passed in the format
4774 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
4775
Srinivas Girigowda56076852013-08-20 14:00:50 -07004776 \param - pValue Pointer to input data
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004777 \param - pTargetApBssid Pointer to target Ap bssid
4778 \param - pChannel Pointer to the Target AP channel
4779 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
4780 \param - pBuf Pointer to data
4781 \param - pBufLen Pointer to data length
4782
4783 \return - 0 for success non-zero for failure
4784
4785 --------------------------------------------------------------------------*/
4786VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
4787 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
4788{
4789 tANI_U8 *inPtr = pValue;
4790 tANI_U8 *dataEnd;
4791 int tempInt;
4792 int j = 0;
4793 int i = 0;
4794 int v = 0;
4795 tANI_U8 tempBuf[32];
4796 tANI_U8 tempByte = 0;
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004797 /* 12 hexa decimal digits, 5 ':' and '\0' */
4798 tANI_U8 macAddress[18];
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004799
4800 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4801 /*no argument after the command*/
4802 if (NULL == inPtr)
4803 {
4804 return -EINVAL;
4805 }
4806
4807 /*no space after the command*/
4808 else if (SPACE_ASCII_VALUE != *inPtr)
4809 {
4810 return -EINVAL;
4811 }
4812
4813 /*removing empty spaces*/
4814 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4815
4816 /*no argument followed by spaces*/
4817 if ('\0' == *inPtr)
4818 {
4819 return -EINVAL;
4820 }
4821
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004822 v = sscanf(inPtr, "%17s", macAddress);
4823 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004824 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004825 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4826 "Invalid MAC address or All hex inputs are not read (%d)", v);
4827 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004828 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004829
4830 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
4831 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
4832 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
4833 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
4834 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
4835 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004836
4837 /* point to the next argument */
4838 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4839 /*no argument after the command*/
4840 if (NULL == inPtr) return -EINVAL;
4841
4842 /*removing empty spaces*/
4843 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4844
4845 /*no argument followed by spaces*/
4846 if ('\0' == *inPtr)
4847 {
4848 return -EINVAL;
4849 }
4850
4851 /*getting the next argument ie the channel number */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004852 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004853 if (1 != v) return -EINVAL;
4854
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004855 v = kstrtos32(tempBuf, 10, &tempInt);
Agarwal Ashish353b3a82014-04-08 14:55:11 +05304856 if ( v < 0 || tempInt <= 0 || tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX )
Kiet Lambe150c22013-11-21 16:30:32 +05304857 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004858
4859 *pChannel = tempInt;
4860
4861 /* point to the next argument */
4862 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4863 /*no argument after the command*/
4864 if (NULL == inPtr) return -EINVAL;
4865 /*removing empty spaces*/
4866 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4867
4868 /*no argument followed by spaces*/
4869 if ('\0' == *inPtr)
4870 {
4871 return -EINVAL;
4872 }
4873
4874 /*getting the next argument ie the dwell time */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004875 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004876 if (1 != v) return -EINVAL;
4877
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004878 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda5a6e0672014-01-09 14:42:57 -08004879 if ( v < 0 || tempInt < 0) return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004880
4881 *pDwellTime = tempInt;
4882
4883 /* point to the next argument */
4884 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4885 /*no argument after the command*/
4886 if (NULL == inPtr) return -EINVAL;
4887 /*removing empty spaces*/
4888 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4889
4890 /*no argument followed by spaces*/
4891 if ('\0' == *inPtr)
4892 {
4893 return -EINVAL;
4894 }
4895
4896 /* find the length of data */
4897 dataEnd = inPtr;
4898 while(('\0' != *dataEnd) )
4899 {
4900 dataEnd++;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004901 }
Kiet Lambe150c22013-11-21 16:30:32 +05304902 *pBufLen = dataEnd - inPtr ;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004903 if ( *pBufLen <= 0) return -EINVAL;
4904
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07004905 /* Allocate the number of bytes based on the number of input characters
4906 whether it is even or odd.
4907 if the number of input characters are even, then we need N/2 byte.
4908 if the number of input characters are odd, then we need do (N+1)/2 to
4909 compensate rounding off.
4910 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
4911 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
4912 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004913 if (NULL == *pBuf)
4914 {
4915 hddLog(VOS_TRACE_LEVEL_FATAL,
4916 "%s: vos_mem_alloc failed ", __func__);
4917 return -EINVAL;
4918 }
4919
4920 /* the buffer received from the upper layer is character buffer,
4921 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
4922 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
4923 and f0 in 3rd location */
4924 for (i = 0, j = 0; j < *pBufLen; j += 2)
4925 {
Kiet Lambe150c22013-11-21 16:30:32 +05304926 if( j+1 == *pBufLen)
4927 {
4928 tempByte = hdd_parse_hex(inPtr[j]);
4929 }
4930 else
4931 {
4932 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
4933 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004934 (*pBuf)[i++] = tempByte;
4935 }
4936 *pBufLen = i;
4937 return VOS_STATUS_SUCCESS;
4938}
4939
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004940/**---------------------------------------------------------------------------
4941
Srinivas Girigowdade697412013-02-14 16:31:48 -08004942 \brief hdd_parse_channellist() - HDD Parse channel list
4943
4944 This function parses the channel list passed in the format
4945 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004946 if the Number of channels (N) does not match with the actual number of channels passed
4947 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
4948 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
4949 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
4950 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08004951
4952 \param - pValue Pointer to input channel list
4953 \param - ChannelList Pointer to local output array to record channel list
4954 \param - pNumChannels Pointer to number of roam scan channels
4955
4956 \return - 0 for success non-zero for failure
4957
4958 --------------------------------------------------------------------------*/
4959VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
4960{
4961 tANI_U8 *inPtr = pValue;
4962 int tempInt;
4963 int j = 0;
4964 int v = 0;
4965 char buf[32];
4966
4967 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4968 /*no argument after the command*/
4969 if (NULL == inPtr)
4970 {
4971 return -EINVAL;
4972 }
4973
4974 /*no space after the command*/
4975 else if (SPACE_ASCII_VALUE != *inPtr)
4976 {
4977 return -EINVAL;
4978 }
4979
4980 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004981 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08004982
4983 /*no argument followed by spaces*/
4984 if ('\0' == *inPtr)
4985 {
4986 return -EINVAL;
4987 }
4988
4989 /*getting the first argument ie the number of channels*/
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004990 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004991 if (1 != v) return -EINVAL;
4992
Srinivas Girigowdade697412013-02-14 16:31:48 -08004993 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004994 if ((v < 0) ||
4995 (tempInt <= 0) ||
4996 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
4997 {
4998 return -EINVAL;
4999 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08005000
5001 *pNumChannels = tempInt;
5002
5003 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
5004 "Number of channels are: %d", *pNumChannels);
5005
5006 for (j = 0; j < (*pNumChannels); j++)
5007 {
5008 /*inPtr pointing to the beginning of first space after number of channels*/
5009 inPtr = strpbrk( inPtr, " " );
5010 /*no channel list after the number of channels argument*/
5011 if (NULL == inPtr)
5012 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07005013 if (0 != j)
5014 {
5015 *pNumChannels = j;
5016 return VOS_STATUS_SUCCESS;
5017 }
5018 else
5019 {
5020 return -EINVAL;
5021 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08005022 }
5023
5024 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07005025 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08005026
5027 /*no channel list after the number of channels argument and spaces*/
5028 if ( '\0' == *inPtr )
5029 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07005030 if (0 != j)
5031 {
5032 *pNumChannels = j;
5033 return VOS_STATUS_SUCCESS;
5034 }
5035 else
5036 {
5037 return -EINVAL;
5038 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08005039 }
5040
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08005041 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07005042 if (1 != v) return -EINVAL;
5043
Srinivas Girigowdade697412013-02-14 16:31:48 -08005044 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07005045 if ((v < 0) ||
5046 (tempInt <= 0) ||
5047 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
5048 {
5049 return -EINVAL;
5050 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08005051 pChannelList[j] = tempInt;
5052
5053 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
5054 "Channel %d added to preferred channel list",
5055 pChannelList[j] );
5056 }
5057
Srinivas Girigowdade697412013-02-14 16:31:48 -08005058 return VOS_STATUS_SUCCESS;
5059}
5060
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07005061
5062/**---------------------------------------------------------------------------
5063
5064 \brief hdd_parse_reassoc_command_data() - HDD Parse reassoc command data
5065
5066 This function parses the reasoc command data passed in the format
5067 REASSOC<space><bssid><space><channel>
5068
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07005069 \param - pValue Pointer to input data (its a NUL terminated string)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07005070 \param - pTargetApBssid Pointer to target Ap bssid
5071 \param - pChannel Pointer to the Target AP channel
5072
5073 \return - 0 for success non-zero for failure
5074
5075 --------------------------------------------------------------------------*/
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07005076VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue,
5077 tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07005078{
5079 tANI_U8 *inPtr = pValue;
5080 int tempInt;
5081 int v = 0;
5082 tANI_U8 tempBuf[32];
Kiet Lamaa8e15a2014-02-11 23:30:06 -08005083 /* 12 hexa decimal digits, 5 ':' and '\0' */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08005084 tANI_U8 macAddress[18];
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07005085
5086 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
5087 /*no argument after the command*/
5088 if (NULL == inPtr)
5089 {
5090 return -EINVAL;
5091 }
5092
5093 /*no space after the command*/
5094 else if (SPACE_ASCII_VALUE != *inPtr)
5095 {
5096 return -EINVAL;
5097 }
5098
5099 /*removing empty spaces*/
5100 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
5101
5102 /*no argument followed by spaces*/
5103 if ('\0' == *inPtr)
5104 {
5105 return -EINVAL;
5106 }
5107
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07005108 v = sscanf(inPtr, "%17s", macAddress);
5109 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07005110 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07005111 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5112 "Invalid MAC address or All hex inputs are not read (%d)", v);
5113 return -EINVAL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07005114 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07005115
5116 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
5117 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
5118 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
5119 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
5120 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
5121 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07005122
5123 /* point to the next argument */
5124 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
5125 /*no argument after the command*/
5126 if (NULL == inPtr) return -EINVAL;
5127
5128 /*removing empty spaces*/
5129 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
5130
5131 /*no argument followed by spaces*/
5132 if ('\0' == *inPtr)
5133 {
5134 return -EINVAL;
5135 }
5136
5137 /*getting the next argument ie the channel number */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08005138 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07005139 if (1 != v) return -EINVAL;
5140
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07005141 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07005142 if ((v < 0) ||
Padma, Santhosh Kumar0fa809b2014-11-13 14:56:56 +05305143 (tempInt < 0) ||
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07005144 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
5145 {
5146 return -EINVAL;
5147 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07005148
5149 *pChannel = tempInt;
5150 return VOS_STATUS_SUCCESS;
5151}
5152
5153#endif
5154
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08005155#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07005156/**---------------------------------------------------------------------------
5157
5158 \brief hdd_parse_get_cckm_ie() - HDD Parse and fetch the CCKM IE
5159
5160 This function parses the SETCCKM IE command
5161 SETCCKMIE<space><ie data>
5162
5163 \param - pValue Pointer to input data
5164 \param - pCckmIe Pointer to output cckm Ie
5165 \param - pCckmIeLen Pointer to output cckm ie length
5166
5167 \return - 0 for success non-zero for failure
5168
5169 --------------------------------------------------------------------------*/
5170VOS_STATUS hdd_parse_get_cckm_ie(tANI_U8 *pValue, tANI_U8 **pCckmIe,
5171 tANI_U8 *pCckmIeLen)
5172{
5173 tANI_U8 *inPtr = pValue;
5174 tANI_U8 *dataEnd;
5175 int j = 0;
5176 int i = 0;
5177 tANI_U8 tempByte = 0;
5178
5179 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
5180 /*no argument after the command*/
5181 if (NULL == inPtr)
5182 {
5183 return -EINVAL;
5184 }
5185
5186 /*no space after the command*/
5187 else if (SPACE_ASCII_VALUE != *inPtr)
5188 {
5189 return -EINVAL;
5190 }
5191
5192 /*removing empty spaces*/
5193 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
5194
5195 /*no argument followed by spaces*/
5196 if ('\0' == *inPtr)
5197 {
5198 return -EINVAL;
5199 }
5200
5201 /* find the length of data */
5202 dataEnd = inPtr;
5203 while(('\0' != *dataEnd) )
5204 {
5205 dataEnd++;
5206 ++(*pCckmIeLen);
5207 }
5208 if ( *pCckmIeLen <= 0) return -EINVAL;
5209
5210 /* Allocate the number of bytes based on the number of input characters
5211 whether it is even or odd.
5212 if the number of input characters are even, then we need N/2 byte.
5213 if the number of input characters are odd, then we need do (N+1)/2 to
5214 compensate rounding off.
5215 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
5216 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
5217 *pCckmIe = vos_mem_malloc((*pCckmIeLen + 1)/2);
5218 if (NULL == *pCckmIe)
5219 {
5220 hddLog(VOS_TRACE_LEVEL_FATAL,
5221 "%s: vos_mem_alloc failed ", __func__);
5222 return -EINVAL;
5223 }
5224 vos_mem_zero(*pCckmIe, (*pCckmIeLen + 1)/2);
5225 /* the buffer received from the upper layer is character buffer,
5226 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
5227 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
5228 and f0 in 3rd location */
5229 for (i = 0, j = 0; j < *pCckmIeLen; j += 2)
5230 {
5231 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
5232 (*pCckmIe)[i++] = tempByte;
5233 }
5234 *pCckmIeLen = i;
5235
5236 return VOS_STATUS_SUCCESS;
5237}
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08005238#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07005239
Jeff Johnson295189b2012-06-20 16:38:30 -07005240/**---------------------------------------------------------------------------
5241
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07005242 \brief hdd_is_valid_mac_address() - Validate MAC address
5243
5244 This function validates whether the given MAC address is valid or not
5245 Expected MAC address is of the format XX:XX:XX:XX:XX:XX
5246 where X is the hexa decimal digit character and separated by ':'
5247 This algorithm works even if MAC address is not separated by ':'
5248
5249 This code checks given input string mac contains exactly 12 hexadecimal digits.
5250 and a separator colon : appears in the input string only after
5251 an even number of hex digits.
5252
5253 \param - pMacAddr pointer to the input MAC address
5254 \return - 1 for valid and 0 for invalid
5255
5256 --------------------------------------------------------------------------*/
5257
5258v_BOOL_t hdd_is_valid_mac_address(const tANI_U8 *pMacAddr)
5259{
5260 int xdigit = 0;
5261 int separator = 0;
5262 while (*pMacAddr)
5263 {
5264 if (isxdigit(*pMacAddr))
5265 {
5266 xdigit++;
5267 }
5268 else if (':' == *pMacAddr)
5269 {
5270 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
5271 break;
5272
5273 ++separator;
5274 }
5275 else
5276 {
5277 separator = -1;
5278 /* Invalid MAC found */
5279 return 0;
5280 }
5281 ++pMacAddr;
5282 }
5283 return (xdigit == 12 && (separator == 5 || separator == 0));
5284}
5285
5286/**---------------------------------------------------------------------------
5287
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305288 \brief __hdd_open() - HDD Open function
Jeff Johnson295189b2012-06-20 16:38:30 -07005289
5290 \param - dev Pointer to net_device structure
5291
5292 \return - 0 for success non-zero for failure
5293
5294 --------------------------------------------------------------------------*/
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305295int __hdd_open(struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07005296{
5297 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5298 hdd_context_t *pHddCtx;
5299 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5300 VOS_STATUS status;
5301 v_BOOL_t in_standby = TRUE;
5302
5303 if (NULL == pAdapter)
5304 {
5305 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Agarwal Ashish971c2882013-10-30 20:11:12 +05305306 "%s: pAdapter is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005307 return -ENODEV;
5308 }
5309
5310 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05305311 MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_OPEN_REQUEST,
5312 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson295189b2012-06-20 16:38:30 -07005313 if (NULL == pHddCtx)
5314 {
5315 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005316 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005317 return -ENODEV;
5318 }
5319
5320 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5321 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
5322 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07005323 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
5324 {
5325 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305326 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07005327 in_standby = FALSE;
5328 break;
5329 }
5330 else
5331 {
5332 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5333 pAdapterNode = pNext;
5334 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005335 }
5336
5337 if (TRUE == in_standby)
5338 {
5339 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
5340 {
5341 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
5342 "wlan out of power save", __func__);
5343 return -EINVAL;
5344 }
5345 }
5346
Jeff Johnson6a81ca42013-04-05 10:37:08 -07005347 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07005348 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
5349 {
5350 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005351 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005352 /* Enable TX queues only when we are connected */
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05305353 hddLog(VOS_TRACE_LEVEL_INFO, FL("Enabling queues"));
Jeff Johnson295189b2012-06-20 16:38:30 -07005354 netif_tx_start_all_queues(dev);
5355 }
5356
5357 return 0;
5358}
5359
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305360/**---------------------------------------------------------------------------
5361
5362 \brief hdd_open() - Wrapper function for __hdd_open to protect it from SSR
5363
5364 This is called in response to ifconfig up
5365
5366 \param - dev Pointer to net_device structure
5367
5368 \return - 0 for success non-zero for failure
5369
5370 --------------------------------------------------------------------------*/
5371int hdd_open(struct net_device *dev)
5372{
5373 int ret;
5374
5375 vos_ssr_protect(__func__);
5376 ret = __hdd_open(dev);
5377 vos_ssr_unprotect(__func__);
5378
5379 return ret;
5380}
5381
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +05305382int __hdd_mon_open (struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07005383{
5384 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5385
5386 if(pAdapter == NULL) {
5387 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005388 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005389 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005390 }
5391
5392 netif_start_queue(dev);
5393
5394 return 0;
5395}
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +05305396
5397int hdd_mon_open (struct net_device *dev)
5398{
5399 int ret;
5400
5401 vos_ssr_protect(__func__);
5402 ret = __hdd_mon_open(dev);
5403 vos_ssr_unprotect(__func__);
5404
5405 return ret;
5406}
5407
Jeff Johnson295189b2012-06-20 16:38:30 -07005408/**---------------------------------------------------------------------------
5409
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305410 \brief __hdd_stop() - HDD stop function
Jeff Johnson295189b2012-06-20 16:38:30 -07005411
5412 \param - dev Pointer to net_device structure
5413
5414 \return - 0 for success non-zero for failure
5415
5416 --------------------------------------------------------------------------*/
5417
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305418int __hdd_stop (struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07005419{
Vinay Krishna Eranna90f43532014-10-27 16:45:54 +05305420 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07005421 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5422 hdd_context_t *pHddCtx;
5423 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5424 VOS_STATUS status;
5425 v_BOOL_t enter_standby = TRUE;
5426
5427 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005428 if (NULL == pAdapter)
5429 {
5430 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Agarwal Ashish971c2882013-10-30 20:11:12 +05305431 "%s: pAdapter is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005432 return -ENODEV;
5433 }
Sachin Ahuja9b4958f2015-01-15 21:37:00 +05305434 MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_STOP_REQUEST,
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05305435 pAdapter->sessionId, pAdapter->device_mode));
Vinay Krishna Eranna90f43532014-10-27 16:45:54 +05305436
5437 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
5438 ret = wlan_hdd_validate_context(pHddCtx);
5439 if (ret)
Jeff Johnson295189b2012-06-20 16:38:30 -07005440 {
Vinay Krishna Eranna90f43532014-10-27 16:45:54 +05305441 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5442 "%s: HDD context is not valid!", __func__);
5443 return ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07005444 }
5445
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05305446 /* Nothing to be done if the interface is not opened */
5447 if (VOS_FALSE == test_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags))
5448 {
5449 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5450 "%s: NETDEV Interface is not OPENED", __func__);
5451 return -ENODEV;
5452 }
5453
5454 /* Make sure the interface is marked as closed */
Jeff Johnson6a81ca42013-04-05 10:37:08 -07005455 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07005456 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05305457
5458 /* Disable TX on the interface, after this hard_start_xmit() will not
5459 * be called on that interface
5460 */
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05305461 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
Jeff Johnson295189b2012-06-20 16:38:30 -07005462 netif_tx_disable(pAdapter->dev);
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05305463
5464 /* Mark the interface status as "down" for outside world */
Jeff Johnson295189b2012-06-20 16:38:30 -07005465 netif_carrier_off(pAdapter->dev);
5466
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05305467 /* The interface is marked as down for outside world (aka kernel)
5468 * But the driver is pretty much alive inside. The driver needs to
5469 * tear down the existing connection on the netdev (session)
5470 * cleanup the data pipes and wait until the control plane is stabilized
5471 * for this interface. The call also needs to wait until the above
5472 * mentioned actions are completed before returning to the caller.
5473 * Notice that the hdd_stop_adapter is requested not to close the session
5474 * That is intentional to be able to scan if it is a STA/P2P interface
5475 */
5476 hdd_stop_adapter(pHddCtx, pAdapter, VOS_FALSE);
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05305477#ifdef FEATURE_WLAN_TDLS
5478 mutex_lock(&pHddCtx->tdls_lock);
5479#endif
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05305480 /* DeInit the adapter. This ensures datapath cleanup as well */
c_hpothu002231a2015-02-05 14:58:51 +05305481 hdd_deinit_adapter(pHddCtx, pAdapter, TRUE);
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05305482#ifdef FEATURE_WLAN_TDLS
5483 mutex_unlock(&pHddCtx->tdls_lock);
5484#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005485 /* SoftAP ifaces should never go in power save mode
5486 making sure same here. */
5487 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
5488 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07005489 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07005490 )
5491 {
5492 /* SoftAP mode, so return from here */
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305493 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5494 "%s: In SAP MODE", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005495 EXIT();
5496 return 0;
5497 }
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05305498 /* Find if any iface is up. If any iface is up then can't put device to
5499 * sleep/power save mode
5500 */
Jeff Johnson295189b2012-06-20 16:38:30 -07005501 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5502 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
5503 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07005504 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
5505 {
5506 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305507 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07005508 enter_standby = FALSE;
5509 break;
5510 }
5511 else
5512 {
5513 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5514 pAdapterNode = pNext;
5515 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005516 }
5517
5518 if (TRUE == enter_standby)
5519 {
5520 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
5521 "entering standby", __func__);
5522 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
5523 {
5524 /*log and return success*/
5525 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
5526 "wlan in power save", __func__);
5527 }
5528 }
5529
5530 EXIT();
5531 return 0;
5532}
5533
5534/**---------------------------------------------------------------------------
5535
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305536 \brief hdd_stop() - wrapper_function for __hdd_stop to protect it from SSR
Jeff Johnson295189b2012-06-20 16:38:30 -07005537
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305538 This is called in response to ifconfig down
5539
5540 \param - dev Pointer to net_device structure
5541
5542 \return - 0 for success non-zero for failure
5543-----------------------------------------------------------------------------*/
5544int hdd_stop (struct net_device *dev)
5545{
5546 int ret;
5547
5548 vos_ssr_protect(__func__);
5549 ret = __hdd_stop(dev);
5550 vos_ssr_unprotect(__func__);
5551
5552 return ret;
5553}
5554
5555/**---------------------------------------------------------------------------
5556
5557 \brief __hdd_uninit() - HDD uninit function
Jeff Johnson295189b2012-06-20 16:38:30 -07005558
5559 \param - dev Pointer to net_device structure
5560
5561 \return - void
5562
5563 --------------------------------------------------------------------------*/
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305564static void __hdd_uninit (struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07005565{
5566 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05305567 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07005568 ENTER();
5569
5570 do
5571 {
5572 if (NULL == pAdapter)
5573 {
5574 hddLog(VOS_TRACE_LEVEL_FATAL,
5575 "%s: NULL pAdapter", __func__);
5576 break;
5577 }
5578
5579 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
5580 {
5581 hddLog(VOS_TRACE_LEVEL_FATAL,
5582 "%s: Invalid magic", __func__);
5583 break;
5584 }
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05305585 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
5586 if (NULL == pHddCtx)
Jeff Johnson295189b2012-06-20 16:38:30 -07005587 {
5588 hddLog(VOS_TRACE_LEVEL_FATAL,
5589 "%s: NULL pHddCtx", __func__);
5590 break;
5591 }
5592
5593 if (dev != pAdapter->dev)
5594 {
5595 hddLog(VOS_TRACE_LEVEL_FATAL,
5596 "%s: Invalid device reference", __func__);
5597 /* we haven't validated all cases so let this go for now */
5598 }
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05305599#ifdef FEATURE_WLAN_TDLS
5600 mutex_lock(&pHddCtx->tdls_lock);
5601#endif
c_hpothu002231a2015-02-05 14:58:51 +05305602 hdd_deinit_adapter(pHddCtx, pAdapter, TRUE);
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05305603#ifdef FEATURE_WLAN_TDLS
5604 mutex_unlock(&pHddCtx->tdls_lock);
5605#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005606
5607 /* after uninit our adapter structure will no longer be valid */
5608 pAdapter->dev = NULL;
5609 pAdapter->magic = 0;
5610 } while (0);
5611
5612 EXIT();
5613}
5614
5615/**---------------------------------------------------------------------------
5616
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305617 \brief hdd_uninit() - Wrapper function to protect __hdd_uninit from SSR
5618
5619 This is called during the netdev unregister to uninitialize all data
5620associated with the device
5621
5622 \param - dev Pointer to net_device structure
5623
5624 \return - void
5625
5626 --------------------------------------------------------------------------*/
5627static void hdd_uninit (struct net_device *dev)
5628{
5629 vos_ssr_protect(__func__);
5630 __hdd_uninit(dev);
5631 vos_ssr_unprotect(__func__);
5632}
5633
5634/**---------------------------------------------------------------------------
5635
Jeff Johnson295189b2012-06-20 16:38:30 -07005636 \brief hdd_release_firmware() -
5637
5638 This function calls the release firmware API to free the firmware buffer.
5639
5640 \param - pFileName Pointer to the File Name.
5641 pCtx - Pointer to the adapter .
5642
5643
5644 \return - 0 for success, non zero for failure
5645
5646 --------------------------------------------------------------------------*/
5647
5648VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
5649{
5650 VOS_STATUS status = VOS_STATUS_SUCCESS;
5651 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
5652 ENTER();
5653
5654
5655 if (!strcmp(WLAN_FW_FILE, pFileName)) {
5656
5657 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
5658
5659 if(pHddCtx->fw) {
5660 release_firmware(pHddCtx->fw);
5661 pHddCtx->fw = NULL;
5662 }
5663 else
5664 status = VOS_STATUS_E_FAILURE;
5665 }
5666 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
5667 if(pHddCtx->nv) {
5668 release_firmware(pHddCtx->nv);
5669 pHddCtx->nv = NULL;
5670 }
5671 else
5672 status = VOS_STATUS_E_FAILURE;
5673
5674 }
5675
5676 EXIT();
5677 return status;
5678}
5679
5680/**---------------------------------------------------------------------------
5681
5682 \brief hdd_request_firmware() -
5683
5684 This function reads the firmware file using the request firmware
5685 API and returns the the firmware data and the firmware file size.
5686
5687 \param - pfileName - Pointer to the file name.
5688 - pCtx - Pointer to the adapter .
5689 - ppfw_data - Pointer to the pointer of the firmware data.
5690 - pSize - Pointer to the file size.
5691
5692 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
5693
5694 --------------------------------------------------------------------------*/
5695
5696
5697VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
5698{
5699 int status;
5700 VOS_STATUS retval = VOS_STATUS_SUCCESS;
5701 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
5702 ENTER();
5703
5704 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
5705
5706 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
5707
5708 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
5709 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
5710 __func__, pfileName);
5711 retval = VOS_STATUS_E_FAILURE;
5712 }
5713
5714 else {
5715 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
5716 *pSize = pHddCtx->fw->size;
5717 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
5718 __func__, *pSize);
5719 }
5720 }
5721 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
5722
5723 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
5724
5725 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
5726 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
5727 __func__, pfileName);
5728 retval = VOS_STATUS_E_FAILURE;
5729 }
5730
5731 else {
5732 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
5733 *pSize = pHddCtx->nv->size;
5734 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
5735 __func__, *pSize);
5736 }
5737 }
5738
5739 EXIT();
5740 return retval;
5741}
5742/**---------------------------------------------------------------------------
5743 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
5744
5745 This is the function invoked by SME to inform the result of a full power
5746 request issued by HDD
5747
5748 \param - callbackcontext - Pointer to cookie
5749 status - result of request
5750
5751 \return - None
5752
5753--------------------------------------------------------------------------*/
5754void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
5755{
5756 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
5757
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07005758 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07005759 if(&pHddCtx->full_pwr_comp_var)
5760 {
5761 complete(&pHddCtx->full_pwr_comp_var);
5762 }
5763}
5764
5765/**---------------------------------------------------------------------------
5766
5767 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
5768
5769 This is the function invoked by SME to inform the result of BMPS
5770 request issued by HDD
5771
5772 \param - callbackcontext - Pointer to cookie
5773 status - result of request
5774
5775 \return - None
5776
5777--------------------------------------------------------------------------*/
5778void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
5779{
5780
5781 struct completion *completion_var = (struct completion*) callbackContext;
5782
Arif Hussain6d2a3322013-11-17 19:50:10 -08005783 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07005784 if(completion_var != NULL)
5785 {
5786 complete(completion_var);
5787 }
5788}
5789
5790/**---------------------------------------------------------------------------
5791
5792 \brief hdd_get_cfg_file_size() -
5793
5794 This function reads the configuration file using the request firmware
5795 API and returns the configuration file size.
5796
5797 \param - pCtx - Pointer to the adapter .
5798 - pFileName - Pointer to the file name.
5799 - pBufSize - Pointer to the buffer size.
5800
5801 \return - 0 for success, non zero for failure
5802
5803 --------------------------------------------------------------------------*/
5804
5805VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
5806{
5807 int status;
5808 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
5809
5810 ENTER();
5811
5812 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
5813
5814 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
5815 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
5816 status = VOS_STATUS_E_FAILURE;
5817 }
5818 else {
5819 *pBufSize = pHddCtx->fw->size;
5820 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
5821 release_firmware(pHddCtx->fw);
5822 pHddCtx->fw = NULL;
5823 }
5824
5825 EXIT();
5826 return VOS_STATUS_SUCCESS;
5827}
5828
5829/**---------------------------------------------------------------------------
5830
5831 \brief hdd_read_cfg_file() -
5832
5833 This function reads the configuration file using the request firmware
5834 API and returns the cfg data and the buffer size of the configuration file.
5835
5836 \param - pCtx - Pointer to the adapter .
5837 - pFileName - Pointer to the file name.
5838 - pBuffer - Pointer to the data buffer.
5839 - pBufSize - Pointer to the buffer size.
5840
5841 \return - 0 for success, non zero for failure
5842
5843 --------------------------------------------------------------------------*/
5844
5845VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
5846 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
5847{
5848 int status;
5849 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
5850
5851 ENTER();
5852
5853 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
5854
5855 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
5856 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
5857 return VOS_STATUS_E_FAILURE;
5858 }
5859 else {
5860 if(*pBufSize != pHddCtx->fw->size) {
5861 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
5862 "file size", __func__);
5863 release_firmware(pHddCtx->fw);
5864 pHddCtx->fw = NULL;
5865 return VOS_STATUS_E_FAILURE;
5866 }
5867 else {
5868 if(pBuffer) {
5869 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
5870 }
5871 release_firmware(pHddCtx->fw);
5872 pHddCtx->fw = NULL;
5873 }
5874 }
5875
5876 EXIT();
5877
5878 return VOS_STATUS_SUCCESS;
5879}
5880
5881/**---------------------------------------------------------------------------
5882
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305883 \brief __hdd_set_mac_address() -
Jeff Johnson295189b2012-06-20 16:38:30 -07005884
5885 This function sets the user specified mac address using
5886 the command ifconfig wlanX hw ether <mac adress>.
5887
5888 \param - dev - Pointer to the net device.
5889 - addr - Pointer to the sockaddr.
5890 \return - 0 for success, non zero for failure
5891
5892 --------------------------------------------------------------------------*/
5893
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305894static int __hdd_set_mac_address(struct net_device *dev, void *addr)
Jeff Johnson295189b2012-06-20 16:38:30 -07005895{
Mahesh A Saptasagar74088392015-02-05 17:22:09 +05305896 hdd_adapter_t *pAdapter;
5897 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07005898 struct sockaddr *psta_mac_addr = addr;
5899 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
Mahesh A Saptasagar74088392015-02-05 17:22:09 +05305900 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07005901
5902 ENTER();
Mahesh A Saptasagar74088392015-02-05 17:22:09 +05305903 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5904 if (NULL == pAdapter)
5905 {
5906 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5907 "%s: Adapter is NULL",__func__);
5908 return -EINVAL;
5909 }
5910 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
5911 ret = wlan_hdd_validate_context(pHddCtx);
5912 if (0 != ret)
5913 {
5914 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5915 "%s: HDD context is not valid",__func__);
5916 return ret;
5917 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005918
5919 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
Jeff Johnson295189b2012-06-20 16:38:30 -07005920 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
5921
5922 EXIT();
5923 return halStatus;
5924}
5925
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305926/**---------------------------------------------------------------------------
5927
5928 \brief hdd_set_mac_address() -
5929
5930 Wrapper function to protect __hdd_set_mac_address() function from ssr
5931
5932 \param - dev - Pointer to the net device.
5933 - addr - Pointer to the sockaddr.
5934 \return - 0 for success, non zero for failure
5935
5936 --------------------------------------------------------------------------*/
5937static int hdd_set_mac_address(struct net_device *dev, void *addr)
5938{
5939 int ret;
5940
5941 vos_ssr_protect(__func__);
5942 ret = __hdd_set_mac_address(dev, addr);
5943 vos_ssr_unprotect(__func__);
5944
5945 return ret;
5946}
5947
Jeff Johnson295189b2012-06-20 16:38:30 -07005948tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
5949{
5950 int i;
5951 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5952 {
Abhishek Singheb183782014-02-06 13:37:21 +05305953 if( 0 == ((pHddCtx->cfg_ini->intfAddrMask) & (1 << i)) )
Jeff Johnson295189b2012-06-20 16:38:30 -07005954 break;
5955 }
5956
5957 if( VOS_MAX_CONCURRENCY_PERSONA == i)
5958 return NULL;
5959
5960 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
5961 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
5962}
5963
5964void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
5965{
5966 int i;
5967 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5968 {
5969 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
5970 {
5971 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
5972 break;
5973 }
5974 }
5975 return;
5976}
5977
5978#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
5979 static struct net_device_ops wlan_drv_ops = {
5980 .ndo_open = hdd_open,
5981 .ndo_stop = hdd_stop,
5982 .ndo_uninit = hdd_uninit,
5983 .ndo_start_xmit = hdd_hard_start_xmit,
5984 .ndo_tx_timeout = hdd_tx_timeout,
5985 .ndo_get_stats = hdd_stats,
5986 .ndo_do_ioctl = hdd_ioctl,
5987 .ndo_set_mac_address = hdd_set_mac_address,
5988 .ndo_select_queue = hdd_select_queue,
5989#ifdef WLAN_FEATURE_PACKET_FILTERING
5990#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
5991 .ndo_set_rx_mode = hdd_set_multicast_list,
5992#else
5993 .ndo_set_multicast_list = hdd_set_multicast_list,
5994#endif //LINUX_VERSION_CODE
5995#endif
5996 };
Jeff Johnson295189b2012-06-20 16:38:30 -07005997 static struct net_device_ops wlan_mon_drv_ops = {
5998 .ndo_open = hdd_mon_open,
5999 .ndo_stop = hdd_stop,
6000 .ndo_uninit = hdd_uninit,
6001 .ndo_start_xmit = hdd_mon_hard_start_xmit,
6002 .ndo_tx_timeout = hdd_tx_timeout,
6003 .ndo_get_stats = hdd_stats,
6004 .ndo_do_ioctl = hdd_ioctl,
6005 .ndo_set_mac_address = hdd_set_mac_address,
6006 };
Mahesh A Saptasagard477b092015-02-06 15:12:16 +05306007 static struct net_device_ops nullify_netdev_ops = {
6008 .ndo_open = NULL,
6009 .ndo_stop = NULL,
6010 .ndo_uninit = NULL,
6011 .ndo_start_xmit = NULL,
6012 .ndo_tx_timeout = NULL,
6013 .ndo_get_stats = NULL,
6014 .ndo_set_mac_address = NULL,
6015 .ndo_do_ioctl = NULL,
6016 .ndo_change_mtu = NULL,
6017 .ndo_select_queue = NULL,
6018 };
Jeff Johnson295189b2012-06-20 16:38:30 -07006019#endif
6020
6021void hdd_set_station_ops( struct net_device *pWlanDev )
6022{
6023#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
Jeff Johnson295189b2012-06-20 16:38:30 -07006024 pWlanDev->netdev_ops = &wlan_drv_ops;
6025#else
6026 pWlanDev->open = hdd_open;
6027 pWlanDev->stop = hdd_stop;
6028 pWlanDev->uninit = hdd_uninit;
6029 pWlanDev->hard_start_xmit = NULL;
6030 pWlanDev->tx_timeout = hdd_tx_timeout;
6031 pWlanDev->get_stats = hdd_stats;
6032 pWlanDev->do_ioctl = hdd_ioctl;
Jeff Johnson295189b2012-06-20 16:38:30 -07006033 pWlanDev->set_mac_address = hdd_set_mac_address;
6034#endif
6035}
6036
Jeff Johnsoneed415b2013-01-18 16:11:20 -08006037static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07006038{
6039 struct net_device *pWlanDev = NULL;
6040 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006041 /*
6042 * cfg80211 initialization and registration....
6043 */
6044 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
6045
Jeff Johnson295189b2012-06-20 16:38:30 -07006046 if(pWlanDev != NULL)
6047 {
6048
6049 //Save the pointer to the net_device in the HDD adapter
6050 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
6051
Jeff Johnson295189b2012-06-20 16:38:30 -07006052 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
6053
6054 pAdapter->dev = pWlanDev;
6055 pAdapter->pHddCtx = pHddCtx;
6056 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
Agarwal Ashish47d18112014-08-04 19:55:07 +05306057 spin_lock_init(&pAdapter->lock_for_active_session);
Jeff Johnson295189b2012-06-20 16:38:30 -07006058
6059 init_completion(&pAdapter->session_open_comp_var);
6060 init_completion(&pAdapter->session_close_comp_var);
6061 init_completion(&pAdapter->disconnect_comp_var);
6062 init_completion(&pAdapter->linkup_event_var);
6063 init_completion(&pAdapter->cancel_rem_on_chan_var);
6064 init_completion(&pAdapter->rem_on_chan_ready_event);
Vinay Krishna Erannaf0e523b2014-03-01 21:00:16 +05306065 init_completion(&pAdapter->pno_comp_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07006066#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
6067 init_completion(&pAdapter->offchannel_tx_event);
6068#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006069 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006070#ifdef FEATURE_WLAN_TDLS
6071 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07006072 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08006073 init_completion(&pAdapter->tdls_mgmt_comp);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05306074 init_completion(&pAdapter->tdls_link_establish_req_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08006075#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006076 init_completion(&pHddCtx->mc_sus_event_var);
6077 init_completion(&pHddCtx->tx_sus_event_var);
Gopichand Nakkala05621412013-06-19 19:37:38 +05306078 init_completion(&pHddCtx->rx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07006079 init_completion(&pAdapter->ula_complete);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07006080 init_completion(&pAdapter->change_country_code);
Jeff Johnson295189b2012-06-20 16:38:30 -07006081
Rajeev79dbe4c2013-10-05 11:03:42 +05306082#ifdef FEATURE_WLAN_BATCH_SCAN
6083 init_completion(&pAdapter->hdd_set_batch_scan_req_var);
6084 init_completion(&pAdapter->hdd_get_batch_scan_req_var);
6085 pAdapter->pBatchScanRsp = NULL;
6086 pAdapter->numScanList = 0;
Rajeev Kumar20140c12013-10-21 19:39:02 -07006087 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
Kiet Lamaa8e15a2014-02-11 23:30:06 -08006088 pAdapter->prev_batch_id = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05306089 mutex_init(&pAdapter->hdd_batch_scan_lock);
6090#endif
6091
Jeff Johnson295189b2012-06-20 16:38:30 -07006092 pAdapter->isLinkUpSvcNeeded = FALSE;
6093 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
6094 //Init the net_device structure
6095 strlcpy(pWlanDev->name, name, IFNAMSIZ);
6096
6097 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
6098 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
6099 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
6100 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
6101
6102 hdd_set_station_ops( pAdapter->dev );
6103
6104 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07006105 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
6106 pAdapter->wdev.wiphy = pHddCtx->wiphy;
6107 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07006108 /* set pWlanDev's parent to underlying device */
6109 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
Kumar Anand82c009f2014-05-29 00:29:42 -07006110
6111 hdd_wmm_init( pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07006112 }
6113
6114 return pAdapter;
6115}
6116
6117VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
6118{
6119 struct net_device *pWlanDev = pAdapter->dev;
6120 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
6121 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
6122 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
6123
6124 if( rtnl_lock_held )
6125 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08006126 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07006127 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
6128 {
6129 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
6130 return VOS_STATUS_E_FAILURE;
6131 }
6132 }
6133 if (register_netdevice(pWlanDev))
6134 {
6135 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
6136 return VOS_STATUS_E_FAILURE;
6137 }
6138 }
6139 else
6140 {
6141 if(register_netdev(pWlanDev))
6142 {
6143 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
6144 return VOS_STATUS_E_FAILURE;
6145 }
6146 }
6147 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
6148
6149 return VOS_STATUS_SUCCESS;
6150}
6151
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07006152static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07006153{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07006154 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07006155
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07006156 if (NULL == pAdapter)
6157 {
6158 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
6159 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07006160 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07006161
6162 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
6163 {
6164 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
6165 return eHAL_STATUS_NOT_INITIALIZED;
6166 }
6167
6168 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
6169
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006170#ifndef WLAN_OPEN_SOURCE
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07006171 /* need to make sure all of our scheduled work has completed.
6172 * This callback is called from MC thread context, so it is safe to
6173 * to call below flush workqueue API from here.
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006174 *
6175 * Even though this is called from MC thread context, if there is a faulty
6176 * work item in the system, that can hang this call forever. So flushing
6177 * this global work queue is not safe; and now we make sure that
6178 * individual work queues are stopped correctly. But the cancel work queue
6179 * is a GPL only API, so the proprietary version of the driver would still
6180 * rely on the global work queue flush.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07006181 */
6182 flush_scheduled_work();
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006183#endif
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07006184
6185 /* We can be blocked while waiting for scheduled work to be
6186 * flushed, and the adapter structure can potentially be freed, in
6187 * which case the magic will have been reset. So make sure the
6188 * magic is still good, and hence the adapter structure is still
6189 * valid, before signaling completion */
6190 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
6191 {
6192 complete(&pAdapter->session_close_comp_var);
6193 }
6194
Jeff Johnson295189b2012-06-20 16:38:30 -07006195 return eHAL_STATUS_SUCCESS;
6196}
6197
6198VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
6199{
6200 struct net_device *pWlanDev = pAdapter->dev;
6201 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
6202 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
6203 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
6204 VOS_STATUS status = VOS_STATUS_E_FAILURE;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306205 long rc = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006206
6207 INIT_COMPLETION(pAdapter->session_open_comp_var);
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07006208 sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07006209 //Open a SME session for future operation
6210 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07006211 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07006212 if ( !HAL_STATUS_SUCCESS( halStatus ) )
6213 {
6214 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07006215 "sme_OpenSession() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07006216 halStatus, halStatus );
6217 status = VOS_STATUS_E_FAILURE;
6218 goto error_sme_open;
6219 }
6220
6221 //Block on a completion variable. Can't wait forever though.
Vinay Krishna Eranna0fe2e7c2014-04-09 21:32:08 +05306222 rc = wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07006223 &pAdapter->session_open_comp_var,
6224 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306225 if (rc <= 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07006226 {
6227 hddLog(VOS_TRACE_LEVEL_FATAL,
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306228 "Session is not opened within timeout period code %ld", rc );
Jeff Johnson295189b2012-06-20 16:38:30 -07006229 status = VOS_STATUS_E_FAILURE;
6230 goto error_sme_open;
6231 }
6232
6233 // Register wireless extensions
6234 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
6235 {
6236 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07006237 "hdd_register_wext() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07006238 halStatus, halStatus );
6239 status = VOS_STATUS_E_FAILURE;
6240 goto error_register_wext;
6241 }
6242 //Safe to register the hard_start_xmit function again
6243#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
6244 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
6245#else
6246 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
6247#endif
6248
6249 //Set the Connection State to Not Connected
Abhishek Singhf4669da2014-05-26 15:07:49 +05306250 hddLog(VOS_TRACE_LEVEL_INFO,
6251 "%s: Set HDD connState to eConnectionState_NotConnected",
6252 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006253 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
6254
6255 //Set the default operation channel
6256 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
6257
6258 /* Make the default Auth Type as OPEN*/
6259 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
6260
6261 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
6262 {
6263 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07006264 "hdd_init_tx_rx() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07006265 status, status );
6266 goto error_init_txrx;
6267 }
6268
6269 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
6270
6271 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
6272 {
6273 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07006274 "hdd_wmm_adapter_init() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07006275 status, status );
6276 goto error_wmm_init;
6277 }
6278
6279 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
6280
6281 return VOS_STATUS_SUCCESS;
6282
6283error_wmm_init:
6284 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
6285 hdd_deinit_tx_rx(pAdapter);
6286error_init_txrx:
6287 hdd_UnregisterWext(pWlanDev);
6288error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07006289 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07006290 {
6291 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07006292 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07006293 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07006294 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07006295 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306296 unsigned long rc;
6297
Jeff Johnson295189b2012-06-20 16:38:30 -07006298 //Block on a completion variable. Can't wait forever though.
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306299 rc = wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07006300 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07006301 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306302 if (rc <= 0)
6303 hddLog(VOS_TRACE_LEVEL_ERROR,
6304 FL("Session is not opened within timeout period code %ld"), rc);
Jeff Johnson295189b2012-06-20 16:38:30 -07006305 }
6306}
6307error_sme_open:
6308 return status;
6309}
6310
Jeff Johnson295189b2012-06-20 16:38:30 -07006311void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
6312{
6313 hdd_cfg80211_state_t *cfgState;
6314
6315 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
6316
6317 if( NULL != cfgState->buf )
6318 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306319 long rc;
Jeff Johnson295189b2012-06-20 16:38:30 -07006320 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
6321 rc = wait_for_completion_interruptible_timeout(
6322 &pAdapter->tx_action_cnf_event,
6323 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306324 if (rc <= 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07006325 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08006326 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306327 "%s ERROR: HDD Wait for Action Confirmation Failed!! %ld"
6328 , __func__, rc);
Jeff Johnson295189b2012-06-20 16:38:30 -07006329 }
6330 }
6331 return;
6332}
Jeff Johnson295189b2012-06-20 16:38:30 -07006333
c_hpothu002231a2015-02-05 14:58:51 +05306334void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
Jeff Johnson295189b2012-06-20 16:38:30 -07006335{
6336 ENTER();
6337 switch ( pAdapter->device_mode )
6338 {
6339 case WLAN_HDD_INFRA_STATION:
6340 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006341 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07006342 {
6343 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
6344 {
6345 hdd_deinit_tx_rx( pAdapter );
6346 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
6347 }
6348
6349 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
6350 {
6351 hdd_wmm_adapter_close( pAdapter );
6352 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
6353 }
6354
Jeff Johnson295189b2012-06-20 16:38:30 -07006355 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07006356 break;
6357 }
6358
6359 case WLAN_HDD_SOFTAP:
6360 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07006361 {
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05306362
6363 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
6364 {
6365 hdd_wmm_adapter_close( pAdapter );
6366 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
6367 }
6368
Jeff Johnson295189b2012-06-20 16:38:30 -07006369 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07006370
c_hpothu002231a2015-02-05 14:58:51 +05306371 hdd_unregister_hostapd(pAdapter, rtnl_held);
Jeff Johnson295189b2012-06-20 16:38:30 -07006372 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07006373 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07006374 break;
6375 }
6376
6377 case WLAN_HDD_MONITOR:
6378 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006379 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07006380 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
6381 {
6382 hdd_deinit_tx_rx( pAdapter );
6383 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
6384 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006385 if(NULL != pAdapterforTx)
6386 {
6387 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
6388 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006389 break;
6390 }
6391
6392
6393 default:
6394 break;
6395 }
6396
6397 EXIT();
6398}
6399
6400void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
6401{
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -08006402 struct net_device *pWlanDev = NULL;
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05306403
6404 ENTER();
6405 if (NULL == pAdapter)
6406 {
6407 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6408 "%s: HDD adapter is Null", __func__);
6409 return;
6410 }
6411
6412 pWlanDev = pAdapter->dev;
Jeff Johnson295189b2012-06-20 16:38:30 -07006413
Rajeev79dbe4c2013-10-05 11:03:42 +05306414#ifdef FEATURE_WLAN_BATCH_SCAN
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05306415 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
6416 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Rajeev Kumarf999e582014-01-09 17:33:29 -08006417 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05306418 || (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)
6419 )
6420 {
Rajeev Kumarf999e582014-01-09 17:33:29 -08006421 if (pAdapter)
Rajeev79dbe4c2013-10-05 11:03:42 +05306422 {
Rajeev Kumarf999e582014-01-09 17:33:29 -08006423 if (eHDD_BATCH_SCAN_STATE_STARTED == pAdapter->batchScanState)
6424 {
6425 hdd_deinit_batch_scan(pAdapter);
6426 }
Rajeev79dbe4c2013-10-05 11:03:42 +05306427 }
Rajeev Kumarf999e582014-01-09 17:33:29 -08006428 }
Rajeev79dbe4c2013-10-05 11:03:42 +05306429#endif
6430
Jeff Johnson295189b2012-06-20 16:38:30 -07006431 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
6432 if( rtnl_held )
6433 {
6434 unregister_netdevice(pWlanDev);
6435 }
6436 else
6437 {
6438 unregister_netdev(pWlanDev);
6439 }
6440 // note that the pAdapter is no longer valid at this point
6441 // since the memory has been reclaimed
6442 }
6443
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05306444 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07006445}
6446
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006447void hdd_set_pwrparams(hdd_context_t *pHddCtx)
6448{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306449 VOS_STATUS status;
6450 hdd_adapter_t *pAdapter = NULL;
6451 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006452
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306453 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006454
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306455 /*loop through all adapters.*/
6456 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006457 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306458 pAdapter = pAdapterNode->pAdapter;
6459 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
6460 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006461
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306462 { // we skip this registration for modes other than STA and P2P client modes.
6463 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6464 pAdapterNode = pNext;
6465 continue;
6466 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006467
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306468 //Apply Dynamic DTIM For P2P
6469 //Only if ignoreDynamicDtimInP2pMode is not set in ini
6470 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
6471 pHddCtx->cfg_ini->enableModulatedDTIM) &&
6472 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
6473 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
6474 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
6475 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
6476 (eConnectionState_Associated ==
6477 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
6478 (pHddCtx->cfg_ini->fIsBmpsEnabled))
6479 {
6480 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006481
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306482 powerRequest.uIgnoreDTIM = 1;
6483 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
6484
6485 if (pHddCtx->cfg_ini->enableModulatedDTIM)
6486 {
6487 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
6488 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
6489 }
6490 else
6491 {
6492 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
6493 }
6494
6495 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
6496 * specified during Enter/Exit BMPS when LCD off*/
6497 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
6498 NULL, eANI_BOOLEAN_FALSE);
6499 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
6500 NULL, eANI_BOOLEAN_FALSE);
6501
6502 /* switch to the DTIM specified in cfg.ini */
6503 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6504 "Switch to DTIM %d", powerRequest.uListenInterval);
6505 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
6506 break;
6507
6508 }
6509
6510 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6511 pAdapterNode = pNext;
6512 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006513}
6514
6515void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
6516{
6517 /*Switch back to DTIM 1*/
6518 tSirSetPowerParamsReq powerRequest = { 0 };
6519
6520 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
6521 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07006522 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006523
6524 /* Update ignoreDTIM and ListedInterval in CFG with default values */
6525 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
6526 NULL, eANI_BOOLEAN_FALSE);
6527 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
6528 NULL, eANI_BOOLEAN_FALSE);
6529
6530 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6531 "Switch to DTIM%d",powerRequest.uListenInterval);
6532 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
6533
6534}
6535
Jeff Johnson295189b2012-06-20 16:38:30 -07006536VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
6537{
6538 VOS_STATUS status = VOS_STATUS_SUCCESS;
Sushant Kaushik4928e542014-12-29 15:25:54 +05306539 if (WLAN_HDD_IS_UNLOAD_IN_PROGRESS(pHddCtx))
6540 {
6541 hddLog( LOGE, FL("Wlan Unload in progress"));
6542 return VOS_STATUS_E_PERM;
6543 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006544 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
6545 {
6546 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
6547 }
6548
6549 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
6550 {
6551 sme_StartAutoBmpsTimer(pHddCtx->hHal);
6552 }
6553
6554 if (pHddCtx->cfg_ini->fIsImpsEnabled)
6555 {
6556 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
6557 }
6558
6559 return status;
6560}
6561
6562VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
6563{
6564 hdd_adapter_t *pAdapter = NULL;
6565 eHalStatus halStatus;
6566 VOS_STATUS status = VOS_STATUS_E_INVAL;
6567 v_BOOL_t disableBmps = FALSE;
6568 v_BOOL_t disableImps = FALSE;
6569
6570 switch(session_type)
6571 {
6572 case WLAN_HDD_INFRA_STATION:
6573 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07006574 case WLAN_HDD_P2P_CLIENT:
6575 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07006576 //Exit BMPS -> Is Sta/P2P Client is already connected
6577 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
6578 if((NULL != pAdapter)&&
6579 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
6580 {
6581 disableBmps = TRUE;
6582 }
6583
6584 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
6585 if((NULL != pAdapter)&&
6586 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
6587 {
6588 disableBmps = TRUE;
6589 }
6590
6591 //Exit both Bmps and Imps incase of Go/SAP Mode
6592 if((WLAN_HDD_SOFTAP == session_type) ||
6593 (WLAN_HDD_P2P_GO == session_type))
6594 {
6595 disableBmps = TRUE;
6596 disableImps = TRUE;
6597 }
6598
6599 if(TRUE == disableImps)
6600 {
6601 if (pHddCtx->cfg_ini->fIsImpsEnabled)
6602 {
6603 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
6604 }
6605 }
6606
6607 if(TRUE == disableBmps)
6608 {
6609 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
6610 {
6611 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
6612
6613 if(eHAL_STATUS_SUCCESS != halStatus)
6614 {
6615 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08006616 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006617 VOS_ASSERT(0);
6618 return status;
6619 }
6620 }
6621
6622 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
6623 {
6624 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
6625
6626 if(eHAL_STATUS_SUCCESS != halStatus)
6627 {
6628 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08006629 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006630 VOS_ASSERT(0);
6631 return status;
6632 }
6633 }
6634 }
6635
6636 if((TRUE == disableBmps) ||
6637 (TRUE == disableImps))
6638 {
6639 /* Now, get the chip into Full Power now */
6640 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
6641 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
6642 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
6643
6644 if(halStatus != eHAL_STATUS_SUCCESS)
6645 {
6646 if(halStatus == eHAL_STATUS_PMC_PENDING)
6647 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306648 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07006649 //Block on a completion variable. Can't wait forever though
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306650 ret = wait_for_completion_interruptible_timeout(
6651 &pHddCtx->full_pwr_comp_var,
6652 msecs_to_jiffies(1000));
6653 if (ret <= 0)
6654 {
6655 hddLog(VOS_TRACE_LEVEL_ERROR,
6656 "%s: wait on full_pwr_comp_var failed %ld",
6657 __func__, ret);
6658 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006659 }
6660 else
6661 {
6662 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08006663 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006664 VOS_ASSERT(0);
6665 return status;
6666 }
6667 }
6668
6669 status = VOS_STATUS_SUCCESS;
6670 }
6671
6672 break;
6673 }
6674 return status;
6675}
6676
6677hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08006678 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07006679 tANI_U8 rtnl_held )
6680{
6681 hdd_adapter_t *pAdapter = NULL;
6682 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
6683 VOS_STATUS status = VOS_STATUS_E_FAILURE;
6684 VOS_STATUS exitbmpsStatus;
6685
Arif Hussain6d2a3322013-11-17 19:50:10 -08006686 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d",__func__,iface_name,session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006687
Nirav Shah436658f2014-02-28 17:05:45 +05306688 if(macAddr == NULL)
6689 {
6690 /* Not received valid macAddr */
6691 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6692 "%s:Unable to add virtual intf: Not able to get"
6693 "valid mac address",__func__);
6694 return NULL;
6695 }
6696
Jeff Johnson295189b2012-06-20 16:38:30 -07006697 //Disable BMPS incase of Concurrency
6698 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
6699
6700 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
6701 {
6702 //Fail to Exit BMPS
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306703 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Exit BMPS", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006704 VOS_ASSERT(0);
6705 return NULL;
6706 }
6707
6708 switch(session_type)
6709 {
6710 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07006711 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006712 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07006713 {
6714 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
6715
6716 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306717 {
6718 hddLog(VOS_TRACE_LEVEL_FATAL,
6719 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006720 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306721 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006722
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306723#ifdef FEATURE_WLAN_TDLS
6724 /* A Mutex Lock is introduced while changing/initializing the mode to
6725 * protect the concurrent access for the Adapters by TDLS module.
6726 */
Rajesh Chauhana34c6e62014-03-25 16:37:58 +05306727 mutex_lock(&pHddCtx->tdls_lock);
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306728#endif
6729
Jeff Johnsone7245742012-09-05 17:12:55 -07006730 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
6731 NL80211_IFTYPE_P2P_CLIENT:
6732 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07006733
Jeff Johnson295189b2012-06-20 16:38:30 -07006734 pAdapter->device_mode = session_type;
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306735#ifdef FEATURE_WLAN_TDLS
6736 mutex_unlock(&pHddCtx->tdls_lock);
6737#endif
Sunil Dutt66485cb2013-12-19 19:05:03 +05306738
6739 status = hdd_init_station_mode( pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07006740 if( VOS_STATUS_SUCCESS != status )
6741 goto err_free_netdev;
6742
6743 status = hdd_register_interface( pAdapter, rtnl_held );
6744 if( VOS_STATUS_SUCCESS != status )
6745 {
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05306746#ifdef FEATURE_WLAN_TDLS
6747 mutex_lock(&pHddCtx->tdls_lock);
6748#endif
c_hpothu002231a2015-02-05 14:58:51 +05306749 hdd_deinit_adapter(pHddCtx, pAdapter, rtnl_held);
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05306750#ifdef FEATURE_WLAN_TDLS
6751 mutex_unlock(&pHddCtx->tdls_lock);
6752#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006753 goto err_free_netdev;
6754 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306755
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05306756 // Workqueue which gets scheduled in IPv4 notification callback.
6757 INIT_WORK(&pAdapter->ipv4NotifierWorkQueue, hdd_ipv4_notifier_work_queue);
6758
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306759#ifdef WLAN_NS_OFFLOAD
6760 // Workqueue which gets scheduled in IPv6 notification callback.
6761 INIT_WORK(&pAdapter->ipv6NotifierWorkQueue, hdd_ipv6_notifier_work_queue);
6762#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006763 //Stop the Interface TX queue.
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05306764 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
Jeff Johnson295189b2012-06-20 16:38:30 -07006765 netif_tx_disable(pAdapter->dev);
6766 //netif_tx_disable(pWlanDev);
6767 netif_carrier_off(pAdapter->dev);
6768
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +05306769 if (WLAN_HDD_P2P_CLIENT == session_type ||
6770 WLAN_HDD_P2P_DEVICE == session_type)
6771 {
6772 /* Initialize the work queue to defer the
6773 * back to back RoC request */
6774 INIT_DELAYED_WORK(&pAdapter->roc_work,
6775 hdd_p2p_roc_work_queue);
6776 }
6777
Jeff Johnson295189b2012-06-20 16:38:30 -07006778 break;
6779 }
6780
Jeff Johnson295189b2012-06-20 16:38:30 -07006781 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07006782 case WLAN_HDD_SOFTAP:
6783 {
6784 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
6785 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306786 {
6787 hddLog(VOS_TRACE_LEVEL_FATAL,
6788 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006789 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306790 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006791
Jeff Johnson295189b2012-06-20 16:38:30 -07006792 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
6793 NL80211_IFTYPE_AP:
6794 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07006795 pAdapter->device_mode = session_type;
6796
6797 status = hdd_init_ap_mode(pAdapter);
6798 if( VOS_STATUS_SUCCESS != status )
6799 goto err_free_netdev;
6800
6801 status = hdd_register_hostapd( pAdapter, rtnl_held );
6802 if( VOS_STATUS_SUCCESS != status )
6803 {
c_hpothu002231a2015-02-05 14:58:51 +05306804 hdd_deinit_adapter(pHddCtx, pAdapter, rtnl_held);
Jeff Johnson295189b2012-06-20 16:38:30 -07006805 goto err_free_netdev;
6806 }
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05306807 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
Jeff Johnson295189b2012-06-20 16:38:30 -07006808 netif_tx_disable(pAdapter->dev);
6809 netif_carrier_off(pAdapter->dev);
6810
6811 hdd_set_conparam( 1 );
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +05306812
6813 if (WLAN_HDD_P2P_GO == session_type)
6814 {
6815 /* Initialize the work queue to
6816 * defer the back to back RoC request */
6817 INIT_DELAYED_WORK(&pAdapter->roc_work,
6818 hdd_p2p_roc_work_queue);
6819 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006820 break;
6821 }
6822 case WLAN_HDD_MONITOR:
6823 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006824 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
6825 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306826 {
6827 hddLog(VOS_TRACE_LEVEL_FATAL,
6828 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006829 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306830 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006831
6832 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
6833 pAdapter->device_mode = session_type;
6834 status = hdd_register_interface( pAdapter, rtnl_held );
6835#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
6836 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
6837#else
6838 pAdapter->dev->open = hdd_mon_open;
6839 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
6840#endif
6841 hdd_init_tx_rx( pAdapter );
6842 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
6843 //Set adapter to be used for data tx. It will use either GO or softap.
6844 pAdapter->sessionCtx.monitor.pAdapterForTx =
6845 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07006846 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
6847 {
6848 pAdapter->sessionCtx.monitor.pAdapterForTx =
6849 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
6850 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006851 /* This workqueue will be used to transmit management packet over
6852 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07006853 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
6854 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
6855 return NULL;
6856 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07006857
Jeff Johnson295189b2012-06-20 16:38:30 -07006858 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
6859 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07006860 }
6861 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07006862 case WLAN_HDD_FTM:
6863 {
6864 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
6865
6866 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306867 {
6868 hddLog(VOS_TRACE_LEVEL_FATAL,
6869 FL("failed to allocate adapter for session %d"), session_type);
6870 return NULL;
6871 }
6872
Jeff Johnson295189b2012-06-20 16:38:30 -07006873 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
6874 * message while loading driver in FTM mode. */
6875 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
6876 pAdapter->device_mode = session_type;
6877 status = hdd_register_interface( pAdapter, rtnl_held );
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05306878
6879 hdd_init_tx_rx( pAdapter );
6880
6881 //Stop the Interface TX queue.
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05306882 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05306883 netif_tx_disable(pAdapter->dev);
6884 netif_carrier_off(pAdapter->dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07006885 }
6886 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07006887 default:
6888 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306889 hddLog(VOS_TRACE_LEVEL_FATAL,"%s Invalid session type %d",
6890 __func__, session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006891 VOS_ASSERT(0);
6892 return NULL;
6893 }
6894 }
6895
Jeff Johnson295189b2012-06-20 16:38:30 -07006896 if( VOS_STATUS_SUCCESS == status )
6897 {
6898 //Add it to the hdd's session list.
6899 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
6900 if( NULL == pHddAdapterNode )
6901 {
6902 status = VOS_STATUS_E_NOMEM;
6903 }
6904 else
6905 {
6906 pHddAdapterNode->pAdapter = pAdapter;
6907 status = hdd_add_adapter_back ( pHddCtx,
6908 pHddAdapterNode );
6909 }
6910 }
6911
6912 if( VOS_STATUS_SUCCESS != status )
6913 {
6914 if( NULL != pAdapter )
6915 {
6916 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
6917 pAdapter = NULL;
6918 }
6919 if( NULL != pHddAdapterNode )
6920 {
6921 vos_mem_free( pHddAdapterNode );
6922 }
6923
6924 goto resume_bmps;
6925 }
6926
6927 if(VOS_STATUS_SUCCESS == status)
6928 {
6929 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
6930
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07006931 //Initialize the WoWL service
6932 if(!hdd_init_wowl(pAdapter))
6933 {
6934 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
6935 goto err_free_netdev;
6936 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006937 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006938 return pAdapter;
6939
6940err_free_netdev:
6941 free_netdev(pAdapter->dev);
6942 wlan_hdd_release_intf_addr( pHddCtx,
6943 pAdapter->macAddressCurrent.bytes );
6944
6945resume_bmps:
6946 //If bmps disabled enable it
6947 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
6948 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306949 if (pHddCtx->hdd_wlan_suspended)
6950 {
6951 hdd_set_pwrparams(pHddCtx);
6952 }
6953 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07006954 }
6955 return NULL;
6956}
6957
6958VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
6959 tANI_U8 rtnl_held )
6960{
6961 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
6962 VOS_STATUS status;
6963
6964 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
6965 if( VOS_STATUS_SUCCESS != status )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306966 {
6967 hddLog(VOS_TRACE_LEVEL_WARN,"%s: adapter list empty %d",
6968 __func__, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07006969 return status;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306970 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006971
6972 while ( pCurrent->pAdapter != pAdapter )
6973 {
6974 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
6975 if( VOS_STATUS_SUCCESS != status )
6976 break;
6977
6978 pCurrent = pNext;
6979 }
6980 pAdapterNode = pCurrent;
6981 if( VOS_STATUS_SUCCESS == status )
6982 {
6983 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
6984 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306985
6986#ifdef FEATURE_WLAN_TDLS
6987
6988 /* A Mutex Lock is introduced while changing/initializing the mode to
6989 * protect the concurrent access for the Adapters by TDLS module.
6990 */
Rajesh Chauhana34c6e62014-03-25 16:37:58 +05306991 mutex_lock(&pHddCtx->tdls_lock);
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306992#endif
6993
Jeff Johnson295189b2012-06-20 16:38:30 -07006994 hdd_remove_adapter( pHddCtx, pAdapterNode );
6995 vos_mem_free( pAdapterNode );
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08006996 pAdapterNode = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006997
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306998#ifdef FEATURE_WLAN_TDLS
6999 mutex_unlock(&pHddCtx->tdls_lock);
7000#endif
7001
Jeff Johnson295189b2012-06-20 16:38:30 -07007002
7003 /* If there is a single session of STA/P2P client, re-enable BMPS */
Agarwal Ashish51325b52014-06-16 16:50:49 +05307004 if ((!vos_concurrent_open_sessions_running()) &&
7005 ((pHddCtx->no_of_open_sessions[VOS_STA_MODE] >= 1) ||
7006 (pHddCtx->no_of_open_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
Jeff Johnson295189b2012-06-20 16:38:30 -07007007 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307008 if (pHddCtx->hdd_wlan_suspended)
7009 {
7010 hdd_set_pwrparams(pHddCtx);
7011 }
7012 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07007013 }
7014
7015 return VOS_STATUS_SUCCESS;
7016 }
7017
7018 return VOS_STATUS_E_FAILURE;
7019}
7020
7021VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
7022{
7023 hdd_adapter_list_node_t *pHddAdapterNode;
7024 VOS_STATUS status;
7025
7026 ENTER();
7027
7028 do
7029 {
7030 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
7031 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
7032 {
7033 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
7034 vos_mem_free( pHddAdapterNode );
7035 }
7036 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
7037
7038 EXIT();
7039
7040 return VOS_STATUS_SUCCESS;
7041}
7042
7043void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
7044{
7045 v_U8_t addIE[1] = {0};
7046
7047 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
7048 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
7049 eANI_BOOLEAN_FALSE) )
7050 {
7051 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08007052 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07007053 }
7054
7055 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
7056 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
7057 eANI_BOOLEAN_FALSE) )
7058 {
7059 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08007060 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07007061 }
7062
7063 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
7064 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
7065 eANI_BOOLEAN_FALSE) )
7066 {
7067 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08007068 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07007069 }
7070}
7071
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307072VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
7073 const v_BOOL_t bCloseSession )
Jeff Johnson295189b2012-06-20 16:38:30 -07007074{
7075 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
7076 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
Kaushik, Sushant4975a572014-10-21 16:07:48 +05307077 hdd_scaninfo_t *pScanInfo = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007078 union iwreq_data wrqu;
Kaushik, Sushant7005e372014-04-08 11:36:54 +05307079 v_U8_t retry = 0;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307080 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07007081
Anand N Sunkad26d71b92014-12-24 18:08:22 +05307082 if (pHddCtx->isLogpInProgress) {
7083 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
7084 "%s:LOGP in Progress. Ignore!!!",__func__);
7085 return VOS_STATUS_E_FAILURE;
7086 }
7087
Jeff Johnson295189b2012-06-20 16:38:30 -07007088 ENTER();
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +05307089
Kaushik, Sushant4975a572014-10-21 16:07:48 +05307090 pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07007091 switch(pAdapter->device_mode)
7092 {
7093 case WLAN_HDD_INFRA_STATION:
7094 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07007095 case WLAN_HDD_P2P_DEVICE:
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05307096 {
7097 hdd_station_ctx_t *pstation = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7098 if( hdd_connIsConnected(pstation) ||
7099 (pstation->conn_info.connState == eConnectionState_Connecting) )
Jeff Johnson295189b2012-06-20 16:38:30 -07007100 {
Mahesh A Saptasagarf5b8eff2015-01-31 01:07:07 +05307101#ifdef FEATURE_WLAN_TDLS
7102 mutex_lock(&pHddCtx->tdls_lock);
7103 wlan_hdd_tdls_exit(pAdapter);
7104 mutex_unlock(&pHddCtx->tdls_lock);
7105#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007106 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
7107 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
7108 pAdapter->sessionId,
7109 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
7110 else
7111 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
7112 pAdapter->sessionId,
7113 eCSR_DISCONNECT_REASON_UNSPECIFIED);
7114 //success implies disconnect command got queued up successfully
7115 if(halStatus == eHAL_STATUS_SUCCESS)
7116 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307117 ret = wait_for_completion_interruptible_timeout(
7118 &pAdapter->disconnect_comp_var,
7119 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
7120 if (ret <= 0)
7121 {
7122 hddLog(VOS_TRACE_LEVEL_ERROR,
7123 "%s: wait on disconnect_comp_var failed %ld",
7124 __func__, ret);
7125 }
7126 }
7127 else
7128 {
7129 hddLog(LOGE, "%s: failed to post disconnect event to SME",
7130 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007131 }
7132 memset(&wrqu, '\0', sizeof(wrqu));
7133 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
7134 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
7135 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
7136 }
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05307137 else if(pstation->conn_info.connState ==
7138 eConnectionState_Disconnecting)
7139 {
7140 ret = wait_for_completion_interruptible_timeout(
7141 &pAdapter->disconnect_comp_var,
7142 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
7143 if (ret <= 0)
7144 {
7145 hddLog(VOS_TRACE_LEVEL_ERROR,
7146 FL("wait on disconnect_comp_var failed %ld"), ret);
7147 }
7148 }
Kaushik, Sushant4975a572014-10-21 16:07:48 +05307149 else if(pScanInfo != NULL && pHddCtx->scan_info.mScanPending)
Jeff Johnson295189b2012-06-20 16:38:30 -07007150 {
Kaushik, Sushant4975a572014-10-21 16:07:48 +05307151 hdd_abort_mac_scan(pHddCtx, pScanInfo->sessionId,
Srinivas, Dasari138af4f2014-02-07 11:13:45 +05307152 eCSR_SCAN_ABORT_DEFAULT);
Jeff Johnson295189b2012-06-20 16:38:30 -07007153 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +05307154 if (pAdapter->device_mode != WLAN_HDD_INFRA_STATION)
7155 {
7156 while (pAdapter->is_roc_inprogress)
7157 {
7158 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7159 "%s: ROC in progress for session %d!!!",
7160 __func__, pAdapter->sessionId);
7161 // waiting for ROC to expire
7162 msleep(500);
7163 /* In GO present case , if retry exceeds 3,
7164 it means something went wrong. */
7165 if ( retry++ > MAX_WAIT_FOR_ROC_COMPLETION )
7166 {
7167 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7168 "%s: ROC completion is not received.!!!", __func__);
Deepthi Gowri70498252015-01-20 15:56:45 +05307169 if (eHAL_STATUS_SUCCESS !=
7170 sme_CancelRemainOnChannel( WLAN_HDD_GET_HAL_CTX( pAdapter),
7171 pAdapter->sessionId ))
7172 {
7173 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7174 FL("Failed to Cancel Remain on Channel"));
7175 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +05307176 wait_for_completion_interruptible_timeout(
7177 &pAdapter->cancel_rem_on_chan_var,
7178 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
7179 break;
7180 }
7181 }
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +05307182#ifdef WLAN_OPEN_SOURCE
7183 cancel_delayed_work_sync(&pAdapter->roc_work);
7184#endif
Kaushik, Sushant7005e372014-04-08 11:36:54 +05307185 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05307186#ifdef WLAN_NS_OFFLOAD
Vinay Krishna Eranna941360f2014-01-16 15:38:22 +05307187#ifdef WLAN_OPEN_SOURCE
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05307188 cancel_work_sync(&pAdapter->ipv6NotifierWorkQueue);
7189#endif
7190#endif
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +05307191
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05307192#ifdef WLAN_OPEN_SOURCE
7193 cancel_work_sync(&pAdapter->ipv4NotifierWorkQueue);
7194#endif
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +05307195
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307196 /* It is possible that the caller of this function does not
7197 * wish to close the session
7198 */
7199 if (VOS_TRUE == bCloseSession &&
7200 test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07007201 {
7202 INIT_COMPLETION(pAdapter->session_close_comp_var);
7203 if (eHAL_STATUS_SUCCESS ==
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307204 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
7205 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07007206 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307207 unsigned long ret;
7208
Jeff Johnson295189b2012-06-20 16:38:30 -07007209 //Block on a completion variable. Can't wait forever though.
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307210 ret = wait_for_completion_timeout(
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307211 &pAdapter->session_close_comp_var,
7212 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307213 if ( 0 >= ret)
7214 {
7215 hddLog(LOGE, "%s: failure waiting for session_close_comp_var %ld",
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307216 __func__, ret);
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307217 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007218 }
7219 }
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05307220 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007221 break;
7222
7223 case WLAN_HDD_SOFTAP:
7224 case WLAN_HDD_P2P_GO:
7225 //Any softap specific cleanup here...
Kaushik, Sushant7005e372014-04-08 11:36:54 +05307226 if (pAdapter->device_mode == WLAN_HDD_P2P_GO) {
7227 while (pAdapter->is_roc_inprogress) {
7228 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7229 "%s: ROC in progress for session %d!!!",
7230 __func__, pAdapter->sessionId);
7231 msleep(500);
7232 if ( retry++ > MAX_WAIT_FOR_ROC_COMPLETION ) {
7233 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7234 "%s: ROC completion is not received.!!!", __func__);
7235 WLANSAP_CancelRemainOnChannel(
7236 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
7237 wait_for_completion_interruptible_timeout(
7238 &pAdapter->cancel_rem_on_chan_var,
7239 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
7240 break;
7241 }
7242 }
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +05307243
7244#ifdef WLAN_OPEN_SOURCE
7245 cancel_delayed_work_sync(&pAdapter->roc_work);
7246#endif
Kaushik, Sushant7005e372014-04-08 11:36:54 +05307247 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007248 mutex_lock(&pHddCtx->sap_lock);
7249 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
7250 {
7251 VOS_STATUS status;
7252 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7253
7254 //Stop Bss.
7255 status = WLANSAP_StopBss(pHddCtx->pvosContext);
7256 if (VOS_IS_STATUS_SUCCESS(status))
7257 {
7258 hdd_hostapd_state_t *pHostapdState =
7259 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
7260
7261 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
7262
7263 if (!VOS_IS_STATUS_SUCCESS(status))
7264 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307265 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss %d",
7266 __func__, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07007267 }
7268 }
7269 else
7270 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007271 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007272 }
7273 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
Agarwal Ashish51325b52014-06-16 16:50:49 +05307274 wlan_hdd_decr_active_session(pHddCtx, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07007275
7276 if (eHAL_STATUS_FAILURE ==
7277 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
7278 0, NULL, eANI_BOOLEAN_FALSE))
7279 {
7280 hddLog(LOGE,
7281 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007282 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007283 }
7284
7285 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
7286 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
7287 eANI_BOOLEAN_FALSE) )
7288 {
7289 hddLog(LOGE,
7290 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
7291 }
7292
7293 // Reset WNI_CFG_PROBE_RSP Flags
7294 wlan_hdd_reset_prob_rspies(pAdapter);
7295 kfree(pAdapter->sessionCtx.ap.beacon);
7296 pAdapter->sessionCtx.ap.beacon = NULL;
7297 }
7298 mutex_unlock(&pHddCtx->sap_lock);
7299 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07007300
Jeff Johnson295189b2012-06-20 16:38:30 -07007301 case WLAN_HDD_MONITOR:
Sameer Thalappilbee426e2013-10-30 10:30:30 -07007302#ifdef WLAN_OPEN_SOURCE
7303 cancel_work_sync(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue);
7304#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007305 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07007306
Jeff Johnson295189b2012-06-20 16:38:30 -07007307 default:
7308 break;
7309 }
7310
7311 EXIT();
7312 return VOS_STATUS_SUCCESS;
7313}
7314
7315VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
7316{
7317 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7318 VOS_STATUS status;
7319 hdd_adapter_t *pAdapter;
7320
7321 ENTER();
7322
7323 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7324
7325 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7326 {
7327 pAdapter = pAdapterNode->pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07007328
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307329 hdd_stop_adapter( pHddCtx, pAdapter, VOS_TRUE );
Jeff Johnson295189b2012-06-20 16:38:30 -07007330
7331 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7332 pAdapterNode = pNext;
7333 }
7334
7335 EXIT();
7336
7337 return VOS_STATUS_SUCCESS;
7338}
7339
Rajeev Kumarf999e582014-01-09 17:33:29 -08007340
7341#ifdef FEATURE_WLAN_BATCH_SCAN
7342/**---------------------------------------------------------------------------
7343
7344 \brief hdd_deinit_batch_scan () - This function cleans up batch scan data
7345 structures
7346
7347 \param - pAdapter Pointer to HDD adapter
7348
7349 \return - None
7350
7351 --------------------------------------------------------------------------*/
7352void hdd_deinit_batch_scan(hdd_adapter_t *pAdapter)
7353{
7354 tHddBatchScanRsp *pNode;
7355 tHddBatchScanRsp *pPrev;
7356
Siddharth Bhalb3e9b792014-02-24 15:14:16 +05307357 if (NULL == pAdapter)
Rajeev Kumarf999e582014-01-09 17:33:29 -08007358 {
Siddharth Bhalb3e9b792014-02-24 15:14:16 +05307359 hddLog(VOS_TRACE_LEVEL_ERROR,
7360 "%s: Adapter context is Null", __func__);
7361 return;
7362 }
7363
7364 pNode = pAdapter->pBatchScanRsp;
7365 while (pNode)
7366 {
7367 pPrev = pNode;
7368 pNode = pNode->pNext;
7369 vos_mem_free((v_VOID_t * )pPrev);
Rajeev Kumarf999e582014-01-09 17:33:29 -08007370 }
7371
7372 pAdapter->pBatchScanRsp = NULL;
7373 pAdapter->numScanList = 0;
7374 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
7375 pAdapter->prev_batch_id = 0;
7376
7377 return;
7378}
7379#endif
7380
7381
Jeff Johnson295189b2012-06-20 16:38:30 -07007382VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
7383{
7384 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7385 VOS_STATUS status;
7386 hdd_adapter_t *pAdapter;
7387
7388 ENTER();
7389
7390 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7391
7392 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7393 {
7394 pAdapter = pAdapterNode->pAdapter;
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05307395 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
Jeff Johnson295189b2012-06-20 16:38:30 -07007396 netif_tx_disable(pAdapter->dev);
7397 netif_carrier_off(pAdapter->dev);
7398
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07007399 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
7400
Jeff Johnson295189b2012-06-20 16:38:30 -07007401 hdd_deinit_tx_rx(pAdapter);
Agarwal Ashish6267caa2014-08-06 19:16:21 +05307402
7403 wlan_hdd_decr_active_session(pHddCtx, pAdapter->device_mode);
7404
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05307405 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
7406 {
7407 hdd_wmm_adapter_close( pAdapter );
7408 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
7409 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007410
Siddharth Bhal2db319d2014-12-03 12:37:18 +05307411 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
7412 {
7413 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
7414 }
7415
Rajeev Kumarf999e582014-01-09 17:33:29 -08007416#ifdef FEATURE_WLAN_BATCH_SCAN
7417 if (eHDD_BATCH_SCAN_STATE_STARTED == pAdapter->batchScanState)
7418 {
7419 hdd_deinit_batch_scan(pAdapter);
7420 }
7421#endif
7422
Mahesh A Saptasagarf5b8eff2015-01-31 01:07:07 +05307423#ifdef FEATURE_WLAN_TDLS
7424 mutex_lock(&pHddCtx->tdls_lock);
7425 wlan_hdd_tdls_exit(pAdapter);
7426 mutex_unlock(&pHddCtx->tdls_lock);
7427#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007428 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7429 pAdapterNode = pNext;
7430 }
7431
7432 EXIT();
7433
7434 return VOS_STATUS_SUCCESS;
7435}
7436
7437VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
7438{
7439 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7440 VOS_STATUS status;
7441 hdd_adapter_t *pAdapter;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05307442 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -07007443
7444 ENTER();
7445
7446 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7447
7448 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7449 {
7450 pAdapter = pAdapterNode->pAdapter;
7451
Kumar Anand82c009f2014-05-29 00:29:42 -07007452 hdd_wmm_init( pAdapter );
7453
Jeff Johnson295189b2012-06-20 16:38:30 -07007454 switch(pAdapter->device_mode)
7455 {
7456 case WLAN_HDD_INFRA_STATION:
7457 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07007458 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05307459
7460 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
7461
Jeff Johnson295189b2012-06-20 16:38:30 -07007462 hdd_init_station_mode(pAdapter);
7463 /* Open the gates for HDD to receive Wext commands */
7464 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07007465 pHddCtx->scan_info.mScanPending = FALSE;
7466 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07007467
7468 //Trigger the initial scan
7469 hdd_wlan_initial_scan(pAdapter);
7470
7471 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05307472 if (eConnectionState_Associated == connState ||
7473 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -07007474 {
7475 union iwreq_data wrqu;
7476 memset(&wrqu, '\0', sizeof(wrqu));
7477 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
7478 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
7479 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07007480 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07007481
Jeff Johnson295189b2012-06-20 16:38:30 -07007482 /* indicate disconnected event to nl80211 */
7483 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
7484 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07007485 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05307486 else if (eConnectionState_Connecting == connState)
7487 {
7488 /*
7489 * Indicate connect failure to supplicant if we were in the
7490 * process of connecting
7491 */
7492 cfg80211_connect_result(pAdapter->dev, NULL,
7493 NULL, 0, NULL, 0,
7494 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
7495 GFP_KERNEL);
7496 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007497 break;
7498
7499 case WLAN_HDD_SOFTAP:
7500 /* softAP can handle SSR */
7501 break;
7502
7503 case WLAN_HDD_P2P_GO:
Sameer Thalappiledf0d792013-08-09 14:31:03 -07007504 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send stop ap to supplicant",
Jeff Johnson295189b2012-06-20 16:38:30 -07007505 __func__);
Sameer Thalappiledf0d792013-08-09 14:31:03 -07007506 cfg80211_ap_stopped(pAdapter->dev, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07007507 break;
7508
7509 case WLAN_HDD_MONITOR:
7510 /* monitor interface start */
7511 break;
7512 default:
7513 break;
7514 }
7515
7516 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7517 pAdapterNode = pNext;
7518 }
7519
7520 EXIT();
7521
7522 return VOS_STATUS_SUCCESS;
7523}
7524
7525VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
7526{
7527 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7528 hdd_adapter_t *pAdapter;
7529 VOS_STATUS status;
7530 v_U32_t roamId;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307531 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07007532
7533 ENTER();
7534
7535 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7536
7537 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7538 {
7539 pAdapter = pAdapterNode->pAdapter;
7540
7541 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
7542 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
7543 {
7544 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7545 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
7546
Abhishek Singhf4669da2014-05-26 15:07:49 +05307547 hddLog(VOS_TRACE_LEVEL_INFO,
7548 "%s: Set HDD connState to eConnectionState_NotConnected",
7549 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007550 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
7551 init_completion(&pAdapter->disconnect_comp_var);
7552 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
7553 eCSR_DISCONNECT_REASON_UNSPECIFIED);
7554
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307555 ret = wait_for_completion_interruptible_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07007556 &pAdapter->disconnect_comp_var,
7557 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307558 if (0 >= ret)
7559 hddLog(LOGE, "%s: failure waiting for disconnect_comp_var %ld",
7560 __func__, ret);
Jeff Johnson295189b2012-06-20 16:38:30 -07007561
7562 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
7563 pHddCtx->isAmpAllowed = VOS_FALSE;
7564 sme_RoamConnect(pHddCtx->hHal,
7565 pAdapter->sessionId, &(pWextState->roamProfile),
7566 &roamId);
7567 }
7568
7569 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7570 pAdapterNode = pNext;
7571 }
7572
7573 EXIT();
7574
7575 return VOS_STATUS_SUCCESS;
7576}
7577
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07007578void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
7579{
7580 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7581 VOS_STATUS status;
7582 hdd_adapter_t *pAdapter;
7583 hdd_station_ctx_t *pHddStaCtx;
7584 hdd_ap_ctx_t *pHddApCtx;
7585 hdd_hostapd_state_t * pHostapdState;
7586 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
7587 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
7588 const char *p2pMode = "DEV";
7589 const char *ccMode = "Standalone";
7590 int n;
7591
7592 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7593 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7594 {
7595 pAdapter = pAdapterNode->pAdapter;
7596 switch (pAdapter->device_mode) {
7597 case WLAN_HDD_INFRA_STATION:
7598 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7599 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
7600 staChannel = pHddStaCtx->conn_info.operationChannel;
7601 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
7602 }
7603 break;
7604 case WLAN_HDD_P2P_CLIENT:
7605 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7606 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
7607 p2pChannel = pHddStaCtx->conn_info.operationChannel;
7608 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
7609 p2pMode = "CLI";
7610 }
7611 break;
7612 case WLAN_HDD_P2P_GO:
7613 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
7614 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
7615 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
7616 p2pChannel = pHddApCtx->operatingChannel;
7617 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
7618 }
7619 p2pMode = "GO";
7620 break;
7621 case WLAN_HDD_SOFTAP:
7622 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
7623 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
7624 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
7625 apChannel = pHddApCtx->operatingChannel;
7626 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
7627 }
7628 break;
7629 default:
7630 break;
7631 }
7632 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7633 pAdapterNode = pNext;
7634 }
7635 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
7636 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
7637 }
7638 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
7639 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
7640 if (p2pChannel > 0) {
7641 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
7642 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
7643 }
7644 if (apChannel > 0) {
7645 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
7646 apChannel, MAC_ADDR_ARRAY(apBssid));
7647 }
7648
7649 if (p2pChannel > 0 && apChannel > 0) {
7650 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
7651 }
7652}
7653
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07007654bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07007655{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07007656 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07007657}
7658
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07007659/* Once SSR is disabled then it cannot be set. */
7660void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07007661{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07007662 if (HDD_SSR_DISABLED == isSsrRequired)
7663 return;
7664
Jeff Johnson295189b2012-06-20 16:38:30 -07007665 isSsrRequired = value;
7666}
7667
7668VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
7669 hdd_adapter_list_node_t** ppAdapterNode)
7670{
7671 VOS_STATUS status;
7672 spin_lock(&pHddCtx->hddAdapters.lock);
7673 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
7674 (hdd_list_node_t**) ppAdapterNode );
7675 spin_unlock(&pHddCtx->hddAdapters.lock);
7676 return status;
7677}
7678
7679VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
7680 hdd_adapter_list_node_t* pAdapterNode,
7681 hdd_adapter_list_node_t** pNextAdapterNode)
7682{
7683 VOS_STATUS status;
7684 spin_lock(&pHddCtx->hddAdapters.lock);
7685 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
7686 (hdd_list_node_t*) pAdapterNode,
7687 (hdd_list_node_t**)pNextAdapterNode );
7688
7689 spin_unlock(&pHddCtx->hddAdapters.lock);
7690 return status;
7691}
7692
7693VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
7694 hdd_adapter_list_node_t* pAdapterNode)
7695{
7696 VOS_STATUS status;
7697 spin_lock(&pHddCtx->hddAdapters.lock);
7698 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
7699 &pAdapterNode->node );
7700 spin_unlock(&pHddCtx->hddAdapters.lock);
7701 return status;
7702}
7703
7704VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
7705 hdd_adapter_list_node_t** ppAdapterNode)
7706{
7707 VOS_STATUS status;
7708 spin_lock(&pHddCtx->hddAdapters.lock);
7709 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
7710 (hdd_list_node_t**) ppAdapterNode );
7711 spin_unlock(&pHddCtx->hddAdapters.lock);
7712 return status;
7713}
7714
7715VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
7716 hdd_adapter_list_node_t* pAdapterNode)
7717{
7718 VOS_STATUS status;
7719 spin_lock(&pHddCtx->hddAdapters.lock);
7720 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
7721 (hdd_list_node_t*) pAdapterNode );
7722 spin_unlock(&pHddCtx->hddAdapters.lock);
7723 return status;
7724}
7725
7726VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
7727 hdd_adapter_list_node_t* pAdapterNode)
7728{
7729 VOS_STATUS status;
7730 spin_lock(&pHddCtx->hddAdapters.lock);
7731 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
7732 (hdd_list_node_t*) pAdapterNode );
7733 spin_unlock(&pHddCtx->hddAdapters.lock);
7734 return status;
7735}
7736
7737hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
7738 tSirMacAddr macAddr )
7739{
7740 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7741 hdd_adapter_t *pAdapter;
7742 VOS_STATUS status;
7743
7744 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7745
7746 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7747 {
7748 pAdapter = pAdapterNode->pAdapter;
7749
7750 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
7751 macAddr, sizeof(tSirMacAddr) ) )
7752 {
7753 return pAdapter;
7754 }
7755 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7756 pAdapterNode = pNext;
7757 }
7758
7759 return NULL;
7760
7761}
7762
7763hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
7764{
7765 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7766 hdd_adapter_t *pAdapter;
7767 VOS_STATUS status;
7768
7769 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7770
7771 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7772 {
7773 pAdapter = pAdapterNode->pAdapter;
7774
7775 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
7776 IFNAMSIZ ) )
7777 {
7778 return pAdapter;
7779 }
7780 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7781 pAdapterNode = pNext;
7782 }
7783
7784 return NULL;
7785
7786}
7787
7788hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
7789{
7790 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7791 hdd_adapter_t *pAdapter;
7792 VOS_STATUS status;
7793
7794 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7795
7796 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7797 {
7798 pAdapter = pAdapterNode->pAdapter;
7799
7800 if( pAdapter && (mode == pAdapter->device_mode) )
7801 {
7802 return pAdapter;
7803 }
7804 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7805 pAdapterNode = pNext;
7806 }
7807
7808 return NULL;
7809
7810}
7811
7812//Remove this function later
7813hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
7814{
7815 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7816 hdd_adapter_t *pAdapter;
7817 VOS_STATUS status;
7818
7819 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7820
7821 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7822 {
7823 pAdapter = pAdapterNode->pAdapter;
7824
7825 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
7826 {
7827 return pAdapter;
7828 }
7829
7830 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7831 pAdapterNode = pNext;
7832 }
7833
7834 return NULL;
7835
7836}
7837
Jeff Johnson295189b2012-06-20 16:38:30 -07007838/**---------------------------------------------------------------------------
7839
7840 \brief hdd_set_monitor_tx_adapter() -
7841
7842 This API initializes the adapter to be used while transmitting on monitor
7843 adapter.
7844
7845 \param - pHddCtx - Pointer to the HDD context.
7846 pAdapter - Adapter that will used for TX. This can be NULL.
7847 \return - None.
7848 --------------------------------------------------------------------------*/
7849void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
7850{
7851 hdd_adapter_t *pMonAdapter;
7852
7853 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
7854
7855 if( NULL != pMonAdapter )
7856 {
7857 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
7858 }
7859}
Jeff Johnson295189b2012-06-20 16:38:30 -07007860/**---------------------------------------------------------------------------
7861
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307862 \brief hdd_get_operating_channel() -
Jeff Johnson295189b2012-06-20 16:38:30 -07007863
7864 This API returns the operating channel of the requested device mode
7865
7866 \param - pHddCtx - Pointer to the HDD context.
7867 - mode - Device mode for which operating channel is required
7868 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
7869 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
7870 \return - channel number. "0" id the requested device is not found OR it is not connected.
7871 --------------------------------------------------------------------------*/
7872v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
7873{
7874 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7875 VOS_STATUS status;
7876 hdd_adapter_t *pAdapter;
7877 v_U8_t operatingChannel = 0;
7878
7879 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7880
7881 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7882 {
7883 pAdapter = pAdapterNode->pAdapter;
7884
7885 if( mode == pAdapter->device_mode )
7886 {
7887 switch(pAdapter->device_mode)
7888 {
7889 case WLAN_HDD_INFRA_STATION:
7890 case WLAN_HDD_P2P_CLIENT:
7891 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
7892 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
7893 break;
7894 case WLAN_HDD_SOFTAP:
7895 case WLAN_HDD_P2P_GO:
7896 /*softap connection info */
7897 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
7898 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
7899 break;
7900 default:
7901 break;
7902 }
7903
7904 break; //Found the device of interest. break the loop
7905 }
7906
7907 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7908 pAdapterNode = pNext;
7909 }
7910 return operatingChannel;
7911}
7912
7913#ifdef WLAN_FEATURE_PACKET_FILTERING
7914/**---------------------------------------------------------------------------
7915
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +05307916 \brief __hdd_set_multicast_list() -
Jeff Johnson295189b2012-06-20 16:38:30 -07007917
7918 This used to set the multicast address list.
7919
7920 \param - dev - Pointer to the WLAN device.
7921 - skb - Pointer to OS packet (sk_buff).
Mahesh A Saptasagar74088392015-02-05 17:22:09 +05307922 \return - success/fail
Jeff Johnson295189b2012-06-20 16:38:30 -07007923
7924 --------------------------------------------------------------------------*/
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +05307925static void __hdd_set_multicast_list(struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07007926{
Mahesh A Saptasagar74088392015-02-05 17:22:09 +05307927 hdd_adapter_t *pAdapter;
7928 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07007929 int mc_count;
Mahesh A Saptasagar74088392015-02-05 17:22:09 +05307930 int i = 0, ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07007931 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307932
Mahesh A Saptasagar74088392015-02-05 17:22:09 +05307933 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307934 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07007935 {
7936 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307937 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007938 return;
7939 }
Mahesh A Saptasagar74088392015-02-05 17:22:09 +05307940 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7941 ret = wlan_hdd_validate_context(pHddCtx);
7942 if (0 != ret)
7943 {
7944 hddLog(VOS_TRACE_LEVEL_ERROR,
7945 "%s: HDD context is not valid",__func__);
7946 return;
7947 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007948 if (dev->flags & IFF_ALLMULTI)
7949 {
7950 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007951 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307952 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07007953 }
Mahesh A Saptasagar74088392015-02-05 17:22:09 +05307954 else
Jeff Johnson295189b2012-06-20 16:38:30 -07007955 {
7956 mc_count = netdev_mc_count(dev);
7957 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007958 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07007959 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
7960 {
7961 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007962 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307963 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07007964 return;
7965 }
7966
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307967 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07007968
7969 netdev_for_each_mc_addr(ha, dev) {
7970 if (i == mc_count)
7971 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307972 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
7973 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
Arif Hussain6d2a3322013-11-17 19:50:10 -08007974 hddLog(VOS_TRACE_LEVEL_INFO, "%s: mlist[%d] = "MAC_ADDRESS_STR,
Mahesh A Saptasagar74088392015-02-05 17:22:09 +05307975 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307976 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07007977 i++;
7978 }
7979 }
7980 return;
7981}
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +05307982
7983static void hdd_set_multicast_list(struct net_device *dev)
7984{
7985 vos_ssr_protect(__func__);
7986 __hdd_set_multicast_list(dev);
7987 vos_ssr_unprotect(__func__);
7988}
Jeff Johnson295189b2012-06-20 16:38:30 -07007989#endif
7990
7991/**---------------------------------------------------------------------------
7992
7993 \brief hdd_select_queue() -
7994
7995 This function is registered with the Linux OS for network
7996 core to decide which queue to use first.
7997
7998 \param - dev - Pointer to the WLAN device.
7999 - skb - Pointer to OS packet (sk_buff).
8000 \return - ac, Queue Index/access category corresponding to UP in IP header
8001
8002 --------------------------------------------------------------------------*/
8003v_U16_t hdd_select_queue(struct net_device *dev,
8004 struct sk_buff *skb)
8005{
8006 return hdd_wmm_select_queue(dev, skb);
8007}
8008
8009
8010/**---------------------------------------------------------------------------
8011
8012 \brief hdd_wlan_initial_scan() -
8013
8014 This function triggers the initial scan
8015
8016 \param - pAdapter - Pointer to the HDD adapter.
8017
8018 --------------------------------------------------------------------------*/
8019void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
8020{
8021 tCsrScanRequest scanReq;
8022 tCsrChannelInfo channelInfo;
8023 eHalStatus halStatus;
Jeff Johnson02797792013-10-26 19:17:13 -07008024 tANI_U32 scanId;
Jeff Johnson295189b2012-06-20 16:38:30 -07008025 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
8026
8027 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
8028 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
8029 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
8030
8031 if(sme_Is11dSupported(pHddCtx->hHal))
8032 {
8033 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
8034 if ( HAL_STATUS_SUCCESS( halStatus ) )
8035 {
8036 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
8037 if( !scanReq.ChannelInfo.ChannelList )
8038 {
8039 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
8040 vos_mem_free(channelInfo.ChannelList);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08008041 channelInfo.ChannelList = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07008042 return;
8043 }
8044 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
8045 channelInfo.numOfChannels);
8046 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
8047 vos_mem_free(channelInfo.ChannelList);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08008048 channelInfo.ChannelList = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07008049 }
8050
8051 scanReq.scanType = eSIR_PASSIVE_SCAN;
8052 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
8053 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
8054 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
8055 }
8056 else
8057 {
8058 scanReq.scanType = eSIR_ACTIVE_SCAN;
8059 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
8060 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
8061 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
8062 }
8063
8064 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
8065 if ( !HAL_STATUS_SUCCESS( halStatus ) )
8066 {
8067 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
8068 __func__, halStatus );
8069 }
8070
8071 if(sme_Is11dSupported(pHddCtx->hHal))
8072 vos_mem_free(scanReq.ChannelInfo.ChannelList);
8073}
8074
Jeff Johnson295189b2012-06-20 16:38:30 -07008075/**---------------------------------------------------------------------------
8076
8077 \brief hdd_full_power_callback() - HDD full power callback function
8078
8079 This is the function invoked by SME to inform the result of a full power
8080 request issued by HDD
8081
8082 \param - callbackcontext - Pointer to cookie
8083 \param - status - result of request
8084
8085 \return - None
8086
8087 --------------------------------------------------------------------------*/
8088static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
8089{
Jeff Johnson72a40512013-12-19 10:14:15 -08008090 struct statsContext *pContext = callbackContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07008091
8092 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308093 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07008094
8095 if (NULL == callbackContext)
8096 {
8097 hddLog(VOS_TRACE_LEVEL_ERROR,
8098 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008099 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07008100 return;
8101 }
8102
Jeff Johnson72a40512013-12-19 10:14:15 -08008103 /* there is a race condition that exists between this callback
8104 function and the caller since the caller could time out either
8105 before or while this code is executing. we use a spinlock to
8106 serialize these actions */
8107 spin_lock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07008108
8109 if (POWER_CONTEXT_MAGIC != pContext->magic)
8110 {
8111 /* the caller presumably timed out so there is nothing we can do */
Jeff Johnson72a40512013-12-19 10:14:15 -08008112 spin_unlock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07008113 hddLog(VOS_TRACE_LEVEL_WARN,
8114 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008115 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07008116 return;
8117 }
8118
Jeff Johnson72a40512013-12-19 10:14:15 -08008119 /* context is valid so caller is still waiting */
8120
8121 /* paranoia: invalidate the magic */
8122 pContext->magic = 0;
8123
8124 /* notify the caller */
Jeff Johnson295189b2012-06-20 16:38:30 -07008125 complete(&pContext->completion);
Jeff Johnson72a40512013-12-19 10:14:15 -08008126
8127 /* serialization is complete */
8128 spin_unlock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07008129}
8130
8131/**---------------------------------------------------------------------------
8132
8133 \brief hdd_wlan_exit() - HDD WLAN exit function
8134
8135 This is the driver exit point (invoked during rmmod)
8136
8137 \param - pHddCtx - Pointer to the HDD Context
8138
8139 \return - None
8140
8141 --------------------------------------------------------------------------*/
8142void hdd_wlan_exit(hdd_context_t *pHddCtx)
8143{
8144 eHalStatus halStatus;
8145 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
8146 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05308147 struct wiphy *wiphy = pHddCtx->wiphy;
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -08008148 hdd_adapter_t* pAdapter = NULL;
Jeff Johnson72a40512013-12-19 10:14:15 -08008149 struct statsContext powerContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07008150 long lrc;
c_hpothu5ab05e92014-06-13 17:34:05 +05308151 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07008152
8153 ENTER();
8154
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +05308155#ifdef WLAN_NS_OFFLOAD
8156 hddLog(LOGE, FL("Unregister IPv6 notifier"));
8157 unregister_inet6addr_notifier(&pHddCtx->ipv6_notifier);
8158#endif
8159 hddLog(LOGE, FL("Unregister IPv4 notifier"));
8160 unregister_inetaddr_notifier(&pHddCtx->ipv4_notifier);
8161
Jeff Johnson88ba7742013-02-27 14:36:02 -08008162 if (VOS_FTM_MODE != hdd_get_conparam())
8163 {
8164 // Unloading, restart logic is no more required.
8165 wlan_hdd_restart_deinit(pHddCtx);
Jeff Johnsone7245742012-09-05 17:12:55 -07008166
Agarwal Ashishb20e0ff2014-12-17 22:50:19 +05308167#ifdef FEATURE_WLAN_TDLS
8168 /* At the time of driver unloading; if tdls connection is present;
8169 * hdd_rx_packet_cbk calls wlan_hdd_tdls_find_peer.
8170 * wlan_hdd_tdls_find_peer always checks for valid context;
8171 * as load/unload in progress there can be a race condition.
8172 * hdd_rx_packet_cbk calls wlan_hdd_tdls_find_peer only
8173 * when tdls state is enabled.
8174 * As soon as driver set load/unload flag; tdls flag also needs
8175 * to be disabled so that hdd_rx_packet_cbk won't call
8176 * wlan_hdd_tdls_find_peer.
8177 */
8178 wlan_hdd_tdls_set_mode(pHddCtx, eTDLS_SUPPORT_DISABLED, FALSE);
8179#endif
8180
c_hpothu5ab05e92014-06-13 17:34:05 +05308181 vosStatus = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
8182 while (NULL != pAdapterNode && VOS_STATUS_E_EMPTY != vosStatus)
Jeff Johnson295189b2012-06-20 16:38:30 -07008183 {
c_hpothu5ab05e92014-06-13 17:34:05 +05308184 pAdapter = pAdapterNode->pAdapter;
8185 if (NULL != pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07008186 {
Agarwal Ashish9ffa5b92014-11-18 21:07:02 +05308187 /* DeInit the adapter. This ensures that all data packets
8188 * are freed.
8189 */
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05308190#ifdef FEATURE_WLAN_TDLS
8191 mutex_lock(&pHddCtx->tdls_lock);
8192#endif
c_hpothu002231a2015-02-05 14:58:51 +05308193 hdd_deinit_adapter(pHddCtx, pAdapter, FALSE);
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05308194#ifdef FEATURE_WLAN_TDLS
8195 mutex_unlock(&pHddCtx->tdls_lock);
8196#endif
Agarwal Ashish9ffa5b92014-11-18 21:07:02 +05308197
c_hpothu5ab05e92014-06-13 17:34:05 +05308198 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode ||
8199 WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)
8200 {
8201 wlan_hdd_cfg80211_deregister_frames(pAdapter);
8202 hdd_UnregisterWext(pAdapter->dev);
8203 }
Kaushik, Sushant4975a572014-10-21 16:07:48 +05308204
Jeff Johnson295189b2012-06-20 16:38:30 -07008205 }
c_hpothu5ab05e92014-06-13 17:34:05 +05308206 vosStatus = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
8207 pAdapterNode = pNext;
Jeff Johnson295189b2012-06-20 16:38:30 -07008208 }
Kaushik, Sushant4975a572014-10-21 16:07:48 +05308209 // Cancel any outstanding scan requests. We are about to close all
8210 // of our adapters, but an adapter structure is what SME passes back
8211 // to our callback function. Hence if there are any outstanding scan
8212 // requests then there is a race condition between when the adapter
8213 // is closed and when the callback is invoked.We try to resolve that
8214 // race condition here by canceling any outstanding scans before we
8215 // close the adapters.
8216 // Note that the scans may be cancelled in an asynchronous manner,
8217 // so ideally there needs to be some kind of synchronization. Rather
8218 // than introduce a new synchronization here, we will utilize the
8219 // fact that we are about to Request Full Power, and since that is
8220 // synchronized, the expectation is that by the time Request Full
8221 // Power has completed all scans will be cancelled.
8222 if (pHddCtx->scan_info.mScanPending)
8223 {
Hema Aparna Medicharlaf05f6cd2015-01-21 14:44:19 +05308224 if(NULL != pAdapter)
8225 {
8226 hddLog(VOS_TRACE_LEVEL_INFO,
8227 FL("abort scan mode: %d sessionId: %d"),
8228 pAdapter->device_mode,
8229 pAdapter->sessionId);
8230 }
8231 hdd_abort_mac_scan(pHddCtx,
8232 pHddCtx->scan_info.sessionId,
8233 eCSR_SCAN_ABORT_DEFAULT);
Kaushik, Sushant4975a572014-10-21 16:07:48 +05308234 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008235 }
c_hpothu5ab05e92014-06-13 17:34:05 +05308236 else
Jeff Johnson88ba7742013-02-27 14:36:02 -08008237 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308238 hddLog(VOS_TRACE_LEVEL_INFO,"%s: FTM MODE",__func__);
Jeff Johnson88ba7742013-02-27 14:36:02 -08008239 wlan_hdd_ftm_close(pHddCtx);
8240 goto free_hdd_ctx;
8241 }
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308242
Jeff Johnson295189b2012-06-20 16:38:30 -07008243 /* DeRegister with platform driver as client for Suspend/Resume */
8244 vosStatus = hddDeregisterPmOps(pHddCtx);
8245 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
8246 {
8247 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
8248 VOS_ASSERT(0);
8249 }
8250
8251 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
8252 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
8253 {
8254 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
8255 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008256
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07008257 //Stop the traffic monitor timer
8258 if ( VOS_TIMER_STATE_RUNNING ==
8259 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr))
8260 {
8261 vos_timer_stop(&pHddCtx->tx_rx_trafficTmr);
8262 }
8263
8264 // Destroy the traffic monitor timer
8265 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
8266 &pHddCtx->tx_rx_trafficTmr)))
8267 {
8268 hddLog(VOS_TRACE_LEVEL_ERROR,
8269 "%s: Cannot deallocate Traffic monitor timer", __func__);
8270 }
8271
Jeff Johnson295189b2012-06-20 16:38:30 -07008272 //Disable IMPS/BMPS as we do not want the device to enter any power
8273 //save mode during shutdown
8274 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
8275 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
8276 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
8277
8278 //Ensure that device is in full power as we will touch H/W during vos_Stop
8279 init_completion(&powerContext.completion);
8280 powerContext.magic = POWER_CONTEXT_MAGIC;
8281
8282 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
8283 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
8284
8285 if (eHAL_STATUS_SUCCESS != halStatus)
8286 {
8287 if (eHAL_STATUS_PMC_PENDING == halStatus)
8288 {
8289 /* request was sent -- wait for the response */
8290 lrc = wait_for_completion_interruptible_timeout(
8291 &powerContext.completion,
8292 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
Jeff Johnson295189b2012-06-20 16:38:30 -07008293 if (lrc <= 0)
8294 {
8295 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008296 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07008297 }
8298 }
8299 else
8300 {
8301 hddLog(VOS_TRACE_LEVEL_ERROR,
8302 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008303 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07008304 /* continue -- need to clean up as much as possible */
8305 }
8306 }
8307
Jeff Johnson72a40512013-12-19 10:14:15 -08008308 /* either we never sent a request, we sent a request and received a
8309 response or we sent a request and timed out. if we never sent a
8310 request or if we sent a request and got a response, we want to
8311 clear the magic out of paranoia. if we timed out there is a
8312 race condition such that the callback function could be
8313 executing at the same time we are. of primary concern is if the
8314 callback function had already verified the "magic" but had not
8315 yet set the completion variable when a timeout occurred. we
8316 serialize these activities by invalidating the magic while
8317 holding a shared spinlock which will cause us to block if the
8318 callback is currently executing */
8319 spin_lock(&hdd_context_lock);
8320 powerContext.magic = 0;
8321 spin_unlock(&hdd_context_lock);
8322
Yue Ma0d4891e2013-08-06 17:01:45 -07008323 hdd_debugfs_exit(pHddCtx);
8324
Jeff Johnson295189b2012-06-20 16:38:30 -07008325 // Unregister the Net Device Notifier
8326 unregister_netdevice_notifier(&hdd_netdev_notifier);
8327
Jeff Johnson295189b2012-06-20 16:38:30 -07008328 hdd_stop_all_adapters( pHddCtx );
8329
Jeff Johnson295189b2012-06-20 16:38:30 -07008330#ifdef WLAN_BTAMP_FEATURE
8331 vosStatus = WLANBAP_Stop(pVosContext);
8332 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
8333 {
8334 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8335 "%s: Failed to stop BAP",__func__);
8336 }
8337#endif //WLAN_BTAMP_FEATURE
8338
8339 //Stop all the modules
8340 vosStatus = vos_stop( pVosContext );
8341 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
8342 {
8343 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8344 "%s: Failed to stop VOSS",__func__);
8345 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
8346 }
8347
Jeff Johnson295189b2012-06-20 16:38:30 -07008348 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07008349 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07008350
8351 //Close the scheduler before calling vos_close to make sure no thread is
8352 // scheduled after the each module close is called i.e after all the data
8353 // structures are freed.
8354 vosStatus = vos_sched_close( pVosContext );
8355 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
8356 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
8357 "%s: Failed to close VOSS Scheduler",__func__);
8358 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
8359 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008360#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07008361#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
8362 /* Destroy the wake lock */
8363 wake_lock_destroy(&pHddCtx->rx_wake_lock);
8364#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08008365 /* Destroy the wake lock */
8366 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008367#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008368
Mihir Shete7a24b5f2013-12-21 12:18:31 +05308369#ifdef CONFIG_ENABLE_LINUX_REG
8370 vosStatus = vos_nv_close();
8371 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
8372 {
8373 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8374 "%s: Failed to close NV", __func__);
8375 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
8376 }
8377#endif
8378
Jeff Johnson295189b2012-06-20 16:38:30 -07008379 //Close VOSS
8380 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
8381 vos_close(pVosContext);
8382
Jeff Johnson295189b2012-06-20 16:38:30 -07008383 //Close Watchdog
8384 if(pHddCtx->cfg_ini->fIsLogpEnabled)
8385 vos_watchdog_close(pVosContext);
8386
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05308387 //Clean up HDD Nlink Service
8388 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05308389
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05308390#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05308391 if (pHddCtx->cfg_ini->wlanLoggingEnable)
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05308392 {
8393 wlan_logging_sock_deactivate_svc();
8394 }
8395#endif
8396
Vinay Krishna Erannaef30b522014-08-26 17:48:16 +05308397#ifdef WLAN_KD_READY_NOTIFIER
8398 nl_srv_exit(pHddCtx->ptt_pid);
8399#else
8400 nl_srv_exit();
8401#endif /* WLAN_KD_READY_NOTIFIER */
8402
8403
Jeff Johnson295189b2012-06-20 16:38:30 -07008404 hdd_close_all_adapters( pHddCtx );
8405
Jeff Johnson295189b2012-06-20 16:38:30 -07008406 /* free the power on lock from platform driver */
8407 if (free_riva_power_on_lock("wlan"))
8408 {
8409 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
8410 __func__);
8411 }
8412
Jeff Johnson88ba7742013-02-27 14:36:02 -08008413free_hdd_ctx:
c_hpothu78c7b602014-05-17 17:35:49 +05308414
8415 //Free up dynamically allocated members inside HDD Adapter
8416 if (pHddCtx->cfg_ini)
8417 {
8418 kfree(pHddCtx->cfg_ini);
8419 pHddCtx->cfg_ini= NULL;
8420 }
8421
Leo Changf04ddad2013-09-18 13:46:38 -07008422 /* FTM mode, WIPHY did not registered
8423 If un-register here, system crash will happen */
8424 if (VOS_FTM_MODE != hdd_get_conparam())
8425 {
8426 wiphy_unregister(wiphy) ;
8427 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008428 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07008429 if (hdd_is_ssr_required())
8430 {
8431 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07008432 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07008433 msleep(5000);
8434 }
8435 hdd_set_ssr_required (VOS_FALSE);
8436}
8437
8438
8439/**---------------------------------------------------------------------------
8440
8441 \brief hdd_update_config_from_nv() - Function to update the contents of
8442 the running configuration with parameters taken from NV storage
8443
8444 \param - pHddCtx - Pointer to the HDD global context
8445
8446 \return - VOS_STATUS_SUCCESS if successful
8447
8448 --------------------------------------------------------------------------*/
8449static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
8450{
Jeff Johnson295189b2012-06-20 16:38:30 -07008451 v_BOOL_t itemIsValid = VOS_FALSE;
8452 VOS_STATUS status;
8453 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
8454 v_U8_t macLoop;
8455
8456 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
8457 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
8458 if(status != VOS_STATUS_SUCCESS)
8459 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08008460 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed");
Jeff Johnson295189b2012-06-20 16:38:30 -07008461 return VOS_STATUS_E_FAILURE;
8462 }
8463
8464 if (itemIsValid == VOS_TRUE)
8465 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08008466 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV");
Jeff Johnson295189b2012-06-20 16:38:30 -07008467 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
8468 VOS_MAX_CONCURRENCY_PERSONA);
8469 if(status != VOS_STATUS_SUCCESS)
8470 {
8471 /* Get MAC from NV fail, not update CFG info
8472 * INI MAC value will be used for MAC setting */
Arif Hussain6d2a3322013-11-17 19:50:10 -08008473 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed");
Jeff Johnson295189b2012-06-20 16:38:30 -07008474 return VOS_STATUS_E_FAILURE;
8475 }
8476
8477 /* If first MAC is not valid, treat all others are not valid
8478 * Then all MACs will be got from ini file */
8479 if(vos_is_macaddr_zero(&macFromNV[0]))
8480 {
8481 /* MAC address in NV file is not configured yet */
8482 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
8483 return VOS_STATUS_E_INVAL;
8484 }
8485
8486 /* Get MAC address from NV, update CFG info */
8487 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
8488 {
8489 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
8490 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308491 hddLog(VOS_TRACE_LEVEL_ERROR,"not valid MAC from NV for %d", macLoop);
Jeff Johnson295189b2012-06-20 16:38:30 -07008492 /* This MAC is not valid, skip it
8493 * This MAC will be got from ini file */
8494 }
8495 else
8496 {
8497 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
8498 (v_U8_t *)&macFromNV[macLoop].bytes[0],
8499 VOS_MAC_ADDR_SIZE);
8500 }
8501 }
8502 }
8503 else
8504 {
8505 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
8506 return VOS_STATUS_E_FAILURE;
8507 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008508
Jeff Johnson295189b2012-06-20 16:38:30 -07008509
8510 return VOS_STATUS_SUCCESS;
8511}
8512
8513/**---------------------------------------------------------------------------
8514
8515 \brief hdd_post_voss_start_config() - HDD post voss start config helper
8516
8517 \param - pAdapter - Pointer to the HDD
8518
8519 \return - None
8520
8521 --------------------------------------------------------------------------*/
8522VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
8523{
8524 eHalStatus halStatus;
8525 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308526 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -07008527
Jeff Johnson295189b2012-06-20 16:38:30 -07008528
8529 // Send ready indication to the HDD. This will kick off the MAC
8530 // into a 'running' state and should kick off an initial scan.
8531 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
8532 if ( !HAL_STATUS_SUCCESS( halStatus ) )
8533 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308534 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07008535 "code %08d [x%08x]",__func__, halStatus, halStatus );
8536 return VOS_STATUS_E_FAILURE;
8537 }
8538
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308539 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -07008540 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
8541 // And RIVA will crash
8542 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
8543 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308544 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
8545 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
8546
8547
Jeff Johnson295189b2012-06-20 16:38:30 -07008548 return VOS_STATUS_SUCCESS;
8549}
8550
Jeff Johnson295189b2012-06-20 16:38:30 -07008551/* wake lock APIs for HDD */
8552void hdd_prevent_suspend(void)
8553{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008554#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008555 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008556#else
8557 wcnss_prevent_suspend();
8558#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008559}
8560
8561void hdd_allow_suspend(void)
8562{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008563#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008564 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008565#else
8566 wcnss_allow_suspend();
8567#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008568}
8569
Mahesh A Saptasagarb9c50402014-01-16 15:49:22 +05308570void hdd_prevent_suspend_timeout(v_U32_t timeout)
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07008571{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008572#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07008573 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07008574#else
8575 /* Do nothing as there is no API in wcnss for timeout*/
8576#endif
8577}
8578
Jeff Johnson295189b2012-06-20 16:38:30 -07008579/**---------------------------------------------------------------------------
8580
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008581 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
8582 information between Host and Riva
8583
8584 This function gets reported version of FW
8585 It also finds the version of Riva headers used to compile the host
8586 It compares the above two and prints a warning if they are different
8587 It gets the SW and HW version string
8588 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
8589 indicating the features they support through a bitmap
8590
8591 \param - pHddCtx - Pointer to HDD context
8592
8593 \return - void
8594
8595 --------------------------------------------------------------------------*/
8596
8597void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
8598{
8599
8600 tSirVersionType versionCompiled;
8601 tSirVersionType versionReported;
8602 tSirVersionString versionString;
8603 tANI_U8 fwFeatCapsMsgSupported = 0;
8604 VOS_STATUS vstatus;
8605
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -08008606 memset(&versionCompiled, 0, sizeof(versionCompiled));
8607 memset(&versionReported, 0, sizeof(versionReported));
8608
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008609 /* retrieve and display WCNSS version information */
8610 do {
8611
8612 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
8613 &versionCompiled);
8614 if (!VOS_IS_STATUS_SUCCESS(vstatus))
8615 {
8616 hddLog(VOS_TRACE_LEVEL_FATAL,
8617 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008618 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008619 break;
8620 }
8621
8622 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
8623 &versionReported);
8624 if (!VOS_IS_STATUS_SUCCESS(vstatus))
8625 {
8626 hddLog(VOS_TRACE_LEVEL_FATAL,
8627 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008628 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008629 break;
8630 }
8631
8632 if ((versionCompiled.major != versionReported.major) ||
8633 (versionCompiled.minor != versionReported.minor) ||
8634 (versionCompiled.version != versionReported.version) ||
8635 (versionCompiled.revision != versionReported.revision))
8636 {
8637 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
8638 "Host expected %u.%u.%u.%u\n",
8639 WLAN_MODULE_NAME,
8640 (int)versionReported.major,
8641 (int)versionReported.minor,
8642 (int)versionReported.version,
8643 (int)versionReported.revision,
8644 (int)versionCompiled.major,
8645 (int)versionCompiled.minor,
8646 (int)versionCompiled.version,
8647 (int)versionCompiled.revision);
8648 }
8649 else
8650 {
8651 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
8652 WLAN_MODULE_NAME,
8653 (int)versionReported.major,
8654 (int)versionReported.minor,
8655 (int)versionReported.version,
8656 (int)versionReported.revision);
8657 }
8658
8659 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
8660 versionString,
8661 sizeof(versionString));
8662 if (!VOS_IS_STATUS_SUCCESS(vstatus))
8663 {
8664 hddLog(VOS_TRACE_LEVEL_FATAL,
8665 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008666 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008667 break;
8668 }
8669
8670 pr_info("%s: WCNSS software version %s\n",
8671 WLAN_MODULE_NAME, versionString);
8672
8673 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
8674 versionString,
8675 sizeof(versionString));
8676 if (!VOS_IS_STATUS_SUCCESS(vstatus))
8677 {
8678 hddLog(VOS_TRACE_LEVEL_FATAL,
8679 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008680 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008681 break;
8682 }
8683
8684 pr_info("%s: WCNSS hardware version %s\n",
8685 WLAN_MODULE_NAME, versionString);
8686
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07008687 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
8688 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008689 send the message only if it the riva is 1.1
8690 minor numbers for different riva branches:
8691 0 -> (1.0)Mainline Build
8692 1 -> (1.1)Mainline Build
8693 2->(1.04) Stability Build
8694 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07008695 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008696 ((versionReported.minor>=1) && (versionReported.version>=1)))
8697 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
8698 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07008699
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008700 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08008701 {
8702#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
8703 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
8704 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
8705#endif
Ravi Joshid2ca7c42013-07-23 08:37:49 -07008706 /* Indicate if IBSS heartbeat monitoring needs to be offloaded */
8707 if (!pHddCtx->cfg_ini->enableIbssHeartBeatOffload)
8708 {
8709 sme_disableFeatureCapablity(IBSS_HEARTBEAT_OFFLOAD);
8710 }
8711
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008712 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08008713 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008714
8715 } while (0);
8716
8717}
Neelansh Mittaledafed22014-09-04 18:54:39 +05308718void wlan_hdd_send_svc_nlink_msg(int type, void *data, int len)
8719{
8720 struct sk_buff *skb;
8721 struct nlmsghdr *nlh;
8722 tAniMsgHdr *ani_hdr;
8723
8724 skb = alloc_skb(NLMSG_SPACE(WLAN_NL_MAX_PAYLOAD), GFP_KERNEL);
8725
8726 if(skb == NULL) {
8727 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8728 "%s: alloc_skb failed", __func__);
8729 return;
8730 }
8731
8732 nlh = (struct nlmsghdr *)skb->data;
8733 nlh->nlmsg_pid = 0; /* from kernel */
8734 nlh->nlmsg_flags = 0;
8735 nlh->nlmsg_seq = 0;
8736 nlh->nlmsg_type = WLAN_NL_MSG_SVC;
8737
8738 ani_hdr = NLMSG_DATA(nlh);
8739 ani_hdr->type = type;
8740
8741 switch(type) {
8742 case WLAN_SVC_SAP_RESTART_IND:
8743 ani_hdr->length = 0;
8744 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr)));
8745 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr)));
8746 break;
8747 default:
8748 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8749 "Attempt to send unknown nlink message %d", type);
8750 kfree_skb(skb);
8751 return;
8752 }
8753
8754 nl_srv_bcast(skb);
8755
8756 return;
8757}
8758
8759
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008760
8761/**---------------------------------------------------------------------------
8762
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308763 \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
8764
8765 \param - pHddCtx - Pointer to the hdd context
8766
8767 \return - true if hardware supports 5GHz
8768
8769 --------------------------------------------------------------------------*/
Vinay Krishna Erannafacf5e22014-02-24 13:16:25 +05308770boolean hdd_is_5g_supported(hdd_context_t * pHddCtx)
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308771{
8772 /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
8773 * then hardware support 5Ghz.
8774 */
8775 if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode())
8776 {
Agarwal Ashish971c2882013-10-30 20:11:12 +05308777 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Hardware supports 5Ghz", __func__);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308778 return true;
8779 }
8780 else
8781 {
Agarwal Ashish971c2882013-10-30 20:11:12 +05308782 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Hardware doesn't supports 5Ghz",
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308783 __func__);
8784 return false;
8785 }
8786}
8787
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308788/**---------------------------------------------------------------------------
8789
8790 \brief hdd_generate_iface_mac_addr_auto() - HDD Mac Interface Auto
8791 generate function
8792
8793 This is generate the random mac address for WLAN interface
8794
8795 \param - pHddCtx - Pointer to HDD context
8796 idx - Start interface index to get auto
8797 generated mac addr.
8798 mac_addr - Mac address
8799
8800 \return - 0 for success, < 0 for failure
8801
8802 --------------------------------------------------------------------------*/
8803
8804static int hdd_generate_iface_mac_addr_auto(hdd_context_t *pHddCtx,
8805 int idx, v_MACADDR_t mac_addr)
8806{
8807 int i;
8808 unsigned int serialno;
8809 serialno = wcnss_get_serial_number();
8810
8811 if (0 != serialno)
8812 {
8813 /* MAC address has 3 bytes of OUI so we have a maximum of 3
8814 bytes of the serial number that can be used to generate
8815 the other 3 bytes of the MAC address. Mask off all but
8816 the lower 3 bytes (this will also make sure we don't
8817 overflow in the next step) */
8818 serialno &= 0x00FFFFFF;
8819
8820 /* we need a unique address for each session */
8821 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
8822
8823 /* autogen other Mac addresses */
8824 for (i = idx; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
8825 {
8826 /* start with the entire default address */
8827 pHddCtx->cfg_ini->intfMacAddr[i] = mac_addr;
8828 /* then replace the lower 3 bytes */
8829 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
8830 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
8831 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
8832
8833 serialno++;
8834 hddLog(VOS_TRACE_LEVEL_ERROR,
8835 "%s: Derived Mac Addr: "
8836 MAC_ADDRESS_STR, __func__,
8837 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[i].bytes));
8838 }
8839
8840 }
8841 else
8842 {
8843 hddLog(LOGE, FL("Failed to Get Serial NO"));
8844 return -1;
8845 }
8846 return 0;
8847}
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308848
8849/**---------------------------------------------------------------------------
8850
Mihir Shetefc7ff5b2014-01-27 11:30:05 +05308851 \brief hdd_11d_scan_done - callback to be executed when 11d scan is
8852 completed to flush out the scan results
8853
8854 11d scan is done during driver load and is a passive scan on all
8855 channels supported by the device, 11d scans may find some APs on
8856 frequencies which are forbidden to be used in the regulatory domain
8857 the device is operating in. If these APs are notified to the supplicant
8858 it may try to connect to these APs, thus flush out all the scan results
8859 which are present in SME after 11d scan is done.
8860
8861 \return - eHalStatus
8862
8863 --------------------------------------------------------------------------*/
8864static eHalStatus hdd_11d_scan_done(tHalHandle halHandle, void *pContext,
8865 tANI_U32 scanId, eCsrScanStatus status)
8866{
8867 ENTER();
8868
8869 sme_ScanFlushResult(halHandle, 0);
8870
8871 EXIT();
8872
8873 return eHAL_STATUS_SUCCESS;
8874}
8875
8876/**---------------------------------------------------------------------------
8877
Jeff Johnson295189b2012-06-20 16:38:30 -07008878 \brief hdd_wlan_startup() - HDD init function
8879
8880 This is the driver startup code executed once a WLAN device has been detected
8881
8882 \param - dev - Pointer to the underlying device
8883
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08008884 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07008885
8886 --------------------------------------------------------------------------*/
8887
8888int hdd_wlan_startup(struct device *dev )
8889{
8890 VOS_STATUS status;
8891 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07008892 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07008893 hdd_context_t *pHddCtx = NULL;
8894 v_CONTEXT_t pVosContext= NULL;
8895#ifdef WLAN_BTAMP_FEATURE
8896 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
8897 WLANBAP_ConfigType btAmpConfig;
8898 hdd_config_t *pConfig;
8899#endif
8900 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07008901 struct wiphy *wiphy;
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308902 v_MACADDR_t mac_addr;
Jeff Johnson295189b2012-06-20 16:38:30 -07008903
8904 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07008905 /*
8906 * cfg80211: wiphy allocation
8907 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308908 wiphy = wlan_hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t)) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07008909
8910 if(wiphy == NULL)
8911 {
8912 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08008913 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07008914 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008915 pHddCtx = wiphy_priv(wiphy);
8916
Jeff Johnson295189b2012-06-20 16:38:30 -07008917 //Initialize the adapter context to zeros.
8918 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
8919
Jeff Johnson295189b2012-06-20 16:38:30 -07008920 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07008921 hdd_prevent_suspend();
Mihir Shete18156292014-03-11 15:38:30 +05308922 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_LOAD_IN_PROGRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -07008923
8924 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
8925
8926 /*Get vos context here bcoz vos_open requires it*/
8927 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
8928
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08008929 if(pVosContext == NULL)
8930 {
8931 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
8932 goto err_free_hdd_context;
8933 }
8934
Jeff Johnson295189b2012-06-20 16:38:30 -07008935 //Save the Global VOSS context in adapter context for future.
8936 pHddCtx->pvosContext = pVosContext;
8937
8938 //Save the adapter context in global context for future.
8939 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
8940
Jeff Johnson295189b2012-06-20 16:38:30 -07008941 pHddCtx->parent_dev = dev;
8942
8943 init_completion(&pHddCtx->full_pwr_comp_var);
8944 init_completion(&pHddCtx->standby_comp_var);
8945 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07008946 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08008947 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Kiet Lam46b8e4e2013-11-06 21:49:53 +05308948 init_completion(&pHddCtx->wiphy_channel_update_event);
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +05308949 init_completion(&pHddCtx->ssr_comp_var);
Amar Singhala49cbc52013-10-08 18:37:44 -07008950
8951#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhalfddc28c2013-09-05 13:03:40 -07008952 init_completion(&pHddCtx->linux_reg_req);
Amar Singhala49cbc52013-10-08 18:37:44 -07008953#else
8954 init_completion(&pHddCtx->driver_crda_req);
8955#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008956
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05308957 spin_lock_init(&pHddCtx->schedScan_lock);
8958
Jeff Johnson295189b2012-06-20 16:38:30 -07008959 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
8960
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05308961#ifdef FEATURE_WLAN_TDLS
8962 /* tdls_lock is initialized before an hdd_open_adapter ( which is
8963 * invoked by other instances also) to protect the concurrent
8964 * access for the Adapters by TDLS module.
8965 */
8966 mutex_init(&pHddCtx->tdls_lock);
8967#endif
Siddharth Bhal76972212014-10-15 16:22:51 +05308968 mutex_init(&pHddCtx->spoofMacAddr.macSpoofingLock);
Agarwal Ashish1f422872014-07-22 00:11:55 +05308969 /* By default Strict Regulatory For FCC should be false */
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05308970
Agarwal Ashish1f422872014-07-22 00:11:55 +05308971 pHddCtx->nEnableStrictRegulatoryForFCC = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07008972 // Load all config first as TL config is needed during vos_open
8973 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
8974 if(pHddCtx->cfg_ini == NULL)
8975 {
8976 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
8977 goto err_free_hdd_context;
8978 }
8979
8980 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
8981
8982 // Read and parse the qcom_cfg.ini file
8983 status = hdd_parse_config_ini( pHddCtx );
8984 if ( VOS_STATUS_SUCCESS != status )
8985 {
8986 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
8987 __func__, WLAN_INI_FILE);
8988 goto err_config;
8989 }
Arif Hussaind5218912013-12-05 01:10:55 -08008990#ifdef MEMORY_DEBUG
8991 if (pHddCtx->cfg_ini->IsMemoryDebugSupportEnabled)
8992 vos_mem_init();
8993
8994 hddLog(VOS_TRACE_LEVEL_INFO, "%s: gEnableMemoryDebug=%d",
8995 __func__, pHddCtx->cfg_ini->IsMemoryDebugSupportEnabled);
8996#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008997
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05308998 /* INI has been read, initialise the configuredMcastBcastFilter with
8999 * INI value as this will serve as the default value
9000 */
9001 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
9002 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
9003 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05309004
9005 if (false == hdd_is_5g_supported(pHddCtx))
9006 {
9007 //5Ghz is not supported.
9008 if (1 != pHddCtx->cfg_ini->nBandCapability)
9009 {
9010 hddLog(VOS_TRACE_LEVEL_INFO,
9011 "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__);
9012 pHddCtx->cfg_ini->nBandCapability = 1;
9013 }
9014 }
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05309015
9016 /* If SNR Monitoring is enabled, FW has to parse all beacons
9017 * for calcaluting and storing the average SNR, so set Nth beacon
9018 * filter to 1 to enable FW to parse all the beaocons
9019 */
9020 if (1 == pHddCtx->cfg_ini->fEnableSNRMonitoring)
9021 {
9022 /* The log level is deliberately set to WARN as overriding
9023 * nthBeaconFilter to 1 will increase power cosumption and this
9024 * might just prove helpful to detect the power issue.
9025 */
9026 hddLog(VOS_TRACE_LEVEL_WARN,
9027 "%s: Setting pHddCtx->cfg_ini->nthBeaconFilter = 1", __func__);
9028 pHddCtx->cfg_ini->nthBeaconFilter = 1;
9029 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009030 /*
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05309031 * cfg80211: Initialization ...
Jeff Johnson295189b2012-06-20 16:38:30 -07009032 */
Manjunathappa Prakasheec4ddf2014-01-13 18:23:51 -08009033 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07009034 {
Manjunathappa Prakasheec4ddf2014-01-13 18:23:51 -08009035 if (0 < wlan_hdd_cfg80211_init(dev, wiphy, pHddCtx->cfg_ini))
9036 {
9037 hddLog(VOS_TRACE_LEVEL_FATAL,
9038 "%s: wlan_hdd_cfg80211_init return failure", __func__);
9039 goto err_config;
9040 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009041 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009042
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08009043 // Update VOS trace levels based upon the cfg.ini
9044 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
9045 pHddCtx->cfg_ini->vosTraceEnableBAP);
9046 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
9047 pHddCtx->cfg_ini->vosTraceEnableTL);
9048 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
9049 pHddCtx->cfg_ini->vosTraceEnableWDI);
9050 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
9051 pHddCtx->cfg_ini->vosTraceEnableHDD);
9052 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
9053 pHddCtx->cfg_ini->vosTraceEnableSME);
9054 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
9055 pHddCtx->cfg_ini->vosTraceEnablePE);
Katya Nigam70d68332013-09-16 16:49:45 +05309056 hdd_vos_trace_enable(VOS_MODULE_ID_PMC,
9057 pHddCtx->cfg_ini->vosTraceEnablePMC);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08009058 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
9059 pHddCtx->cfg_ini->vosTraceEnableWDA);
9060 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
9061 pHddCtx->cfg_ini->vosTraceEnableSYS);
9062 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
9063 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08009064 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
9065 pHddCtx->cfg_ini->vosTraceEnableSAP);
9066 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
9067 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08009068
Jeff Johnson295189b2012-06-20 16:38:30 -07009069 // Update WDI trace levels based upon the cfg.ini
9070 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
9071 pHddCtx->cfg_ini->wdiTraceEnableDAL);
9072 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
9073 pHddCtx->cfg_ini->wdiTraceEnableCTL);
9074 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
9075 pHddCtx->cfg_ini->wdiTraceEnableDAT);
9076 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
9077 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07009078
Jeff Johnson88ba7742013-02-27 14:36:02 -08009079 if (VOS_FTM_MODE == hdd_get_conparam())
9080 {
Jeff Johnson295189b2012-06-20 16:38:30 -07009081 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
9082 {
9083 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
9084 goto err_free_hdd_context;
9085 }
9086 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
c_hpothu2de0ef62014-04-15 16:16:15 +05309087
9088 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -07009089 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08009090 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009091
Jeff Johnson88ba7742013-02-27 14:36:02 -08009092 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07009093 if(pHddCtx->cfg_ini->fIsLogpEnabled)
9094 {
9095 status = vos_watchdog_open(pVosContext,
9096 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
9097
9098 if(!VOS_IS_STATUS_SUCCESS( status ))
9099 {
9100 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05309101 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07009102 }
9103 }
9104
9105 pHddCtx->isLogpInProgress = FALSE;
9106 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
9107
Amar Singhala49cbc52013-10-08 18:37:44 -07009108#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -07009109 /* initialize the NV module. This is required so that
9110 we can initialize the channel information in wiphy
9111 from the NV.bin data. The channel information in
9112 wiphy needs to be initialized before wiphy registration */
9113
9114 status = vos_nv_open();
9115 if (!VOS_IS_STATUS_SUCCESS(status))
9116 {
9117 /* NV module cannot be initialized */
9118 hddLog( VOS_TRACE_LEVEL_FATAL,
9119 "%s: vos_nv_open failed", __func__);
Vinay Krishna Eranna2025d892014-09-18 16:51:42 +05309120 goto err_wdclose;
Amar Singhal0a402232013-10-11 20:57:16 -07009121 }
9122
9123 status = vos_init_wiphy_from_nv_bin();
9124 if (!VOS_IS_STATUS_SUCCESS(status))
9125 {
9126 /* NV module cannot be initialized */
9127 hddLog( VOS_TRACE_LEVEL_FATAL,
9128 "%s: vos_init_wiphy failed", __func__);
9129 goto err_vos_nv_close;
9130 }
9131
Amar Singhala49cbc52013-10-08 18:37:44 -07009132#endif
Girish Gowlibf0e1ab2015-01-19 16:05:16 +05309133 vos_set_roam_delay_stats_enabled(pHddCtx->cfg_ini->gEnableRoamDelayStats);
Arun Kumar Khandavalliebb19482014-03-25 13:56:53 +05309134 status = vos_open( &pVosContext, pHddCtx->parent_dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07009135 if ( !VOS_IS_STATUS_SUCCESS( status ))
9136 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08009137 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
Mihir Shetee1093ba2014-01-21 20:13:32 +05309138 goto err_vos_nv_close;
Jeff Johnson295189b2012-06-20 16:38:30 -07009139 }
9140
Jeff Johnson295189b2012-06-20 16:38:30 -07009141 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
9142
9143 if ( NULL == pHddCtx->hHal )
9144 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08009145 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009146 goto err_vosclose;
9147 }
9148
Jeff Johnsonbc676b42013-02-14 16:04:08 -08009149 status = vos_preStart( pHddCtx->pvosContext );
9150 if ( !VOS_IS_STATUS_SUCCESS( status ) )
9151 {
9152 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05309153 goto err_vosclose;
Jeff Johnsonbc676b42013-02-14 16:04:08 -08009154 }
Jeff Johnsone7245742012-09-05 17:12:55 -07009155
Arif Hussaineaf68602013-12-30 23:10:44 -08009156 if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan)
9157 {
9158 pHddCtx->cfg_ini->enableDFSChnlScan = enable_dfs_chan_scan;
9159 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_dfs_chan_scan set to %d",
9160 __func__, enable_dfs_chan_scan);
9161 }
9162 if (0 == enable_11d || 1 == enable_11d)
9163 {
9164 pHddCtx->cfg_ini->Is11dSupportEnabled = enable_11d;
9165 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_11d set to %d",
9166 __func__, enable_11d);
9167 }
9168
Jeff Johnsonbc676b42013-02-14 16:04:08 -08009169 /* Note that the vos_preStart() sequence triggers the cfg download.
9170 The cfg download must occur before we update the SME config
9171 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07009172 status = hdd_set_sme_config( pHddCtx );
9173
9174 if ( VOS_STATUS_SUCCESS != status )
9175 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08009176 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05309177 goto err_vosclose;
Jeff Johnsonbc676b42013-02-14 16:04:08 -08009178 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009179
Jeff Johnson295189b2012-06-20 16:38:30 -07009180 /* In the integrated architecture we update the configuration from
9181 the INI file and from NV before vOSS has been started so that
9182 the final contents are available to send down to the cCPU */
9183
9184 // Apply the cfg.ini to cfg.dat
9185 if (FALSE == hdd_update_config_dat(pHddCtx))
9186 {
9187 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05309188 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07009189 }
9190
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05309191 // Get mac addr from platform driver
9192 ret = wcnss_get_wlan_mac_address((char*)&mac_addr.bytes);
9193
9194 if ((0 == ret) && (!vos_is_macaddr_zero(&mac_addr)))
Jeff Johnson295189b2012-06-20 16:38:30 -07009195 {
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05309196 /* Store the mac addr for first interface */
9197 pHddCtx->cfg_ini->intfMacAddr[0] = mac_addr;
9198
9199 hddLog(VOS_TRACE_LEVEL_ERROR,
9200 "%s: WLAN Mac Addr: "
9201 MAC_ADDRESS_STR, __func__,
9202 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
9203
9204 /* Here, passing Arg2 as 1 because we do not want to change the
9205 last 3 bytes (means non OUI bytes) of first interface mac
9206 addr.
9207 */
9208 if (0 != hdd_generate_iface_mac_addr_auto(pHddCtx, 1, mac_addr))
9209 {
9210 hddLog(VOS_TRACE_LEVEL_ERROR,
9211 "%s: Failed to generate wlan interface mac addr "
9212 "using MAC from ini file ", __func__);
9213 }
9214 }
9215 else if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
9216 {
9217 // Apply the NV to cfg.dat
9218 /* Prima Update MAC address only at here */
Jeff Johnson295189b2012-06-20 16:38:30 -07009219#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
9220 /* There was not a valid set of MAC Addresses in NV. See if the
9221 default addresses were modified by the cfg.ini settings. If so,
9222 we'll use them, but if not, we'll autogenerate a set of MAC
9223 addresses based upon the device serial number */
9224
9225 static const v_MACADDR_t default_address =
9226 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
Jeff Johnson295189b2012-06-20 16:38:30 -07009227
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05309228 if (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
9229 sizeof(default_address)))
Jeff Johnson295189b2012-06-20 16:38:30 -07009230 {
9231 /* cfg.ini has the default address, invoke autogen logic */
9232
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05309233 /* Here, passing Arg2 as 0 because we want to change the
9234 last 3 bytes (means non OUI bytes) of all the interfaces
9235 mac addr.
9236 */
9237 if (0 != hdd_generate_iface_mac_addr_auto(pHddCtx, 0,
9238 default_address))
Jeff Johnson295189b2012-06-20 16:38:30 -07009239 {
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05309240 hddLog(VOS_TRACE_LEVEL_ERROR,
9241 "%s: Failed to generate wlan interface mac addr "
9242 "using MAC from ini file " MAC_ADDRESS_STR, __func__,
9243 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
Jeff Johnson295189b2012-06-20 16:38:30 -07009244 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009245 }
9246 else
9247#endif //WLAN_AUTOGEN_MACADDR_FEATURE
9248 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08009249 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07009250 "%s: Invalid MAC address in NV, using MAC from ini file "
9251 MAC_ADDRESS_STR, __func__,
9252 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
9253 }
9254 }
9255 {
9256 eHalStatus halStatus;
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05309257
9258 /* Set the MAC Address Currently this is used by HAL to
9259 * add self sta. Remove this once self sta is added as
9260 * part of session open.
9261 */
Jeff Johnson295189b2012-06-20 16:38:30 -07009262 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
9263 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
9264 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05309265
Jeff Johnson295189b2012-06-20 16:38:30 -07009266 if (!HAL_STATUS_SUCCESS( halStatus ))
9267 {
9268 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
9269 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05309270 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07009271 }
9272 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009273
9274 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
9275 Note: Firmware image will be read and downloaded inside vos_start API */
9276 status = vos_start( pHddCtx->pvosContext );
9277 if ( !VOS_IS_STATUS_SUCCESS( status ) )
9278 {
9279 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05309280 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07009281 }
9282
Leo Chang6cec3e22014-01-21 15:33:49 -08009283#ifdef FEATURE_WLAN_CH_AVOID
9284 /* Plug in avoid channel notification callback
9285 * This should happen before ADD_SELF_STA
9286 * FW will send first IND with ADD_SELF_STA REQ from host */
Pradeep Reddy POTTETI5c2e16d2014-06-27 16:47:38 +05309287
9288 /* check the Channel Avoidance is enabled */
9289 if (TRUE == pHddCtx->cfg_ini->fenableCHAvoidance)
9290 {
9291 sme_AddChAvoidCallback(pHddCtx->hHal,
9292 hdd_hostapd_ch_avoid_cb);
9293 }
Leo Chang6cec3e22014-01-21 15:33:49 -08009294#endif /* FEATURE_WLAN_CH_AVOID */
9295
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07009296 /* Exchange capability info between Host and FW and also get versioning info from FW */
9297 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07009298
Agarwal Ashishad9281b2014-06-10 14:57:30 +05309299#ifdef CONFIG_ENABLE_LINUX_REG
9300 status = wlan_hdd_init_channels(pHddCtx);
9301 if ( !VOS_IS_STATUS_SUCCESS( status ) )
9302 {
9303 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: wlan_hdd_init_channels failed",
9304 __func__);
9305 goto err_vosstop;
9306 }
9307#endif
9308
Jeff Johnson295189b2012-06-20 16:38:30 -07009309 status = hdd_post_voss_start_config( pHddCtx );
9310 if ( !VOS_IS_STATUS_SUCCESS( status ) )
9311 {
9312 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
9313 __func__);
9314 goto err_vosstop;
9315 }
Amar Singhala49cbc52013-10-08 18:37:44 -07009316
9317#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05309318 wlan_hdd_cfg80211_update_reg_info( wiphy );
9319
9320 /* registration of wiphy dev with cfg80211 */
9321 if (0 > wlan_hdd_cfg80211_register(wiphy))
9322 {
9323 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
9324 goto err_vosstop;
9325 }
Amar Singhala49cbc52013-10-08 18:37:44 -07009326#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009327
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05309328#ifdef CONFIG_ENABLE_LINUX_REG
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05309329 /* registration of wiphy dev with cfg80211 */
9330 if (0 > wlan_hdd_cfg80211_register(wiphy))
9331 {
9332 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
9333 goto err_vosstop;
9334 }
9335
Agarwal Ashish6db9d532014-09-30 18:19:10 +05309336 status = wlan_hdd_init_channels_for_cc(pHddCtx, INIT);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05309337 if ( !VOS_IS_STATUS_SUCCESS( status ) )
9338 {
9339 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: wlan_hdd_init_channels_for_cc failed",
9340 __func__);
9341 goto err_unregister_wiphy;
9342 }
9343#endif
9344
c_hpothu4a298be2014-12-22 21:12:51 +05309345 wcnss_wlan_set_drvdata(pHddCtx->parent_dev, pHddCtx);
9346
Jeff Johnson295189b2012-06-20 16:38:30 -07009347 if (VOS_STA_SAP_MODE == hdd_get_conparam())
9348 {
9349 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
9350 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
9351 }
9352 else
9353 {
Jeff Johnson295189b2012-06-20 16:38:30 -07009354 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
9355 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
9356 if (pAdapter != NULL)
9357 {
Katya Nigama7d81d72014-11-12 12:44:34 +05309358 if (pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated && !(pHddCtx->cfg_ini->intfMacAddr[0].bytes[0] & 0x02))
Jeff Johnson295189b2012-06-20 16:38:30 -07009359 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05309360 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
9361 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
9362 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07009363
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05309364 /* Generate the P2P Device Address. This consists of the device's
9365 * primary MAC address with the locally administered bit set.
9366 */
9367 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07009368 }
9369 else
9370 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05309371 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
9372 if (p2p_dev_addr != NULL)
9373 {
9374 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
9375 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
9376 }
9377 else
9378 {
9379 hddLog(VOS_TRACE_LEVEL_FATAL,
9380 "%s: Failed to allocate mac_address for p2p_device",
9381 __func__);
9382 goto err_close_adapter;
9383 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009384 }
Jeff Johnsone7245742012-09-05 17:12:55 -07009385
9386 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
9387 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
9388 if ( NULL == pP2pAdapter )
9389 {
9390 hddLog(VOS_TRACE_LEVEL_FATAL,
9391 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07009392 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07009393 goto err_close_adapter;
9394 }
Jeff Johnsone7245742012-09-05 17:12:55 -07009395 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009396 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009397
9398 if( pAdapter == NULL )
9399 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08009400 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
9401 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07009402 }
Jeff Johnsone7245742012-09-05 17:12:55 -07009403
Arif Hussain66559122013-11-21 10:11:40 -08009404 if (country_code)
9405 {
9406 eHalStatus ret;
Arif Hussaincb607082013-12-20 11:57:42 -08009407 INIT_COMPLETION(pAdapter->change_country_code);
Arif Hussain66559122013-11-21 10:11:40 -08009408 hdd_checkandupdate_dfssetting(pAdapter, country_code);
9409#ifndef CONFIG_ENABLE_LINUX_REG
9410 hdd_checkandupdate_phymode(pAdapter, country_code);
9411#endif
Arif Hussaineaf68602013-12-30 23:10:44 -08009412 ret = sme_ChangeCountryCode(pHddCtx->hHal,
9413 (void *)(tSmeChangeCountryCallback)
9414 wlan_hdd_change_country_code_callback,
Arif Hussain66559122013-11-21 10:11:40 -08009415 country_code,
9416 pAdapter, pHddCtx->pvosContext,
Abhishek Singha306a442013-11-07 18:39:01 +05309417 eSIR_TRUE, eSIR_TRUE);
Arif Hussain66559122013-11-21 10:11:40 -08009418 if (eHAL_STATUS_SUCCESS == ret)
9419 {
Arif Hussaincb607082013-12-20 11:57:42 -08009420 ret = wait_for_completion_interruptible_timeout(
9421 &pAdapter->change_country_code,
9422 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
9423
9424 if (0 >= ret)
9425 {
9426 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
9427 "%s: SME while setting country code timed out", __func__);
9428 }
Arif Hussain66559122013-11-21 10:11:40 -08009429 }
9430 else
9431 {
Arif Hussaincb607082013-12-20 11:57:42 -08009432 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
9433 "%s: SME Change Country code from module param fail ret=%d",
9434 __func__, ret);
Arif Hussain66559122013-11-21 10:11:40 -08009435 }
9436 }
9437
Jeff Johnson295189b2012-06-20 16:38:30 -07009438#ifdef WLAN_BTAMP_FEATURE
9439 vStatus = WLANBAP_Open(pVosContext);
9440 if(!VOS_IS_STATUS_SUCCESS(vStatus))
9441 {
9442 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
9443 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07009444 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07009445 }
9446
9447 vStatus = BSL_Init(pVosContext);
9448 if(!VOS_IS_STATUS_SUCCESS(vStatus))
9449 {
9450 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
9451 "%s: Failed to Init BSL",__func__);
9452 goto err_bap_close;
9453 }
9454 vStatus = WLANBAP_Start(pVosContext);
9455 if (!VOS_IS_STATUS_SUCCESS(vStatus))
9456 {
9457 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
9458 "%s: Failed to start TL",__func__);
9459 goto err_bap_close;
9460 }
9461
9462 pConfig = pHddCtx->cfg_ini;
9463 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
9464 status = WLANBAP_SetConfig(&btAmpConfig);
9465
9466#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07009467
Mihir Shete9c238772014-10-15 14:35:16 +05309468 /*
9469 * UapsdMask is 0xf if U-APSD is enbaled for all AC's...
9470 * The value of CFG_QOS_WMM_UAPSD_MASK_DEFAULT is 0xaa(Magic Value)
9471 * which is greater than 0xf. So the below check is safe to make
9472 * sure that there is no entry for UapsdMask in the ini
9473 */
9474 if (CFG_QOS_WMM_UAPSD_MASK_DEFAULT == pHddCtx->cfg_ini->UapsdMask)
9475 {
9476 if(IS_DYNAMIC_WMM_PS_ENABLED)
9477 {
9478 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: Enable UAPSD for VI & VO",
9479 __func__);
9480 pHddCtx->cfg_ini->UapsdMask =
9481 CFG_QOS_WMM_UAPSD_MASK_DYMANIC_WMM_PS_DEFAULT;
9482 }
9483 else
9484 {
9485 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: Do not enable UAPSD",
9486 __func__);
9487 pHddCtx->cfg_ini->UapsdMask =
9488 CFG_QOS_WMM_UAPSD_MASK_LEGACY_WMM_PS_DEFAULT;
9489 }
9490 }
9491
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07009492#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
9493 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
9494 {
9495 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
9496 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
9497 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
9498 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
9499 }
9500#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009501
Agarwal Ashish4b87f922014-06-18 03:03:21 +05309502 wlan_hdd_tdls_init(pHddCtx);
9503
Mihir Shetefc7ff5b2014-01-27 11:30:05 +05309504 sme_Register11dScanDoneCallback(pHddCtx->hHal, hdd_11d_scan_done);
9505
Jeff Johnson295189b2012-06-20 16:38:30 -07009506 /* Register with platform driver as client for Suspend/Resume */
9507 status = hddRegisterPmOps(pHddCtx);
9508 if ( !VOS_IS_STATUS_SUCCESS( status ) )
9509 {
9510 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
9511#ifdef WLAN_BTAMP_FEATURE
9512 goto err_bap_stop;
9513#else
Jeff Johnsone7245742012-09-05 17:12:55 -07009514 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07009515#endif //WLAN_BTAMP_FEATURE
9516 }
9517
Yue Ma0d4891e2013-08-06 17:01:45 -07009518 /* Open debugfs interface */
9519 if (VOS_STATUS_SUCCESS != hdd_debugfs_init(pAdapter))
9520 {
9521 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
9522 "%s: hdd_debugfs_init failed!", __func__);
Yue Ma0d4891e2013-08-06 17:01:45 -07009523 }
9524
Jeff Johnson295189b2012-06-20 16:38:30 -07009525 /* Register TM level change handler function to the platform */
9526 status = hddDevTmRegisterNotifyCallback(pHddCtx);
9527 if ( !VOS_IS_STATUS_SUCCESS( status ) )
9528 {
9529 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
9530 goto err_unregister_pmops;
9531 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009532
9533 /* register for riva power on lock to platform driver */
9534 if (req_riva_power_on_lock("wlan"))
9535 {
9536 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
9537 __func__);
9538 goto err_unregister_pmops;
9539 }
9540
Jeff Johnson295189b2012-06-20 16:38:30 -07009541 // register net device notifier for device change notification
9542 ret = register_netdevice_notifier(&hdd_netdev_notifier);
9543
9544 if(ret < 0)
9545 {
9546 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
9547 goto err_free_power_on_lock;
9548 }
9549
9550 //Initialize the nlink service
9551 if(nl_srv_init() != 0)
9552 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05309553 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009554 goto err_reg_netdev;
9555 }
9556
Leo Chang4ce1cc52013-10-21 18:27:15 -07009557#ifdef WLAN_KD_READY_NOTIFIER
9558 pHddCtx->kd_nl_init = 1;
9559#endif /* WLAN_KD_READY_NOTIFIER */
9560
Jeff Johnson295189b2012-06-20 16:38:30 -07009561 //Initialize the BTC service
9562 if(btc_activate_service(pHddCtx) != 0)
9563 {
9564 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
9565 goto err_nl_srv;
9566 }
9567
9568#ifdef PTT_SOCK_SVC_ENABLE
9569 //Initialize the PTT service
9570 if(ptt_sock_activate_svc(pHddCtx) != 0)
9571 {
9572 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
9573 goto err_nl_srv;
9574 }
9575#endif
9576
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05309577#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9578 if(pHddCtx->cfg_ini && pHddCtx->cfg_ini->wlanLoggingEnable)
9579 {
Deepthi Gowri78083a32014-11-04 12:55:51 +05309580 if(wlan_logging_sock_activate_svc(
9581 pHddCtx->cfg_ini->wlanLoggingFEToConsole,
9582 pHddCtx->cfg_ini->wlanLoggingNumBuf))
9583 {
9584 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wlan_logging_sock_activate_svc"
9585 " failed", __func__);
9586 goto err_nl_srv;
9587 }
9588 //TODO: To Remove enableDhcpDebug and use gEnableDebugLog for
9589 //EAPOL and DHCP
Sachin Ahuja8c65f382014-12-12 15:34:21 +05309590 if (!pHddCtx->cfg_ini->gEnableDebugLog)
9591 pHddCtx->cfg_ini->gEnableDebugLog =
9592 VOS_PKT_PROTO_TYPE_EAPOL | VOS_PKT_PROTO_TYPE_DHCP;
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05309593 }
9594#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009595 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07009596 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07009597 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07009598 /* Action frame registered in one adapter which will
9599 * applicable to all interfaces
9600 */
Agarwal Ashish8fa0e9a2014-05-23 00:40:12 +05309601 wlan_hdd_cfg80211_register_frames(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07009602 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009603
9604 mutex_init(&pHddCtx->sap_lock);
Mahesh A Saptasagar60627942014-10-13 13:55:14 +05309605 mutex_init(&pHddCtx->roc_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07009606
Jeff Johnson295189b2012-06-20 16:38:30 -07009607
Sameer Thalappil50dc0092013-02-19 17:23:33 -08009608#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07009609#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
9610 /* Initialize the wake lcok */
9611 wake_lock_init(&pHddCtx->rx_wake_lock,
9612 WAKE_LOCK_SUSPEND,
9613 "qcom_rx_wakelock");
9614#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08009615 /* Initialize the wake lcok */
9616 wake_lock_init(&pHddCtx->sap_wake_lock,
9617 WAKE_LOCK_SUSPEND,
9618 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08009619#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07009620
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07009621 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
9622 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07009623
Katya Nigam5c306ea2014-06-19 15:39:54 +05309624 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_NO_LOAD_UNLOAD_IN_PROGRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -07009625 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
9626 hdd_allow_suspend();
Katya Nigam5c306ea2014-06-19 15:39:54 +05309627
9628#ifdef FEATURE_WLAN_SCAN_PNO
9629 /*SME must send channel update configuration to RIVA*/
9630 sme_UpdateChannelConfig(pHddCtx->hHal);
9631#endif
Abhishek Singhf644b272014-08-21 02:59:39 +05309632 /* Send the update default channel list to the FW*/
9633 sme_UpdateChannelList(pHddCtx->hHal);
Abhishek Singha306a442013-11-07 18:39:01 +05309634#ifndef CONFIG_ENABLE_LINUX_REG
9635 /*updating wiphy so that regulatory user hints can be processed*/
9636 if (wiphy)
9637 {
9638 regulatory_hint(wiphy, "00");
9639 }
9640#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07009641 // Initialize the restart logic
9642 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05309643
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07009644 //Register the traffic monitor timer now
9645 if ( pHddCtx->cfg_ini->dynSplitscan)
9646 {
9647 vos_timer_init(&pHddCtx->tx_rx_trafficTmr,
9648 VOS_TIMER_TYPE_SW,
9649 hdd_tx_rx_pkt_cnt_stat_timer_handler,
9650 (void *)pHddCtx);
9651 }
Dino Mycle6fb96c12014-06-10 11:52:40 +05309652#ifdef WLAN_FEATURE_EXTSCAN
9653 sme_EXTScanRegisterCallback(pHddCtx->hHal,
9654 wlan_hdd_cfg80211_extscan_callback,
9655 pHddCtx);
9656#endif /* WLAN_FEATURE_EXTSCAN */
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +05309657
9658#ifdef WLAN_NS_OFFLOAD
9659 // Register IPv6 notifier to notify if any change in IP
9660 // So that we can reconfigure the offload parameters
9661 pHddCtx->ipv6_notifier.notifier_call = wlan_hdd_ipv6_changed;
9662 ret = register_inet6addr_notifier(&pHddCtx->ipv6_notifier);
9663 if (ret)
9664 {
9665 hddLog(LOGE, FL("Failed to register IPv6 notifier"));
9666 }
9667 else
9668 {
9669 hddLog(LOGE, FL("Registered IPv6 notifier"));
9670 }
9671#endif
9672
9673 // Register IPv4 notifier to notify if any change in IP
9674 // So that we can reconfigure the offload parameters
9675 pHddCtx->ipv4_notifier.notifier_call = wlan_hdd_ipv4_changed;
9676 ret = register_inetaddr_notifier(&pHddCtx->ipv4_notifier);
9677 if (ret)
9678 {
9679 hddLog(LOGE, FL("Failed to register IPv4 notifier"));
9680 }
9681 else
9682 {
9683 hddLog(LOGE, FL("Registered IPv4 notifier"));
9684 }
9685
Jeff Johnson295189b2012-06-20 16:38:30 -07009686 goto success;
9687
9688err_nl_srv:
Leo Chang59cdc7e2013-07-10 10:08:21 -07009689#ifdef WLAN_KD_READY_NOTIFIER
9690 nl_srv_exit(pHddCtx->ptt_pid);
9691#else
Jeff Johnson295189b2012-06-20 16:38:30 -07009692 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07009693#endif /* WLAN_KD_READY_NOTIFIER */
Jeff Johnson295189b2012-06-20 16:38:30 -07009694err_reg_netdev:
9695 unregister_netdevice_notifier(&hdd_netdev_notifier);
9696
9697err_free_power_on_lock:
9698 free_riva_power_on_lock("wlan");
9699
9700err_unregister_pmops:
9701 hddDevTmUnregisterNotifyCallback(pHddCtx);
9702 hddDeregisterPmOps(pHddCtx);
9703
Yue Ma0d4891e2013-08-06 17:01:45 -07009704 hdd_debugfs_exit(pHddCtx);
9705
Jeff Johnson295189b2012-06-20 16:38:30 -07009706#ifdef WLAN_BTAMP_FEATURE
9707err_bap_stop:
9708 WLANBAP_Stop(pVosContext);
9709#endif
9710
9711#ifdef WLAN_BTAMP_FEATURE
9712err_bap_close:
9713 WLANBAP_Close(pVosContext);
9714#endif
9715
Jeff Johnson295189b2012-06-20 16:38:30 -07009716err_close_adapter:
9717 hdd_close_all_adapters( pHddCtx );
Mahesh A Saptasagar9ecefe42014-07-15 18:43:49 +05309718#ifdef CONFIG_ENABLE_LINUX_REG
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05309719err_unregister_wiphy:
Mahesh A Saptasagar9ecefe42014-07-15 18:43:49 +05309720#endif
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05309721 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07009722err_vosstop:
9723 vos_stop(pVosContext);
9724
Amar Singhala49cbc52013-10-08 18:37:44 -07009725err_vosclose:
Jeff Johnson295189b2012-06-20 16:38:30 -07009726 status = vos_sched_close( pVosContext );
9727 if (!VOS_IS_STATUS_SUCCESS(status)) {
9728 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
9729 "%s: Failed to close VOSS Scheduler", __func__);
9730 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
9731 }
Amar Singhala49cbc52013-10-08 18:37:44 -07009732 vos_close(pVosContext );
9733
Amar Singhal0a402232013-10-11 20:57:16 -07009734err_vos_nv_close:
9735
c_hpothue6a36282014-03-19 12:27:38 +05309736#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -07009737 vos_nv_close();
9738
c_hpothu70f8d812014-03-22 22:59:23 +05309739#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009740
9741err_wdclose:
9742 if(pHddCtx->cfg_ini->fIsLogpEnabled)
9743 vos_watchdog_close(pVosContext);
9744
Jeff Johnson295189b2012-06-20 16:38:30 -07009745err_config:
9746 kfree(pHddCtx->cfg_ini);
9747 pHddCtx->cfg_ini= NULL;
9748
9749err_free_hdd_context:
9750 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07009751 wiphy_free(wiphy) ;
9752 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07009753 VOS_BUG(1);
9754
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08009755 if (hdd_is_ssr_required())
9756 {
9757 /* WDI timeout had happened during load, so SSR is needed here */
9758 subsystem_restart("wcnss");
9759 msleep(5000);
9760 }
9761 hdd_set_ssr_required (VOS_FALSE);
9762
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08009763 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07009764
9765success:
9766 EXIT();
9767 return 0;
9768}
9769
9770/**---------------------------------------------------------------------------
9771
Jeff Johnson32d95a32012-09-10 13:15:23 -07009772 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07009773
Jeff Johnson32d95a32012-09-10 13:15:23 -07009774 This is the driver entry point - called in different timeline depending
9775 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07009776
9777 \param - None
9778
9779 \return - 0 for success, non zero for failure
9780
9781 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07009782static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07009783{
9784 VOS_STATUS status;
9785 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07009786 struct device *dev = NULL;
9787 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07009788#ifdef HAVE_WCNSS_CAL_DOWNLOAD
9789 int max_retries = 0;
9790#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009791
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05309792#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9793 wlan_logging_sock_init_svc();
9794#endif
9795
Jeff Johnson295189b2012-06-20 16:38:30 -07009796 ENTER();
9797
Sameer Thalappil50dc0092013-02-19 17:23:33 -08009798#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07009799 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07009800#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009801
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05309802 hddTraceInit();
Jeff Johnson295189b2012-06-20 16:38:30 -07009803 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
9804 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
9805
Jeff Johnson295189b2012-06-20 16:38:30 -07009806#ifdef ANI_BUS_TYPE_PCI
9807
9808 dev = wcnss_wlan_get_device();
9809
9810#endif // ANI_BUS_TYPE_PCI
9811
9812#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07009813
9814#ifdef HAVE_WCNSS_CAL_DOWNLOAD
9815 /* wait until WCNSS driver downloads NV */
9816 while (!wcnss_device_ready() && 5 >= ++max_retries) {
9817 msleep(1000);
9818 }
9819 if (max_retries >= 5) {
9820 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05309821#ifdef WLAN_OPEN_SOURCE
9822 wake_lock_destroy(&wlan_wake_lock);
9823#endif
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05309824
9825#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9826 wlan_logging_sock_deinit_svc();
9827#endif
9828
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07009829 return -ENODEV;
9830 }
9831#endif
9832
Jeff Johnson295189b2012-06-20 16:38:30 -07009833 dev = wcnss_wlan_get_device();
9834#endif // ANI_BUS_TYPE_PLATFORM
9835
9836
9837 do {
9838 if (NULL == dev) {
9839 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
9840 ret_status = -1;
9841 break;
9842 }
9843
Jeff Johnson295189b2012-06-20 16:38:30 -07009844#ifdef TIMER_MANAGER
9845 vos_timer_manager_init();
9846#endif
9847
9848 /* Preopen VOSS so that it is ready to start at least SAL */
9849 status = vos_preOpen(&pVosContext);
9850
9851 if (!VOS_IS_STATUS_SUCCESS(status))
9852 {
9853 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
9854 ret_status = -1;
9855 break;
9856 }
9857
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009858#ifndef MODULE
9859 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
9860 */
9861 hdd_set_conparam((v_UINT_t)con_mode);
9862#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009863
9864 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08009865 if (hdd_wlan_startup(dev))
9866 {
Jeff Johnson295189b2012-06-20 16:38:30 -07009867 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08009868 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009869 vos_preClose( &pVosContext );
9870 ret_status = -1;
9871 break;
9872 }
9873
Jeff Johnson295189b2012-06-20 16:38:30 -07009874 } while (0);
9875
9876 if (0 != ret_status)
9877 {
Jeff Johnson295189b2012-06-20 16:38:30 -07009878#ifdef TIMER_MANAGER
9879 vos_timer_exit();
9880#endif
9881#ifdef MEMORY_DEBUG
9882 vos_mem_exit();
9883#endif
9884
Sameer Thalappil50dc0092013-02-19 17:23:33 -08009885#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07009886 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07009887#endif
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05309888
9889#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9890 wlan_logging_sock_deinit_svc();
9891#endif
9892
Jeff Johnson295189b2012-06-20 16:38:30 -07009893 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
9894 }
9895 else
9896 {
9897 //Send WLAN UP indication to Nlink Service
9898 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
9899
9900 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Jeff Johnson295189b2012-06-20 16:38:30 -07009901 }
9902
9903 EXIT();
9904
9905 return ret_status;
9906}
9907
Jeff Johnson32d95a32012-09-10 13:15:23 -07009908/**---------------------------------------------------------------------------
9909
9910 \brief hdd_module_init() - Init Function
9911
9912 This is the driver entry point (invoked when module is loaded using insmod)
9913
9914 \param - None
9915
9916 \return - 0 for success, non zero for failure
9917
9918 --------------------------------------------------------------------------*/
9919#ifdef MODULE
9920static int __init hdd_module_init ( void)
9921{
9922 return hdd_driver_init();
9923}
Jeff Johnson32d95a32012-09-10 13:15:23 -07009924#else /* #ifdef MODULE */
9925static int __init hdd_module_init ( void)
9926{
9927 /* Driver initialization is delayed to fwpath_changed_handler */
9928 return 0;
9929}
Jeff Johnson32d95a32012-09-10 13:15:23 -07009930#endif /* #ifdef MODULE */
9931
Jeff Johnson295189b2012-06-20 16:38:30 -07009932
9933/**---------------------------------------------------------------------------
9934
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009935 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07009936
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009937 This is the driver exit point (invoked when module is unloaded using rmmod
9938 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07009939
9940 \param - None
9941
9942 \return - None
9943
9944 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009945static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07009946{
9947 hdd_context_t *pHddCtx = NULL;
9948 v_CONTEXT_t pVosContext = NULL;
Siddharth Bhala204f572015-01-17 02:03:36 +05309949 pVosWatchdogContext pVosWDCtx = NULL;
Agarwal Ashish5e414792014-06-08 15:25:23 +05309950 v_REGDOMAIN_t regId;
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +05309951 unsigned long rc = 0;
Siddharth Bhala204f572015-01-17 02:03:36 +05309952 unsigned long flags;
Jeff Johnson295189b2012-06-20 16:38:30 -07009953
9954 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
9955
9956 //Get the global vos context
9957 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
9958
9959 if(!pVosContext)
9960 {
9961 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
9962 goto done;
9963 }
9964
9965 //Get the HDD context.
9966 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
9967
9968 if(!pHddCtx)
9969 {
9970 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
9971 }
9972 else
9973 {
Siddharth Bhala204f572015-01-17 02:03:36 +05309974 pVosWDCtx = get_vos_watchdog_ctxt();
9975 if(pVosWDCtx == NULL)
9976 {
9977 hddLog(VOS_TRACE_LEVEL_ERROR, FL("WD context is invalid"));
9978 goto done;
9979 }
Mahesh A Saptasagard477b092015-02-06 15:12:16 +05309980 rtnl_lock();
9981 hdd_nullify_netdev_ops(pHddCtx);
9982 rtnl_unlock();
Siddharth Bhala204f572015-01-17 02:03:36 +05309983 spin_lock_irqsave(&pVosWDCtx->wdLock, flags);
9984 if (!pHddCtx->isLogpInProgress || (TRUE ==
9985 vos_is_wlan_in_badState(VOS_MODULE_ID_HDD, NULL)))
9986 {
9987 //SSR isn't in progress OR last wlan reinit wasn't successful
9988 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_UNLOAD_IN_PROGRESS;
9989 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
9990 spin_unlock_irqrestore(&pVosWDCtx->wdLock, flags);
9991 }
9992 else
9993 {
9994 INIT_COMPLETION(pHddCtx->ssr_comp_var);
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +05309995
Siddharth Bhala204f572015-01-17 02:03:36 +05309996 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_UNLOAD_IN_PROGRESS;
9997 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
9998 spin_unlock_irqrestore(&pVosWDCtx->wdLock, flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07009999
Siddharth Bhala204f572015-01-17 02:03:36 +053010000 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
10001 "%s:SSR is in Progress; block rmmod !!!", __func__);
10002 rc = wait_for_completion_timeout(&pHddCtx->ssr_comp_var,
10003 msecs_to_jiffies(30000));
10004 if(!rc)
10005 {
10006 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
10007 "%s:SSR timedout, fatal error", __func__);
10008 VOS_BUG(0);
10009 }
10010 }
10011
10012 /* We wait for active entry threads to exit from driver
10013 * by waiting until rtnl_lock is available.
10014 */
10015 rtnl_lock();
10016 rtnl_unlock();
Jeff Johnson295189b2012-06-20 16:38:30 -070010017
c_hpothu8adb97b2014-12-08 19:38:20 +053010018 /* Driver Need to send country code 00 in below condition
10019 * 1) If gCountryCodePriority is set to 1; and last country
10020 * code set is through 11d. This needs to be done in case
10021 * when NV country code is 00.
10022 * This Needs to be done as when kernel store last country
10023 * code and if stored country code is not through 11d,
10024 * in sme_HandleChangeCountryCodeByUser we will disable 11d
10025 * in next load/unload as soon as we get any country through
10026 * 11d. In sme_HandleChangeCountryCodeByUser
10027 * pMsg->countryCode will be last countryCode and
10028 * pMac->scan.countryCode11d will be country through 11d so
10029 * due to mismatch driver will disable 11d.
10030 *
10031 */
Agarwal Ashish8db39882014-07-30 21:56:07 +053010032
c_hpothu8adb97b2014-12-08 19:38:20 +053010033 if ((eANI_BOOLEAN_TRUE == sme_Is11dCountrycode(pHddCtx->hHal) &&
Agarwal Ashish8dcd2862014-07-25 11:58:52 +053010034 pHddCtx->cfg_ini->fSupplicantCountryCodeHasPriority &&
Abhishek Singh2a705962014-10-30 14:47:28 +053010035 sme_Is11dSupported(pHddCtx->hHal)))
c_hpothu8adb97b2014-12-08 19:38:20 +053010036 {
10037 hddLog(VOS_TRACE_LEVEL_INFO,
Agarwal Ashish8dcd2862014-07-25 11:58:52 +053010038 FL("CountryCode 00 is being set while unloading driver"));
c_hpothu8adb97b2014-12-08 19:38:20 +053010039 vos_nv_getRegDomainFromCountryCode(&regId , "00", COUNTRY_USER);
10040 }
Agarwal Ashish5e414792014-06-08 15:25:23 +053010041
c_hpothu8adb97b2014-12-08 19:38:20 +053010042 //Do all the cleanup before deregistering the driver
10043 hdd_wlan_exit(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -070010044 }
10045
Jeff Johnson295189b2012-06-20 16:38:30 -070010046 vos_preClose( &pVosContext );
10047
10048#ifdef TIMER_MANAGER
10049 vos_timer_exit();
10050#endif
10051#ifdef MEMORY_DEBUG
10052 vos_mem_exit();
10053#endif
10054
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +053010055#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
10056 wlan_logging_sock_deinit_svc();
10057#endif
10058
Jeff Johnson295189b2012-06-20 16:38:30 -070010059done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -080010060#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -070010061 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -070010062#endif
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +053010063
Jeff Johnson295189b2012-06-20 16:38:30 -070010064 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
10065}
10066
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070010067/**---------------------------------------------------------------------------
10068
10069 \brief hdd_module_exit() - Exit function
10070
10071 This is the driver exit point (invoked when module is unloaded using rmmod)
10072
10073 \param - None
10074
10075 \return - None
10076
10077 --------------------------------------------------------------------------*/
10078static void __exit hdd_module_exit(void)
10079{
10080 hdd_driver_exit();
10081}
10082
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070010083#ifdef MODULE
10084static int fwpath_changed_handler(const char *kmessage,
10085 struct kernel_param *kp)
10086{
Jeff Johnson76052702013-04-16 13:55:05 -070010087 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070010088}
10089
10090static int con_mode_handler(const char *kmessage,
10091 struct kernel_param *kp)
10092{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -070010093 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070010094}
10095#else /* #ifdef MODULE */
10096/**---------------------------------------------------------------------------
10097
Jeff Johnson76052702013-04-16 13:55:05 -070010098 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070010099
Jeff Johnson76052702013-04-16 13:55:05 -070010100 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070010101 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -070010102 - invoked when module parameter fwpath is modified from userspace to signal
10103 initializing the WLAN driver or when con_mode is modified from userspace
10104 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070010105
10106 \return - 0 for success, non zero for failure
10107
10108 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -070010109static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070010110{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -070010111 int ret_status;
10112
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070010113 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -070010114 ret_status = hdd_driver_init();
10115 wlan_hdd_inited = ret_status ? 0 : 1;
10116 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070010117 }
10118
10119 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -070010120
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070010121 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -070010122
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -070010123 ret_status = hdd_driver_init();
10124 wlan_hdd_inited = ret_status ? 0 : 1;
10125 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070010126}
10127
Jeff Johnson295189b2012-06-20 16:38:30 -070010128/**---------------------------------------------------------------------------
10129
Jeff Johnson76052702013-04-16 13:55:05 -070010130 \brief fwpath_changed_handler() - Handler Function
10131
10132 Handle changes to the fwpath parameter
10133
10134 \return - 0 for success, non zero for failure
10135
10136 --------------------------------------------------------------------------*/
10137static int fwpath_changed_handler(const char *kmessage,
10138 struct kernel_param *kp)
10139{
10140 int ret;
10141
10142 ret = param_set_copystring(kmessage, kp);
10143 if (0 == ret)
10144 ret = kickstart_driver();
10145 return ret;
10146}
10147
10148/**---------------------------------------------------------------------------
10149
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070010150 \brief con_mode_handler() -
10151
10152 Handler function for module param con_mode when it is changed by userspace
10153 Dynamically linked - do nothing
10154 Statically linked - exit and init driver, as in rmmod and insmod
10155
Jeff Johnson76052702013-04-16 13:55:05 -070010156 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070010157
Jeff Johnson76052702013-04-16 13:55:05 -070010158 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070010159
10160 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -070010161static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070010162{
Jeff Johnson76052702013-04-16 13:55:05 -070010163 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070010164
Jeff Johnson76052702013-04-16 13:55:05 -070010165 ret = param_set_int(kmessage, kp);
10166 if (0 == ret)
10167 ret = kickstart_driver();
10168 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070010169}
10170#endif /* #ifdef MODULE */
10171
10172/**---------------------------------------------------------------------------
10173
Jeff Johnson295189b2012-06-20 16:38:30 -070010174 \brief hdd_get_conparam() -
10175
10176 This is the driver exit point (invoked when module is unloaded using rmmod)
10177
10178 \param - None
10179
10180 \return - tVOS_CON_MODE
10181
10182 --------------------------------------------------------------------------*/
10183tVOS_CON_MODE hdd_get_conparam ( void )
10184{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070010185#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -070010186 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070010187#else
10188 return (tVOS_CON_MODE)curr_con_mode;
10189#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070010190}
10191void hdd_set_conparam ( v_UINT_t newParam )
10192{
10193 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070010194#ifndef MODULE
10195 curr_con_mode = con_mode;
10196#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070010197}
10198/**---------------------------------------------------------------------------
10199
10200 \brief hdd_softap_sta_deauth() - function
10201
10202 This to take counter measure to handle deauth req from HDD
10203
10204 \param - pAdapter - Pointer to the HDD
10205
10206 \param - enable - boolean value
10207
10208 \return - None
10209
10210 --------------------------------------------------------------------------*/
10211
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +053010212VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter,
10213 struct tagCsrDelStaParams *pDelStaParams)
Jeff Johnson295189b2012-06-20 16:38:30 -070010214{
Jeff Johnson295189b2012-06-20 16:38:30 -070010215 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -080010216 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -070010217
10218 ENTER();
10219
Rajesh Chauhan18488fc2013-08-22 10:15:03 -070010220 hddLog(LOG1, "hdd_softap_sta_deauth:(%p, false)",
10221 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -070010222
10223 //Ignore request to deauth bcmc station
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +053010224 if (pDelStaParams->peerMacAddr[0] & 0x1)
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -080010225 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -070010226
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +053010227 vosStatus = WLANSAP_DeauthSta(pVosContext, pDelStaParams);
Jeff Johnson295189b2012-06-20 16:38:30 -070010228
10229 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -080010230 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -070010231}
10232
10233/**---------------------------------------------------------------------------
10234
Rashmi Ramanna1f0948d2014-08-28 15:33:48 +053010235 \brief hdd_del_all_sta() - function
10236
10237 This function removes all the stations associated on stopping AP/P2P GO.
10238
10239 \param - pAdapter - Pointer to the HDD
10240
10241 \return - None
10242
10243 --------------------------------------------------------------------------*/
10244
10245int hdd_del_all_sta(hdd_adapter_t *pAdapter)
10246{
10247 v_U16_t i;
10248 VOS_STATUS vos_status;
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +053010249 v_CONTEXT_t pVosContext = ( WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
10250 ptSapContext pSapCtx = NULL;
10251 pSapCtx = VOS_GET_SAP_CB(pVosContext);
10252 if(pSapCtx == NULL){
10253 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
10254 FL("psapCtx is NULL"));
10255 return 1;
10256 }
Rashmi Ramanna1f0948d2014-08-28 15:33:48 +053010257 ENTER();
10258
10259 hddLog(VOS_TRACE_LEVEL_INFO,
10260 "%s: Delete all STAs associated.",__func__);
10261 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
10262 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
10263 )
10264 {
10265 for(i = 0; i < WLAN_MAX_STA_COUNT; i++)
10266 {
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +053010267 if ((pSapCtx->aStaInfo[i].isUsed) &&
10268 (!pSapCtx->aStaInfo[i].isDeauthInProgress))
Rashmi Ramanna1f0948d2014-08-28 15:33:48 +053010269 {
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +053010270 struct tagCsrDelStaParams delStaParams;
10271
10272 WLANSAP_PopulateDelStaParams(
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +053010273 pSapCtx->aStaInfo[i].macAddrSTA.bytes,
Sushant Kaushik4cd28f62014-12-26 14:23:50 +053010274 eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
10275 SIR_MAC_MGMT_DEAUTH >> 4,
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +053010276 &delStaParams);
10277 vos_status = hdd_softap_sta_deauth(pAdapter, &delStaParams);
Rashmi Ramanna1f0948d2014-08-28 15:33:48 +053010278 if (VOS_IS_STATUS_SUCCESS(vos_status))
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +053010279 pSapCtx->aStaInfo[i].isDeauthInProgress = TRUE;
Rashmi Ramanna1f0948d2014-08-28 15:33:48 +053010280 }
10281 }
10282 }
10283
10284 EXIT();
10285 return 0;
10286}
10287
10288/**---------------------------------------------------------------------------
10289
Jeff Johnson295189b2012-06-20 16:38:30 -070010290 \brief hdd_softap_sta_disassoc() - function
10291
10292 This to take counter measure to handle deauth req from HDD
10293
10294 \param - pAdapter - Pointer to the HDD
10295
10296 \param - enable - boolean value
10297
10298 \return - None
10299
10300 --------------------------------------------------------------------------*/
10301
10302void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
10303{
10304 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
10305
10306 ENTER();
10307
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +053010308 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -070010309
10310 //Ignore request to disassoc bcmc station
10311 if( pDestMacAddress[0] & 0x1 )
10312 return;
10313
10314 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
10315}
10316
10317void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
10318{
10319 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
10320
10321 ENTER();
10322
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +053010323 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -070010324
10325 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
10326}
10327
Jeff Johnson295189b2012-06-20 16:38:30 -070010328/**---------------------------------------------------------------------------
10329 *
10330 * \brief hdd_get__concurrency_mode() -
10331 *
10332 *
10333 * \param - None
10334 *
10335 * \return - CONCURRENCY MODE
10336 *
10337 * --------------------------------------------------------------------------*/
10338tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
10339{
10340 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
10341 hdd_context_t *pHddCtx;
10342
10343 if (NULL != pVosContext)
10344 {
10345 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
10346 if (NULL != pHddCtx)
10347 {
10348 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
10349 }
10350 }
10351
10352 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070010353 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -070010354 return VOS_STA;
10355}
Sushant Kaushikabb7ee62014-07-18 16:20:12 +053010356v_BOOL_t
10357wlan_hdd_is_GO_power_collapse_allowed (hdd_context_t* pHddCtx)
10358{
10359 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -070010360
Sushant Kaushikabb7ee62014-07-18 16:20:12 +053010361 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_GO);
10362 if (pAdapter == NULL)
10363 {
10364 hddLog(VOS_TRACE_LEVEL_INFO,
10365 FL("GO doesn't exist"));
10366 return TRUE;
10367 }
10368 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
10369 {
10370 hddLog(VOS_TRACE_LEVEL_INFO,
10371 FL("GO started"));
10372 return TRUE;
10373 }
10374 else
10375 /* wait till GO changes its interface to p2p device */
10376 hddLog(VOS_TRACE_LEVEL_INFO,
10377 FL("Del_bss called, avoid apps suspend"));
10378 return FALSE;
10379
10380}
Jeff Johnson295189b2012-06-20 16:38:30 -070010381/* Decide whether to allow/not the apps power collapse.
10382 * Allow apps power collapse if we are in connected state.
10383 * if not, allow only if we are in IMPS */
10384v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
10385{
10386 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -080010387 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -080010388 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -070010389 hdd_config_t *pConfig = pHddCtx->cfg_ini;
10390 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
10391 hdd_adapter_t *pAdapter = NULL;
10392 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -080010393 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -070010394
Jeff Johnson295189b2012-06-20 16:38:30 -070010395 if (VOS_STA_SAP_MODE == hdd_get_conparam())
10396 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -070010397
Yathish9f22e662012-12-10 14:21:35 -080010398 concurrent_state = hdd_get_concurrency_mode();
10399
Sushant Kaushikabb7ee62014-07-18 16:20:12 +053010400 if ((concurrent_state == (VOS_STA | VOS_P2P_GO)) &&
10401 !(wlan_hdd_is_GO_power_collapse_allowed(pHddCtx)))
10402 return FALSE;
Yathish9f22e662012-12-10 14:21:35 -080010403#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
Sushant Kaushikabb7ee62014-07-18 16:20:12 +053010404
Yathish9f22e662012-12-10 14:21:35 -080010405 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
Sushant Kaushikabb7ee62014-07-18 16:20:12 +053010406 (concurrent_state == (VOS_STA | VOS_P2P_GO)))&&
Yathish9f22e662012-12-10 14:21:35 -080010407 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
10408 return TRUE;
10409#endif
10410
Jeff Johnson295189b2012-06-20 16:38:30 -070010411 /*loop through all adapters. TBD fix for Concurrency */
10412 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10413 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
10414 {
10415 pAdapter = pAdapterNode->pAdapter;
10416 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
10417 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
10418 {
Srikant Kuppafef66a72013-01-30 17:32:44 -080010419 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
c_hpothu4e8faac2014-05-16 17:38:44 +053010420 && (pmcState != IMPS && pmcState != BMPS && pmcState != UAPSD
c_hpothu1c6957d2015-01-06 18:19:47 +053010421 && pmcState != STOPPED && pmcState != STANDBY &&
10422 pmcState != WOWL)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -080010423 (eANI_BOOLEAN_TRUE == scanRspPending) ||
10424 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -070010425 {
Srikant Kuppafef66a72013-01-30 17:32:44 -080010426 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -080010427 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
10428 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -070010429 return FALSE;
10430 }
10431 }
10432 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10433 pAdapterNode = pNext;
10434 }
10435 return TRUE;
10436}
10437
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -080010438/* Decides whether to send suspend notification to Riva
10439 * if any adapter is in BMPS; then it is required */
10440v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
10441{
10442 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
10443 hdd_config_t *pConfig = pHddCtx->cfg_ini;
10444
10445 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
10446 {
10447 return TRUE;
10448 }
10449 return FALSE;
10450}
10451
Jeff Johnson295189b2012-06-20 16:38:30 -070010452void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
10453{
10454 switch(mode)
10455 {
Chilam Ngc4244af2013-04-01 15:37:32 -070010456 case VOS_STA_MODE:
10457 case VOS_P2P_CLIENT_MODE:
10458 case VOS_P2P_GO_MODE:
10459 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -070010460 pHddCtx->concurrency_mode |= (1 << mode);
Agarwal Ashish51325b52014-06-16 16:50:49 +053010461 pHddCtx->no_of_open_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -070010462 break;
10463 default:
10464 break;
Jeff Johnson295189b2012-06-20 16:38:30 -070010465 }
Agarwal Ashish51325b52014-06-16 16:50:49 +053010466 hddLog(VOS_TRACE_LEVEL_INFO, FL("concurrency_mode = 0x%x "
10467 "Number of open sessions for mode %d = %d"),
10468 pHddCtx->concurrency_mode, mode,
10469 pHddCtx->no_of_open_sessions[mode]);
Jeff Johnson295189b2012-06-20 16:38:30 -070010470}
10471
10472
10473void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
10474{
10475 switch(mode)
10476 {
Chilam Ngc4244af2013-04-01 15:37:32 -070010477 case VOS_STA_MODE:
10478 case VOS_P2P_CLIENT_MODE:
10479 case VOS_P2P_GO_MODE:
10480 case VOS_STA_SAP_MODE:
Agarwal Ashish51325b52014-06-16 16:50:49 +053010481 pHddCtx->no_of_open_sessions[mode]--;
10482 if (!(pHddCtx->no_of_open_sessions[mode]))
10483 pHddCtx->concurrency_mode &= (~(1 << mode));
Jeff Johnson295189b2012-06-20 16:38:30 -070010484 break;
10485 default:
10486 break;
10487 }
Agarwal Ashish51325b52014-06-16 16:50:49 +053010488 hddLog(VOS_TRACE_LEVEL_INFO, FL("concurrency_mode = 0x%x "
10489 "Number of open sessions for mode %d = %d"),
10490 pHddCtx->concurrency_mode, mode, pHddCtx->no_of_open_sessions[mode]);
10491
10492}
10493/**---------------------------------------------------------------------------
10494 *
10495 * \brief wlan_hdd_incr_active_session()
10496 *
10497 * This function increments the number of active sessions
10498 * maintained per device mode
10499 * Incase of STA/P2P CLI/IBSS upon connection indication it is incremented
10500 * Incase of SAP/P2P GO upon bss start it is incremented
10501 *
10502 * \param pHddCtx - HDD Context
10503 * \param mode - device mode
10504 *
10505 * \return - None
10506 *
10507 * --------------------------------------------------------------------------*/
10508void wlan_hdd_incr_active_session(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
10509{
10510 switch (mode) {
10511 case VOS_STA_MODE:
10512 case VOS_P2P_CLIENT_MODE:
10513 case VOS_P2P_GO_MODE:
10514 case VOS_STA_SAP_MODE:
10515 pHddCtx->no_of_active_sessions[mode]++;
10516 break;
10517 default:
10518 hddLog(VOS_TRACE_LEVEL_INFO, FL("Not Expected Mode %d"), mode);
10519 break;
10520 }
10521 hddLog(VOS_TRACE_LEVEL_INFO, FL("No.# of active sessions for mode %d = %d"),
10522 mode,
10523 pHddCtx->no_of_active_sessions[mode]);
10524}
10525
10526/**---------------------------------------------------------------------------
10527 *
10528 * \brief wlan_hdd_decr_active_session()
10529 *
10530 * This function decrements the number of active sessions
10531 * maintained per device mode
10532 * Incase of STA/P2P CLI/IBSS upon disconnection it is decremented
10533 * Incase of SAP/P2P GO upon bss stop it is decremented
10534 *
10535 * \param pHddCtx - HDD Context
10536 * \param mode - device mode
10537 *
10538 * \return - None
10539 *
10540 * --------------------------------------------------------------------------*/
10541void wlan_hdd_decr_active_session(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
10542{
10543 switch (mode) {
10544 case VOS_STA_MODE:
10545 case VOS_P2P_CLIENT_MODE:
10546 case VOS_P2P_GO_MODE:
10547 case VOS_STA_SAP_MODE:
Agarwal Ashish5325f522014-08-06 00:58:44 +053010548 if (pHddCtx->no_of_active_sessions[mode] > 0)
10549 pHddCtx->no_of_active_sessions[mode]--;
10550 else
10551 hddLog(VOS_TRACE_LEVEL_INFO, FL(" No.# of Active sessions"
10552 "is already Zero"));
Agarwal Ashish51325b52014-06-16 16:50:49 +053010553 break;
10554 default:
10555 hddLog(VOS_TRACE_LEVEL_INFO, FL("Not Expected Mode %d"), mode);
10556 break;
10557 }
10558 hddLog(VOS_TRACE_LEVEL_INFO, FL("No.# of active sessions for mode %d = %d"),
10559 mode,
10560 pHddCtx->no_of_active_sessions[mode]);
Jeff Johnson295189b2012-06-20 16:38:30 -070010561}
10562
Jeff Johnsone7245742012-09-05 17:12:55 -070010563/**---------------------------------------------------------------------------
10564 *
10565 * \brief wlan_hdd_restart_init
10566 *
10567 * This function initalizes restart timer/flag. An internal function.
10568 *
10569 * \param - pHddCtx
10570 *
10571 * \return - None
10572 *
10573 * --------------------------------------------------------------------------*/
10574
10575static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
10576{
10577 /* Initialize */
10578 pHddCtx->hdd_restart_retries = 0;
10579 atomic_set(&pHddCtx->isRestartInProgress, 0);
10580 vos_timer_init(&pHddCtx->hdd_restart_timer,
10581 VOS_TIMER_TYPE_SW,
10582 wlan_hdd_restart_timer_cb,
10583 pHddCtx);
10584}
10585/**---------------------------------------------------------------------------
10586 *
10587 * \brief wlan_hdd_restart_deinit
10588 *
10589 * This function cleans up the resources used. An internal function.
10590 *
10591 * \param - pHddCtx
10592 *
10593 * \return - None
10594 *
10595 * --------------------------------------------------------------------------*/
10596
10597static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
10598{
10599
10600 VOS_STATUS vos_status;
10601 /* Block any further calls */
10602 atomic_set(&pHddCtx->isRestartInProgress, 1);
10603 /* Cleanup */
10604 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
10605 if (!VOS_IS_STATUS_SUCCESS(vos_status))
c_hpothu6ff1c3c2013-10-01 19:01:57 +053010606 hddLog(LOGE, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -070010607 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
10608 if (!VOS_IS_STATUS_SUCCESS(vos_status))
c_hpothu6ff1c3c2013-10-01 19:01:57 +053010609 hddLog(LOGE, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -070010610
10611}
10612
10613/**---------------------------------------------------------------------------
10614 *
10615 * \brief wlan_hdd_framework_restart
10616 *
10617 * This function uses a cfg80211 API to start a framework initiated WLAN
10618 * driver module unload/load.
10619 *
10620 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
10621 *
10622 *
10623 * \param - pHddCtx
10624 *
10625 * \return - VOS_STATUS_SUCCESS: Success
10626 * VOS_STATUS_E_EMPTY: Adapter is Empty
10627 * VOS_STATUS_E_NOMEM: No memory
10628
10629 * --------------------------------------------------------------------------*/
10630
10631static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
10632{
10633 VOS_STATUS status = VOS_STATUS_SUCCESS;
10634 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -070010635 int len = (sizeof (struct ieee80211_mgmt));
10636 struct ieee80211_mgmt *mgmt = NULL;
10637
10638 /* Prepare the DEAUTH managment frame with reason code */
10639 mgmt = kzalloc(len, GFP_KERNEL);
10640 if(mgmt == NULL)
10641 {
10642 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
10643 "%s: memory allocation failed (%d bytes)", __func__, len);
10644 return VOS_STATUS_E_NOMEM;
10645 }
10646 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -070010647
10648 /* Iterate over all adapters/devices */
10649 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10650 do
10651 {
10652 if( (status == VOS_STATUS_SUCCESS) &&
10653 pAdapterNode &&
10654 pAdapterNode->pAdapter)
10655 {
10656 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
10657 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
10658 pAdapterNode->pAdapter->dev->name,
10659 pAdapterNode->pAdapter->device_mode,
10660 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -070010661 /*
10662 * CFG80211 event to restart the driver
10663 *
10664 * 'cfg80211_send_unprot_deauth' sends a
10665 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
10666 * of SME(Linux Kernel) state machine.
10667 *
10668 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
10669 * the driver.
10670 *
10671 */
10672
10673 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -070010674 }
10675 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10676 pAdapterNode = pNext;
10677 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
10678
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -070010679
10680 /* Free the allocated management frame */
10681 kfree(mgmt);
10682
Jeff Johnsone7245742012-09-05 17:12:55 -070010683 /* Retry until we unload or reach max count */
10684 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
10685 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
10686
10687 return status;
10688
10689}
10690/**---------------------------------------------------------------------------
10691 *
10692 * \brief wlan_hdd_restart_timer_cb
10693 *
10694 * Restart timer callback. An internal function.
10695 *
10696 * \param - User data:
10697 *
10698 * \return - None
10699 *
10700 * --------------------------------------------------------------------------*/
10701
10702void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
10703{
10704 hdd_context_t *pHddCtx = usrDataForCallback;
10705 wlan_hdd_framework_restart(pHddCtx);
10706 return;
10707
10708}
10709
10710
10711/**---------------------------------------------------------------------------
10712 *
10713 * \brief wlan_hdd_restart_driver
10714 *
10715 * This function sends an event to supplicant to restart the WLAN driver.
10716 *
10717 * This function is called from vos_wlanRestart.
10718 *
10719 * \param - pHddCtx
10720 *
10721 * \return - VOS_STATUS_SUCCESS: Success
10722 * VOS_STATUS_E_EMPTY: Adapter is Empty
10723 * VOS_STATUS_E_ALREADY: Request already in progress
10724
10725 * --------------------------------------------------------------------------*/
10726VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
10727{
10728 VOS_STATUS status = VOS_STATUS_SUCCESS;
10729
10730 /* A tight check to make sure reentrancy */
10731 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
10732 {
Mihir Shetefd528652014-06-23 19:07:50 +053010733 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnsone7245742012-09-05 17:12:55 -070010734 "%s: WLAN restart is already in progress", __func__);
10735
10736 return VOS_STATUS_E_ALREADY;
10737 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -070010738 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -080010739#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -070010740 wcnss_reset_intr();
10741#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -070010742
Jeff Johnsone7245742012-09-05 17:12:55 -070010743 return status;
10744}
10745
Mihir Shetee1093ba2014-01-21 20:13:32 +053010746/**---------------------------------------------------------------------------
10747 *
10748 * \brief wlan_hdd_init_channels
10749 *
10750 * This function is used to initialize the channel list in CSR
10751 *
10752 * This function is called from hdd_wlan_startup
10753 *
10754 * \param - pHddCtx: HDD context
10755 *
10756 * \return - VOS_STATUS_SUCCESS: Success
10757 * VOS_STATUS_E_FAULT: Failure reported by SME
10758
10759 * --------------------------------------------------------------------------*/
10760static VOS_STATUS wlan_hdd_init_channels(hdd_context_t *pHddCtx)
10761{
10762 eHalStatus status;
10763
10764 status = sme_InitChannels(pHddCtx->hHal);
10765 if (HAL_STATUS_SUCCESS(status))
10766 {
10767 return VOS_STATUS_SUCCESS;
10768 }
10769 else
10770 {
10771 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Channel initialization failed(%d)",
10772 __func__, status);
10773 return VOS_STATUS_E_FAULT;
10774 }
10775}
10776
Mihir Shete04206452014-11-20 17:50:58 +053010777#ifdef CONFIG_ENABLE_LINUX_REG
Agarwal Ashish6db9d532014-09-30 18:19:10 +053010778VOS_STATUS wlan_hdd_init_channels_for_cc(hdd_context_t *pHddCtx, driver_load_type init )
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053010779{
10780 eHalStatus status;
10781
Agarwal Ashish6db9d532014-09-30 18:19:10 +053010782 status = sme_InitChannelsForCC(pHddCtx->hHal, init);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053010783 if (HAL_STATUS_SUCCESS(status))
10784 {
10785 return VOS_STATUS_SUCCESS;
10786 }
10787 else
10788 {
10789 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Issue reg hint failed(%d)",
10790 __func__, status);
10791 return VOS_STATUS_E_FAULT;
10792 }
10793}
Mihir Shete04206452014-11-20 17:50:58 +053010794#endif
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -070010795/*
10796 * API to find if there is any STA or P2P-Client is connected
10797 */
10798VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
10799{
10800 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
10801}
Jeff Johnsone7245742012-09-05 17:12:55 -070010802
Agarwal Ashish57e84372014-12-05 18:26:53 +053010803/*
10804 * API to find if there is any session connected
10805 */
10806VOS_STATUS hdd_is_any_session_connected(hdd_context_t *pHddCtx)
10807{
10808 return sme_is_any_session_connected(pHddCtx->hHal);
10809}
10810
10811
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053010812int wlan_hdd_scan_abort(hdd_adapter_t *pAdapter)
10813{
10814 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10815 hdd_scaninfo_t *pScanInfo = NULL;
Girish Gowli4bf7a632014-06-12 13:42:11 +053010816 long status = 0;
c_hpothua3d45d52015-01-05 14:11:17 +053010817 tSirAbortScanStatus abortScanStatus;
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053010818
10819 pScanInfo = &pHddCtx->scan_info;
10820 if (pScanInfo->mScanPending)
10821 {
c_hpothua3d45d52015-01-05 14:11:17 +053010822 abortScanStatus = hdd_abort_mac_scan(pHddCtx, pScanInfo->sessionId,
10823 eCSR_SCAN_ABORT_DEFAULT);
10824 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
10825 FL("abortScanStatus: %d"), abortScanStatus);
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053010826
c_hpothua3d45d52015-01-05 14:11:17 +053010827 /* If there is active scan command lets wait for the completion else
10828 * there is no need to wait as scan command might be in the SME pending
10829 * command list.
10830 */
10831 if (abortScanStatus == eSIR_ABORT_ACTIVE_SCAN_LIST_NOT_EMPTY)
10832 {
10833 INIT_COMPLETION(pScanInfo->abortscan_event_var);
10834 status = wait_for_completion_interruptible_timeout(
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053010835 &pScanInfo->abortscan_event_var,
10836 msecs_to_jiffies(5000));
c_hpothua3d45d52015-01-05 14:11:17 +053010837 if (0 >= status)
10838 {
10839 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Girish Gowli4bf7a632014-06-12 13:42:11 +053010840 "%s: Timeout or Interrupt occurred while waiting for abort"
10841 "scan, status- %ld", __func__, status);
c_hpothua3d45d52015-01-05 14:11:17 +053010842 return -ETIMEDOUT;
10843 }
10844 }
10845 else if (abortScanStatus == eSIR_ABORT_SCAN_FAILURE)
10846 {
10847 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
10848 FL("hdd_abort_mac_scan failed"));
10849 return -VOS_STATUS_E_FAILURE;
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053010850 }
10851 }
Girish Gowli4bf7a632014-06-12 13:42:11 +053010852 return 0;
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053010853}
10854
c_hpothu225aa7c2014-10-22 17:45:13 +053010855VOS_STATUS wlan_hdd_cancel_remain_on_channel(hdd_context_t *pHddCtx)
10856{
10857 hdd_adapter_t *pAdapter;
10858 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
10859 VOS_STATUS vosStatus;
10860
10861 vosStatus = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10862 while (NULL != pAdapterNode && VOS_STATUS_E_EMPTY != vosStatus)
10863 {
10864 pAdapter = pAdapterNode->pAdapter;
10865 if (NULL != pAdapter)
10866 {
10867 if (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode ||
10868 WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ||
10869 WLAN_HDD_P2P_GO == pAdapter->device_mode)
10870 {
10871 hddLog(LOG1, FL("abort ROC deviceMode: %d"),
10872 pAdapter->device_mode);
10873 if (VOS_STATUS_SUCCESS !=
10874 wlan_hdd_cancel_existing_remain_on_channel(pAdapter))
10875 {
10876 hddLog(LOGE, FL("failed to abort ROC"));
10877 return VOS_STATUS_E_FAILURE;
10878 }
10879 }
10880 }
10881 vosStatus = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10882 pAdapterNode = pNext;
10883 }
10884 return VOS_STATUS_SUCCESS;
10885}
Mahesh A Saptasagard477b092015-02-06 15:12:16 +053010886
10887void hdd_nullify_netdev_ops(hdd_context_t *pHddCtx)
10888{
10889 VOS_STATUS status;
10890 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
10891 hdd_adapter_t *pAdapter;
10892
10893 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10894 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
10895 {
10896 pAdapter = pAdapterNode->pAdapter;
10897 if (NULL != pAdapter)
10898 {
10899 /* Disable TX on the interface, after this hard_start_xmit() will
10900 * not be called on that interface
10901 */
10902 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
10903 netif_tx_disable(pAdapter->dev);
10904 /* Mark the interface status as "down" for outside world */
10905 netif_carrier_off(pAdapter->dev);
10906 pAdapter->dev->netdev_ops = &nullify_netdev_ops;
10907 }
10908 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10909 pAdapterNode = pNext;
10910 }
10911}
10912
Jeff Johnson295189b2012-06-20 16:38:30 -070010913//Register the module init/exit functions
10914module_init(hdd_module_init);
10915module_exit(hdd_module_exit);
10916
10917MODULE_LICENSE("Dual BSD/GPL");
10918MODULE_AUTHOR("Qualcomm Atheros, Inc.");
10919MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
10920
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070010921module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
10922 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -070010923
Jeff Johnson76052702013-04-16 13:55:05 -070010924module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -070010925 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Arif Hussain66559122013-11-21 10:11:40 -080010926
10927module_param(enable_dfs_chan_scan, int,
10928 S_IRUSR | S_IRGRP | S_IROTH);
10929
10930module_param(enable_11d, int,
10931 S_IRUSR | S_IRGRP | S_IROTH);
10932
10933module_param(country_code, charp,
10934 S_IRUSR | S_IRGRP | S_IROTH);