blob: 382bc92e270bbeafb566a3717ac9162b889f2d93 [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Kiet Lam842dad02014-02-18 18:44:02 -08002 * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved.
3 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
Kiet Lama7f454d2014-07-24 12:04:06 -070023 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
Gopichand Nakkala92f07d82013-01-08 21:16:34 -080026 */
Kiet Lam842dad02014-02-18 18:44:02 -080027
28
Kiet Lama7f454d2014-07-24 12:04:06 -070029
30
Jeff Johnson295189b2012-06-20 16:38:30 -070031/*========================================================================
32
33 \file wlan_hdd_main.c
34
35 \brief WLAN Host Device Driver implementation
36
37 Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved.
38
39 Qualcomm Confidential and Proprietary.
40
41 ========================================================================*/
42
43/**=========================================================================
44
45 EDIT HISTORY FOR FILE
46
47
48 This section contains comments describing changes made to the module.
49 Notice that changes are listed in reverse chronological order.
50
51
52 $Header:$ $DateTime: $ $Author: $
53
54
55 when who what, where, why
56 -------- --- --------------------------------------------------------
57 04/5/09 Shailender Created module.
58 02/24/10 Sudhir.S.Kohalli Added to support param for SoftAP module
59 06/03/10 js - Added support to hostapd driven deauth/disassoc/mic failure
60 ==========================================================================*/
61
62/*--------------------------------------------------------------------------
63 Include Files
64 ------------------------------------------------------------------------*/
65//#include <wlan_qct_driver.h>
66#include <wlan_hdd_includes.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070067#include <vos_api.h>
68#include <vos_sched.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070069#include <linux/etherdevice.h>
70#include <linux/firmware.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070071#ifdef ANI_BUS_TYPE_PLATFORM
72#include <linux/wcnss_wlan.h>
73#endif //ANI_BUS_TYPE_PLATFORM
74#ifdef ANI_BUS_TYPE_PCI
75#include "wcnss_wlan.h"
76#endif /* ANI_BUS_TYPE_PCI */
77#include <wlan_hdd_tx_rx.h>
78#include <palTimer.h>
79#include <wniApi.h>
80#include <wlan_nlink_srv.h>
81#include <wlan_btc_svc.h>
82#include <wlan_hdd_cfg.h>
83#include <wlan_ptt_sock_svc.h>
Vinay Krishna Erannad938c422014-03-10 17:14:21 +053084#include <wlan_logging_sock_svc.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070085#include <wlan_hdd_wowl.h>
86#include <wlan_hdd_misc.h>
87#include <wlan_hdd_wext.h>
88#ifdef WLAN_BTAMP_FEATURE
89#include <bap_hdd_main.h>
90#include <bapInternal.h>
91#endif // WLAN_BTAMP_FEATURE
Sushant Kaushik4b7cb302014-01-06 17:45:01 +053092#include "wlan_hdd_trace.h"
93#include "vos_types.h"
94#include "vos_trace.h"
Jeff Johnson295189b2012-06-20 16:38:30 -070095#include <linux/wireless.h>
96#include <net/cfg80211.h>
Vinay Krishna Erannad9cbdb32014-01-16 12:59:10 +053097#include <linux/inetdevice.h>
98#include <net/addrconf.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070099#include "wlan_hdd_cfg80211.h"
100#include "wlan_hdd_p2p.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700101#include <linux/rtnetlink.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700102int wlan_hdd_ftm_start(hdd_context_t *pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700103#include "sapApi.h"
104#include <linux/semaphore.h>
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -0700105#include <linux/ctype.h>
Arun Kumar Khandavalli74fe3032014-03-17 20:35:34 +0530106#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0))
107#include <soc/qcom/subsystem_restart.h>
108#else
Jeff Johnson295189b2012-06-20 16:38:30 -0700109#include <mach/subsystem_restart.h>
Arun Kumar Khandavalli74fe3032014-03-17 20:35:34 +0530110#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700111#include <wlan_hdd_hostapd.h>
112#include <wlan_hdd_softap_tx_rx.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700113#include "cfgApi.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700114#include "wlan_hdd_dev_pwr.h"
115#ifdef WLAN_BTAMP_FEATURE
116#include "bap_hdd_misc.h"
117#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700118#include "wlan_qct_pal_trace.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700119#include "qwlan_version.h"
Yathish9f22e662012-12-10 14:21:35 -0800120#include "wlan_qct_wda.h"
Chilam NG571c65a2013-01-19 12:27:36 +0530121#ifdef FEATURE_WLAN_TDLS
122#include "wlan_hdd_tdls.h"
123#endif
Yue Ma0d4891e2013-08-06 17:01:45 -0700124#include "wlan_hdd_debugfs.h"
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +0530125#include "sapInternal.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700126
127#ifdef MODULE
128#define WLAN_MODULE_NAME module_name(THIS_MODULE)
129#else
130#define WLAN_MODULE_NAME "wlan"
131#endif
132
133#ifdef TIMER_MANAGER
134#define TIMER_MANAGER_STR " +TIMER_MANAGER"
135#else
136#define TIMER_MANAGER_STR ""
137#endif
138
139#ifdef MEMORY_DEBUG
140#define MEMORY_DEBUG_STR " +MEMORY_DEBUG"
141#else
142#define MEMORY_DEBUG_STR ""
143#endif
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530144#define MAX_WAIT_FOR_ROC_COMPLETION 3
Jeff Johnson295189b2012-06-20 16:38:30 -0700145/* the Android framework expects this param even though we don't use it */
146#define BUF_LEN 20
Jeff Johnson76052702013-04-16 13:55:05 -0700147static char fwpath_buffer[BUF_LEN];
148static struct kparam_string fwpath = {
149 .string = fwpath_buffer,
150 .maxlen = BUF_LEN,
151};
Arif Hussain66559122013-11-21 10:11:40 -0800152
153static char *country_code;
154static int enable_11d = -1;
155static int enable_dfs_chan_scan = -1;
c_hpothu92367912014-05-01 15:18:17 +0530156static int gbcnMissRate = -1;
Arif Hussain66559122013-11-21 10:11:40 -0800157
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700158#ifndef MODULE
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700159static int wlan_hdd_inited;
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700160#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700161
Jeff Johnsone7245742012-09-05 17:12:55 -0700162/*
Jeff Johnson72a40512013-12-19 10:14:15 -0800163 * spinlock for synchronizing asynchronous request/response
164 * (full description of use in wlan_hdd_main.h)
165 */
166DEFINE_SPINLOCK(hdd_context_lock);
167
168/*
Jeff Johnsone7245742012-09-05 17:12:55 -0700169 * The rate at which the driver sends RESTART event to supplicant
170 * once the function 'vos_wlanRestart()' is called
171 *
172 */
173#define WLAN_HDD_RESTART_RETRY_DELAY_MS 5000 /* 5 second */
174#define WLAN_HDD_RESTART_RETRY_MAX_CNT 5 /* 5 retries */
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -0700175
176/*
177 * Size of Driver command strings from upper layer
178 */
179#define SIZE_OF_SETROAMMODE 11 /* size of SETROAMMODE */
180#define SIZE_OF_GETROAMMODE 11 /* size of GETROAMMODE */
181
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -0800182#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda5cecb202013-10-08 09:13:25 -0700183#define TID_MIN_VALUE 0
184#define TID_MAX_VALUE 15
185static VOS_STATUS hdd_get_tsm_stats(hdd_adapter_t *pAdapter, const tANI_U8 tid,
186 tAniTrafStrmMetrics* pTsmMetrics);
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -0800187static VOS_STATUS hdd_parse_ese_beacon_req(tANI_U8 *pValue,
188 tCsrEseBeaconReq *pEseBcnReq);
189#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -0700190
Atul Mittal1d722422014-03-19 11:15:07 +0530191/*
192 * Maximum buffer size used for returning the data back to user space
193 */
194#define WLAN_MAX_BUF_SIZE 1024
195#define WLAN_PRIV_DATA_MAX_LEN 8192
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -0700196
c_hpothu92367912014-05-01 15:18:17 +0530197//wait time for beacon miss rate.
198#define BCN_MISS_RATE_TIME 500
199
Sameer Thalappil50dc0092013-02-19 17:23:33 -0800200#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -0700201static struct wake_lock wlan_wake_lock;
Jeff Johnsone7245742012-09-05 17:12:55 -0700202#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700203/* set when SSR is needed after unload */
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -0700204static e_hdd_ssr_required isSsrRequired = HDD_SSR_NOT_REQUIRED;
Jeff Johnson295189b2012-06-20 16:38:30 -0700205
206//internal function declaration
Jeff Johnsone7245742012-09-05 17:12:55 -0700207static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx);
208static void wlan_hdd_restart_init(hdd_context_t *pHddCtx);
209static void wlan_hdd_restart_deinit(hdd_context_t *pHddCtx);
210void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback);
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800211void hdd_set_wlan_suspend_mode(bool suspend);
Jeff Johnsone7245742012-09-05 17:12:55 -0700212
Jeff Johnson295189b2012-06-20 16:38:30 -0700213v_U16_t hdd_select_queue(struct net_device *dev,
214 struct sk_buff *skb);
215
216#ifdef WLAN_FEATURE_PACKET_FILTERING
217static void hdd_set_multicast_list(struct net_device *dev);
218#endif
219
220void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter);
221
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -0800222#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -0800223void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand);
224static VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels);
Srinivas Girigowda100eb322013-03-15 16:48:20 -0700225static VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid,
226 tANI_U8 *pChannel, tANI_U8 *pDwellTime,
227 tANI_U8 **pBuf, tANI_U8 *pBufLen);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -0700228static VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue,
229 tANI_U8 *pTargetApBssid,
230 tANI_U8 *pChannel);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800231#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -0800232#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda5cecb202013-10-08 09:13:25 -0700233VOS_STATUS hdd_parse_get_cckm_ie(tANI_U8 *pValue, tANI_U8 **pCckmIe, tANI_U8 *pCckmIeLen);
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -0800234#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -0700235
Mihir Shetee1093ba2014-01-21 20:13:32 +0530236static VOS_STATUS wlan_hdd_init_channels(hdd_context_t *pHddCtx);
Sushant Kaushik8bc7df22014-04-09 17:55:29 +0530237const char * hdd_device_modetoString(v_U8_t device_mode)
238{
239 switch(device_mode)
240 {
241 CASE_RETURN_STRING( WLAN_HDD_INFRA_STATION );
242 CASE_RETURN_STRING( WLAN_HDD_SOFTAP );
243 CASE_RETURN_STRING( WLAN_HDD_P2P_CLIENT );
244 CASE_RETURN_STRING( WLAN_HDD_P2P_GO );
245 CASE_RETURN_STRING( WLAN_HDD_MONITOR);
246 CASE_RETURN_STRING( WLAN_HDD_FTM );
247 CASE_RETURN_STRING( WLAN_HDD_IBSS );
248 CASE_RETURN_STRING( WLAN_HDD_P2P_DEVICE );
249 default:
250 return "device_mode Unknown";
251 }
252}
Mihir Shetee1093ba2014-01-21 20:13:32 +0530253
Jeff Johnson295189b2012-06-20 16:38:30 -0700254static int hdd_netdev_notifier_call(struct notifier_block * nb,
255 unsigned long state,
256 void *ndev)
257{
258 struct net_device *dev = ndev;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700259 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson27cee452013-03-27 11:10:24 -0700260 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700261#ifdef WLAN_BTAMP_FEATURE
262 VOS_STATUS status;
Jeff Johnson295189b2012-06-20 16:38:30 -0700263#endif
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +0530264 long result;
Jeff Johnson295189b2012-06-20 16:38:30 -0700265
266 //Make sure that this callback corresponds to our device.
Jeff Johnson27cee452013-03-27 11:10:24 -0700267 if ((strncmp(dev->name, "wlan", 4)) &&
Amar Singhal4c723bd2013-03-25 18:14:15 -0700268 (strncmp(dev->name, "p2p", 3)))
269 return NOTIFY_DONE;
270
Jeff Johnson295189b2012-06-20 16:38:30 -0700271 if (!dev->ieee80211_ptr)
Jeff Johnson27cee452013-03-27 11:10:24 -0700272 return NOTIFY_DONE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700273
Jeff Johnson27cee452013-03-27 11:10:24 -0700274 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -0700275 {
Jeff Johnsona8a1a482012-12-12 16:49:33 -0800276 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Adapter Null Pointer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700277 VOS_ASSERT(0);
278 return NOTIFY_DONE;
279 }
280
Jeff Johnson27cee452013-03-27 11:10:24 -0700281 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
282 if (NULL == pHddCtx)
283 {
284 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Context Null Pointer", __func__);
285 VOS_ASSERT(0);
286 return NOTIFY_DONE;
287 }
Sameer Thalappil14067972014-01-23 14:54:54 -0800288 if (pHddCtx->isLogpInProgress)
289 return NOTIFY_DONE;
290
Jeff Johnson27cee452013-03-27 11:10:24 -0700291
292 hddLog(VOS_TRACE_LEVEL_INFO, "%s: %s New Net Device State = %lu",
293 __func__, dev->name, state);
Jeff Johnson295189b2012-06-20 16:38:30 -0700294
295 switch (state) {
296 case NETDEV_REGISTER:
297 break;
298
299 case NETDEV_UNREGISTER:
300 break;
301
302 case NETDEV_UP:
303 break;
304
305 case NETDEV_DOWN:
306 break;
307
308 case NETDEV_CHANGE:
Jeff Johnsone7245742012-09-05 17:12:55 -0700309 if(TRUE == pAdapter->isLinkUpSvcNeeded)
310 complete(&pAdapter->linkup_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700311 break;
312
313 case NETDEV_GOING_DOWN:
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +0530314 result = wlan_hdd_scan_abort(pAdapter);
Girish Gowli4bf7a632014-06-12 13:42:11 +0530315 if (result < 0)
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +0530316 {
317 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
318 "%s: Timeout occurred while waiting for abortscan %ld",
319 __func__, result);
Jeff Johnson295189b2012-06-20 16:38:30 -0700320 }
321 else
322 {
323 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +0530324 "%s: Scan Abort Successful" , __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700325 }
326#ifdef WLAN_BTAMP_FEATURE
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700327 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: disabling AMP", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700328 status = WLANBAP_StopAmp();
329 if(VOS_STATUS_SUCCESS != status )
330 {
331 pHddCtx->isAmpAllowed = VOS_TRUE;
332 hddLog(VOS_TRACE_LEVEL_FATAL,
333 "%s: Failed to stop AMP", __func__);
334 }
335 else
336 {
337 //a state m/c implementation in PAL is TBD to avoid this delay
338 msleep(500);
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700339 if ( pHddCtx->isAmpAllowed )
340 {
341 WLANBAP_DeregisterFromHCI();
342 pHddCtx->isAmpAllowed = VOS_FALSE;
343 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700344 }
345#endif //WLAN_BTAMP_FEATURE
346 break;
347
348 default:
349 break;
350 }
351
352 return NOTIFY_DONE;
353}
354
355struct notifier_block hdd_netdev_notifier = {
356 .notifier_call = hdd_netdev_notifier_call,
357};
358
359/*---------------------------------------------------------------------------
360 * Function definitions
361 *-------------------------------------------------------------------------*/
Jeff Johnson295189b2012-06-20 16:38:30 -0700362void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx);
363void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -0700364//variable to hold the insmod parameters
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700365static int con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -0700366#ifndef MODULE
367/* current con_mode - used only for statically linked driver
368 * con_mode is changed by userspace to indicate a mode change which will
369 * result in calling the module exit and init functions. The module
370 * exit function will clean up based on the value of con_mode prior to it
371 * being changed by userspace. So curr_con_mode records the current con_mode
372 * for exit when con_mode becomes the next mode for init
373 */
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700374static int curr_con_mode;
Jeff Johnson295189b2012-06-20 16:38:30 -0700375#endif
376
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -0800377/**---------------------------------------------------------------------------
378
379 \brief hdd_vos_trace_enable() - Configure initial VOS Trace enable
380
381 Called immediately after the cfg.ini is read in order to configure
382 the desired trace levels.
383
384 \param - moduleId - module whose trace level is being configured
385 \param - bitmask - bitmask of log levels to be enabled
386
387 \return - void
388
389 --------------------------------------------------------------------------*/
390static void hdd_vos_trace_enable(VOS_MODULE_ID moduleId, v_U32_t bitmask)
391{
392 wpt_tracelevel level;
393
394 /* if the bitmask is the default value, then a bitmask was not
395 specified in cfg.ini, so leave the logging level alone (it
396 will remain at the "compiled in" default value) */
397 if (CFG_VOS_TRACE_ENABLE_DEFAULT == bitmask)
398 {
399 return;
400 }
401
402 /* a mask was specified. start by disabling all logging */
403 vos_trace_setValue(moduleId, VOS_TRACE_LEVEL_NONE, 0);
404
405 /* now cycle through the bitmask until all "set" bits are serviced */
406 level = VOS_TRACE_LEVEL_FATAL;
407 while (0 != bitmask)
408 {
409 if (bitmask & 1)
410 {
411 vos_trace_setValue(moduleId, level, 1);
412 }
413 level++;
414 bitmask >>= 1;
415 }
416}
417
418
Jeff Johnson295189b2012-06-20 16:38:30 -0700419/**---------------------------------------------------------------------------
420
421 \brief hdd_wdi_trace_enable() - Configure initial WDI Trace enable
422
423 Called immediately after the cfg.ini is read in order to configure
424 the desired trace levels in the WDI.
425
426 \param - moduleId - module whose trace level is being configured
427 \param - bitmask - bitmask of log levels to be enabled
428
429 \return - void
430
431 --------------------------------------------------------------------------*/
432static void hdd_wdi_trace_enable(wpt_moduleid moduleId, v_U32_t bitmask)
433{
434 wpt_tracelevel level;
435
436 /* if the bitmask is the default value, then a bitmask was not
437 specified in cfg.ini, so leave the logging level alone (it
438 will remain at the "compiled in" default value) */
439 if (CFG_WDI_TRACE_ENABLE_DEFAULT == bitmask)
440 {
441 return;
442 }
443
444 /* a mask was specified. start by disabling all logging */
445 wpalTraceSetLevel(moduleId, eWLAN_PAL_TRACE_LEVEL_NONE, 0);
446
447 /* now cycle through the bitmask until all "set" bits are serviced */
448 level = eWLAN_PAL_TRACE_LEVEL_FATAL;
449 while (0 != bitmask)
450 {
451 if (bitmask & 1)
452 {
453 wpalTraceSetLevel(moduleId, level, 1);
454 }
455 level++;
456 bitmask >>= 1;
457 }
458}
Jeff Johnson295189b2012-06-20 16:38:30 -0700459
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530460/*
461 * FUNCTION: wlan_hdd_validate_context
462 * This function is used to check the HDD context
463 */
464int wlan_hdd_validate_context(hdd_context_t *pHddCtx)
465{
466 ENTER();
467
468 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
469 {
470 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
471 "%s: HDD context is Null", __func__);
472 return -ENODEV;
473 }
474
475 if (pHddCtx->isLogpInProgress)
476 {
477 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
478 "%s: LOGP in Progress. Ignore!!!", __func__);
479 return -EAGAIN;
480 }
481
Mihir Shete18156292014-03-11 15:38:30 +0530482 if (WLAN_HDD_IS_LOAD_UNLOAD_IN_PROGRESS(pHddCtx))
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530483 {
484 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
485 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
486 return -EAGAIN;
487 }
488 return 0;
489}
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700490#ifdef CONFIG_ENABLE_LINUX_REG
491void hdd_checkandupdate_phymode( hdd_context_t *pHddCtx)
492{
493 hdd_adapter_t *pAdapter = NULL;
494 hdd_station_ctx_t *pHddStaCtx = NULL;
495 eCsrPhyMode phyMode;
496 hdd_config_t *cfg_param = NULL;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530497
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700498 if (NULL == pHddCtx)
499 {
500 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
501 "HDD Context is null !!");
502 return ;
503 }
504
505 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
506 if (NULL == pAdapter)
507 {
508 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
509 "pAdapter is null !!");
510 return ;
511 }
512
513 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
514 if (NULL == pHddStaCtx)
515 {
516 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
517 "pHddStaCtx is null !!");
518 return ;
519 }
520
521 cfg_param = pHddCtx->cfg_ini;
522 if (NULL == cfg_param)
523 {
524 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
525 "cfg_params not available !!");
526 return ;
527 }
528
529 phyMode = sme_GetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter));
530
531 if (!pHddCtx->isVHT80Allowed)
532 {
533 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
534 (eCSR_DOT11_MODE_11ac == phyMode) ||
535 (eCSR_DOT11_MODE_11ac_ONLY == phyMode))
536 {
537 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
538 "Setting phymode to 11n!!");
539 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter), eCSR_DOT11_MODE_11n);
540 }
541 }
542 else
543 {
544 /*New country Supports 11ac as well resetting value back from .ini*/
545 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter),
546 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->dot11Mode));
547 return ;
548 }
549
550 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
551 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode) ||
552 (eCSR_CFG_DOT11_MODE_11AC == pHddStaCtx->conn_info.dot11Mode)))
553 {
554 VOS_STATUS vosStatus;
555
556 // need to issue a disconnect to CSR.
557 INIT_COMPLETION(pAdapter->disconnect_comp_var);
558 vosStatus = sme_RoamDisconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
559 pAdapter->sessionId,
560 eCSR_DISCONNECT_REASON_UNSPECIFIED );
561
562 if (VOS_STATUS_SUCCESS == vosStatus)
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530563 {
564 long ret;
565
566 ret = wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700567 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530568 if (0 >= ret)
569 hddLog(LOGE, FL("failure waiting for disconnect_comp_var %ld"),
570 ret);
571 }
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700572
573 }
574}
575#else
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530576void hdd_checkandupdate_phymode( hdd_adapter_t *pAdapter, char *country_code)
577{
578 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
579 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
580 hdd_config_t *cfg_param;
581 eCsrPhyMode phyMode;
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530582 long ret;
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530583
584 if (NULL == pHddCtx)
585 {
586 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
587 "HDD Context is null !!");
588 return ;
589 }
590
591 cfg_param = pHddCtx->cfg_ini;
592
593 if (NULL == cfg_param)
594 {
595 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
596 "cfg_params not available !!");
597 return ;
598 }
599
600 phyMode = sme_GetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter));
601
602 if (NULL != strstr(cfg_param->listOfNon11acCountryCode, country_code))
603 {
604 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
605 (eCSR_DOT11_MODE_11ac == phyMode) ||
606 (eCSR_DOT11_MODE_11ac_ONLY == phyMode))
607 {
608 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
609 "Setting phymode to 11n!!");
610 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter), eCSR_DOT11_MODE_11n);
611 }
612 }
613 else
614 {
615 /*New country Supports 11ac as well resetting value back from .ini*/
616 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter),
617 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->dot11Mode));
618 return ;
619 }
620
621 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
622 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode) ||
623 (eCSR_CFG_DOT11_MODE_11AC == pHddStaCtx->conn_info.dot11Mode)))
624 {
625 VOS_STATUS vosStatus;
626
627 // need to issue a disconnect to CSR.
628 INIT_COMPLETION(pAdapter->disconnect_comp_var);
629 vosStatus = sme_RoamDisconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
630 pAdapter->sessionId,
631 eCSR_DISCONNECT_REASON_UNSPECIFIED );
632
633 if (VOS_STATUS_SUCCESS == vosStatus)
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530634 {
635 ret = wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530636 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530637 if (ret <= 0)
638 {
639 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
640 "wait on disconnect_comp_var is failed %ld", ret);
641 }
642 }
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530643
644 }
645}
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700646#endif //CONFIG_ENABLE_LINUX_REG
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530647
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700648void hdd_checkandupdate_dfssetting( hdd_adapter_t *pAdapter, char *country_code)
649{
650 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
651 hdd_config_t *cfg_param;
652
653 if (NULL == pHddCtx)
654 {
655 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
656 "HDD Context is null !!");
657 return ;
658 }
659
660 cfg_param = pHddCtx->cfg_ini;
661
662 if (NULL == cfg_param)
663 {
664 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
665 "cfg_params not available !!");
666 return ;
667 }
668
Agarwal Ashish738843c2014-09-25 12:27:56 +0530669 if (NULL != strstr(cfg_param->listOfNonDfsCountryCode, country_code) ||
670 pHddCtx->disable_dfs_flag == TRUE)
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700671 {
672 /*New country doesn't support DFS */
673 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), 0);
674 }
675 else
676 {
677 /*New country Supports DFS as well resetting value back from .ini*/
678 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), cfg_param->enableDFSChnlScan);
679 }
680
681}
682
Rajeev79dbe4c2013-10-05 11:03:42 +0530683#ifdef FEATURE_WLAN_BATCH_SCAN
684
685/**---------------------------------------------------------------------------
686
687 \brief hdd_extract_assigned_int_from_str() - Extracts assigned integer from
688 input string
689
690 This function extracts assigned integer from string in below format:
691 "STRING=10" : extracts integer 10 from this string
692
693 \param - pInPtr Pointer to input string
694 \param - base Base for string to int conversion(10 for decimal 16 for hex)
695 \param - pOutPtr Pointer to variable in which extracted integer needs to be
696 assigned
697 \param - pLastArg to tell whether it is last arguement in input string or
698 not
699
700 \return - NULL for failure cases
701 pointer to next arguement in input string for success cases
702 --------------------------------------------------------------------------*/
703static tANI_U8 *
704hdd_extract_assigned_int_from_str
705(
706 tANI_U8 *pInPtr,
707 tANI_U8 base,
708 tANI_U32 *pOutPtr,
709 tANI_U8 *pLastArg
710)
711{
712 int tempInt;
713 int v = 0;
714 char buf[32];
715 int val = 0;
716 *pLastArg = FALSE;
717
718 pInPtr = strnchr(pInPtr, strlen(pInPtr), EQUALS_TO_ASCII_VALUE);
719 if (NULL == pInPtr)
720 {
721 return NULL;
722 }
723
724 pInPtr++;
725
726 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
727
728 val = sscanf(pInPtr, "%32s ", buf);
729 if (val < 0 && val > strlen(pInPtr))
730 {
731 return NULL;
732 }
733 pInPtr += val;
734 v = kstrtos32(buf, base, &tempInt);
735 if (v < 0)
736 {
737 return NULL;
738 }
Rajeev Kumar4d93d842014-01-02 18:31:21 -0800739 if (tempInt < 0)
740 {
741 tempInt = 0;
742 }
Rajeev79dbe4c2013-10-05 11:03:42 +0530743 *pOutPtr = tempInt;
744
745 pInPtr = strnchr(pInPtr, strlen(pInPtr), SPACE_ASCII_VALUE);
746 if (NULL == pInPtr)
747 {
748 *pLastArg = TRUE;
749 return NULL;
750 }
751 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
752
753 return pInPtr;
754}
755
756/**---------------------------------------------------------------------------
757
758 \brief hdd_extract_assigned_char_from_str() - Extracts assigned char from
759 input string
760
761 This function extracts assigned character from string in below format:
762 "STRING=A" : extracts char 'A' from this string
763
764 \param - pInPtr Pointer to input string
765 \param - pOutPtr Pointer to variable in which extracted char needs to be
766 assigned
767 \param - pLastArg to tell whether it is last arguement in input string or
768 not
769
770 \return - NULL for failure cases
771 pointer to next arguement in input string for success cases
772 --------------------------------------------------------------------------*/
773static tANI_U8 *
774hdd_extract_assigned_char_from_str
775(
776 tANI_U8 *pInPtr,
777 tANI_U8 *pOutPtr,
778 tANI_U8 *pLastArg
779)
780{
781 *pLastArg = FALSE;
782
783 pInPtr = strnchr(pInPtr, strlen(pInPtr), EQUALS_TO_ASCII_VALUE);
784 if (NULL == pInPtr)
785 {
786 return NULL;
787 }
788
789 pInPtr++;
790
791 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
792
793 *pOutPtr = *pInPtr;
794
795 pInPtr = strnchr(pInPtr, strlen(pInPtr), SPACE_ASCII_VALUE);
796 if (NULL == pInPtr)
797 {
798 *pLastArg = TRUE;
799 return NULL;
800 }
801 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
802
803 return pInPtr;
804}
805
806
807/**---------------------------------------------------------------------------
808
809 \brief hdd_parse_set_batchscan_command () - HDD parse set batch scan command
810
811 This function parses set batch scan command in below format:
812 WLS_BATCHING_SET <space> followed by below arguements
813 "SCANFREQ=XX" : Optional defaults to 30 sec
814 "MSCAN=XX" : Required number of scans to attempt to batch
815 "BESTN=XX" : Best Network (RSSI) defaults to 16
816 "CHANNEL=<X,Y>" : optional defaults to all channels, can list 'A'or` B.
817 A. implies only 5 GHz , B. implies only 2.4GHz
818 "RTT=X" : optional defaults to 0
819 returns the MIN of MSCAN or the max # of scans firmware can cache or -1 on
820 error
821
822 For example input commands:
823 1) WLS_BATCHING_SET SCANFREQ=60 MSCAN=10 BESTN=20 CHANNEL=A RTT=0 -> This is
824 translated into set batch scan with following parameters:
825 a) Frequence 60 seconds
826 b) Batch 10 scans together
827 c) Best RSSI to be 20
828 d) 5GHz band only
829 e) RTT is equal to 0
830
831 \param - pValue Pointer to input channel list
832 \param - pHddSetBatchScanReq Pointer to HDD batch scan request structure
833
834 \return - 0 for success non-zero for failure
835
836 --------------------------------------------------------------------------*/
837static int
838hdd_parse_set_batchscan_command
839(
840 tANI_U8 *pValue,
841 tSirSetBatchScanReq *pHddSetBatchScanReq
842)
843{
844 tANI_U8 *inPtr = pValue;
845 tANI_U8 val = 0;
846 tANI_U8 lastArg = 0;
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800847 tANI_U32 nScanFreq;
848 tANI_U32 nMscan;
849 tANI_U32 nBestN;
850 tANI_U8 ucRfBand;
851 tANI_U32 nRtt;
Rajeev Kumarc933d982013-11-18 20:04:20 -0800852 tANI_U32 temp;
Rajeev79dbe4c2013-10-05 11:03:42 +0530853
854 /*initialize default values*/
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800855 nScanFreq = HDD_SET_BATCH_SCAN_DEFAULT_FREQ;
856 ucRfBand = HDD_SET_BATCH_SCAN_DEFAULT_BAND;
857 nRtt = 0;
858 nBestN = HDD_SET_BATCH_SCAN_BEST_NETWORK;
Rajeev79dbe4c2013-10-05 11:03:42 +0530859
860 /*go to space after WLS_BATCHING_SET command*/
861 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
862 /*no argument after the command*/
863 if (NULL == inPtr)
864 {
865 return -EINVAL;
866 }
867
868 /*no space after the command*/
869 else if (SPACE_ASCII_VALUE != *inPtr)
870 {
871 return -EINVAL;
872 }
873
874 /*removing empty spaces*/
875 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
876
877 /*no argument followed by spaces*/
878 if ('\0' == *inPtr)
879 {
880 return -EINVAL;
881 }
882
883 /*check and parse SCANFREQ*/
884 if ((strncmp(inPtr, "SCANFREQ", 8) == 0))
885 {
886 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumarc933d982013-11-18 20:04:20 -0800887 &temp, &lastArg);
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800888
Rajeev Kumarc933d982013-11-18 20:04:20 -0800889 if (0 != temp)
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800890 {
Rajeev Kumarc933d982013-11-18 20:04:20 -0800891 nScanFreq = temp;
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800892 }
893
Rajeev79dbe4c2013-10-05 11:03:42 +0530894 if ( (NULL == inPtr) || (TRUE == lastArg))
895 {
896 return -EINVAL;
897 }
898 }
899
900 /*check and parse MSCAN*/
901 if ((strncmp(inPtr, "MSCAN", 5) == 0))
902 {
903 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800904 &nMscan, &lastArg);
905
906 if (0 == nMscan)
907 {
908 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
909 "invalid MSCAN=%d", nMscan);
910 return -EINVAL;
911 }
912
Rajeev79dbe4c2013-10-05 11:03:42 +0530913 if (TRUE == lastArg)
914 {
915 goto done;
916 }
917 else if (NULL == inPtr)
918 {
919 return -EINVAL;
920 }
921 }
922 else
923 {
924 return -EINVAL;
925 }
926
927 /*check and parse BESTN*/
928 if ((strncmp(inPtr, "BESTN", 5) == 0))
929 {
930 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumarc933d982013-11-18 20:04:20 -0800931 &temp, &lastArg);
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800932
Rajeev Kumarc933d982013-11-18 20:04:20 -0800933 if (0 != temp)
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800934 {
Rajeev Kumarc933d982013-11-18 20:04:20 -0800935 nBestN = temp;
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800936 }
937
Rajeev79dbe4c2013-10-05 11:03:42 +0530938 if (TRUE == lastArg)
939 {
940 goto done;
941 }
942 else if (NULL == inPtr)
943 {
944 return -EINVAL;
945 }
946 }
947
948 /*check and parse CHANNEL*/
949 if ((strncmp(inPtr, "CHANNEL", 7) == 0))
950 {
951 inPtr = hdd_extract_assigned_char_from_str(inPtr, &val, &lastArg);
Rajeev Kumarc933d982013-11-18 20:04:20 -0800952
Rajeev79dbe4c2013-10-05 11:03:42 +0530953 if (('A' == val) || ('a' == val))
954 {
c_hpothuebf89732014-02-25 13:00:24 +0530955 ucRfBand = HDD_SET_BATCH_SCAN_5GHz_BAND_ONLY;
Rajeev79dbe4c2013-10-05 11:03:42 +0530956 }
957 else if (('B' == val) || ('b' == val))
958 {
c_hpothuebf89732014-02-25 13:00:24 +0530959 ucRfBand = HDD_SET_BATCH_SCAN_24GHz_BAND_ONLY;
Rajeev79dbe4c2013-10-05 11:03:42 +0530960 }
961 else
962 {
Rajeev Kumarc933d982013-11-18 20:04:20 -0800963 ucRfBand = HDD_SET_BATCH_SCAN_DEFAULT_BAND;
964 }
965
966 if (TRUE == lastArg)
967 {
968 goto done;
969 }
970 else if (NULL == inPtr)
971 {
Rajeev79dbe4c2013-10-05 11:03:42 +0530972 return -EINVAL;
973 }
974 }
975
976 /*check and parse RTT*/
977 if ((strncmp(inPtr, "RTT", 3) == 0))
978 {
979 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800980 &nRtt, &lastArg);
Rajeev79dbe4c2013-10-05 11:03:42 +0530981 if (TRUE == lastArg)
982 {
983 goto done;
984 }
985 if (NULL == inPtr)
986 {
987 return -EINVAL;
988 }
989 }
990
991
992done:
993
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800994 pHddSetBatchScanReq->scanFrequency = nScanFreq;
995 pHddSetBatchScanReq->numberOfScansToBatch = nMscan;
996 pHddSetBatchScanReq->bestNetwork = nBestN;
997 pHddSetBatchScanReq->rfBand = ucRfBand;
998 pHddSetBatchScanReq->rtt = nRtt;
999
Rajeev79dbe4c2013-10-05 11:03:42 +05301000 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1001 "Received WLS_BATCHING_SET with SCANFREQ=%d "
1002 "MSCAN=%d BESTN=%d CHANNEL=%d RTT=%d",
1003 pHddSetBatchScanReq->scanFrequency,
1004 pHddSetBatchScanReq->numberOfScansToBatch,
1005 pHddSetBatchScanReq->bestNetwork,
1006 pHddSetBatchScanReq->rfBand,
1007 pHddSetBatchScanReq->rtt);
1008
1009 return 0;
1010}/*End of hdd_parse_set_batchscan_command*/
1011
1012/**---------------------------------------------------------------------------
1013
1014 \brief hdd_set_batch_scan_req_callback () - This function is called after
1015 receiving set batch scan response from FW and it saves set batch scan
1016 response data FW to HDD context and sets the completion event on
1017 which hdd_ioctl is waiting
1018
1019 \param - callbackContext Pointer to HDD adapter
1020 \param - pRsp Pointer to set batch scan response data received from FW
1021
1022 \return - nothing
1023
1024 --------------------------------------------------------------------------*/
1025static void hdd_set_batch_scan_req_callback
1026(
1027 void *callbackContext,
1028 tSirSetBatchScanRsp *pRsp
1029)
1030{
1031 hdd_adapter_t* pAdapter = (hdd_adapter_t*)callbackContext;
1032 tSirSetBatchScanRsp *pHddSetBatchScanRsp;
1033
1034 /*sanity check*/
1035 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
1036 {
1037 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1038 "%s: Invalid pAdapter magic", __func__);
1039 VOS_ASSERT(0);
1040 return;
1041 }
1042 pHddSetBatchScanRsp = &pAdapter->hddSetBatchScanRsp;
1043
1044 /*save set batch scan response*/
1045 pHddSetBatchScanRsp->nScansToBatch = pRsp->nScansToBatch;
1046
1047 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1048 "Received set batch scan rsp from FW with nScansToBatch=%d",
1049 pHddSetBatchScanRsp->nScansToBatch);
1050
1051 pAdapter->hdd_wait_for_set_batch_scan_rsp = FALSE;
1052 complete(&pAdapter->hdd_set_batch_scan_req_var);
1053
1054 return;
1055}/*End of hdd_set_batch_scan_req_callback*/
1056
1057
1058/**---------------------------------------------------------------------------
1059
1060 \brief hdd_populate_batch_scan_rsp_queue () - This function stores AP meta
1061 info in hdd batch scan response queue
1062
1063 \param - pAdapter Pointer to hdd adapter
1064 \param - pAPMetaInfo Pointer to access point meta info
1065 \param - scanId scan ID of batch scan response
1066 \param - isLastAp tells whether AP is last AP in batch scan response or not
1067
1068 \return - nothing
1069
1070 --------------------------------------------------------------------------*/
1071static void hdd_populate_batch_scan_rsp_queue( hdd_adapter_t* pAdapter,
1072 tpSirBatchScanNetworkInfo pApMetaInfo, tANI_U32 scanId, v_BOOL_t isLastAp)
1073{
1074 tHddBatchScanRsp *pHead;
1075 tHddBatchScanRsp *pNode;
1076 tHddBatchScanRsp *pPrev;
1077 tHddBatchScanRsp *pTemp;
1078 tANI_U8 ssidLen;
1079
1080 /*head of hdd batch scan response queue*/
1081 pHead = pAdapter->pBatchScanRsp;
1082
1083 pNode = (tHddBatchScanRsp *)vos_mem_malloc(sizeof(tHddBatchScanRsp));
1084 if (NULL == pNode)
1085 {
1086 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1087 "%s: Could not allocate memory", __func__);
1088 VOS_ASSERT(0);
1089 return;
1090 }
1091
1092 vos_mem_copy(pNode->ApInfo.bssid, pApMetaInfo->bssid,
1093 sizeof(pNode->ApInfo.bssid));
1094 ssidLen = strlen(pApMetaInfo->ssid);
1095 if (SIR_MAX_SSID_SIZE < ssidLen)
1096 {
1097 /*invalid scan result*/
1098 vos_mem_free(pNode);
1099 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1100 "%s: Invalid AP meta info ssidlen %d", __func__, ssidLen);
1101 return;
1102 }
1103 vos_mem_copy(pNode->ApInfo.ssid, pApMetaInfo->ssid, ssidLen);
1104 /*null terminate ssid*/
1105 pNode->ApInfo.ssid[ssidLen] = '\0';
1106 pNode->ApInfo.ch = pApMetaInfo->ch;
1107 pNode->ApInfo.rssi = pApMetaInfo->rssi;
1108 pNode->ApInfo.age = pApMetaInfo->timestamp;
1109 pNode->ApInfo.batchId = scanId;
1110 pNode->ApInfo.isLastAp = isLastAp;
1111
1112 pNode->pNext = NULL;
1113 if (NULL == pHead)
1114 {
1115 pAdapter->pBatchScanRsp = pNode;
1116 }
1117 else
1118 {
1119 pTemp = pHead;
1120 while (NULL != pTemp)
1121 {
1122 pPrev = pTemp;
1123 pTemp = pTemp->pNext;
1124 }
1125 pPrev->pNext = pNode;
1126 }
1127
1128 return;
1129}/*End of hdd_populate_batch_scan_rsp_queue*/
1130
1131/**---------------------------------------------------------------------------
1132
1133 \brief hdd_batch_scan_result_ind_callback () - This function is called after
1134 receiving batch scan response indication from FW. It saves get batch scan
1135 response data in HDD batch scan response queue. This callback sets the
1136 completion event on which hdd_ioctl is waiting only after getting complete
1137 batch scan response data from FW
1138
1139 \param - callbackContext Pointer to HDD adapter
1140 \param - pRsp Pointer to get batch scan response data received from FW
1141
1142 \return - nothing
1143
1144 --------------------------------------------------------------------------*/
1145static void hdd_batch_scan_result_ind_callback
1146(
1147 void *callbackContext,
1148 void *pRsp
1149)
1150{
1151 v_BOOL_t isLastAp;
1152 tANI_U32 numApMetaInfo;
Rajeev Kumarce651e42013-10-21 18:57:15 -07001153 tANI_U32 numNetworkInScanList;
Rajeev79dbe4c2013-10-05 11:03:42 +05301154 tANI_U32 numberScanList;
1155 tANI_U32 nextScanListOffset;
1156 tANI_U32 nextApMetaInfoOffset;
1157 hdd_adapter_t* pAdapter;
1158 tpSirBatchScanList pScanList;
1159 tpSirBatchScanNetworkInfo pApMetaInfo;
1160 tpSirBatchScanResultIndParam pBatchScanRsp;/*batch scan rsp data from FW*/
1161 tSirSetBatchScanReq *pReq;
1162
1163 pAdapter = (hdd_adapter_t *)callbackContext;
1164 /*sanity check*/
Rajeev Kumar5286bb92013-12-05 11:52:10 -08001165 if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
Rajeev79dbe4c2013-10-05 11:03:42 +05301166 {
1167 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1168 "%s: Invalid pAdapter magic", __func__);
1169 VOS_ASSERT(0);
1170 return;
1171 }
1172
1173 /*initialize locals*/
1174 pReq = &pAdapter->hddSetBatchScanReq;
1175 pBatchScanRsp = (tpSirBatchScanResultIndParam)pRsp;
1176 isLastAp = FALSE;
1177 numApMetaInfo = 0;
Rajeev Kumarce651e42013-10-21 18:57:15 -07001178 numNetworkInScanList = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05301179 numberScanList = 0;
1180 nextScanListOffset = 0;
1181 nextApMetaInfoOffset = 0;
1182 pScanList = NULL;
1183 pApMetaInfo = NULL;
1184
1185 if ((NULL == pBatchScanRsp) || (NULL == pReq))
1186 {
1187 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1188 "%s: pBatchScanRsp is %p pReq %p", __func__, pBatchScanRsp, pReq);
1189 isLastAp = TRUE;
1190 goto done;
1191 }
1192
1193 pAdapter->numScanList = numberScanList = pBatchScanRsp->numScanLists;
1194 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1195 "Batch scan rsp: numberScalList %d", numberScanList);
1196
1197 if ((!numberScanList) || (numberScanList > pReq->numberOfScansToBatch))
1198 {
1199 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1200 "%s: numberScanList %d", __func__, numberScanList);
1201 isLastAp = TRUE;
1202 goto done;
1203 }
1204
1205 while (numberScanList)
1206 {
Rajeev Kumarce651e42013-10-21 18:57:15 -07001207 pScanList = (tpSirBatchScanList)((tANI_U8 *)pBatchScanRsp->scanResults +
Rajeev79dbe4c2013-10-05 11:03:42 +05301208 nextScanListOffset);
1209 if (NULL == pScanList)
1210 {
1211 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1212 "%s: pScanList is %p", __func__, pScanList);
1213 isLastAp = TRUE;
1214 goto done;
1215 }
Rajeev Kumarce651e42013-10-21 18:57:15 -07001216 numNetworkInScanList = numApMetaInfo = pScanList->numNetworksInScanList;
Rajeev79dbe4c2013-10-05 11:03:42 +05301217 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumarce651e42013-10-21 18:57:15 -07001218 "Batch scan rsp: numApMetaInfo %d scanId %d",
1219 numApMetaInfo, pScanList->scanId);
Rajeev79dbe4c2013-10-05 11:03:42 +05301220
1221 if ((!numApMetaInfo) || (numApMetaInfo > pReq->bestNetwork))
1222 {
1223 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1224 "%s: numApMetaInfo %d", __func__, numApMetaInfo);
1225 isLastAp = TRUE;
1226 goto done;
1227 }
1228
Rajeev Kumarce651e42013-10-21 18:57:15 -07001229 /*Initialize next AP meta info offset for next scan list*/
1230 nextApMetaInfoOffset = 0;
1231
Rajeev79dbe4c2013-10-05 11:03:42 +05301232 while (numApMetaInfo)
1233 {
1234 pApMetaInfo = (tpSirBatchScanNetworkInfo)(pScanList->scanList +
1235 nextApMetaInfoOffset);
1236 if (NULL == pApMetaInfo)
1237 {
1238 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1239 "%s: pApMetaInfo is %p", __func__, pApMetaInfo);
1240 isLastAp = TRUE;
1241 goto done;
1242 }
1243 /*calculate AP age*/
1244 pApMetaInfo->timestamp =
1245 pBatchScanRsp->timestamp - pApMetaInfo->timestamp;
1246
1247 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
Arif Hussaina7c8e412013-11-20 11:06:42 -08001248 "%s: bssId "MAC_ADDRESS_STR
1249 " ch %d rssi %d timestamp %d", __func__,
1250 MAC_ADDR_ARRAY(pApMetaInfo->bssid),
1251 pApMetaInfo->ch, pApMetaInfo->rssi,
1252 pApMetaInfo->timestamp);
Rajeev79dbe4c2013-10-05 11:03:42 +05301253
1254 /*mark last AP in batch scan response*/
1255 if ((TRUE == pBatchScanRsp->isLastResult) &&
1256 (1 == numberScanList) && (1 == numApMetaInfo))
1257 {
1258 isLastAp = TRUE;
1259 }
1260
1261 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1262 /*store batch scan repsonse in hdd queue*/
1263 hdd_populate_batch_scan_rsp_queue(pAdapter, pApMetaInfo,
1264 pScanList->scanId, isLastAp);
1265 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1266
1267 nextApMetaInfoOffset += sizeof(tSirBatchScanNetworkInfo);
1268 numApMetaInfo--;
1269 }
1270
Rajeev Kumarce651e42013-10-21 18:57:15 -07001271 nextScanListOffset += ((sizeof(tSirBatchScanList) - sizeof(tANI_U8))
1272 + (sizeof(tSirBatchScanNetworkInfo)
1273 * numNetworkInScanList));
Rajeev79dbe4c2013-10-05 11:03:42 +05301274 numberScanList--;
1275 }
1276
1277done:
1278
1279 /*notify hdd_ioctl only if complete batch scan rsp is received and it was
1280 requested from hdd_ioctl*/
1281 if ((TRUE == pAdapter->hdd_wait_for_get_batch_scan_rsp) &&
1282 (TRUE == isLastAp))
1283 {
1284 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
1285 complete(&pAdapter->hdd_get_batch_scan_req_var);
1286 }
1287
1288 return;
1289}/*End of hdd_batch_scan_result_ind_callback*/
1290
1291/**---------------------------------------------------------------------------
1292
1293 \brief hdd_format_batch_scan_rsp () - This function formats batch scan
1294 response as per batch scan FR request format by putting proper markers
1295
1296 \param - pDest pointer to destination buffer
1297 \param - cur_len current length
1298 \param - tot_len total remaining size which can be written to user space
1299 \param - pApMetaInfo Pointer to get batch scan response AP meta info
1300 \param - pAdapter Pointer to HDD adapter
1301
1302 \return - ret no of characters written
1303
1304 --------------------------------------------------------------------------*/
1305static tANI_U32
1306hdd_format_batch_scan_rsp
1307(
1308 tANI_U8 *pDest,
1309 tANI_U32 cur_len,
1310 tANI_U32 tot_len,
1311 tHddBatchScanRsp *pApMetaInfo,
1312 hdd_adapter_t* pAdapter
1313)
1314{
1315 tANI_U32 ret = 0;
1316 tANI_U32 rem_len = 0;
1317 tANI_U8 temp_len = 0;
1318 tANI_U8 temp_total_len = 0;
1319 tANI_U8 temp[HDD_BATCH_SCAN_AP_META_INFO_SIZE];
1320 tANI_U8 *pTemp = temp;
1321
1322 /*Batch scan reponse needs to be returned to user space in
1323 following format:
1324 "scancount=X\n" where X is the number of scans in current batch
1325 batch
1326 "trunc\n" optional present if current scan truncated
1327 "bssid=XX:XX:XX:XX:XX:XX\n"
1328 "ssid=XXXX\n"
1329 "freq=X\n" frequency in Mhz
1330 "level=XX\n"
1331 "age=X\n" ms
1332 "dist=X\n" cm (-1 if not available)
1333 "errror=X\n" (-1if not available)
1334 "====\n" (end of ap marker)
1335 "####\n" (end of scan marker)
1336 "----\n" (end of results)*/
1337 /*send scan result in above format to user space based on
1338 available length*/
1339 /*The GET response may have more data than the driver can return in its
1340 buffer. In that case the buffer should be filled to the nearest complete
1341 scan, ending with "%%%%".Subsequent callsshould return the remaining data
1342 starting with the next scan (optional .trunc\n., .apcount=X\n., etc).
1343 The final buffer should end with "----\n"*/
1344
1345 /*sanity*/
1346 if (cur_len > tot_len)
1347 {
1348 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1349 "%s: invaid cur_len %d tot_len %d", __func__, cur_len, tot_len);
1350 return 0;
1351 }
1352 else
1353 {
1354 rem_len = (tot_len - cur_len);
1355 }
1356
1357 /*end scan marker*/
1358 if (pApMetaInfo->ApInfo.batchId != pAdapter->prev_batch_id)
1359 {
1360 temp_len = snprintf(pTemp, sizeof(temp), "####\n");
1361 pTemp += temp_len;
1362 temp_total_len += temp_len;
1363 }
1364
1365 /*bssid*/
1366 temp_len = snprintf(pTemp, sizeof(temp),
1367 "bssid=0x%x:0x%x:0x%x:0x%x:0x%x:0x%x\n",
1368 pApMetaInfo->ApInfo.bssid[0], pApMetaInfo->ApInfo.bssid[1],
1369 pApMetaInfo->ApInfo.bssid[2], pApMetaInfo->ApInfo.bssid[3],
1370 pApMetaInfo->ApInfo.bssid[4], pApMetaInfo->ApInfo.bssid[5]);
1371 pTemp += temp_len;
1372 temp_total_len += temp_len;
1373
1374 /*ssid*/
1375 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "ssid=%s\n",
1376 pApMetaInfo->ApInfo.ssid);
1377 pTemp += temp_len;
1378 temp_total_len += temp_len;
1379
1380 /*freq*/
1381 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "freq=%d\n",
Rajeev Kumarc40f7512013-11-04 14:13:23 -08001382 sme_ChnToFreq(pApMetaInfo->ApInfo.ch));
Rajeev79dbe4c2013-10-05 11:03:42 +05301383 pTemp += temp_len;
1384 temp_total_len += temp_len;
1385
1386 /*level*/
1387 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "level=%d\n",
1388 pApMetaInfo->ApInfo.rssi);
1389 pTemp += temp_len;
1390 temp_total_len += temp_len;
1391
1392 /*age*/
Jeff Johnson02797792013-10-26 19:17:13 -07001393 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "age=%d\n",
Rajeev79dbe4c2013-10-05 11:03:42 +05301394 pApMetaInfo->ApInfo.age);
1395 pTemp += temp_len;
1396 temp_total_len += temp_len;
1397
1398 /*dist*/
1399 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "dist=-1\n");
1400 pTemp += temp_len;
1401 temp_total_len += temp_len;
1402
1403 /*error*/
1404 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "error=-1\n");
1405 pTemp += temp_len;
1406 temp_total_len += temp_len;
1407
1408 /*end AP marker*/
1409 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "====\n");
1410 pTemp += temp_len;
1411 temp_total_len += temp_len;
1412
1413 /*last AP in batch scan response*/
1414 if(TRUE == pApMetaInfo->ApInfo.isLastAp)
1415 {
1416 /*end scan marker*/
1417 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "####\n");
1418 pTemp += temp_len;
1419 temp_total_len += temp_len;
1420
1421 /*end batch scan result marker*/
1422 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "----\n");
1423 pTemp += temp_len;
1424 temp_total_len += temp_len;
Kiet Lamaa8e15a2014-02-11 23:30:06 -08001425
Rajeev79dbe4c2013-10-05 11:03:42 +05301426 }
1427
1428 if (temp_total_len < rem_len)
1429 {
1430 ret = temp_total_len + 1;
1431 strlcpy(pDest, temp, ret);
1432 pAdapter->isTruncated = FALSE;
1433 }
1434 else
1435 {
1436 pAdapter->isTruncated = TRUE;
1437 if (rem_len >= strlen("%%%%"))
1438 {
Rajeev Kumarc933d982013-11-18 20:04:20 -08001439 ret = snprintf(pDest, sizeof(temp), "%%%%");
Rajeev79dbe4c2013-10-05 11:03:42 +05301440 }
Rajeev Kumarc933d982013-11-18 20:04:20 -08001441 else
Rajeev79dbe4c2013-10-05 11:03:42 +05301442 {
1443 ret = 0;
1444 }
1445 }
1446
1447 return ret;
1448
1449}/*End of hdd_format_batch_scan_rsp*/
1450
1451/**---------------------------------------------------------------------------
1452
1453 \brief hdd_populate_user_batch_scan_rsp() - This function populates user data
1454 buffer starting with head of hdd batch scan response queue
1455
1456 \param - pAdapter Pointer to HDD adapter
1457 \param - pDest Pointer to user data buffer
1458 \param - cur_len current offset in user buffer
1459 \param - rem_len remaining no of bytes in user buffer
1460
1461 \return - number of bytes written in user buffer
1462
1463 --------------------------------------------------------------------------*/
1464
1465tANI_U32 hdd_populate_user_batch_scan_rsp
1466(
1467 hdd_adapter_t* pAdapter,
1468 tANI_U8 *pDest,
1469 tANI_U32 cur_len,
1470 tANI_U32 rem_len
1471)
1472{
1473 tHddBatchScanRsp *pHead;
1474 tHddBatchScanRsp *pPrev;
1475 tANI_U32 len;
1476
Rajeev79dbe4c2013-10-05 11:03:42 +05301477 pAdapter->isTruncated = FALSE;
1478
1479 /*head of hdd batch scan response queue*/
1480 pHead = pAdapter->pBatchScanRsp;
1481 while (pHead)
1482 {
1483 len = hdd_format_batch_scan_rsp(pDest, cur_len, rem_len, pHead,
1484 pAdapter);
1485 pDest += len;
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07001486 pDest--;
Rajeev79dbe4c2013-10-05 11:03:42 +05301487 cur_len += len;
1488 if(TRUE == pAdapter->isTruncated)
1489 {
1490 /*result is truncated return rest of scan rsp in next req*/
1491 cur_len = rem_len;
1492 break;
1493 }
1494 pPrev = pHead;
1495 pHead = pHead->pNext;
1496 pAdapter->pBatchScanRsp = pHead;
Rajeev Kumarbe17d8b2014-01-10 15:39:45 -08001497 if (TRUE == pPrev->ApInfo.isLastAp)
1498 {
1499 pAdapter->prev_batch_id = 0;
1500 }
1501 else
1502 {
1503 pAdapter->prev_batch_id = pPrev->ApInfo.batchId;
1504 }
Rajeev79dbe4c2013-10-05 11:03:42 +05301505 vos_mem_free(pPrev);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08001506 pPrev = NULL;
Rajeev79dbe4c2013-10-05 11:03:42 +05301507 }
1508
1509 return cur_len;
1510}/*End of hdd_populate_user_batch_scan_rsp*/
1511
1512/**---------------------------------------------------------------------------
1513
1514 \brief hdd_return_batch_scan_rsp_to_user () - This function returns batch
1515 scan response data from HDD queue to user space
1516 It does following in detail:
1517 a) if HDD has enough data in its queue then it 1st copies data to user
1518 space and then send get batch scan indication message to FW. In this
1519 case it does not wait on any event and batch scan response data will
1520 be populated in HDD response queue in MC thread context after receiving
1521 indication from FW
1522 b) else send get batch scan indication message to FW and wait on an event
1523 which will be set once HDD receives complete batch scan response from
1524 FW and then this function returns batch scan response to user space
1525
1526 \param - pAdapter Pointer to HDD adapter
1527 \param - pPrivData Pointer to priv_data
1528
1529 \return - 0 for success -EFAULT for failure
1530
1531 --------------------------------------------------------------------------*/
1532
1533int hdd_return_batch_scan_rsp_to_user
1534(
1535 hdd_adapter_t* pAdapter,
1536 hdd_priv_data_t *pPrivData,
1537 tANI_U8 *command
1538)
1539{
1540 tANI_U8 *pDest;
1541 tANI_U32 count = 0;
1542 tANI_U32 len = 0;
1543 tANI_U32 cur_len = 0;
1544 tANI_U32 rem_len = 0;
1545 eHalStatus halStatus;
1546 unsigned long rc;
1547 tSirTriggerBatchScanResultInd *pReq;
1548
1549 pReq = &pAdapter->hddTriggerBatchScanResultInd;
1550 pReq->param = 0;/*batch scan client*/
1551 pDest = (tANI_U8 *)(command + pPrivData->used_len);
1552 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
1553
1554 cur_len = pPrivData->used_len;
1555 if (pPrivData->total_len > pPrivData->used_len)
1556 {
1557 rem_len = pPrivData->total_len - pPrivData->used_len;
1558 }
1559 else
1560 {
1561 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1562 "%s: Invalid user data buffer total_len %d used_len %d",
1563 __func__, pPrivData->total_len, pPrivData->used_len);
1564 return -EFAULT;
1565 }
1566
1567 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1568 len = hdd_populate_user_batch_scan_rsp(pAdapter, pDest,
1569 cur_len, rem_len);
1570 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1571
1572 /*enough scan result available in cache to return to user space or
1573 scan result needs to be fetched 1st from fw and then return*/
Rajeev Kumar99db6262013-11-11 15:23:36 -08001574 if (len == cur_len)
Rajeev79dbe4c2013-10-05 11:03:42 +05301575 {
1576 pAdapter->hdd_wait_for_get_batch_scan_rsp = TRUE;
1577 halStatus = sme_TriggerBatchScanResultInd(
1578 WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
1579 pAdapter->sessionId, hdd_batch_scan_result_ind_callback,
1580 pAdapter);
1581 if ( eHAL_STATUS_SUCCESS == halStatus )
1582 {
1583 if (TRUE == pAdapter->hdd_wait_for_get_batch_scan_rsp)
1584 {
1585 INIT_COMPLETION(pAdapter->hdd_get_batch_scan_req_var);
1586 rc = wait_for_completion_timeout(
1587 &pAdapter->hdd_get_batch_scan_req_var,
1588 msecs_to_jiffies(HDD_GET_BATCH_SCAN_RSP_TIME_OUT));
1589 if (0 == rc)
1590 {
1591 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1592 "%s: Timeout waiting to fetch batch scan rsp from fw",
1593 __func__);
1594 return -EFAULT;
1595 }
1596 }
1597
1598 len = snprintf(pDest, HDD_BATCH_SCAN_AP_META_INFO_SIZE,
Jeff Johnson02797792013-10-26 19:17:13 -07001599 "scancount=%u\n", pAdapter->numScanList);
Rajeev79dbe4c2013-10-05 11:03:42 +05301600 pDest += len;
1601 cur_len += len;
1602
1603 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1604 len = hdd_populate_user_batch_scan_rsp(pAdapter, pDest,
1605 cur_len, rem_len);
1606 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1607
1608 count = 0;
1609 len = (len - pPrivData->used_len);
1610 pDest = (command + pPrivData->used_len);
1611 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar99db6262013-11-11 15:23:36 -08001612 "NEW BATCH SCAN RESULT:");
Rajeev79dbe4c2013-10-05 11:03:42 +05301613 while(count < len)
1614 {
1615 printk("%c", *(pDest + count));
1616 count++;
1617 }
1618 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1619 "%s: copy %d data to user buffer", __func__, len);
1620 if (copy_to_user(pPrivData->buf, pDest, len))
1621 {
1622 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1623 "%s: failed to copy data to user buffer", __func__);
1624 return -EFAULT;
1625 }
1626 }
1627 else
1628 {
1629 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1630 "sme_GetBatchScanScan returned failure halStatus %d",
1631 halStatus);
1632 return -EINVAL;
1633 }
1634 }
1635 else
1636 {
Rajeev79dbe4c2013-10-05 11:03:42 +05301637 count = 0;
1638 len = (len - pPrivData->used_len);
1639 pDest = (command + pPrivData->used_len);
1640 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar99db6262013-11-11 15:23:36 -08001641 "REMAINING TRUNCATED BATCH SCAN RESULT:");
Rajeev79dbe4c2013-10-05 11:03:42 +05301642 while(count < len)
1643 {
1644 printk("%c", *(pDest + count));
1645 count++;
1646 }
Rajeev Kumar99db6262013-11-11 15:23:36 -08001647 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1648 "%s: copy %d data to user buffer", __func__, len);
Rajeev79dbe4c2013-10-05 11:03:42 +05301649 if (copy_to_user(pPrivData->buf, pDest, len))
1650 {
1651 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1652 "%s: failed to copy data to user buffer", __func__);
1653 return -EFAULT;
1654 }
Rajeev79dbe4c2013-10-05 11:03:42 +05301655 }
1656
1657 return 0;
1658} /*End of hdd_return_batch_scan_rsp_to_user*/
1659
Rajeev Kumar8b373292014-01-08 20:36:55 -08001660
1661/**---------------------------------------------------------------------------
1662
1663 \brief hdd_handle_batch_scan_ioctl () - This function handles WLS_BATCHING
1664 IOCTLs from user space. Following BATCH SCAN DEV IOCTs are handled:
1665 WLS_BATCHING VERSION
1666 WLS_BATCHING SET
1667 WLS_BATCHING GET
1668 WLS_BATCHING STOP
1669
1670 \param - pAdapter Pointer to HDD adapter
1671 \param - pPrivdata Pointer to priv_data
1672 \param - command Pointer to command
1673
1674 \return - 0 for success -EFAULT for failure
1675
1676 --------------------------------------------------------------------------*/
1677
1678int hdd_handle_batch_scan_ioctl
1679(
1680 hdd_adapter_t *pAdapter,
1681 hdd_priv_data_t *pPrivdata,
1682 tANI_U8 *command
1683)
1684{
1685 int ret = 0;
Yue Mae36e3552014-03-05 17:06:20 -08001686 hdd_context_t *pHddCtx;
1687
1688 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
1689 ret = wlan_hdd_validate_context(pHddCtx);
1690 if (ret)
1691 {
1692 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1693 "%s: HDD context is not valid!", __func__);
1694 goto exit;
1695 }
Rajeev Kumar8b373292014-01-08 20:36:55 -08001696
1697 if (strncmp(command, "WLS_BATCHING VERSION", 20) == 0)
1698 {
1699 char extra[32];
1700 tANI_U8 len = 0;
1701 tANI_U8 version = HDD_BATCH_SCAN_VERSION;
1702
1703 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
1704 {
1705 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1706 "%s: Batch scan feature is not supported by FW", __func__);
1707 ret = -EINVAL;
1708 goto exit;
1709 }
1710
1711 len = scnprintf(extra, sizeof(extra), "WLS_BATCHING_VERSION %d",
1712 version);
1713 if (copy_to_user(pPrivdata->buf, &extra, len + 1))
1714 {
1715 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1716 "%s: failed to copy data to user buffer", __func__);
1717 ret = -EFAULT;
1718 goto exit;
1719 }
1720 ret = HDD_BATCH_SCAN_VERSION;
1721 }
1722 else if (strncmp(command, "WLS_BATCHING SET", 16) == 0)
1723 {
1724 int status;
1725 tANI_U8 *value = (command + 16);
1726 eHalStatus halStatus;
1727 unsigned long rc;
1728 tSirSetBatchScanReq *pReq = &pAdapter->hddSetBatchScanReq;
1729 tSirSetBatchScanRsp *pRsp = &pAdapter->hddSetBatchScanRsp;
1730
1731 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
1732 {
1733 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1734 "%s: Batch scan feature is not supported by FW", __func__);
1735 ret = -EINVAL;
1736 goto exit;
1737 }
1738
1739 if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) &&
1740 (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) &&
1741 (WLAN_HDD_P2P_GO != pAdapter->device_mode) &&
1742 (WLAN_HDD_P2P_DEVICE != pAdapter->device_mode))
1743 {
1744 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Sushant Kaushik8bc7df22014-04-09 17:55:29 +05301745 "Received WLS_BATCHING SET command in invalid mode %s (%d) "
Rajeev Kumar8b373292014-01-08 20:36:55 -08001746 "WLS_BATCHING_SET is only allowed in infra STA/P2P client mode",
Sushant Kaushik8bc7df22014-04-09 17:55:29 +05301747 hdd_device_modetoString(pAdapter->device_mode),
1748 pAdapter->device_mode);
Rajeev Kumar8b373292014-01-08 20:36:55 -08001749 ret = -EINVAL;
1750 goto exit;
1751 }
1752
1753 status = hdd_parse_set_batchscan_command(value, pReq);
1754 if (status)
1755 {
1756 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1757 "Invalid WLS_BATCHING SET command");
1758 ret = -EINVAL;
1759 goto exit;
1760 }
1761
1762
1763 pAdapter->hdd_wait_for_set_batch_scan_rsp = TRUE;
1764 halStatus = sme_SetBatchScanReq(WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
1765 pAdapter->sessionId, hdd_set_batch_scan_req_callback,
1766 pAdapter);
1767
1768 if ( eHAL_STATUS_SUCCESS == halStatus )
1769 {
Mahesh A Saptasagar5f568172014-05-14 17:02:33 +05301770 char extra[32];
1771 tANI_U8 len = 0;
1772 tANI_U8 mScan = 0;
1773
Rajeev Kumar8b373292014-01-08 20:36:55 -08001774 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1775 "sme_SetBatchScanReq returned success halStatus %d",
1776 halStatus);
1777 if (TRUE == pAdapter->hdd_wait_for_set_batch_scan_rsp)
1778 {
1779 INIT_COMPLETION(pAdapter->hdd_set_batch_scan_req_var);
1780 rc = wait_for_completion_timeout(
1781 &pAdapter->hdd_set_batch_scan_req_var,
1782 msecs_to_jiffies(HDD_SET_BATCH_SCAN_REQ_TIME_OUT));
1783 if (0 == rc)
1784 {
1785 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1786 "%s: Timeout waiting for set batch scan to complete",
1787 __func__);
1788 ret = -EINVAL;
1789 goto exit;
1790 }
1791 }
1792 if ( !pRsp->nScansToBatch )
1793 {
1794 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1795 "%s: Received set batch scan failure response from FW",
1796 __func__);
1797 ret = -EINVAL;
1798 goto exit;
1799 }
1800 /*As per the Batch Scan Framework API we should return the MIN of
1801 either MSCAN or the max # of scans firmware can cache*/
Mahesh A Saptasagar5f568172014-05-14 17:02:33 +05301802 mScan = MIN(pReq->numberOfScansToBatch , pRsp->nScansToBatch);
Rajeev Kumar8b373292014-01-08 20:36:55 -08001803
1804 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STARTED;
1805
1806 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1807 "%s: request MSCAN %d response MSCAN %d ret %d",
Mahesh A Saptasagar5f568172014-05-14 17:02:33 +05301808 __func__, pReq->numberOfScansToBatch, pRsp->nScansToBatch, mScan);
1809 len = scnprintf(extra, sizeof(extra), "%d", mScan);
1810 if (copy_to_user(pPrivdata->buf, &extra, len + 1))
1811 {
1812 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1813 "%s: failed to copy MSCAN value to user buffer", __func__);
1814 ret = -EFAULT;
1815 goto exit;
1816 }
Rajeev Kumar8b373292014-01-08 20:36:55 -08001817 }
1818 else
1819 {
1820 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1821 "sme_SetBatchScanReq returned failure halStatus %d",
1822 halStatus);
1823 ret = -EINVAL;
1824 goto exit;
1825 }
1826 }
1827 else if (strncmp(command, "WLS_BATCHING STOP", 17) == 0)
1828 {
1829 eHalStatus halStatus;
1830 tSirStopBatchScanInd *pInd = &pAdapter->hddStopBatchScanInd;
1831 pInd->param = 0;
1832
1833 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
1834 {
1835 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1836 "%s: Batch scan feature is not supported by FW", __func__);
1837 ret = -EINVAL;
1838 goto exit;
1839 }
1840
1841 if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState)
1842 {
Deepthi Gowribfd17132014-11-14 17:59:04 +05301843 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Rajeev Kumar8b373292014-01-08 20:36:55 -08001844 "Batch scan is not yet enabled batch scan state %d",
1845 pAdapter->batchScanState);
1846 ret = -EINVAL;
1847 goto exit;
1848 }
1849
Kiet Lamaa8e15a2014-02-11 23:30:06 -08001850 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1851 hdd_deinit_batch_scan(pAdapter);
1852 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1853
Rajeev Kumar8b373292014-01-08 20:36:55 -08001854 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
1855
1856 halStatus = sme_StopBatchScanInd(WLAN_HDD_GET_HAL_CTX(pAdapter), pInd,
1857 pAdapter->sessionId);
1858 if ( eHAL_STATUS_SUCCESS == halStatus )
1859 {
1860 ret = 0;
1861 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1862 "sme_StopBatchScanInd returned success halStatus %d",
1863 halStatus);
1864 }
1865 else
1866 {
1867 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1868 "sme_StopBatchScanInd returned failure halStatus %d",
1869 halStatus);
1870 ret = -EINVAL;
1871 goto exit;
1872 }
1873 }
1874 else if (strncmp(command, "WLS_BATCHING GET", 16) == 0)
1875 {
1876 tANI_U32 remain_len;
1877
1878 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
1879 {
1880 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1881 "%s: Batch scan feature is not supported by FW", __func__);
1882 ret = -EINVAL;
1883 goto exit;
1884 }
1885
1886 if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState)
1887 {
Deepthi Gowribfd17132014-11-14 17:59:04 +05301888 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Rajeev Kumar8b373292014-01-08 20:36:55 -08001889 "Batch scan is not yet enabled could not return results"
1890 "Batch Scan state %d",
1891 pAdapter->batchScanState);
1892 ret = -EINVAL;
1893 goto exit;
1894 }
1895
1896 pPrivdata->used_len = 16;
1897 remain_len = pPrivdata->total_len - pPrivdata->used_len;
1898 if (remain_len < pPrivdata->total_len)
1899 {
1900 /*Clear previous batch scan response data if any*/
1901 vos_mem_zero((tANI_U8 *)(command + pPrivdata->used_len), remain_len);
1902 }
1903 else
1904 {
1905 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1906 "Invalid total length from user space can't fetch batch"
1907 " scan response total_len %d used_len %d remain len %d",
1908 pPrivdata->total_len, pPrivdata->used_len, remain_len);
1909 ret = -EINVAL;
1910 goto exit;
1911 }
1912 ret = hdd_return_batch_scan_rsp_to_user(pAdapter, pPrivdata, command);
1913 }
1914
1915exit:
1916
1917 return ret;
1918}
1919
1920
Rajeev79dbe4c2013-10-05 11:03:42 +05301921#endif/*End of FEATURE_WLAN_BATCH_SCAN*/
1922
c_hpothu92367912014-05-01 15:18:17 +05301923static void getBcnMissRateCB(VOS_STATUS status, int bcnMissRate, void *data)
1924{
c_hpothu39eb1e32014-06-26 16:31:50 +05301925 bcnMissRateContext_t *pCBCtx;
1926
1927 if (NULL == data)
1928 {
1929 hddLog(VOS_TRACE_LEVEL_ERROR, FL("argument data is NULL"));
1930 return;
1931 }
c_hpothu92367912014-05-01 15:18:17 +05301932
1933 /* there is a race condition that exists between this callback
1934 function and the caller since the caller could time out either
1935 before or while this code is executing. we use a spinlock to
1936 serialize these actions */
1937 spin_lock(&hdd_context_lock);
1938
c_hpothu39eb1e32014-06-26 16:31:50 +05301939 pCBCtx = (bcnMissRateContext_t *)data;
c_hpothu92367912014-05-01 15:18:17 +05301940 gbcnMissRate = -1;
1941
c_hpothu39eb1e32014-06-26 16:31:50 +05301942 if (pCBCtx->magic != BCN_MISS_RATE_CONTEXT_MAGIC)
c_hpothu92367912014-05-01 15:18:17 +05301943 {
1944 hddLog(VOS_TRACE_LEVEL_ERROR,
c_hpothu39eb1e32014-06-26 16:31:50 +05301945 FL("invalid context magic: %08x"), pCBCtx->magic);
c_hpothu92367912014-05-01 15:18:17 +05301946 spin_unlock(&hdd_context_lock);
1947 return ;
1948 }
1949
1950 if (VOS_STATUS_SUCCESS == status)
1951 {
c_hpothu39eb1e32014-06-26 16:31:50 +05301952 gbcnMissRate = bcnMissRate;
c_hpothu92367912014-05-01 15:18:17 +05301953 }
c_hpothu39eb1e32014-06-26 16:31:50 +05301954 else
1955 {
1956 hddLog(VOS_TRACE_LEVEL_ERROR, FL("failed to get bcnMissRate"));
1957 }
1958
c_hpothu92367912014-05-01 15:18:17 +05301959 complete(&(pCBCtx->completion));
1960 spin_unlock(&hdd_context_lock);
1961
1962 return;
1963}
1964
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05301965static int hdd_get_dwell_time(hdd_config_t *pCfg, tANI_U8 *command, char *extra, tANI_U8 n, tANI_U8 *len)
1966{
1967 int ret = 0;
1968
1969 if (!pCfg || !command || !extra || !len)
1970 {
1971 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1972 "%s: argument passsed for GETDWELLTIME is incorrect", __func__);
1973 ret = -EINVAL;
1974 return ret;
1975 }
1976
1977 if (strncmp(command, "GETDWELLTIME ACTIVE MAX", 23) == 0)
1978 {
1979 *len = scnprintf(extra, n, "GETDWELLTIME ACTIVE MAX %u\n",
1980 (int)pCfg->nActiveMaxChnTime);
1981 return ret;
1982 }
1983 else if (strncmp(command, "GETDWELLTIME ACTIVE MIN", 23) == 0)
1984 {
1985 *len = scnprintf(extra, n, "GETDWELLTIME ACTIVE MIN %u\n",
1986 (int)pCfg->nActiveMinChnTime);
1987 return ret;
1988 }
1989 else if (strncmp(command, "GETDWELLTIME PASSIVE MAX", 24) == 0)
1990 {
1991 *len = scnprintf(extra, n, "GETDWELLTIME PASSIVE MAX %u\n",
1992 (int)pCfg->nPassiveMaxChnTime);
1993 return ret;
1994 }
1995 else if (strncmp(command, "GETDWELLTIME PASSIVE MIN", 24) == 0)
1996 {
1997 *len = scnprintf(extra, n, "GETDWELLTIME PASSIVE MIN %u\n",
1998 (int)pCfg->nPassiveMinChnTime);
1999 return ret;
2000 }
Rajesh Babu Prathipati0fd227e2014-07-05 12:50:00 +05302001 else if (strncmp(command, "GETDWELLTIME", 12) == 0)
2002 {
2003 *len = scnprintf(extra, n, "GETDWELLTIME %u \n",
2004 (int)pCfg->nActiveMaxChnTime);
2005 return ret;
2006 }
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302007 else
2008 {
2009 ret = -EINVAL;
2010 }
2011
2012 return ret;
2013}
2014
2015static int hdd_set_dwell_time(hdd_adapter_t *pAdapter, tANI_U8 *command)
2016{
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302017 tHalHandle hHal;
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302018 hdd_config_t *pCfg;
2019 tANI_U8 *value = command;
2020 int val = 0, ret = 0, temp = 0;
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302021 tSmeConfigParams smeConfig;
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302022
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302023 if (!pAdapter || !command || !(pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini)
2024 || !(hHal = (WLAN_HDD_GET_HAL_CTX(pAdapter))))
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302025 {
2026 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2027 "%s: argument passed for SETDWELLTIME is incorrect", __func__);
2028 ret = -EINVAL;
2029 return ret;
2030 }
2031
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302032 vos_mem_zero(&smeConfig, sizeof(smeConfig));
2033 sme_GetConfigParam(hHal, &smeConfig);
2034
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302035 if (strncmp(command, "SETDWELLTIME ACTIVE MAX", 23) == 0 )
2036 {
2037 value = value + 24;
2038 temp = kstrtou32(value, 10, &val);
2039 if (temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_MIN ||
2040 val > CFG_ACTIVE_MAX_CHANNEL_TIME_MAX )
2041 {
2042 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2043 "%s: argument passed for SETDWELLTIME ACTIVE MAX is incorrect", __func__);
2044 ret = -EFAULT;
2045 return ret;
2046 }
2047 pCfg->nActiveMaxChnTime = val;
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302048 smeConfig.csrConfig.nActiveMaxChnTime = val;
2049 sme_UpdateConfig(hHal, &smeConfig);
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302050 }
2051 else if (strncmp(command, "SETDWELLTIME ACTIVE MIN", 23) == 0)
2052 {
2053 value = value + 24;
2054 temp = kstrtou32(value, 10, &val);
2055 if (temp !=0 || val < CFG_ACTIVE_MIN_CHANNEL_TIME_MIN ||
2056 val > CFG_ACTIVE_MIN_CHANNEL_TIME_MAX )
2057 {
2058 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2059 "%s: argument passsed for SETDWELLTIME ACTIVE MIN is incorrect", __func__);
2060 ret = -EFAULT;
2061 return ret;
2062 }
2063 pCfg->nActiveMinChnTime = val;
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302064 smeConfig.csrConfig.nActiveMinChnTime = val;
2065 sme_UpdateConfig(hHal, &smeConfig);
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302066 }
2067 else if (strncmp(command, "SETDWELLTIME PASSIVE MAX", 24) == 0)
2068 {
2069 value = value + 25;
2070 temp = kstrtou32(value, 10, &val);
2071 if (temp != 0 || val < CFG_PASSIVE_MAX_CHANNEL_TIME_MIN ||
2072 val > CFG_PASSIVE_MAX_CHANNEL_TIME_MAX )
2073 {
2074 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2075 "%s: argument passed for SETDWELLTIME PASSIVE MAX is incorrect", __func__);
2076 ret = -EFAULT;
2077 return ret;
2078 }
2079 pCfg->nPassiveMaxChnTime = val;
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302080 smeConfig.csrConfig.nPassiveMaxChnTime = val;
2081 sme_UpdateConfig(hHal, &smeConfig);
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302082 }
2083 else if (strncmp(command, "SETDWELLTIME PASSIVE MIN", 24) == 0)
2084 {
2085 value = value + 25;
2086 temp = kstrtou32(value, 10, &val);
2087 if (temp != 0 || val < CFG_PASSIVE_MIN_CHANNEL_TIME_MIN ||
2088 val > CFG_PASSIVE_MIN_CHANNEL_TIME_MAX )
2089 {
2090 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2091 "%s: argument passed for SETDWELLTIME PASSIVE MIN is incorrect", __func__);
2092 ret = -EFAULT;
2093 return ret;
2094 }
2095 pCfg->nPassiveMinChnTime = val;
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302096 smeConfig.csrConfig.nPassiveMinChnTime = val;
2097 sme_UpdateConfig(hHal, &smeConfig);
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302098 }
Rajesh Babu Prathipati0fd227e2014-07-05 12:50:00 +05302099 else if (strncmp(command, "SETDWELLTIME", 12) == 0)
2100 {
2101 value = value + 13;
2102 temp = kstrtou32(value, 10, &val);
2103 if (temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_MIN ||
2104 val > CFG_ACTIVE_MAX_CHANNEL_TIME_MAX )
2105 {
2106 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2107 "%s: argument passed for SETDWELLTIME is incorrect", __func__);
2108 ret = -EFAULT;
2109 return ret;
2110 }
2111 pCfg->nActiveMaxChnTime = val;
2112 smeConfig.csrConfig.nActiveMaxChnTime = val;
2113 sme_UpdateConfig(hHal, &smeConfig);
2114 }
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302115 else
2116 {
2117 ret = -EINVAL;
2118 }
2119
2120 return ret;
2121}
2122
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002123static int hdd_driver_command(hdd_adapter_t *pAdapter,
2124 hdd_priv_data_t *ppriv_data)
Jeff Johnson295189b2012-06-20 16:38:30 -07002125{
Jeff Johnson295189b2012-06-20 16:38:30 -07002126 hdd_priv_data_t priv_data;
2127 tANI_U8 *command = NULL;
Kaushik, Sushant96122442014-10-21 16:40:18 +05302128 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2129 hdd_scaninfo_t *pScanInfo = NULL;
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002130 int ret = 0;
Kaushik, Sushant96122442014-10-21 16:40:18 +05302131 int status;
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002132 /*
2133 * Note that valid pointers are provided by caller
2134 */
Jeff Johnson295189b2012-06-20 16:38:30 -07002135
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002136 /* copy to local struct to avoid numerous changes to legacy code */
2137 priv_data = *ppriv_data;
Jeff Johnson295189b2012-06-20 16:38:30 -07002138
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002139 if (priv_data.total_len <= 0 ||
2140 priv_data.total_len > WLAN_PRIV_DATA_MAX_LEN)
Sameer Thalappil8ef3a0e2013-04-05 14:36:04 -07002141 {
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002142 hddLog(VOS_TRACE_LEVEL_WARN,
2143 "%s:invalid priv_data.total_len(%d)!!!", __func__,
2144 priv_data.total_len);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07002145 ret = -EINVAL;
2146 goto exit;
2147 }
Kaushik, Sushant96122442014-10-21 16:40:18 +05302148 status = wlan_hdd_validate_context(pHddCtx);
2149 if (0 != status)
2150 {
2151 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2152 "%s: HDD context is not valid", __func__);
2153 return status;
2154 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07002155 /* Allocate +1 for '\0' */
2156 command = kmalloc(priv_data.total_len + 1, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07002157 if (!command)
2158 {
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002159 hddLog(VOS_TRACE_LEVEL_ERROR,
2160 "%s: failed to allocate memory", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002161 ret = -ENOMEM;
2162 goto exit;
2163 }
2164
2165 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
2166 {
2167 ret = -EFAULT;
2168 goto exit;
2169 }
2170
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002171 /* Make sure the command is NUL-terminated */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07002172 command[priv_data.total_len] = '\0';
2173
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002174 /* at one time the following block of code was conditional. braces
2175 * have been retained to avoid re-indenting the legacy code
2176 */
Jeff Johnson295189b2012-06-20 16:38:30 -07002177 {
2178 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2179
2180 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07002181 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -07002182
2183 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
2184 {
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302185 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2186 TRACE_CODE_HDD_P2P_DEV_ADDR_IOCTL,
2187 pAdapter->sessionId, (unsigned)
2188 (*(pHddCtx->p2pDeviceAddress.bytes+2)<<24 |
2189 *(pHddCtx->p2pDeviceAddress.bytes+3)<<16 |
2190 *(pHddCtx->p2pDeviceAddress.bytes+4)<<8 |
2191 *(pHddCtx->p2pDeviceAddress.bytes+5))));
Jeff Johnson295189b2012-06-20 16:38:30 -07002192 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
2193 sizeof(tSirMacAddr)))
2194 {
2195 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Arif Hussain6d2a3322013-11-17 19:50:10 -08002196 "%s: failed to copy data to user buffer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002197 ret = -EFAULT;
2198 }
2199 }
Amar Singhal0974e402013-02-12 14:27:46 -08002200 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07002201 {
Amar Singhal0974e402013-02-12 14:27:46 -08002202 tANI_U8 *ptr = command ;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002203
Jeff Johnson295189b2012-06-20 16:38:30 -07002204 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -08002205
2206 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -07002207 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07002208 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -08002209 "%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 -07002210 /* Change band request received */
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002211 ret = hdd_setBand_helper(pAdapter->dev, ptr);
Abhishek Singh2ec36ab2014-08-07 16:14:25 +05302212 if(ret < 0)
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302213 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002214 "%s: failed to set band ret=%d", __func__, ret);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002215 }
Kiet Lamf040f472013-11-20 21:15:23 +05302216 else if(strncmp(command, "SETWMMPS", 8) == 0)
2217 {
2218 tANI_U8 *ptr = command;
2219 ret = hdd_wmmps_helper(pAdapter, ptr);
2220 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07002221 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
2222 {
2223 char *country_code;
2224
2225 country_code = command + 8;
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07002226
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002227 INIT_COMPLETION(pAdapter->change_country_code);
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07002228 hdd_checkandupdate_dfssetting(pAdapter, country_code);
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -07002229#ifndef CONFIG_ENABLE_LINUX_REG
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +05302230 hdd_checkandupdate_phymode(pAdapter, country_code);
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -07002231#endif
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002232 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal,
2233 (void *)(tSmeChangeCountryCallback)
2234 wlan_hdd_change_country_code_callback,
Abhishek Singha306a442013-11-07 18:39:01 +05302235 country_code, pAdapter, pHddCtx->pvosContext, eSIR_TRUE, eSIR_TRUE);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002236 if (eHAL_STATUS_SUCCESS == ret)
2237 {
2238 ret = wait_for_completion_interruptible_timeout(
2239 &pAdapter->change_country_code,
2240 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
2241 if (0 >= ret)
2242 {
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002243 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: SME while setting country code timed out %d",
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302244 __func__, ret);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002245 }
2246 }
2247 else
Jeff Johnson32d95a32012-09-10 13:15:23 -07002248 {
2249 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002250 "%s: SME Change Country code fail ret=%d", __func__, ret);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002251 ret = -EINVAL;
Jeff Johnson32d95a32012-09-10 13:15:23 -07002252 }
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002253
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07002254 }
2255 /*
2256 command should be a string having format
2257 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
2258 */
Amar Singhal0974e402013-02-12 14:27:46 -08002259 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07002260 {
Amar Singhal0974e402013-02-12 14:27:46 -08002261 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07002262
2263 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002264 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07002265
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -08002266 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -07002267 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -08002268 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
2269 {
2270 int suspend = 0;
2271 tANI_U8 *ptr = (tANI_U8*)command + 15;
2272
2273 suspend = *ptr - '0';
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302274 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2275 TRACE_CODE_HDD_SETSUSPENDMODE_IOCTL,
2276 pAdapter->sessionId, suspend));
Sameer Thalappil45931fb2013-02-01 11:18:05 -08002277 hdd_set_wlan_suspend_mode(suspend);
2278 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002279#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
2280 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
2281 {
2282 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002283 tANI_S8 rssi = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002284 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
2285 eHalStatus status = eHAL_STATUS_SUCCESS;
2286
2287 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
2288 value = value + 15;
2289
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002290 /* Convert the value from ascii to integer */
2291 ret = kstrtos8(value, 10, &rssi);
2292 if (ret < 0)
2293 {
2294 /* If the input value is greater than max value of datatype, then also
2295 kstrtou8 fails */
2296 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2297 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdafa7157d2013-10-31 10:14:22 -07002298 __func__,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002299 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
2300 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
2301 ret = -EINVAL;
2302 goto exit;
2303 }
2304
Srinivas Girigowdade697412013-02-14 16:31:48 -08002305 lookUpThreshold = abs(rssi);
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002306
Srinivas Girigowdade697412013-02-14 16:31:48 -08002307 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
2308 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
2309 {
2310 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2311 "Neighbor lookup threshold value %d is out of range"
2312 " (Min: %d Max: %d)", lookUpThreshold,
2313 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
2314 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
2315 ret = -EINVAL;
2316 goto exit;
2317 }
2318
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302319 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2320 TRACE_CODE_HDD_SETROAMTRIGGER_IOCTL,
2321 pAdapter->sessionId, lookUpThreshold));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002322 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2323 "%s: Received Command to Set Roam trigger"
2324 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
2325
2326 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
2327 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
2328 if (eHAL_STATUS_SUCCESS != status)
2329 {
2330 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2331 "%s: Failed to set roam trigger, try again", __func__);
2332 ret = -EPERM;
2333 goto exit;
2334 }
2335
2336 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
mukul sharmad6e1fdd2014-06-23 19:19:09 +05302337 pHddCtx->cfg_ini->nNeighborReassocRssiThreshold = lookUpThreshold + 5;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002338 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
2339 }
2340 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
2341 {
2342 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
2343 int rssi = (-1) * lookUpThreshold;
2344 char extra[32];
2345 tANI_U8 len = 0;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302346 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2347 TRACE_CODE_HDD_GETROAMTRIGGER_IOCTL,
2348 pAdapter->sessionId, lookUpThreshold));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002349 len = scnprintf(extra, sizeof(extra), "%s %d", command, rssi);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002350 if (copy_to_user(priv_data.buf, &extra, len + 1))
2351 {
2352 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2353 "%s: failed to copy data to user buffer", __func__);
2354 ret = -EFAULT;
2355 goto exit;
2356 }
2357 }
2358 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
2359 {
2360 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002361 tANI_U8 roamScanPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002362 tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002363
Srinivas Girigowdade697412013-02-14 16:31:48 -08002364 /* input refresh period is in terms of seconds */
2365 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
2366 value = value + 18;
2367 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002368 ret = kstrtou8(value, 10, &roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002369 if (ret < 0)
2370 {
2371 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002372 kstrtou8 fails */
Srinivas Girigowdade697412013-02-14 16:31:48 -08002373 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002374 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdade697412013-02-14 16:31:48 -08002375 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07002376 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
2377 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002378 ret = -EINVAL;
2379 goto exit;
2380 }
2381
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002382 if ((roamScanPeriod < (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000)) ||
2383 (roamScanPeriod > (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000)))
Srinivas Girigowdade697412013-02-14 16:31:48 -08002384 {
2385 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002386 "Roam scan period value %d is out of range"
2387 " (Min: %d Max: %d)", roamScanPeriod,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07002388 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
2389 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002390 ret = -EINVAL;
2391 goto exit;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302392 }
2393 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2394 TRACE_CODE_HDD_SETROAMSCANPERIOD_IOCTL,
2395 pAdapter->sessionId, roamScanPeriod));
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002396 neighborEmptyScanRefreshPeriod = roamScanPeriod * 1000;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002397
2398 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2399 "%s: Received Command to Set roam scan period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002400 " (Empty Scan refresh period) = %d", __func__, roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002401
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002402 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod;
2403 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002404 }
2405 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
2406 {
2407 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
2408 char extra[32];
2409 tANI_U8 len = 0;
2410
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302411 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2412 TRACE_CODE_HDD_GETROAMSCANPERIOD_IOCTL,
2413 pAdapter->sessionId, nEmptyScanRefreshPeriod));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002414 len = scnprintf(extra, sizeof(extra), "%s %d",
2415 "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002416 /* Returned value is in units of seconds */
2417 if (copy_to_user(priv_data.buf, &extra, len + 1))
2418 {
2419 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2420 "%s: failed to copy data to user buffer", __func__);
2421 ret = -EFAULT;
2422 goto exit;
2423 }
2424 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002425 else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0)
2426 {
2427 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002428 tANI_U8 roamScanRefreshPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002429 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002430
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002431 /* input refresh period is in terms of seconds */
2432 /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */
2433 value = value + 25;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002434
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002435 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002436 ret = kstrtou8(value, 10, &roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002437 if (ret < 0)
2438 {
2439 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002440 kstrtou8 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002441 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002442 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002443 __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002444 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
2445 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
2446 ret = -EINVAL;
2447 goto exit;
2448 }
2449
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002450 if ((roamScanRefreshPeriod < (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000)) ||
2451 (roamScanRefreshPeriod > (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000)))
2452 {
2453 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2454 "Neighbor scan results refresh period value %d is out of range"
2455 " (Min: %d Max: %d)", roamScanRefreshPeriod,
2456 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
2457 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
2458 ret = -EINVAL;
2459 goto exit;
2460 }
2461 neighborScanRefreshPeriod = roamScanRefreshPeriod * 1000;
2462
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002463 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2464 "%s: Received Command to Set roam scan refresh period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002465 " (Scan refresh period) = %d", __func__, roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002466
2467 pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod;
2468 sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
2469 }
2470 else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0)
2471 {
2472 tANI_U16 value = sme_getNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
2473 char extra[32];
2474 tANI_U8 len = 0;
2475
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002476 len = scnprintf(extra, sizeof(extra), "%s %d",
2477 "GETROAMSCANREFRESHPERIOD", (value/1000));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002478 /* Returned value is in units of seconds */
2479 if (copy_to_user(priv_data.buf, &extra, len + 1))
2480 {
2481 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2482 "%s: failed to copy data to user buffer", __func__);
2483 ret = -EFAULT;
2484 goto exit;
2485 }
2486 }
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07002487#ifdef FEATURE_WLAN_LFR
2488 /* SETROAMMODE */
2489 else if (strncmp(command, "SETROAMMODE", SIZE_OF_SETROAMMODE) == 0)
2490 {
2491 tANI_U8 *value = command;
2492 tANI_BOOLEAN roamMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
2493
2494 /* Move pointer to ahead of SETROAMMODE<delimiter> */
2495 value = value + SIZE_OF_SETROAMMODE + 1;
2496
2497 /* Convert the value from ascii to integer */
2498 ret = kstrtou8(value, SIZE_OF_SETROAMMODE, &roamMode);
2499 if (ret < 0)
2500 {
2501 /* If the input value is greater than max value of datatype, then also
2502 kstrtou8 fails */
2503 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2504 "%s: kstrtou8 failed range [%d - %d]", __func__,
2505 CFG_LFR_FEATURE_ENABLED_MIN,
2506 CFG_LFR_FEATURE_ENABLED_MAX);
2507 ret = -EINVAL;
2508 goto exit;
2509 }
2510 if ((roamMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
2511 (roamMode > CFG_LFR_FEATURE_ENABLED_MAX))
2512 {
2513 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2514 "Roam Mode value %d is out of range"
2515 " (Min: %d Max: %d)", roamMode,
2516 CFG_LFR_FEATURE_ENABLED_MIN,
2517 CFG_LFR_FEATURE_ENABLED_MAX);
2518 ret = -EINVAL;
2519 goto exit;
2520 }
2521
2522 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2523 "%s: Received Command to Set Roam Mode = %d", __func__, roamMode);
2524 /*
2525 * Note that
2526 * SETROAMMODE 0 is to enable LFR while
2527 * SETROAMMODE 1 is to disable LFR, but
2528 * NotifyIsFastRoamIniFeatureEnabled 0/1 is to enable/disable.
2529 * So, we have to invert the value to call sme_UpdateIsFastRoamIniFeatureEnabled.
2530 */
2531 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
2532 roamMode = CFG_LFR_FEATURE_ENABLED_MAX; /* Roam enable */
2533 else
2534 roamMode = CFG_LFR_FEATURE_ENABLED_MIN; /* Roam disable */
2535
2536 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = roamMode;
2537 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), roamMode);
2538 }
2539 /* GETROAMMODE */
2540 else if (strncmp(priv_data.buf, "GETROAMMODE", SIZE_OF_GETROAMMODE) == 0)
2541 {
2542 tANI_BOOLEAN roamMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2543 char extra[32];
2544 tANI_U8 len = 0;
2545
2546 /*
2547 * roamMode value shall be inverted because the sementics is different.
2548 */
2549 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
2550 roamMode = CFG_LFR_FEATURE_ENABLED_MAX;
2551 else
2552 roamMode = CFG_LFR_FEATURE_ENABLED_MIN;
2553
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002554 len = scnprintf(extra, sizeof(extra), "%s %d", command, roamMode);
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07002555 if (copy_to_user(priv_data.buf, &extra, len + 1))
2556 {
2557 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2558 "%s: failed to copy data to user buffer", __func__);
2559 ret = -EFAULT;
2560 goto exit;
2561 }
2562 }
2563#endif
Srinivas Girigowdade697412013-02-14 16:31:48 -08002564#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002565#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -08002566 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
2567 {
2568 tANI_U8 *value = command;
2569 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
2570
2571 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
2572 value = value + 13;
2573 /* Convert the value from ascii to integer */
2574 ret = kstrtou8(value, 10, &roamRssiDiff);
2575 if (ret < 0)
2576 {
2577 /* If the input value is greater than max value of datatype, then also
2578 kstrtou8 fails */
2579 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2580 "%s: kstrtou8 failed range [%d - %d]", __func__,
2581 CFG_ROAM_RSSI_DIFF_MIN,
2582 CFG_ROAM_RSSI_DIFF_MAX);
2583 ret = -EINVAL;
2584 goto exit;
2585 }
2586
2587 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
2588 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
2589 {
2590 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2591 "Roam rssi diff value %d is out of range"
2592 " (Min: %d Max: %d)", roamRssiDiff,
2593 CFG_ROAM_RSSI_DIFF_MIN,
2594 CFG_ROAM_RSSI_DIFF_MAX);
2595 ret = -EINVAL;
2596 goto exit;
2597 }
2598
2599 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2600 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
2601
2602 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
2603 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
2604 }
2605 else if (strncmp(priv_data.buf, "GETROAMDELTA", 12) == 0)
2606 {
2607 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
2608 char extra[32];
2609 tANI_U8 len = 0;
2610
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302611 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2612 TRACE_CODE_HDD_GETROAMDELTA_IOCTL,
2613 pAdapter->sessionId, roamRssiDiff));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002614 len = scnprintf(extra, sizeof(extra), "%s %d",
2615 command, roamRssiDiff);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002616 if (copy_to_user(priv_data.buf, &extra, len + 1))
2617 {
2618 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2619 "%s: failed to copy data to user buffer", __func__);
2620 ret = -EFAULT;
2621 goto exit;
2622 }
2623 }
2624#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002625#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -08002626 else if (strncmp(command, "GETBAND", 7) == 0)
2627 {
2628 int band = -1;
2629 char extra[32];
2630 tANI_U8 len = 0;
2631 hdd_getBand_helper(pHddCtx, &band);
2632
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302633 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2634 TRACE_CODE_HDD_GETBAND_IOCTL,
2635 pAdapter->sessionId, band));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002636 len = scnprintf(extra, sizeof(extra), "%s %d", command, band);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002637 if (copy_to_user(priv_data.buf, &extra, len + 1))
2638 {
2639 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2640 "%s: failed to copy data to user buffer", __func__);
2641 ret = -EFAULT;
2642 goto exit;
2643 }
2644 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002645 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
2646 {
2647 tANI_U8 *value = command;
2648 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2649 tANI_U8 numChannels = 0;
2650 eHalStatus status = eHAL_STATUS_SUCCESS;
2651
2652 status = hdd_parse_channellist(value, ChannelList, &numChannels);
2653 if (eHAL_STATUS_SUCCESS != status)
2654 {
2655 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2656 "%s: Failed to parse channel list information", __func__);
2657 ret = -EINVAL;
2658 goto exit;
2659 }
2660
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302661 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2662 TRACE_CODE_HDD_SETROAMSCANCHANNELS_IOCTL,
2663 pAdapter->sessionId, numChannels));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002664 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
2665 {
2666 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2667 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
2668 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
2669 ret = -EINVAL;
2670 goto exit;
2671 }
2672 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
2673 numChannels);
2674 if (eHAL_STATUS_SUCCESS != status)
2675 {
2676 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2677 "%s: Failed to update channel list information", __func__);
2678 ret = -EINVAL;
2679 goto exit;
2680 }
2681 }
2682 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
2683 {
2684 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2685 tANI_U8 numChannels = 0;
Jeff Johnson51b67782013-04-05 12:35:41 -07002686 tANI_U8 j = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002687 char extra[128] = {0};
Jeff Johnson51b67782013-04-05 12:35:41 -07002688 int len;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002689
2690 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
2691 ChannelList, &numChannels ))
2692 {
2693 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2694 "%s: failed to get roam scan channel list", __func__);
2695 ret = -EFAULT;
2696 goto exit;
2697 }
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302698 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2699 TRACE_CODE_HDD_GETROAMSCANCHANNELS_IOCTL,
2700 pAdapter->sessionId, numChannels));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002701 /* output channel list is of the format
2702 [Number of roam scan channels][Channel1][Channel2]... */
2703 /* copy the number of channels in the 0th index */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002704 len = scnprintf(extra, sizeof(extra), "%s %d", command, numChannels);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002705 for (j = 0; (j < numChannels); j++)
2706 {
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002707 len += scnprintf(extra + len, sizeof(extra) - len, " %d",
2708 ChannelList[j]);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002709 }
2710
2711 if (copy_to_user(priv_data.buf, &extra, len + 1))
2712 {
2713 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2714 "%s: failed to copy data to user buffer", __func__);
2715 ret = -EFAULT;
2716 goto exit;
2717 }
2718 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002719 else if (strncmp(command, "GETCCXMODE", 10) == 0)
2720 {
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002721 tANI_BOOLEAN eseMode = sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002722 char extra[32];
2723 tANI_U8 len = 0;
2724
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002725 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002726 then this operation is not permitted (return FAILURE) */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002727 if (eseMode &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002728 hdd_is_okc_mode_enabled(pHddCtx) &&
2729 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2730 {
2731 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002732 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002733 " hence this operation is not permitted!", __func__);
2734 ret = -EPERM;
2735 goto exit;
2736 }
2737
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002738 len = scnprintf(extra, sizeof(extra), "%s %d",
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002739 "GETCCXMODE", eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002740 if (copy_to_user(priv_data.buf, &extra, len + 1))
2741 {
2742 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2743 "%s: failed to copy data to user buffer", __func__);
2744 ret = -EFAULT;
2745 goto exit;
2746 }
2747 }
2748 else if (strncmp(command, "GETOKCMODE", 10) == 0)
2749 {
2750 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
2751 char extra[32];
2752 tANI_U8 len = 0;
2753
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002754 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002755 then this operation is not permitted (return FAILURE) */
2756 if (okcMode &&
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002757 sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002758 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2759 {
2760 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002761 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002762 " hence this operation is not permitted!", __func__);
2763 ret = -EPERM;
2764 goto exit;
2765 }
2766
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002767 len = scnprintf(extra, sizeof(extra), "%s %d",
2768 "GETOKCMODE", okcMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002769 if (copy_to_user(priv_data.buf, &extra, len + 1))
2770 {
2771 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2772 "%s: failed to copy data to user buffer", __func__);
2773 ret = -EFAULT;
2774 goto exit;
2775 }
2776 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002777 else if (strncmp(command, "GETFASTROAM", 11) == 0)
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002778 {
2779 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2780 char extra[32];
2781 tANI_U8 len = 0;
2782
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002783 len = scnprintf(extra, sizeof(extra), "%s %d",
2784 "GETFASTROAM", lfrMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002785 if (copy_to_user(priv_data.buf, &extra, len + 1))
2786 {
2787 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2788 "%s: failed to copy data to user buffer", __func__);
2789 ret = -EFAULT;
2790 goto exit;
2791 }
2792 }
2793 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
2794 {
2795 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2796 char extra[32];
2797 tANI_U8 len = 0;
2798
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002799 len = scnprintf(extra, sizeof(extra), "%s %d",
2800 "GETFASTTRANSITION", ft);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002801 if (copy_to_user(priv_data.buf, &extra, len + 1))
2802 {
2803 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2804 "%s: failed to copy data to user buffer", __func__);
2805 ret = -EFAULT;
2806 goto exit;
2807 }
2808 }
2809 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
2810 {
2811 tANI_U8 *value = command;
2812 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
2813
2814 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
2815 value = value + 26;
2816 /* Convert the value from ascii to integer */
2817 ret = kstrtou8(value, 10, &minTime);
2818 if (ret < 0)
2819 {
2820 /* If the input value is greater than max value of datatype, then also
2821 kstrtou8 fails */
2822 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2823 "%s: kstrtou8 failed range [%d - %d]", __func__,
2824 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
2825 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
2826 ret = -EINVAL;
2827 goto exit;
2828 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002829 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
2830 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
2831 {
2832 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2833 "scan min channel time value %d is out of range"
2834 " (Min: %d Max: %d)", minTime,
2835 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
2836 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
2837 ret = -EINVAL;
2838 goto exit;
2839 }
2840
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302841 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2842 TRACE_CODE_HDD_SETROAMSCANCHANNELMINTIME_IOCTL,
2843 pAdapter->sessionId, minTime));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002844 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2845 "%s: Received Command to change channel min time = %d", __func__, minTime);
2846
2847 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
2848 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
2849 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002850 else if (strncmp(command, "SENDACTIONFRAME", 15) == 0)
2851 {
2852 tANI_U8 *value = command;
2853 tANI_U8 channel = 0;
2854 tANI_U8 dwellTime = 0;
2855 tANI_U8 bufLen = 0;
2856 tANI_U8 *buf = NULL;
2857 tSirMacAddr targetApBssid;
2858 eHalStatus status = eHAL_STATUS_SUCCESS;
2859 struct ieee80211_channel chan;
2860 tANI_U8 finalLen = 0;
2861 tANI_U8 *finalBuf = NULL;
2862 tANI_U8 temp = 0;
2863 u64 cookie;
2864 hdd_station_ctx_t *pHddStaCtx = NULL;
2865 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2866
2867 /* if not associated, no need to send action frame */
2868 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2869 {
2870 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2871 ret = -EINVAL;
2872 goto exit;
2873 }
2874
2875 status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel,
2876 &dwellTime, &buf, &bufLen);
2877 if (eHAL_STATUS_SUCCESS != status)
2878 {
2879 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2880 "%s: Failed to parse send action frame data", __func__);
2881 ret = -EINVAL;
2882 goto exit;
2883 }
2884
2885 /* if the target bssid is different from currently associated AP,
2886 then no need to send action frame */
2887 if (VOS_TRUE != vos_mem_compare(targetApBssid,
2888 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2889 {
2890 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__);
2891 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002892 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002893 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002894 goto exit;
2895 }
2896
2897 /* if the channel number is different from operating channel then
2898 no need to send action frame */
2899 if (channel != pHddStaCtx->conn_info.operationChannel)
2900 {
2901 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2902 "%s: channel(%d) is different from operating channel(%d)",
2903 __func__, channel, pHddStaCtx->conn_info.operationChannel);
2904 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002905 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002906 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002907 goto exit;
2908 }
2909 chan.center_freq = sme_ChnToFreq(channel);
2910
2911 finalLen = bufLen + 24;
2912 finalBuf = vos_mem_malloc(finalLen);
2913 if (NULL == finalBuf)
2914 {
2915 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__);
2916 ret = -ENOMEM;
Jeff Johnson11c33152013-04-16 17:52:40 -07002917 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002918 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002919 goto exit;
2920 }
2921 vos_mem_zero(finalBuf, finalLen);
2922
2923 /* Fill subtype */
2924 temp = SIR_MAC_MGMT_ACTION << 4;
2925 vos_mem_copy(finalBuf + 0, &temp, sizeof(temp));
2926
2927 /* Fill type */
2928 temp = SIR_MAC_MGMT_FRAME;
2929 vos_mem_copy(finalBuf + 2, &temp, sizeof(temp));
2930
2931 /* Fill destination address (bssid of the AP) */
2932 vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid));
2933
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07002934 /* Fill source address (STA mac address) */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002935 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
2936
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07002937 /* Fill BSSID (AP mac address) */
2938 vos_mem_copy(finalBuf + 16, targetApBssid, sizeof(targetApBssid));
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002939
2940 /* Fill received buffer from 24th address */
2941 vos_mem_copy(finalBuf + 24, buf, bufLen);
2942
Jeff Johnson11c33152013-04-16 17:52:40 -07002943 /* done with the parsed buffer */
2944 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002945 buf = NULL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002946
DARAM SUDHA39eede62014-02-12 11:16:40 +05302947 wlan_hdd_mgmt_tx( NULL,
Yue Maf49ba872013-08-19 12:04:25 -07002948#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2949 &(pAdapter->wdev),
2950#else
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002951 pAdapter->dev,
Yue Maf49ba872013-08-19 12:04:25 -07002952#endif
2953 &chan, 0,
2954#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
2955 NL80211_CHAN_HT20, 1,
2956#endif
2957 dwellTime, finalBuf, finalLen, 1,
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002958 1, &cookie );
2959 vos_mem_free(finalBuf);
2960 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002961 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
2962 {
2963 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
2964 char extra[32];
2965 tANI_U8 len = 0;
2966
2967 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002968 len = scnprintf(extra, sizeof(extra), "%s %d",
2969 "GETROAMSCANCHANNELMINTIME", val);
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302970 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2971 TRACE_CODE_HDD_GETROAMSCANCHANNELMINTIME_IOCTL,
2972 pAdapter->sessionId, val));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002973 if (copy_to_user(priv_data.buf, &extra, len + 1))
2974 {
2975 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2976 "%s: failed to copy data to user buffer", __func__);
2977 ret = -EFAULT;
2978 goto exit;
2979 }
2980 }
2981 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
2982 {
2983 tANI_U8 *value = command;
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002984 tANI_U16 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002985
2986 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
2987 value = value + 19;
2988 /* Convert the value from ascii to integer */
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002989 ret = kstrtou16(value, 10, &maxTime);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002990 if (ret < 0)
2991 {
2992 /* If the input value is greater than max value of datatype, then also
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002993 kstrtou16 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002994 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002995 "%s: kstrtou16 failed range [%d - %d]", __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002996 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
2997 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
2998 ret = -EINVAL;
2999 goto exit;
3000 }
3001
3002 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
3003 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
3004 {
3005 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3006 "lfr mode value %d is out of range"
3007 " (Min: %d Max: %d)", maxTime,
3008 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
3009 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
3010 ret = -EINVAL;
3011 goto exit;
3012 }
3013
3014 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3015 "%s: Received Command to change channel max time = %d", __func__, maxTime);
3016
3017 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
3018 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
3019 }
3020 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
3021 {
3022 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
3023 char extra[32];
3024 tANI_U8 len = 0;
3025
3026 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003027 len = scnprintf(extra, sizeof(extra), "%s %d",
3028 "GETSCANCHANNELTIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003029 if (copy_to_user(priv_data.buf, &extra, len + 1))
3030 {
3031 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3032 "%s: failed to copy data to user buffer", __func__);
3033 ret = -EFAULT;
3034 goto exit;
3035 }
3036 }
3037 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
3038 {
3039 tANI_U8 *value = command;
3040 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
3041
3042 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
3043 value = value + 16;
3044 /* Convert the value from ascii to integer */
3045 ret = kstrtou16(value, 10, &val);
3046 if (ret < 0)
3047 {
3048 /* If the input value is greater than max value of datatype, then also
3049 kstrtou16 fails */
3050 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3051 "%s: kstrtou16 failed range [%d - %d]", __func__,
3052 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
3053 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
3054 ret = -EINVAL;
3055 goto exit;
3056 }
3057
3058 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
3059 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
3060 {
3061 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3062 "scan home time value %d is out of range"
3063 " (Min: %d Max: %d)", val,
3064 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
3065 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
3066 ret = -EINVAL;
3067 goto exit;
3068 }
3069
3070 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3071 "%s: Received Command to change scan home time = %d", __func__, val);
3072
3073 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
3074 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
3075 }
3076 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
3077 {
3078 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
3079 char extra[32];
3080 tANI_U8 len = 0;
3081
3082 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003083 len = scnprintf(extra, sizeof(extra), "%s %d",
3084 "GETSCANHOMETIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003085 if (copy_to_user(priv_data.buf, &extra, len + 1))
3086 {
3087 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3088 "%s: failed to copy data to user buffer", __func__);
3089 ret = -EFAULT;
3090 goto exit;
3091 }
3092 }
3093 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
3094 {
3095 tANI_U8 *value = command;
3096 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
3097
3098 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
3099 value = value + 17;
3100 /* Convert the value from ascii to integer */
3101 ret = kstrtou8(value, 10, &val);
3102 if (ret < 0)
3103 {
3104 /* If the input value is greater than max value of datatype, then also
3105 kstrtou8 fails */
3106 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3107 "%s: kstrtou8 failed range [%d - %d]", __func__,
3108 CFG_ROAM_INTRA_BAND_MIN,
3109 CFG_ROAM_INTRA_BAND_MAX);
3110 ret = -EINVAL;
3111 goto exit;
3112 }
3113
3114 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
3115 (val > CFG_ROAM_INTRA_BAND_MAX))
3116 {
3117 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3118 "intra band mode value %d is out of range"
3119 " (Min: %d Max: %d)", val,
3120 CFG_ROAM_INTRA_BAND_MIN,
3121 CFG_ROAM_INTRA_BAND_MAX);
3122 ret = -EINVAL;
3123 goto exit;
3124 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003125 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3126 "%s: Received Command to change intra band = %d", __func__, val);
3127
3128 pHddCtx->cfg_ini->nRoamIntraBand = val;
3129 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
3130 }
3131 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
3132 {
3133 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
3134 char extra[32];
3135 tANI_U8 len = 0;
3136
3137 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003138 len = scnprintf(extra, sizeof(extra), "%s %d",
3139 "GETROAMINTRABAND", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003140 if (copy_to_user(priv_data.buf, &extra, len + 1))
3141 {
3142 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3143 "%s: failed to copy data to user buffer", __func__);
3144 ret = -EFAULT;
3145 goto exit;
3146 }
3147 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003148 else if (strncmp(command, "SETSCANNPROBES", 14) == 0)
3149 {
3150 tANI_U8 *value = command;
3151 tANI_U8 nProbes = CFG_ROAM_SCAN_N_PROBES_DEFAULT;
3152
3153 /* Move pointer to ahead of SETSCANNPROBES<delimiter> */
3154 value = value + 15;
3155 /* Convert the value from ascii to integer */
3156 ret = kstrtou8(value, 10, &nProbes);
3157 if (ret < 0)
3158 {
3159 /* If the input value is greater than max value of datatype, then also
3160 kstrtou8 fails */
3161 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3162 "%s: kstrtou8 failed range [%d - %d]", __func__,
3163 CFG_ROAM_SCAN_N_PROBES_MIN,
3164 CFG_ROAM_SCAN_N_PROBES_MAX);
3165 ret = -EINVAL;
3166 goto exit;
3167 }
3168
3169 if ((nProbes < CFG_ROAM_SCAN_N_PROBES_MIN) ||
3170 (nProbes > CFG_ROAM_SCAN_N_PROBES_MAX))
3171 {
3172 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3173 "NProbes value %d is out of range"
3174 " (Min: %d Max: %d)", nProbes,
3175 CFG_ROAM_SCAN_N_PROBES_MIN,
3176 CFG_ROAM_SCAN_N_PROBES_MAX);
3177 ret = -EINVAL;
3178 goto exit;
3179 }
3180
3181 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3182 "%s: Received Command to Set nProbes = %d", __func__, nProbes);
3183
3184 pHddCtx->cfg_ini->nProbes = nProbes;
3185 sme_UpdateRoamScanNProbes((tHalHandle)(pHddCtx->hHal), nProbes);
3186 }
3187 else if (strncmp(priv_data.buf, "GETSCANNPROBES", 14) == 0)
3188 {
3189 tANI_U8 val = sme_getRoamScanNProbes((tHalHandle)(pHddCtx->hHal));
3190 char extra[32];
3191 tANI_U8 len = 0;
3192
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003193 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003194 if (copy_to_user(priv_data.buf, &extra, len + 1))
3195 {
3196 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3197 "%s: failed to copy data to user buffer", __func__);
3198 ret = -EFAULT;
3199 goto exit;
3200 }
3201 }
3202 else if (strncmp(command, "SETSCANHOMEAWAYTIME", 19) == 0)
3203 {
3204 tANI_U8 *value = command;
3205 tANI_U16 homeAwayTime = CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT;
3206
3207 /* Move pointer to ahead of SETSCANHOMEAWAYTIME<delimiter> */
3208 /* input value is in units of msec */
3209 value = value + 20;
3210 /* Convert the value from ascii to integer */
3211 ret = kstrtou16(value, 10, &homeAwayTime);
3212 if (ret < 0)
3213 {
3214 /* If the input value is greater than max value of datatype, then also
3215 kstrtou8 fails */
3216 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3217 "%s: kstrtou8 failed range [%d - %d]", __func__,
3218 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
3219 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
3220 ret = -EINVAL;
3221 goto exit;
3222 }
3223
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003224 if ((homeAwayTime < CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN) ||
3225 (homeAwayTime > CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX))
3226 {
3227 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3228 "homeAwayTime value %d is out of range"
3229 " (Min: %d Max: %d)", homeAwayTime,
3230 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
3231 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
3232 ret = -EINVAL;
3233 goto exit;
3234 }
3235
3236 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3237 "%s: Received Command to Set scan away time = %d", __func__, homeAwayTime);
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07003238 if (pHddCtx->cfg_ini->nRoamScanHomeAwayTime != homeAwayTime)
3239 {
3240 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
3241 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_TRUE);
3242 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003243 }
3244 else if (strncmp(priv_data.buf, "GETSCANHOMEAWAYTIME", 19) == 0)
3245 {
3246 tANI_U16 val = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
3247 char extra[32];
3248 tANI_U8 len = 0;
3249
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003250 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003251 if (copy_to_user(priv_data.buf, &extra, len + 1))
3252 {
3253 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3254 "%s: failed to copy data to user buffer", __func__);
3255 ret = -EFAULT;
3256 goto exit;
3257 }
3258 }
3259 else if (strncmp(command, "REASSOC", 7) == 0)
3260 {
3261 tANI_U8 *value = command;
3262 tANI_U8 channel = 0;
3263 tSirMacAddr targetApBssid;
3264 eHalStatus status = eHAL_STATUS_SUCCESS;
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07003265#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
3266 tCsrHandoffRequest handoffInfo;
3267#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003268 hdd_station_ctx_t *pHddStaCtx = NULL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003269 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3270
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003271 /* if not associated, no need to proceed with reassoc */
3272 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3273 {
3274 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
3275 ret = -EINVAL;
3276 goto exit;
3277 }
3278
3279 status = hdd_parse_reassoc_command_data(value, targetApBssid, &channel);
3280 if (eHAL_STATUS_SUCCESS != status)
3281 {
3282 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3283 "%s: Failed to parse reassoc command data", __func__);
3284 ret = -EINVAL;
3285 goto exit;
3286 }
3287
3288 /* if the target bssid is same as currently associated AP,
3289 then no need to proceed with reassoc */
3290 if (VOS_TRUE == vos_mem_compare(targetApBssid,
3291 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
3292 {
3293 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Reassoc BSSID is same as currently associated AP bssid",__func__);
3294 ret = -EINVAL;
3295 goto exit;
3296 }
3297
3298 /* Check channel number is a valid channel number */
3299 if(VOS_STATUS_SUCCESS !=
3300 wlan_hdd_validate_operation_channel(pAdapter, channel))
3301 {
3302 hddLog(VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08003303 "%s: Invalid Channel [%d]", __func__, channel);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003304 return -EINVAL;
3305 }
3306
3307 /* Proceed with reassoc */
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07003308#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
3309 handoffInfo.channel = channel;
3310 vos_mem_copy(handoffInfo.bssid, targetApBssid, sizeof(tSirMacAddr));
3311 sme_HandoffRequest(pHddCtx->hHal, &handoffInfo);
3312#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003313 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07003314 else if (strncmp(command, "SETWESMODE", 10) == 0)
3315 {
3316 tANI_U8 *value = command;
3317 tANI_BOOLEAN wesMode = CFG_ENABLE_WES_MODE_NAME_DEFAULT;
3318
3319 /* Move pointer to ahead of SETWESMODE<delimiter> */
3320 value = value + 11;
3321 /* Convert the value from ascii to integer */
3322 ret = kstrtou8(value, 10, &wesMode);
3323 if (ret < 0)
3324 {
3325 /* If the input value is greater than max value of datatype, then also
3326 kstrtou8 fails */
3327 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3328 "%s: kstrtou8 failed range [%d - %d]", __func__,
3329 CFG_ENABLE_WES_MODE_NAME_MIN,
3330 CFG_ENABLE_WES_MODE_NAME_MAX);
3331 ret = -EINVAL;
3332 goto exit;
3333 }
3334
3335 if ((wesMode < CFG_ENABLE_WES_MODE_NAME_MIN) ||
3336 (wesMode > CFG_ENABLE_WES_MODE_NAME_MAX))
3337 {
3338 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3339 "WES Mode value %d is out of range"
3340 " (Min: %d Max: %d)", wesMode,
3341 CFG_ENABLE_WES_MODE_NAME_MIN,
3342 CFG_ENABLE_WES_MODE_NAME_MAX);
3343 ret = -EINVAL;
3344 goto exit;
3345 }
3346 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3347 "%s: Received Command to Set WES Mode rssi diff = %d", __func__, wesMode);
3348
3349 pHddCtx->cfg_ini->isWESModeEnabled = wesMode;
3350 sme_UpdateWESMode((tHalHandle)(pHddCtx->hHal), wesMode);
3351 }
3352 else if (strncmp(priv_data.buf, "GETWESMODE", 10) == 0)
3353 {
3354 tANI_BOOLEAN wesMode = sme_GetWESMode((tHalHandle)(pHddCtx->hHal));
3355 char extra[32];
3356 tANI_U8 len = 0;
3357
Arif Hussain826d9412013-11-12 16:44:54 -08003358 len = scnprintf(extra, sizeof(extra), "%s %d", command, wesMode);
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07003359 if (copy_to_user(priv_data.buf, &extra, len + 1))
3360 {
3361 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3362 "%s: failed to copy data to user buffer", __func__);
3363 ret = -EFAULT;
3364 goto exit;
3365 }
3366 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003367#endif /* WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_ESE || FEATURE_WLAN_LFR */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003368#ifdef FEATURE_WLAN_LFR
3369 else if (strncmp(command, "SETFASTROAM", 11) == 0)
3370 {
3371 tANI_U8 *value = command;
3372 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
3373
3374 /* Move pointer to ahead of SETFASTROAM<delimiter> */
3375 value = value + 12;
3376 /* Convert the value from ascii to integer */
3377 ret = kstrtou8(value, 10, &lfrMode);
3378 if (ret < 0)
3379 {
3380 /* If the input value is greater than max value of datatype, then also
3381 kstrtou8 fails */
3382 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3383 "%s: kstrtou8 failed range [%d - %d]", __func__,
3384 CFG_LFR_FEATURE_ENABLED_MIN,
3385 CFG_LFR_FEATURE_ENABLED_MAX);
3386 ret = -EINVAL;
3387 goto exit;
3388 }
3389
3390 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
3391 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
3392 {
3393 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3394 "lfr mode value %d is out of range"
3395 " (Min: %d Max: %d)", lfrMode,
3396 CFG_LFR_FEATURE_ENABLED_MIN,
3397 CFG_LFR_FEATURE_ENABLED_MAX);
3398 ret = -EINVAL;
3399 goto exit;
3400 }
3401
3402 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3403 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
3404
3405 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
3406 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
3407 }
3408#endif
3409#ifdef WLAN_FEATURE_VOWIFI_11R
3410 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
3411 {
3412 tANI_U8 *value = command;
3413 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
3414
3415 /* Move pointer to ahead of SETFASTROAM<delimiter> */
3416 value = value + 18;
3417 /* Convert the value from ascii to integer */
3418 ret = kstrtou8(value, 10, &ft);
3419 if (ret < 0)
3420 {
3421 /* If the input value is greater than max value of datatype, then also
3422 kstrtou8 fails */
3423 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3424 "%s: kstrtou8 failed range [%d - %d]", __func__,
3425 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
3426 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
3427 ret = -EINVAL;
3428 goto exit;
3429 }
3430
3431 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
3432 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
3433 {
3434 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3435 "ft mode value %d is out of range"
3436 " (Min: %d Max: %d)", ft,
3437 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
3438 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
3439 ret = -EINVAL;
3440 goto exit;
3441 }
3442
3443 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3444 "%s: Received Command to change ft mode = %d", __func__, ft);
3445
3446 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
3447 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
3448 }
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05303449
3450 else if (strncmp(command, "FASTREASSOC", 11) == 0)
3451 {
3452 tANI_U8 *value = command;
Padma, Santhosh Kumarf4582d32014-11-06 19:24:51 +05303453 tANI_U8 channel = 0;
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05303454 tSirMacAddr targetApBssid;
3455 tANI_U8 trigger = 0;
3456 eHalStatus status = eHAL_STATUS_SUCCESS;
Padma, Santhosh Kumarb980a6f2014-11-06 19:07:24 +05303457 tHalHandle hHal;
3458 v_U32_t roamId = 0;
3459 tCsrRoamModifyProfileFields modProfileFields;
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05303460 hdd_station_ctx_t *pHddStaCtx = NULL;
3461 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Padma, Santhosh Kumarb980a6f2014-11-06 19:07:24 +05303462 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05303463
3464 /* if not associated, no need to proceed with reassoc */
3465 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3466 {
3467 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
3468 ret = -EINVAL;
3469 goto exit;
3470 }
3471
Padma, Santhosh Kumarf4582d32014-11-06 19:24:51 +05303472 status = hdd_parse_reassoc_command_data(value, targetApBssid, &channel);
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05303473 if (eHAL_STATUS_SUCCESS != status)
3474 {
3475 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3476 "%s: Failed to parse reassoc command data", __func__);
3477 ret = -EINVAL;
3478 goto exit;
3479 }
3480
3481 /* if the target bssid is same as currently associated AP,
Padma, Santhosh Kumarb980a6f2014-11-06 19:07:24 +05303482 issue reassoc to same AP */
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05303483 if (VOS_TRUE == vos_mem_compare(targetApBssid,
3484 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
3485 {
3486 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3487 "%s:11r Reassoc BSSID is same as currently associated AP bssid",
3488 __func__);
Padma, Santhosh Kumarb980a6f2014-11-06 19:07:24 +05303489 sme_GetModifyProfileFields(hHal, pAdapter->sessionId,
3490 &modProfileFields);
3491 sme_RoamReassoc(hHal, pAdapter->sessionId,
3492 NULL, modProfileFields, &roamId, 1);
3493 return 0;
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05303494 }
Padma, Santhosh Kumar0fa809b2014-11-13 14:56:56 +05303495
3496 /* Check channel number is a valid channel number */
3497 if(VOS_STATUS_SUCCESS !=
3498 wlan_hdd_validate_operation_channel(pAdapter, channel))
3499 {
3500 hddLog(VOS_TRACE_LEVEL_ERROR,
3501 "%s: Invalid Channel [%d]", __func__, channel);
3502 return -EINVAL;
3503 }
3504
Padma, Santhosh Kumarf4582d32014-11-06 19:24:51 +05303505 trigger = eSME_ROAM_TRIGGER_SCAN;
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05303506
3507 /* Proceed with scan/roam */
3508 smeIssueFastRoamNeighborAPEvent(WLAN_HDD_GET_HAL_CTX(pAdapter),
3509 &targetApBssid[0],
3510 (tSmeFastRoamTrigger)(trigger));
3511 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003512#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003513#ifdef FEATURE_WLAN_ESE
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003514 else if (strncmp(command, "SETCCXMODE", 10) == 0)
3515 {
3516 tANI_U8 *value = command;
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003517 tANI_U8 eseMode = CFG_ESE_FEATURE_ENABLED_DEFAULT;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003518
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003519 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003520 then this operation is not permitted (return FAILURE) */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003521 if (sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003522 hdd_is_okc_mode_enabled(pHddCtx) &&
3523 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
3524 {
3525 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003526 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003527 " hence this operation is not permitted!", __func__);
3528 ret = -EPERM;
3529 goto exit;
3530 }
3531
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003532 /* Move pointer to ahead of SETCCXMODE<delimiter> */
3533 value = value + 11;
3534 /* Convert the value from ascii to integer */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003535 ret = kstrtou8(value, 10, &eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003536 if (ret < 0)
3537 {
3538 /* If the input value is greater than max value of datatype, then also
3539 kstrtou8 fails */
3540 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3541 "%s: kstrtou8 failed range [%d - %d]", __func__,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003542 CFG_ESE_FEATURE_ENABLED_MIN,
3543 CFG_ESE_FEATURE_ENABLED_MAX);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003544 ret = -EINVAL;
3545 goto exit;
3546 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003547 if ((eseMode < CFG_ESE_FEATURE_ENABLED_MIN) ||
3548 (eseMode > CFG_ESE_FEATURE_ENABLED_MAX))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003549 {
3550 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003551 "Ese mode value %d is out of range"
3552 " (Min: %d Max: %d)", eseMode,
3553 CFG_ESE_FEATURE_ENABLED_MIN,
3554 CFG_ESE_FEATURE_ENABLED_MAX);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003555 ret = -EINVAL;
3556 goto exit;
3557 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003558 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003559 "%s: Received Command to change ese mode = %d", __func__, eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003560
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003561 pHddCtx->cfg_ini->isEseIniFeatureEnabled = eseMode;
3562 sme_UpdateIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal), eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003563 }
3564#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003565 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
3566 {
3567 tANI_U8 *value = command;
3568 tANI_BOOLEAN roamScanControl = 0;
3569
3570 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
3571 value = value + 19;
3572 /* Convert the value from ascii to integer */
3573 ret = kstrtou8(value, 10, &roamScanControl);
3574 if (ret < 0)
3575 {
3576 /* If the input value is greater than max value of datatype, then also
3577 kstrtou8 fails */
3578 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3579 "%s: kstrtou8 failed ", __func__);
3580 ret = -EINVAL;
3581 goto exit;
3582 }
3583
3584 if (0 != roamScanControl)
3585 {
3586 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3587 "roam scan control invalid value = %d",
3588 roamScanControl);
3589 ret = -EINVAL;
3590 goto exit;
3591 }
3592 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3593 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
3594
3595 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
3596 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003597#ifdef FEATURE_WLAN_OKC
3598 else if (strncmp(command, "SETOKCMODE", 10) == 0)
3599 {
3600 tANI_U8 *value = command;
3601 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
3602
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003603 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003604 then this operation is not permitted (return FAILURE) */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003605 if (sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003606 hdd_is_okc_mode_enabled(pHddCtx) &&
3607 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
3608 {
3609 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003610 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003611 " hence this operation is not permitted!", __func__);
3612 ret = -EPERM;
3613 goto exit;
3614 }
3615
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003616 /* Move pointer to ahead of SETOKCMODE<delimiter> */
3617 value = value + 11;
3618 /* Convert the value from ascii to integer */
3619 ret = kstrtou8(value, 10, &okcMode);
3620 if (ret < 0)
3621 {
3622 /* If the input value is greater than max value of datatype, then also
3623 kstrtou8 fails */
3624 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3625 "%s: kstrtou8 failed range [%d - %d]", __func__,
3626 CFG_OKC_FEATURE_ENABLED_MIN,
3627 CFG_OKC_FEATURE_ENABLED_MAX);
3628 ret = -EINVAL;
3629 goto exit;
3630 }
3631
3632 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
3633 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
3634 {
3635 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3636 "Okc mode value %d is out of range"
3637 " (Min: %d Max: %d)", okcMode,
3638 CFG_OKC_FEATURE_ENABLED_MIN,
3639 CFG_OKC_FEATURE_ENABLED_MAX);
3640 ret = -EINVAL;
3641 goto exit;
3642 }
3643
3644 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3645 "%s: Received Command to change okc mode = %d", __func__, okcMode);
3646
3647 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
3648 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07003649#endif /* FEATURE_WLAN_OKC */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003650 else if (strncmp(priv_data.buf, "GETROAMSCANCONTROL", 18) == 0)
3651 {
3652 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
3653 char extra[32];
3654 tANI_U8 len = 0;
3655
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003656 len = scnprintf(extra, sizeof(extra), "%s %d",
3657 command, roamScanControl);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003658 if (copy_to_user(priv_data.buf, &extra, len + 1))
3659 {
3660 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3661 "%s: failed to copy data to user buffer", __func__);
3662 ret = -EFAULT;
3663 goto exit;
3664 }
3665 }
Gopichand Nakkala227c7f32013-06-26 22:44:57 +05303666#ifdef WLAN_FEATURE_PACKET_FILTERING
3667 else if (strncmp(command, "ENABLE_PKTFILTER_IPV6", 21) == 0)
3668 {
3669 tANI_U8 filterType = 0;
3670 tANI_U8 *value = command;
3671
3672 /* Move pointer to ahead of ENABLE_PKTFILTER_IPV6<delimiter> */
3673 value = value + 22;
3674
3675 /* Convert the value from ascii to integer */
3676 ret = kstrtou8(value, 10, &filterType);
3677 if (ret < 0)
3678 {
3679 /* If the input value is greater than max value of datatype,
3680 * then also kstrtou8 fails
3681 */
3682 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3683 "%s: kstrtou8 failed range ", __func__);
3684 ret = -EINVAL;
3685 goto exit;
3686 }
3687
3688 if (filterType != 0 && filterType != 1)
3689 {
3690 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3691 "%s: Accepted Values are 0 and 1 ", __func__);
3692 ret = -EINVAL;
3693 goto exit;
3694 }
3695 wlan_hdd_setIPv6Filter(WLAN_HDD_GET_CTX(pAdapter), filterType,
3696 pAdapter->sessionId);
3697 }
3698#endif
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303699 else if (strncmp(command, "BTCOEXMODE", 10) == 0 )
3700 {
Kiet Lamad161252014-07-22 11:23:32 -07003701 char *dhcpPhase;
Satyanarayana Dash1faea4f2014-09-22 16:21:04 +05303702 int ret;
3703
Kiet Lamad161252014-07-22 11:23:32 -07003704 dhcpPhase = command + 11;
3705 if ('1' == *dhcpPhase)
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303706 {
Deepthi Gowribfd17132014-11-14 17:59:04 +05303707 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Kiet Lamad161252014-07-22 11:23:32 -07003708 FL("send DHCP START indication"));
c_hpothu9b781ba2013-12-30 20:57:45 +05303709
3710 pHddCtx->btCoexModeSet = TRUE;
Kiet Lamad161252014-07-22 11:23:32 -07003711
Satyanarayana Dash1faea4f2014-09-22 16:21:04 +05303712 ret = wlan_hdd_scan_abort(pAdapter);
3713 if (ret < 0)
3714 {
3715 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3716 FL("failed to abort existing scan %d"), ret);
3717 }
3718
Kiet Lamad161252014-07-22 11:23:32 -07003719 sme_DHCPStartInd(pHddCtx->hHal, pAdapter->device_mode,
3720 pAdapter->sessionId);
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303721 }
Kiet Lamad161252014-07-22 11:23:32 -07003722 else if ('2' == *dhcpPhase)
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303723 {
Deepthi Gowribfd17132014-11-14 17:59:04 +05303724 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Kiet Lamad161252014-07-22 11:23:32 -07003725 FL("send DHCP STOP indication"));
c_hpothu9b781ba2013-12-30 20:57:45 +05303726
3727 pHddCtx->btCoexModeSet = FALSE;
Kiet Lamad161252014-07-22 11:23:32 -07003728
3729 sme_DHCPStopInd(pHddCtx->hHal, pAdapter->device_mode,
3730 pAdapter->sessionId);
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303731 }
3732 }
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07003733 else if (strncmp(command, "SCAN-ACTIVE", 11) == 0)
3734 {
c_hpothudbefd3e2014-04-28 15:59:47 +05303735 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3736 FL("making default scan to ACTIVE"));
3737 pHddCtx->scan_info.scan_mode = eSIR_ACTIVE_SCAN;
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07003738 }
3739 else if (strncmp(command, "SCAN-PASSIVE", 12) == 0)
3740 {
c_hpothudbefd3e2014-04-28 15:59:47 +05303741 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3742 FL("making default scan to PASSIVE"));
3743 pHddCtx->scan_info.scan_mode = eSIR_PASSIVE_SCAN;
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07003744 }
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303745 else if (strncmp(command, "GETDWELLTIME", 12) == 0)
3746 {
3747 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3748 char extra[32];
3749 tANI_U8 len = 0;
3750
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05303751 memset(extra, 0, sizeof(extra));
3752 ret = hdd_get_dwell_time(pCfg, command, extra, sizeof(extra), &len);
3753 if (ret != 0 || copy_to_user(priv_data.buf, &extra, len + 1))
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303754 {
3755 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3756 "%s: failed to copy data to user buffer", __func__);
3757 ret = -EFAULT;
3758 goto exit;
3759 }
3760 ret = len;
3761 }
3762 else if (strncmp(command, "SETDWELLTIME", 12) == 0)
3763 {
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05303764 ret = hdd_set_dwell_time(pAdapter, command);
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303765 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07003766 else if ( strncasecmp(command, "MIRACAST", 8) == 0 )
3767 {
3768 tANI_U8 filterType = 0;
3769 tANI_U8 *value;
3770 value = command + 9;
3771
3772 /* Convert the value from ascii to integer */
3773 ret = kstrtou8(value, 10, &filterType);
3774 if (ret < 0)
3775 {
3776 /* If the input value is greater than max value of datatype,
3777 * then also kstrtou8 fails
3778 */
3779 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3780 "%s: kstrtou8 failed range ", __func__);
3781 ret = -EINVAL;
3782 goto exit;
3783 }
3784 if ((filterType < WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL ) ||
3785 (filterType > WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL))
3786 {
3787 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3788 "%s: Accepted Values are 0 to 2. 0-Disabled, 1-Source,"
3789 " 2-Sink ", __func__);
3790 ret = -EINVAL;
3791 goto exit;
3792 }
3793 //Filtertype value should be either 0-Disabled, 1-Source, 2-sink
3794 pHddCtx->drvr_miracast = filterType;
Kaushik, Sushant96122442014-10-21 16:40:18 +05303795 pScanInfo = &pHddCtx->scan_info;
3796 if (filterType && pScanInfo != NULL &&
3797 pHddCtx->scan_info.mScanPending)
3798 {
3799 /*Miracast Session started. Abort Scan */
3800 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3801 "%s, Aborting Scan For Miracast",__func__);
3802 hdd_abort_mac_scan(pHddCtx, pScanInfo->sessionId,
3803 eCSR_SCAN_ABORT_DEFAULT);
3804 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07003805 hdd_tx_rx_pkt_cnt_stat_timer_handler(pHddCtx);
Ganesh Kondabattini8f6e3b32014-08-25 16:07:54 +05303806 sme_SetMiracastMode(pHddCtx->hHal, pHddCtx->drvr_miracast);
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07003807 }
Leo Chang614d2072013-08-22 14:59:44 -07003808 else if (strncmp(command, "SETMCRATE", 9) == 0)
3809 {
Leo Chang614d2072013-08-22 14:59:44 -07003810 tANI_U8 *value = command;
3811 int targetRate;
Leo Chang1f98cbd2013-10-17 15:03:52 -07003812 tSirRateUpdateInd *rateUpdate;
3813 eHalStatus status;
Leo Chang614d2072013-08-22 14:59:44 -07003814
3815 /* Only valid for SAP mode */
3816 if (WLAN_HDD_SOFTAP != pAdapter->device_mode)
3817 {
3818 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3819 "%s: SAP mode is not running", __func__);
3820 ret = -EFAULT;
3821 goto exit;
3822 }
3823
3824 /* Move pointer to ahead of SETMCRATE<delimiter> */
3825 /* input value is in units of hundred kbps */
3826 value = value + 10;
3827 /* Convert the value from ascii to integer, decimal base */
3828 ret = kstrtouint(value, 10, &targetRate);
3829
Leo Chang1f98cbd2013-10-17 15:03:52 -07003830 rateUpdate = (tSirRateUpdateInd *)vos_mem_malloc(sizeof(tSirRateUpdateInd));
3831 if (NULL == rateUpdate)
Leo Chang614d2072013-08-22 14:59:44 -07003832 {
Leo Chang1f98cbd2013-10-17 15:03:52 -07003833 hddLog(VOS_TRACE_LEVEL_ERROR,
3834 "%s: SETMCRATE indication alloc fail", __func__);
3835 ret = -EFAULT;
3836 goto exit;
3837 }
3838 vos_mem_zero(rateUpdate, sizeof(tSirRateUpdateInd ));
3839
3840 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3841 "MC Target rate %d", targetRate);
3842 /* Ignore unicast */
3843 rateUpdate->ucastDataRate = -1;
3844 rateUpdate->mcastDataRate24GHz = targetRate;
3845 rateUpdate->mcastDataRate5GHz = targetRate;
3846 rateUpdate->mcastDataRate24GHzTxFlag = 0;
3847 rateUpdate->mcastDataRate5GHzTxFlag = 0;
3848 status = sme_SendRateUpdateInd(pHddCtx->hHal, rateUpdate);
3849 if (eHAL_STATUS_SUCCESS != status)
3850 {
3851 hddLog(VOS_TRACE_LEVEL_ERROR,
3852 "%s: SET_MC_RATE failed", __func__);
3853 vos_mem_free(rateUpdate);
3854 ret = -EFAULT;
3855 goto exit;
Leo Chang614d2072013-08-22 14:59:44 -07003856 }
3857 }
Rajeev79dbe4c2013-10-05 11:03:42 +05303858#ifdef FEATURE_WLAN_BATCH_SCAN
Rajeev Kumar8b373292014-01-08 20:36:55 -08003859 else if (strncmp(command, "WLS_BATCHING", 12) == 0)
Rajeev79dbe4c2013-10-05 11:03:42 +05303860 {
Rajeev Kumar8b373292014-01-08 20:36:55 -08003861 ret = hdd_handle_batch_scan_ioctl(pAdapter, &priv_data, command);
Rajeev79dbe4c2013-10-05 11:03:42 +05303862 }
3863#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003864#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003865 else if (strncmp(command, "SETCCXROAMSCANCHANNELS", 22) == 0)
3866 {
3867 tANI_U8 *value = command;
3868 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
3869 tANI_U8 numChannels = 0;
3870 eHalStatus status = eHAL_STATUS_SUCCESS;
3871
3872 status = hdd_parse_channellist(value, ChannelList, &numChannels);
3873 if (eHAL_STATUS_SUCCESS != status)
3874 {
3875 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3876 "%s: Failed to parse channel list information", __func__);
3877 ret = -EINVAL;
3878 goto exit;
3879 }
3880
3881 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
3882 {
3883 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3884 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
3885 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
3886 ret = -EINVAL;
3887 goto exit;
3888 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003889 status = sme_SetEseRoamScanChannelList((tHalHandle)(pHddCtx->hHal),
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003890 ChannelList,
3891 numChannels);
3892 if (eHAL_STATUS_SUCCESS != status)
3893 {
3894 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3895 "%s: Failed to update channel list information", __func__);
3896 ret = -EINVAL;
3897 goto exit;
3898 }
3899 }
3900 else if (strncmp(command, "GETTSMSTATS", 11) == 0)
3901 {
3902 tANI_U8 *value = command;
3903 char extra[128] = {0};
3904 int len = 0;
3905 tANI_U8 tid = 0;
3906 hdd_station_ctx_t *pHddStaCtx = NULL;
3907 tAniTrafStrmMetrics tsmMetrics;
3908 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3909
3910 /* if not associated, return error */
3911 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3912 {
3913 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:Not associated!",__func__);
3914 ret = -EINVAL;
3915 goto exit;
3916 }
3917
3918 /* Move pointer to ahead of GETTSMSTATS<delimiter> */
3919 value = value + 12;
3920 /* Convert the value from ascii to integer */
3921 ret = kstrtou8(value, 10, &tid);
3922 if (ret < 0)
3923 {
3924 /* If the input value is greater than max value of datatype, then also
3925 kstrtou8 fails */
3926 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3927 "%s: kstrtou8 failed range [%d - %d]", __func__,
3928 TID_MIN_VALUE,
3929 TID_MAX_VALUE);
3930 ret = -EINVAL;
3931 goto exit;
3932 }
3933
3934 if ((tid < TID_MIN_VALUE) || (tid > TID_MAX_VALUE))
3935 {
3936 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3937 "tid value %d is out of range"
3938 " (Min: %d Max: %d)", tid,
3939 TID_MIN_VALUE,
3940 TID_MAX_VALUE);
3941 ret = -EINVAL;
3942 goto exit;
3943 }
3944
3945 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3946 "%s: Received Command to get tsm stats tid = %d", __func__, tid);
3947
3948 if (VOS_STATUS_SUCCESS != hdd_get_tsm_stats(pAdapter, tid, &tsmMetrics))
3949 {
3950 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3951 "%s: failed to get tsm stats", __func__);
3952 ret = -EFAULT;
3953 goto exit;
3954 }
3955
3956 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3957 "UplinkPktQueueDly(%d)\n"
3958 "UplinkPktQueueDlyHist[0](%d)\n"
3959 "UplinkPktQueueDlyHist[1](%d)\n"
3960 "UplinkPktQueueDlyHist[2](%d)\n"
3961 "UplinkPktQueueDlyHist[3](%d)\n"
Arun Kumar Khandavallie8768212014-02-17 16:43:34 +05303962 "UplinkPktTxDly(%u)\n"
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003963 "UplinkPktLoss(%d)\n"
3964 "UplinkPktCount(%d)\n"
3965 "RoamingCount(%d)\n"
3966 "RoamingDly(%d)", tsmMetrics.UplinkPktQueueDly,
3967 tsmMetrics.UplinkPktQueueDlyHist[0],
3968 tsmMetrics.UplinkPktQueueDlyHist[1],
3969 tsmMetrics.UplinkPktQueueDlyHist[2],
3970 tsmMetrics.UplinkPktQueueDlyHist[3],
3971 tsmMetrics.UplinkPktTxDly, tsmMetrics.UplinkPktLoss,
3972 tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount, tsmMetrics.RoamingDly);
3973
3974 /* Output TSM stats is of the format
3975 GETTSMSTATS [PktQueueDly] [PktQueueDlyHist[0]]:[PktQueueDlyHist[1]] ...[RoamingDly]
3976 eg., GETTSMSTATS 10 1:0:0:161 20 1 17 8 39800 */
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003977 len = scnprintf(extra, sizeof(extra), "%s %d %d:%d:%d:%d %u %d %d %d %d", command,
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003978 tsmMetrics.UplinkPktQueueDly, tsmMetrics.UplinkPktQueueDlyHist[0],
3979 tsmMetrics.UplinkPktQueueDlyHist[1], tsmMetrics.UplinkPktQueueDlyHist[2],
3980 tsmMetrics.UplinkPktQueueDlyHist[3], tsmMetrics.UplinkPktTxDly,
3981 tsmMetrics.UplinkPktLoss, tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount,
3982 tsmMetrics.RoamingDly);
3983
3984 if (copy_to_user(priv_data.buf, &extra, len + 1))
3985 {
3986 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3987 "%s: failed to copy data to user buffer", __func__);
3988 ret = -EFAULT;
3989 goto exit;
3990 }
3991 }
3992 else if (strncmp(command, "SETCCKMIE", 9) == 0)
3993 {
3994 tANI_U8 *value = command;
3995 tANI_U8 *cckmIe = NULL;
3996 tANI_U8 cckmIeLen = 0;
3997 eHalStatus status = eHAL_STATUS_SUCCESS;
3998
3999 status = hdd_parse_get_cckm_ie(value, &cckmIe, &cckmIeLen);
4000 if (eHAL_STATUS_SUCCESS != status)
4001 {
4002 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4003 "%s: Failed to parse cckm ie data", __func__);
4004 ret = -EINVAL;
4005 goto exit;
4006 }
4007
4008 if (cckmIeLen > DOT11F_IE_RSN_MAX_LEN)
4009 {
4010 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4011 "%s: CCKM Ie input length is more than max[%d]", __func__,
4012 DOT11F_IE_RSN_MAX_LEN);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08004013 vos_mem_free(cckmIe);
4014 cckmIe = NULL;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004015 ret = -EINVAL;
4016 goto exit;
4017 }
4018 sme_SetCCKMIe((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, cckmIe, cckmIeLen);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08004019 vos_mem_free(cckmIe);
4020 cckmIe = NULL;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004021 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004022 else if (strncmp(command, "CCXBEACONREQ", 12) == 0)
4023 {
4024 tANI_U8 *value = command;
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004025 tCsrEseBeaconReq eseBcnReq;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004026 eHalStatus status = eHAL_STATUS_SUCCESS;
Srinivas Girigowda0c6d7fe2014-05-28 18:18:10 -07004027
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004028 status = hdd_parse_ese_beacon_req(value, &eseBcnReq);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004029 if (eHAL_STATUS_SUCCESS != status)
4030 {
4031 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004032 "%s: Failed to parse ese beacon req", __func__);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004033 ret = -EINVAL;
4034 goto exit;
4035 }
Srinivas Girigowda0c6d7fe2014-05-28 18:18:10 -07004036 if (!hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))) {
4037 hddLog(VOS_TRACE_LEVEL_INFO, FL("Not associated"));
4038 hdd_indicateEseBcnReportNoResults (pAdapter,
4039 eseBcnReq.bcnReq[0].measurementToken,
4040 0x02, //BIT(1) set for measurement done
4041 0); // no BSS
4042 goto exit;
4043 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004044
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004045 status = sme_SetEseBeaconRequest((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, &eseBcnReq);
4046 if (eHAL_STATUS_SUCCESS != status)
4047 {
4048 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4049 "%s: sme_SetEseBeaconRequest failed (%d)", __func__, status);
4050 ret = -EINVAL;
4051 goto exit;
4052 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004053 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004054#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
c_hpothu92367912014-05-01 15:18:17 +05304055 else if (strncmp(command, "GETBCNMISSRATE", 14) == 0)
4056 {
4057 eHalStatus status;
4058 char buf[32], len;
4059 long waitRet;
4060 bcnMissRateContext_t getBcnMissRateCtx;
4061
4062 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4063
4064 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
4065 {
4066 hddLog(VOS_TRACE_LEVEL_WARN,
4067 FL("GETBCNMISSRATE: STA is not in connected state"));
4068 ret = -1;
4069 goto exit;
4070 }
4071
4072 init_completion(&(getBcnMissRateCtx.completion));
4073 getBcnMissRateCtx.magic = BCN_MISS_RATE_CONTEXT_MAGIC;
4074
4075 status = sme_getBcnMissRate((tHalHandle)(pHddCtx->hHal),
4076 pAdapter->sessionId,
4077 (void *)getBcnMissRateCB,
4078 (void *)(&getBcnMissRateCtx));
4079 if( eHAL_STATUS_SUCCESS != status)
4080 {
4081 hddLog(VOS_TRACE_LEVEL_INFO,
4082 FL("GETBCNMISSRATE: fail to post WDA cmd"));
4083 ret = -EINVAL;
4084 goto exit;
4085 }
4086
4087 waitRet = wait_for_completion_interruptible_timeout
4088 (&getBcnMissRateCtx.completion, BCN_MISS_RATE_TIME);
4089 if(waitRet <= 0)
4090 {
4091 hddLog(VOS_TRACE_LEVEL_ERROR,
4092 FL("failed to wait on bcnMissRateComp %d"), ret);
4093
4094 //Make magic number to zero so that callback is not called.
4095 spin_lock(&hdd_context_lock);
4096 getBcnMissRateCtx.magic = 0x0;
4097 spin_unlock(&hdd_context_lock);
4098 ret = -EINVAL;
4099 goto exit;
4100 }
4101
4102 hddLog(VOS_TRACE_LEVEL_INFO,
4103 FL("GETBCNMISSRATE: bcnMissRate: %d"), gbcnMissRate);
4104
4105 len = snprintf(buf, sizeof(buf), "GETBCNMISSRATE %d", gbcnMissRate);
4106 if (copy_to_user(priv_data.buf, &buf, len + 1))
4107 {
4108 hddLog(VOS_TRACE_LEVEL_ERROR,
4109 "%s: failed to copy data to user buffer", __func__);
4110 ret = -EFAULT;
4111 goto exit;
4112 }
4113 ret = len;
4114 }
Atul Mittal87ec2422014-09-24 13:12:50 +05304115#ifdef FEATURE_WLAN_TDLS
4116 else if (strncmp(command, "TDLSSECONDARYCHANNELOFFSET", 26) == 0) {
4117 tANI_U8 *value = command;
4118 int set_value;
4119 /* Move pointer to ahead of TDLSOFFCH*/
4120 value += 26;
4121 sscanf(value, "%d", &set_value);
4122 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4123 "%s: Tdls offchannel offset:%d",
4124 __func__, set_value);
4125 ret = iw_set_tdlssecoffchanneloffset(pHddCtx, set_value);
4126 if (ret < 0)
4127 {
4128 ret = -EINVAL;
4129 goto exit;
4130 }
4131
4132 } else if (strncmp(command, "TDLSOFFCHANNELMODE", 18) == 0) {
4133 tANI_U8 *value = command;
4134 int set_value;
4135 /* Move pointer to ahead of tdlsoffchnmode*/
4136 value += 18;
4137 sscanf(value, "%d", &set_value);
4138 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4139 "%s: Tdls offchannel mode:%d",
4140 __func__, set_value);
4141 ret = iw_set_tdlsoffchannelmode(pAdapter, set_value);
4142 if (ret < 0)
4143 {
4144 ret = -EINVAL;
4145 goto exit;
4146 }
4147 } else if (strncmp(command, "TDLSOFFCHANNEL", 14) == 0) {
4148 tANI_U8 *value = command;
4149 int set_value;
4150 /* Move pointer to ahead of TDLSOFFCH*/
4151 value += 14;
4152 sscanf(value, "%d", &set_value);
4153 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4154 "%s: Tdls offchannel num: %d",
4155 __func__, set_value);
4156 ret = iw_set_tdlsoffchannel(pHddCtx, set_value);
4157 if (ret < 0)
4158 {
4159 ret = -EINVAL;
4160 goto exit;
4161 }
4162 }
4163#endif
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07004164 else {
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05304165 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
4166 TRACE_CODE_HDD_UNSUPPORTED_IOCTL,
4167 pAdapter->sessionId, 0));
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07004168 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
4169 __func__, command);
4170 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004171 }
4172exit:
4173 if (command)
4174 {
4175 kfree(command);
4176 }
4177 return ret;
4178}
4179
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07004180#ifdef CONFIG_COMPAT
4181static int hdd_driver_compat_ioctl(hdd_adapter_t *pAdapter, struct ifreq *ifr)
4182{
4183 struct {
4184 compat_uptr_t buf;
4185 int used_len;
4186 int total_len;
4187 } compat_priv_data;
4188 hdd_priv_data_t priv_data;
4189 int ret = 0;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004190
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07004191 /*
4192 * Note that pAdapter and ifr have already been verified by caller,
4193 * and HDD context has also been validated
4194 */
4195 if (copy_from_user(&compat_priv_data, ifr->ifr_data,
4196 sizeof(compat_priv_data))) {
4197 ret = -EFAULT;
4198 goto exit;
4199 }
4200 priv_data.buf = compat_ptr(compat_priv_data.buf);
4201 priv_data.used_len = compat_priv_data.used_len;
4202 priv_data.total_len = compat_priv_data.total_len;
4203 ret = hdd_driver_command(pAdapter, &priv_data);
4204 exit:
4205 return ret;
4206}
4207#else /* CONFIG_COMPAT */
4208static int hdd_driver_compat_ioctl(hdd_adapter_t *pAdapter, struct ifreq *ifr)
4209{
4210 /* will never be invoked */
4211 return 0;
4212}
4213#endif /* CONFIG_COMPAT */
4214
4215static int hdd_driver_ioctl(hdd_adapter_t *pAdapter, struct ifreq *ifr)
4216{
4217 hdd_priv_data_t priv_data;
4218 int ret = 0;
4219
4220 /*
4221 * Note that pAdapter and ifr have already been verified by caller,
4222 * and HDD context has also been validated
4223 */
4224 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(priv_data))) {
4225 ret = -EFAULT;
4226 } else {
4227 ret = hdd_driver_command(pAdapter, &priv_data);
4228 }
4229 return ret;
4230}
4231
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05304232int __hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07004233{
4234 hdd_adapter_t *pAdapter;
4235 hdd_context_t *pHddCtx;
4236 int ret;
4237
4238 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4239 if (NULL == pAdapter) {
4240 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4241 "%s: HDD adapter context is Null", __func__);
4242 ret = -ENODEV;
4243 goto exit;
4244 }
4245 if (dev != pAdapter->dev) {
4246 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4247 "%s: HDD adapter/dev inconsistency", __func__);
4248 ret = -ENODEV;
4249 goto exit;
4250 }
4251
4252 if ((!ifr) || (!ifr->ifr_data)) {
4253 ret = -EINVAL;
4254 goto exit;
4255 }
4256
4257 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4258 ret = wlan_hdd_validate_context(pHddCtx);
4259 if (ret) {
Mahesh A Saptasagar5b16d0a2014-11-03 17:55:29 +05304260 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07004261 "%s: invalid context", __func__);
4262 ret = -EBUSY;
4263 goto exit;
4264 }
4265
4266 switch (cmd) {
4267 case (SIOCDEVPRIVATE + 1):
4268 if (is_compat_task())
4269 ret = hdd_driver_compat_ioctl(pAdapter, ifr);
4270 else
4271 ret = hdd_driver_ioctl(pAdapter, ifr);
4272 break;
4273 default:
4274 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unknown ioctl %d",
4275 __func__, cmd);
4276 ret = -EINVAL;
4277 break;
4278 }
4279 exit:
4280 return ret;
4281}
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004282
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05304283int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
4284{
4285 int ret;
4286
4287 vos_ssr_protect(__func__);
4288 ret = __hdd_ioctl(dev, ifr, cmd);
4289 vos_ssr_unprotect(__func__);
4290
4291 return ret;
4292}
4293
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004294#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004295/**---------------------------------------------------------------------------
4296
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004297 \brief hdd_parse_ese_beacon_req() - Parse ese beacon request
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004298
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004299 This function parses the ese beacon request passed in the format
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004300 CCXBEACONREQ<space><Number of fields><space><Measurement token>
4301 <space>Channel 1<space>Scan Mode <space>Meas Duration<space>Channel N
4302 <space>Scan Mode N<space>Meas Duration N
4303 if the Number of bcn req fields (N) does not match with the actual number of fields passed
4304 then take N.
4305 <Meas Token><Channel><Scan Mode> and <Meas Duration> are treated as one pair
4306 For example, CCXBEACONREQ 2 1 1 1 30 2 44 0 40.
4307 This function does not take care of removing duplicate channels from the list
4308
4309 \param - pValue Pointer to data
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004310 \param - pEseBcnReq output pointer to store parsed ie information
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004311
4312 \return - 0 for success non-zero for failure
4313
4314 --------------------------------------------------------------------------*/
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004315static VOS_STATUS hdd_parse_ese_beacon_req(tANI_U8 *pValue,
4316 tCsrEseBeaconReq *pEseBcnReq)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004317{
4318 tANI_U8 *inPtr = pValue;
4319 int tempInt = 0;
4320 int j = 0, i = 0, v = 0;
4321 char buf[32];
4322
4323 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4324 /*no argument after the command*/
4325 if (NULL == inPtr)
4326 {
4327 return -EINVAL;
4328 }
4329 /*no space after the command*/
4330 else if (SPACE_ASCII_VALUE != *inPtr)
4331 {
4332 return -EINVAL;
4333 }
4334
4335 /*removing empty spaces*/
4336 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
4337
4338 /*no argument followed by spaces*/
4339 if ('\0' == *inPtr) return -EINVAL;
4340
4341 /*getting the first argument ie measurement token*/
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004342 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004343 if (1 != v) return -EINVAL;
4344
4345 v = kstrtos32(buf, 10, &tempInt);
4346 if ( v < 0) return -EINVAL;
4347
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004348 pEseBcnReq->numBcnReqIe = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004349
4350 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004351 "Number of Bcn Req Ie fields(%d)", pEseBcnReq->numBcnReqIe);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004352
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004353 for (j = 0; j < (pEseBcnReq->numBcnReqIe); j++)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004354 {
4355 for (i = 0; i < 4; i++)
4356 {
4357 /*inPtr pointing to the beginning of first space after number of ie fields*/
4358 inPtr = strpbrk( inPtr, " " );
4359 /*no ie data after the number of ie fields argument*/
4360 if (NULL == inPtr) return -EINVAL;
4361
4362 /*removing empty space*/
4363 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
4364
4365 /*no ie data after the number of ie fields argument and spaces*/
4366 if ( '\0' == *inPtr ) return -EINVAL;
4367
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004368 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004369 if (1 != v) return -EINVAL;
4370
4371 v = kstrtos32(buf, 10, &tempInt);
4372 if (v < 0) return -EINVAL;
4373
4374 switch (i)
4375 {
4376 case 0: /* Measurement token */
4377 if (tempInt <= 0)
4378 {
4379 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4380 "Invalid Measurement Token(%d)", tempInt);
4381 return -EINVAL;
4382 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004383 pEseBcnReq->bcnReq[j].measurementToken = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004384 break;
4385
4386 case 1: /* Channel number */
4387 if ((tempInt <= 0) ||
4388 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4389 {
4390 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4391 "Invalid Channel Number(%d)", tempInt);
4392 return -EINVAL;
4393 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004394 pEseBcnReq->bcnReq[j].channel = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004395 break;
4396
4397 case 2: /* Scan mode */
Varun Reddy Yeturu0b18d5a2013-12-04 11:42:23 -08004398 if ((tempInt < eSIR_PASSIVE_SCAN) || (tempInt > eSIR_BEACON_TABLE))
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004399 {
4400 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4401 "Invalid Scan Mode(%d) Expected{0|1|2}", tempInt);
4402 return -EINVAL;
4403 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004404 pEseBcnReq->bcnReq[j].scanMode= tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004405 break;
4406
4407 case 3: /* Measurement duration */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004408 if (((tempInt <= 0) && (pEseBcnReq->bcnReq[j].scanMode != eSIR_BEACON_TABLE)) ||
4409 ((tempInt < 0) && (pEseBcnReq->bcnReq[j].scanMode == eSIR_BEACON_TABLE)))
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004410 {
4411 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4412 "Invalid Measurement Duration(%d)", tempInt);
4413 return -EINVAL;
4414 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004415 pEseBcnReq->bcnReq[j].measurementDuration = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004416 break;
4417 }
4418 }
4419 }
4420
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004421 for (j = 0; j < pEseBcnReq->numBcnReqIe; j++)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004422 {
4423 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arun Kumar Khandavallie8768212014-02-17 16:43:34 +05304424 "Index(%d) Measurement Token(%u)Channel(%u) Scan Mode(%u) Measurement Duration(%u)\n",
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004425 j,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004426 pEseBcnReq->bcnReq[j].measurementToken,
4427 pEseBcnReq->bcnReq[j].channel,
4428 pEseBcnReq->bcnReq[j].scanMode,
4429 pEseBcnReq->bcnReq[j].measurementDuration);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004430 }
4431
4432 return VOS_STATUS_SUCCESS;
4433}
4434
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004435static void hdd_GetTsmStatsCB( tAniTrafStrmMetrics tsmMetrics, const tANI_U32 staId, void *pContext )
4436{
4437 struct statsContext *pStatsContext = NULL;
4438 hdd_adapter_t *pAdapter = NULL;
4439
4440 if (NULL == pContext)
4441 {
4442 hddLog(VOS_TRACE_LEVEL_ERROR,
4443 "%s: Bad param, pContext [%p]",
4444 __func__, pContext);
4445 return;
4446 }
4447
Jeff Johnson72a40512013-12-19 10:14:15 -08004448 /* there is a race condition that exists between this callback
4449 function and the caller since the caller could time out either
4450 before or while this code is executing. we use a spinlock to
4451 serialize these actions */
4452 spin_lock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004453
4454 pStatsContext = pContext;
4455 pAdapter = pStatsContext->pAdapter;
4456 if ((NULL == pAdapter) || (STATS_CONTEXT_MAGIC != pStatsContext->magic))
4457 {
4458 /* the caller presumably timed out so there is nothing we can do */
Jeff Johnson72a40512013-12-19 10:14:15 -08004459 spin_unlock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004460 hddLog(VOS_TRACE_LEVEL_WARN,
4461 "%s: Invalid context, pAdapter [%p] magic [%08x]",
4462 __func__, pAdapter, pStatsContext->magic);
4463 return;
4464 }
4465
Jeff Johnson72a40512013-12-19 10:14:15 -08004466 /* context is valid so caller is still waiting */
4467
4468 /* paranoia: invalidate the magic */
4469 pStatsContext->magic = 0;
4470
4471 /* copy over the tsm stats */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004472 pAdapter->tsmStats.UplinkPktQueueDly = tsmMetrics.UplinkPktQueueDly;
4473 vos_mem_copy(pAdapter->tsmStats.UplinkPktQueueDlyHist,
4474 tsmMetrics.UplinkPktQueueDlyHist,
4475 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
4476 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
4477 pAdapter->tsmStats.UplinkPktTxDly = tsmMetrics.UplinkPktTxDly;
4478 pAdapter->tsmStats.UplinkPktLoss = tsmMetrics.UplinkPktLoss;
4479 pAdapter->tsmStats.UplinkPktCount = tsmMetrics.UplinkPktCount;
4480 pAdapter->tsmStats.RoamingCount = tsmMetrics.RoamingCount;
4481 pAdapter->tsmStats.RoamingDly = tsmMetrics.RoamingDly;
4482
Jeff Johnson72a40512013-12-19 10:14:15 -08004483 /* notify the caller */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004484 complete(&pStatsContext->completion);
Jeff Johnson72a40512013-12-19 10:14:15 -08004485
4486 /* serialization is complete */
4487 spin_unlock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004488}
4489
4490
4491
4492static VOS_STATUS hdd_get_tsm_stats(hdd_adapter_t *pAdapter, const tANI_U8 tid,
4493 tAniTrafStrmMetrics* pTsmMetrics)
4494{
4495 hdd_station_ctx_t *pHddStaCtx = NULL;
4496 eHalStatus hstatus;
Jeff Johnson72a40512013-12-19 10:14:15 -08004497 VOS_STATUS vstatus = VOS_STATUS_SUCCESS;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004498 long lrc;
4499 struct statsContext context;
4500 hdd_context_t *pHddCtx = NULL;
4501
4502 if (NULL == pAdapter)
4503 {
4504 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: pAdapter is NULL", __func__);
4505 return VOS_STATUS_E_FAULT;
4506 }
4507
4508 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4509 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4510
4511 /* we are connected prepare our callback context */
4512 init_completion(&context.completion);
4513 context.pAdapter = pAdapter;
4514 context.magic = STATS_CONTEXT_MAGIC;
4515
4516 /* query tsm stats */
4517 hstatus = sme_GetTsmStats(pHddCtx->hHal, hdd_GetTsmStatsCB,
4518 pHddStaCtx->conn_info.staId[ 0 ],
4519 pHddStaCtx->conn_info.bssId,
4520 &context, pHddCtx->pvosContext, tid);
4521
4522 if (eHAL_STATUS_SUCCESS != hstatus)
4523 {
Jeff Johnson72a40512013-12-19 10:14:15 -08004524 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unable to retrieve statistics",
4525 __func__);
4526 vstatus = VOS_STATUS_E_FAULT;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004527 }
4528 else
4529 {
4530 /* request was sent -- wait for the response */
4531 lrc = wait_for_completion_interruptible_timeout(&context.completion,
4532 msecs_to_jiffies(WLAN_WAIT_TIME_STATS));
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004533 if (lrc <= 0)
4534 {
4535 hddLog(VOS_TRACE_LEVEL_ERROR,
4536 "%s: SME %s while retrieving statistics",
4537 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson72a40512013-12-19 10:14:15 -08004538 vstatus = VOS_STATUS_E_TIMEOUT;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004539 }
4540 }
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004541
Jeff Johnson72a40512013-12-19 10:14:15 -08004542 /* either we never sent a request, we sent a request and received a
4543 response or we sent a request and timed out. if we never sent a
4544 request or if we sent a request and got a response, we want to
4545 clear the magic out of paranoia. if we timed out there is a
4546 race condition such that the callback function could be
4547 executing at the same time we are. of primary concern is if the
4548 callback function had already verified the "magic" but had not
4549 yet set the completion variable when a timeout occurred. we
4550 serialize these activities by invalidating the magic while
4551 holding a shared spinlock which will cause us to block if the
4552 callback is currently executing */
4553 spin_lock(&hdd_context_lock);
4554 context.magic = 0;
4555 spin_unlock(&hdd_context_lock);
4556
4557 if (VOS_STATUS_SUCCESS == vstatus)
4558 {
4559 pTsmMetrics->UplinkPktQueueDly = pAdapter->tsmStats.UplinkPktQueueDly;
4560 vos_mem_copy(pTsmMetrics->UplinkPktQueueDlyHist,
4561 pAdapter->tsmStats.UplinkPktQueueDlyHist,
4562 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
4563 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
4564 pTsmMetrics->UplinkPktTxDly = pAdapter->tsmStats.UplinkPktTxDly;
4565 pTsmMetrics->UplinkPktLoss = pAdapter->tsmStats.UplinkPktLoss;
4566 pTsmMetrics->UplinkPktCount = pAdapter->tsmStats.UplinkPktCount;
4567 pTsmMetrics->RoamingCount = pAdapter->tsmStats.RoamingCount;
4568 pTsmMetrics->RoamingDly = pAdapter->tsmStats.RoamingDly;
4569 }
4570 return vstatus;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004571}
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004572#endif /*FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004573
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004574#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -08004575void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
4576{
4577 eCsrBand band = -1;
4578 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
4579 switch (band)
4580 {
4581 case eCSR_BAND_ALL:
4582 *pBand = WLAN_HDD_UI_BAND_AUTO;
4583 break;
4584
4585 case eCSR_BAND_24:
4586 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
4587 break;
4588
4589 case eCSR_BAND_5G:
4590 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
4591 break;
4592
4593 default:
4594 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
4595 *pBand = -1;
4596 break;
4597 }
4598}
4599
4600/**---------------------------------------------------------------------------
4601
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004602 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
4603
4604 This function parses the send action frame data passed in the format
4605 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
4606
Srinivas Girigowda56076852013-08-20 14:00:50 -07004607 \param - pValue Pointer to input data
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004608 \param - pTargetApBssid Pointer to target Ap bssid
4609 \param - pChannel Pointer to the Target AP channel
4610 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
4611 \param - pBuf Pointer to data
4612 \param - pBufLen Pointer to data length
4613
4614 \return - 0 for success non-zero for failure
4615
4616 --------------------------------------------------------------------------*/
4617VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
4618 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
4619{
4620 tANI_U8 *inPtr = pValue;
4621 tANI_U8 *dataEnd;
4622 int tempInt;
4623 int j = 0;
4624 int i = 0;
4625 int v = 0;
4626 tANI_U8 tempBuf[32];
4627 tANI_U8 tempByte = 0;
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004628 /* 12 hexa decimal digits, 5 ':' and '\0' */
4629 tANI_U8 macAddress[18];
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004630
4631 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4632 /*no argument after the command*/
4633 if (NULL == inPtr)
4634 {
4635 return -EINVAL;
4636 }
4637
4638 /*no space after the command*/
4639 else if (SPACE_ASCII_VALUE != *inPtr)
4640 {
4641 return -EINVAL;
4642 }
4643
4644 /*removing empty spaces*/
4645 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4646
4647 /*no argument followed by spaces*/
4648 if ('\0' == *inPtr)
4649 {
4650 return -EINVAL;
4651 }
4652
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004653 v = sscanf(inPtr, "%17s", macAddress);
4654 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004655 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004656 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4657 "Invalid MAC address or All hex inputs are not read (%d)", v);
4658 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004659 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004660
4661 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
4662 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
4663 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
4664 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
4665 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
4666 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004667
4668 /* point to the next argument */
4669 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4670 /*no argument after the command*/
4671 if (NULL == inPtr) return -EINVAL;
4672
4673 /*removing empty spaces*/
4674 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4675
4676 /*no argument followed by spaces*/
4677 if ('\0' == *inPtr)
4678 {
4679 return -EINVAL;
4680 }
4681
4682 /*getting the next argument ie the channel number */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004683 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004684 if (1 != v) return -EINVAL;
4685
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004686 v = kstrtos32(tempBuf, 10, &tempInt);
Agarwal Ashish353b3a82014-04-08 14:55:11 +05304687 if ( v < 0 || tempInt <= 0 || tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX )
Kiet Lambe150c22013-11-21 16:30:32 +05304688 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004689
4690 *pChannel = tempInt;
4691
4692 /* point to the next argument */
4693 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4694 /*no argument after the command*/
4695 if (NULL == inPtr) return -EINVAL;
4696 /*removing empty spaces*/
4697 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4698
4699 /*no argument followed by spaces*/
4700 if ('\0' == *inPtr)
4701 {
4702 return -EINVAL;
4703 }
4704
4705 /*getting the next argument ie the dwell time */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004706 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004707 if (1 != v) return -EINVAL;
4708
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004709 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda5a6e0672014-01-09 14:42:57 -08004710 if ( v < 0 || tempInt < 0) return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004711
4712 *pDwellTime = tempInt;
4713
4714 /* point to the next argument */
4715 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4716 /*no argument after the command*/
4717 if (NULL == inPtr) return -EINVAL;
4718 /*removing empty spaces*/
4719 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4720
4721 /*no argument followed by spaces*/
4722 if ('\0' == *inPtr)
4723 {
4724 return -EINVAL;
4725 }
4726
4727 /* find the length of data */
4728 dataEnd = inPtr;
4729 while(('\0' != *dataEnd) )
4730 {
4731 dataEnd++;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004732 }
Kiet Lambe150c22013-11-21 16:30:32 +05304733 *pBufLen = dataEnd - inPtr ;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004734 if ( *pBufLen <= 0) return -EINVAL;
4735
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07004736 /* Allocate the number of bytes based on the number of input characters
4737 whether it is even or odd.
4738 if the number of input characters are even, then we need N/2 byte.
4739 if the number of input characters are odd, then we need do (N+1)/2 to
4740 compensate rounding off.
4741 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
4742 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
4743 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004744 if (NULL == *pBuf)
4745 {
4746 hddLog(VOS_TRACE_LEVEL_FATAL,
4747 "%s: vos_mem_alloc failed ", __func__);
4748 return -EINVAL;
4749 }
4750
4751 /* the buffer received from the upper layer is character buffer,
4752 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
4753 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
4754 and f0 in 3rd location */
4755 for (i = 0, j = 0; j < *pBufLen; j += 2)
4756 {
Kiet Lambe150c22013-11-21 16:30:32 +05304757 if( j+1 == *pBufLen)
4758 {
4759 tempByte = hdd_parse_hex(inPtr[j]);
4760 }
4761 else
4762 {
4763 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
4764 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004765 (*pBuf)[i++] = tempByte;
4766 }
4767 *pBufLen = i;
4768 return VOS_STATUS_SUCCESS;
4769}
4770
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004771/**---------------------------------------------------------------------------
4772
Srinivas Girigowdade697412013-02-14 16:31:48 -08004773 \brief hdd_parse_channellist() - HDD Parse channel list
4774
4775 This function parses the channel list passed in the format
4776 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004777 if the Number of channels (N) does not match with the actual number of channels passed
4778 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
4779 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
4780 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
4781 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08004782
4783 \param - pValue Pointer to input channel list
4784 \param - ChannelList Pointer to local output array to record channel list
4785 \param - pNumChannels Pointer to number of roam scan channels
4786
4787 \return - 0 for success non-zero for failure
4788
4789 --------------------------------------------------------------------------*/
4790VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
4791{
4792 tANI_U8 *inPtr = pValue;
4793 int tempInt;
4794 int j = 0;
4795 int v = 0;
4796 char buf[32];
4797
4798 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4799 /*no argument after the command*/
4800 if (NULL == inPtr)
4801 {
4802 return -EINVAL;
4803 }
4804
4805 /*no space after the command*/
4806 else if (SPACE_ASCII_VALUE != *inPtr)
4807 {
4808 return -EINVAL;
4809 }
4810
4811 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004812 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08004813
4814 /*no argument followed by spaces*/
4815 if ('\0' == *inPtr)
4816 {
4817 return -EINVAL;
4818 }
4819
4820 /*getting the first argument ie the number of channels*/
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004821 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004822 if (1 != v) return -EINVAL;
4823
Srinivas Girigowdade697412013-02-14 16:31:48 -08004824 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004825 if ((v < 0) ||
4826 (tempInt <= 0) ||
4827 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
4828 {
4829 return -EINVAL;
4830 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004831
4832 *pNumChannels = tempInt;
4833
4834 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
4835 "Number of channels are: %d", *pNumChannels);
4836
4837 for (j = 0; j < (*pNumChannels); j++)
4838 {
4839 /*inPtr pointing to the beginning of first space after number of channels*/
4840 inPtr = strpbrk( inPtr, " " );
4841 /*no channel list after the number of channels argument*/
4842 if (NULL == inPtr)
4843 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004844 if (0 != j)
4845 {
4846 *pNumChannels = j;
4847 return VOS_STATUS_SUCCESS;
4848 }
4849 else
4850 {
4851 return -EINVAL;
4852 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004853 }
4854
4855 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004856 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08004857
4858 /*no channel list after the number of channels argument and spaces*/
4859 if ( '\0' == *inPtr )
4860 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004861 if (0 != j)
4862 {
4863 *pNumChannels = j;
4864 return VOS_STATUS_SUCCESS;
4865 }
4866 else
4867 {
4868 return -EINVAL;
4869 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004870 }
4871
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004872 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004873 if (1 != v) return -EINVAL;
4874
Srinivas Girigowdade697412013-02-14 16:31:48 -08004875 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004876 if ((v < 0) ||
4877 (tempInt <= 0) ||
4878 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4879 {
4880 return -EINVAL;
4881 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004882 pChannelList[j] = tempInt;
4883
4884 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
4885 "Channel %d added to preferred channel list",
4886 pChannelList[j] );
4887 }
4888
Srinivas Girigowdade697412013-02-14 16:31:48 -08004889 return VOS_STATUS_SUCCESS;
4890}
4891
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004892
4893/**---------------------------------------------------------------------------
4894
4895 \brief hdd_parse_reassoc_command_data() - HDD Parse reassoc command data
4896
4897 This function parses the reasoc command data passed in the format
4898 REASSOC<space><bssid><space><channel>
4899
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004900 \param - pValue Pointer to input data (its a NUL terminated string)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004901 \param - pTargetApBssid Pointer to target Ap bssid
4902 \param - pChannel Pointer to the Target AP channel
4903
4904 \return - 0 for success non-zero for failure
4905
4906 --------------------------------------------------------------------------*/
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004907VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue,
4908 tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004909{
4910 tANI_U8 *inPtr = pValue;
4911 int tempInt;
4912 int v = 0;
4913 tANI_U8 tempBuf[32];
Kiet Lamaa8e15a2014-02-11 23:30:06 -08004914 /* 12 hexa decimal digits, 5 ':' and '\0' */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004915 tANI_U8 macAddress[18];
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004916
4917 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4918 /*no argument after the command*/
4919 if (NULL == inPtr)
4920 {
4921 return -EINVAL;
4922 }
4923
4924 /*no space after the command*/
4925 else if (SPACE_ASCII_VALUE != *inPtr)
4926 {
4927 return -EINVAL;
4928 }
4929
4930 /*removing empty spaces*/
4931 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4932
4933 /*no argument followed by spaces*/
4934 if ('\0' == *inPtr)
4935 {
4936 return -EINVAL;
4937 }
4938
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004939 v = sscanf(inPtr, "%17s", macAddress);
4940 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004941 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004942 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4943 "Invalid MAC address or All hex inputs are not read (%d)", v);
4944 return -EINVAL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004945 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004946
4947 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
4948 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
4949 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
4950 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
4951 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
4952 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004953
4954 /* point to the next argument */
4955 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4956 /*no argument after the command*/
4957 if (NULL == inPtr) return -EINVAL;
4958
4959 /*removing empty spaces*/
4960 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4961
4962 /*no argument followed by spaces*/
4963 if ('\0' == *inPtr)
4964 {
4965 return -EINVAL;
4966 }
4967
4968 /*getting the next argument ie the channel number */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004969 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004970 if (1 != v) return -EINVAL;
4971
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004972 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004973 if ((v < 0) ||
Padma, Santhosh Kumar0fa809b2014-11-13 14:56:56 +05304974 (tempInt < 0) ||
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004975 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4976 {
4977 return -EINVAL;
4978 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004979
4980 *pChannel = tempInt;
4981 return VOS_STATUS_SUCCESS;
4982}
4983
4984#endif
4985
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004986#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004987/**---------------------------------------------------------------------------
4988
4989 \brief hdd_parse_get_cckm_ie() - HDD Parse and fetch the CCKM IE
4990
4991 This function parses the SETCCKM IE command
4992 SETCCKMIE<space><ie data>
4993
4994 \param - pValue Pointer to input data
4995 \param - pCckmIe Pointer to output cckm Ie
4996 \param - pCckmIeLen Pointer to output cckm ie length
4997
4998 \return - 0 for success non-zero for failure
4999
5000 --------------------------------------------------------------------------*/
5001VOS_STATUS hdd_parse_get_cckm_ie(tANI_U8 *pValue, tANI_U8 **pCckmIe,
5002 tANI_U8 *pCckmIeLen)
5003{
5004 tANI_U8 *inPtr = pValue;
5005 tANI_U8 *dataEnd;
5006 int j = 0;
5007 int i = 0;
5008 tANI_U8 tempByte = 0;
5009
5010 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
5011 /*no argument after the command*/
5012 if (NULL == inPtr)
5013 {
5014 return -EINVAL;
5015 }
5016
5017 /*no space after the command*/
5018 else if (SPACE_ASCII_VALUE != *inPtr)
5019 {
5020 return -EINVAL;
5021 }
5022
5023 /*removing empty spaces*/
5024 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
5025
5026 /*no argument followed by spaces*/
5027 if ('\0' == *inPtr)
5028 {
5029 return -EINVAL;
5030 }
5031
5032 /* find the length of data */
5033 dataEnd = inPtr;
5034 while(('\0' != *dataEnd) )
5035 {
5036 dataEnd++;
5037 ++(*pCckmIeLen);
5038 }
5039 if ( *pCckmIeLen <= 0) return -EINVAL;
5040
5041 /* Allocate the number of bytes based on the number of input characters
5042 whether it is even or odd.
5043 if the number of input characters are even, then we need N/2 byte.
5044 if the number of input characters are odd, then we need do (N+1)/2 to
5045 compensate rounding off.
5046 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
5047 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
5048 *pCckmIe = vos_mem_malloc((*pCckmIeLen + 1)/2);
5049 if (NULL == *pCckmIe)
5050 {
5051 hddLog(VOS_TRACE_LEVEL_FATAL,
5052 "%s: vos_mem_alloc failed ", __func__);
5053 return -EINVAL;
5054 }
5055 vos_mem_zero(*pCckmIe, (*pCckmIeLen + 1)/2);
5056 /* the buffer received from the upper layer is character buffer,
5057 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
5058 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
5059 and f0 in 3rd location */
5060 for (i = 0, j = 0; j < *pCckmIeLen; j += 2)
5061 {
5062 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
5063 (*pCckmIe)[i++] = tempByte;
5064 }
5065 *pCckmIeLen = i;
5066
5067 return VOS_STATUS_SUCCESS;
5068}
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08005069#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07005070
Jeff Johnson295189b2012-06-20 16:38:30 -07005071/**---------------------------------------------------------------------------
5072
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07005073 \brief hdd_is_valid_mac_address() - Validate MAC address
5074
5075 This function validates whether the given MAC address is valid or not
5076 Expected MAC address is of the format XX:XX:XX:XX:XX:XX
5077 where X is the hexa decimal digit character and separated by ':'
5078 This algorithm works even if MAC address is not separated by ':'
5079
5080 This code checks given input string mac contains exactly 12 hexadecimal digits.
5081 and a separator colon : appears in the input string only after
5082 an even number of hex digits.
5083
5084 \param - pMacAddr pointer to the input MAC address
5085 \return - 1 for valid and 0 for invalid
5086
5087 --------------------------------------------------------------------------*/
5088
5089v_BOOL_t hdd_is_valid_mac_address(const tANI_U8 *pMacAddr)
5090{
5091 int xdigit = 0;
5092 int separator = 0;
5093 while (*pMacAddr)
5094 {
5095 if (isxdigit(*pMacAddr))
5096 {
5097 xdigit++;
5098 }
5099 else if (':' == *pMacAddr)
5100 {
5101 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
5102 break;
5103
5104 ++separator;
5105 }
5106 else
5107 {
5108 separator = -1;
5109 /* Invalid MAC found */
5110 return 0;
5111 }
5112 ++pMacAddr;
5113 }
5114 return (xdigit == 12 && (separator == 5 || separator == 0));
5115}
5116
5117/**---------------------------------------------------------------------------
5118
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305119 \brief __hdd_open() - HDD Open function
Jeff Johnson295189b2012-06-20 16:38:30 -07005120
5121 \param - dev Pointer to net_device structure
5122
5123 \return - 0 for success non-zero for failure
5124
5125 --------------------------------------------------------------------------*/
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305126int __hdd_open(struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07005127{
5128 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5129 hdd_context_t *pHddCtx;
5130 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5131 VOS_STATUS status;
5132 v_BOOL_t in_standby = TRUE;
5133
5134 if (NULL == pAdapter)
5135 {
5136 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Agarwal Ashish971c2882013-10-30 20:11:12 +05305137 "%s: pAdapter is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005138 return -ENODEV;
5139 }
5140
5141 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05305142 MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_OPEN_REQUEST,
5143 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson295189b2012-06-20 16:38:30 -07005144 if (NULL == pHddCtx)
5145 {
5146 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005147 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005148 return -ENODEV;
5149 }
5150
5151 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5152 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
5153 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07005154 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
5155 {
5156 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305157 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07005158 in_standby = FALSE;
5159 break;
5160 }
5161 else
5162 {
5163 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5164 pAdapterNode = pNext;
5165 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005166 }
5167
5168 if (TRUE == in_standby)
5169 {
5170 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
5171 {
5172 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
5173 "wlan out of power save", __func__);
5174 return -EINVAL;
5175 }
5176 }
5177
Jeff Johnson6a81ca42013-04-05 10:37:08 -07005178 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07005179 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
5180 {
5181 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005182 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005183 /* Enable TX queues only when we are connected */
5184 netif_tx_start_all_queues(dev);
5185 }
5186
5187 return 0;
5188}
5189
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305190/**---------------------------------------------------------------------------
5191
5192 \brief hdd_open() - Wrapper function for __hdd_open to protect it from SSR
5193
5194 This is called in response to ifconfig up
5195
5196 \param - dev Pointer to net_device structure
5197
5198 \return - 0 for success non-zero for failure
5199
5200 --------------------------------------------------------------------------*/
5201int hdd_open(struct net_device *dev)
5202{
5203 int ret;
5204
5205 vos_ssr_protect(__func__);
5206 ret = __hdd_open(dev);
5207 vos_ssr_unprotect(__func__);
5208
5209 return ret;
5210}
5211
Jeff Johnson295189b2012-06-20 16:38:30 -07005212int hdd_mon_open (struct net_device *dev)
5213{
5214 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5215
5216 if(pAdapter == NULL) {
5217 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005218 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005219 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005220 }
5221
5222 netif_start_queue(dev);
5223
5224 return 0;
5225}
5226/**---------------------------------------------------------------------------
5227
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305228 \brief __hdd_stop() - HDD stop function
Jeff Johnson295189b2012-06-20 16:38:30 -07005229
5230 \param - dev Pointer to net_device structure
5231
5232 \return - 0 for success non-zero for failure
5233
5234 --------------------------------------------------------------------------*/
5235
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305236int __hdd_stop (struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07005237{
Vinay Krishna Eranna90f43532014-10-27 16:45:54 +05305238 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07005239 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5240 hdd_context_t *pHddCtx;
5241 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5242 VOS_STATUS status;
5243 v_BOOL_t enter_standby = TRUE;
5244
5245 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005246 if (NULL == pAdapter)
5247 {
5248 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Agarwal Ashish971c2882013-10-30 20:11:12 +05305249 "%s: pAdapter is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005250 return -ENODEV;
5251 }
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05305252 MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_OPEN_REQUEST,
5253 pAdapter->sessionId, pAdapter->device_mode));
Vinay Krishna Eranna90f43532014-10-27 16:45:54 +05305254
5255 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
5256 ret = wlan_hdd_validate_context(pHddCtx);
5257 if (ret)
Jeff Johnson295189b2012-06-20 16:38:30 -07005258 {
Vinay Krishna Eranna90f43532014-10-27 16:45:54 +05305259 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5260 "%s: HDD context is not valid!", __func__);
5261 return ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07005262 }
5263
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05305264 /* Nothing to be done if the interface is not opened */
5265 if (VOS_FALSE == test_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags))
5266 {
5267 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5268 "%s: NETDEV Interface is not OPENED", __func__);
5269 return -ENODEV;
5270 }
5271
5272 /* Make sure the interface is marked as closed */
Jeff Johnson6a81ca42013-04-05 10:37:08 -07005273 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07005274 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05305275
5276 /* Disable TX on the interface, after this hard_start_xmit() will not
5277 * be called on that interface
5278 */
Jeff Johnson295189b2012-06-20 16:38:30 -07005279 netif_tx_disable(pAdapter->dev);
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05305280
5281 /* Mark the interface status as "down" for outside world */
Jeff Johnson295189b2012-06-20 16:38:30 -07005282 netif_carrier_off(pAdapter->dev);
5283
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05305284 /* The interface is marked as down for outside world (aka kernel)
5285 * But the driver is pretty much alive inside. The driver needs to
5286 * tear down the existing connection on the netdev (session)
5287 * cleanup the data pipes and wait until the control plane is stabilized
5288 * for this interface. The call also needs to wait until the above
5289 * mentioned actions are completed before returning to the caller.
5290 * Notice that the hdd_stop_adapter is requested not to close the session
5291 * That is intentional to be able to scan if it is a STA/P2P interface
5292 */
5293 hdd_stop_adapter(pHddCtx, pAdapter, VOS_FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -07005294
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05305295 /* DeInit the adapter. This ensures datapath cleanup as well */
5296 hdd_deinit_adapter(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005297 /* SoftAP ifaces should never go in power save mode
5298 making sure same here. */
5299 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
5300 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07005301 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07005302 )
5303 {
5304 /* SoftAP mode, so return from here */
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305305 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5306 "%s: In SAP MODE", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005307 EXIT();
5308 return 0;
5309 }
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05305310 /* Find if any iface is up. If any iface is up then can't put device to
5311 * sleep/power save mode
5312 */
Jeff Johnson295189b2012-06-20 16:38:30 -07005313 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5314 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
5315 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07005316 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
5317 {
5318 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305319 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07005320 enter_standby = FALSE;
5321 break;
5322 }
5323 else
5324 {
5325 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5326 pAdapterNode = pNext;
5327 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005328 }
5329
5330 if (TRUE == enter_standby)
5331 {
5332 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
5333 "entering standby", __func__);
5334 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
5335 {
5336 /*log and return success*/
5337 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
5338 "wlan in power save", __func__);
5339 }
5340 }
5341
5342 EXIT();
5343 return 0;
5344}
5345
5346/**---------------------------------------------------------------------------
5347
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305348 \brief hdd_stop() - wrapper_function for __hdd_stop to protect it from SSR
Jeff Johnson295189b2012-06-20 16:38:30 -07005349
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305350 This is called in response to ifconfig down
5351
5352 \param - dev Pointer to net_device structure
5353
5354 \return - 0 for success non-zero for failure
5355-----------------------------------------------------------------------------*/
5356int hdd_stop (struct net_device *dev)
5357{
5358 int ret;
5359
5360 vos_ssr_protect(__func__);
5361 ret = __hdd_stop(dev);
5362 vos_ssr_unprotect(__func__);
5363
5364 return ret;
5365}
5366
5367/**---------------------------------------------------------------------------
5368
5369 \brief __hdd_uninit() - HDD uninit function
Jeff Johnson295189b2012-06-20 16:38:30 -07005370
5371 \param - dev Pointer to net_device structure
5372
5373 \return - void
5374
5375 --------------------------------------------------------------------------*/
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305376static void __hdd_uninit (struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07005377{
5378 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5379
5380 ENTER();
5381
5382 do
5383 {
5384 if (NULL == pAdapter)
5385 {
5386 hddLog(VOS_TRACE_LEVEL_FATAL,
5387 "%s: NULL pAdapter", __func__);
5388 break;
5389 }
5390
5391 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
5392 {
5393 hddLog(VOS_TRACE_LEVEL_FATAL,
5394 "%s: Invalid magic", __func__);
5395 break;
5396 }
5397
5398 if (NULL == pAdapter->pHddCtx)
5399 {
5400 hddLog(VOS_TRACE_LEVEL_FATAL,
5401 "%s: NULL pHddCtx", __func__);
5402 break;
5403 }
5404
5405 if (dev != pAdapter->dev)
5406 {
5407 hddLog(VOS_TRACE_LEVEL_FATAL,
5408 "%s: Invalid device reference", __func__);
5409 /* we haven't validated all cases so let this go for now */
5410 }
5411
5412 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
5413
5414 /* after uninit our adapter structure will no longer be valid */
5415 pAdapter->dev = NULL;
5416 pAdapter->magic = 0;
5417 } while (0);
5418
5419 EXIT();
5420}
5421
5422/**---------------------------------------------------------------------------
5423
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305424 \brief hdd_uninit() - Wrapper function to protect __hdd_uninit from SSR
5425
5426 This is called during the netdev unregister to uninitialize all data
5427associated with the device
5428
5429 \param - dev Pointer to net_device structure
5430
5431 \return - void
5432
5433 --------------------------------------------------------------------------*/
5434static void hdd_uninit (struct net_device *dev)
5435{
5436 vos_ssr_protect(__func__);
5437 __hdd_uninit(dev);
5438 vos_ssr_unprotect(__func__);
5439}
5440
5441/**---------------------------------------------------------------------------
5442
Jeff Johnson295189b2012-06-20 16:38:30 -07005443 \brief hdd_release_firmware() -
5444
5445 This function calls the release firmware API to free the firmware buffer.
5446
5447 \param - pFileName Pointer to the File Name.
5448 pCtx - Pointer to the adapter .
5449
5450
5451 \return - 0 for success, non zero for failure
5452
5453 --------------------------------------------------------------------------*/
5454
5455VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
5456{
5457 VOS_STATUS status = VOS_STATUS_SUCCESS;
5458 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
5459 ENTER();
5460
5461
5462 if (!strcmp(WLAN_FW_FILE, pFileName)) {
5463
5464 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
5465
5466 if(pHddCtx->fw) {
5467 release_firmware(pHddCtx->fw);
5468 pHddCtx->fw = NULL;
5469 }
5470 else
5471 status = VOS_STATUS_E_FAILURE;
5472 }
5473 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
5474 if(pHddCtx->nv) {
5475 release_firmware(pHddCtx->nv);
5476 pHddCtx->nv = NULL;
5477 }
5478 else
5479 status = VOS_STATUS_E_FAILURE;
5480
5481 }
5482
5483 EXIT();
5484 return status;
5485}
5486
5487/**---------------------------------------------------------------------------
5488
5489 \brief hdd_request_firmware() -
5490
5491 This function reads the firmware file using the request firmware
5492 API and returns the the firmware data and the firmware file size.
5493
5494 \param - pfileName - Pointer to the file name.
5495 - pCtx - Pointer to the adapter .
5496 - ppfw_data - Pointer to the pointer of the firmware data.
5497 - pSize - Pointer to the file size.
5498
5499 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
5500
5501 --------------------------------------------------------------------------*/
5502
5503
5504VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
5505{
5506 int status;
5507 VOS_STATUS retval = VOS_STATUS_SUCCESS;
5508 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
5509 ENTER();
5510
5511 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
5512
5513 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
5514
5515 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
5516 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
5517 __func__, pfileName);
5518 retval = VOS_STATUS_E_FAILURE;
5519 }
5520
5521 else {
5522 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
5523 *pSize = pHddCtx->fw->size;
5524 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
5525 __func__, *pSize);
5526 }
5527 }
5528 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
5529
5530 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
5531
5532 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
5533 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
5534 __func__, pfileName);
5535 retval = VOS_STATUS_E_FAILURE;
5536 }
5537
5538 else {
5539 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
5540 *pSize = pHddCtx->nv->size;
5541 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
5542 __func__, *pSize);
5543 }
5544 }
5545
5546 EXIT();
5547 return retval;
5548}
5549/**---------------------------------------------------------------------------
5550 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
5551
5552 This is the function invoked by SME to inform the result of a full power
5553 request issued by HDD
5554
5555 \param - callbackcontext - Pointer to cookie
5556 status - result of request
5557
5558 \return - None
5559
5560--------------------------------------------------------------------------*/
5561void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
5562{
5563 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
5564
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07005565 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07005566 if(&pHddCtx->full_pwr_comp_var)
5567 {
5568 complete(&pHddCtx->full_pwr_comp_var);
5569 }
5570}
5571
5572/**---------------------------------------------------------------------------
5573
5574 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
5575
5576 This is the function invoked by SME to inform the result of BMPS
5577 request issued by HDD
5578
5579 \param - callbackcontext - Pointer to cookie
5580 status - result of request
5581
5582 \return - None
5583
5584--------------------------------------------------------------------------*/
5585void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
5586{
5587
5588 struct completion *completion_var = (struct completion*) callbackContext;
5589
Arif Hussain6d2a3322013-11-17 19:50:10 -08005590 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07005591 if(completion_var != NULL)
5592 {
5593 complete(completion_var);
5594 }
5595}
5596
5597/**---------------------------------------------------------------------------
5598
5599 \brief hdd_get_cfg_file_size() -
5600
5601 This function reads the configuration file using the request firmware
5602 API and returns the configuration file size.
5603
5604 \param - pCtx - Pointer to the adapter .
5605 - pFileName - Pointer to the file name.
5606 - pBufSize - Pointer to the buffer size.
5607
5608 \return - 0 for success, non zero for failure
5609
5610 --------------------------------------------------------------------------*/
5611
5612VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
5613{
5614 int status;
5615 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
5616
5617 ENTER();
5618
5619 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
5620
5621 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
5622 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
5623 status = VOS_STATUS_E_FAILURE;
5624 }
5625 else {
5626 *pBufSize = pHddCtx->fw->size;
5627 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
5628 release_firmware(pHddCtx->fw);
5629 pHddCtx->fw = NULL;
5630 }
5631
5632 EXIT();
5633 return VOS_STATUS_SUCCESS;
5634}
5635
5636/**---------------------------------------------------------------------------
5637
5638 \brief hdd_read_cfg_file() -
5639
5640 This function reads the configuration file using the request firmware
5641 API and returns the cfg data and the buffer size of the configuration file.
5642
5643 \param - pCtx - Pointer to the adapter .
5644 - pFileName - Pointer to the file name.
5645 - pBuffer - Pointer to the data buffer.
5646 - pBufSize - Pointer to the buffer size.
5647
5648 \return - 0 for success, non zero for failure
5649
5650 --------------------------------------------------------------------------*/
5651
5652VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
5653 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
5654{
5655 int status;
5656 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
5657
5658 ENTER();
5659
5660 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
5661
5662 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
5663 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
5664 return VOS_STATUS_E_FAILURE;
5665 }
5666 else {
5667 if(*pBufSize != pHddCtx->fw->size) {
5668 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
5669 "file size", __func__);
5670 release_firmware(pHddCtx->fw);
5671 pHddCtx->fw = NULL;
5672 return VOS_STATUS_E_FAILURE;
5673 }
5674 else {
5675 if(pBuffer) {
5676 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
5677 }
5678 release_firmware(pHddCtx->fw);
5679 pHddCtx->fw = NULL;
5680 }
5681 }
5682
5683 EXIT();
5684
5685 return VOS_STATUS_SUCCESS;
5686}
5687
5688/**---------------------------------------------------------------------------
5689
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305690 \brief __hdd_set_mac_address() -
Jeff Johnson295189b2012-06-20 16:38:30 -07005691
5692 This function sets the user specified mac address using
5693 the command ifconfig wlanX hw ether <mac adress>.
5694
5695 \param - dev - Pointer to the net device.
5696 - addr - Pointer to the sockaddr.
5697 \return - 0 for success, non zero for failure
5698
5699 --------------------------------------------------------------------------*/
5700
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305701static int __hdd_set_mac_address(struct net_device *dev, void *addr)
Jeff Johnson295189b2012-06-20 16:38:30 -07005702{
5703 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5704 struct sockaddr *psta_mac_addr = addr;
5705 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5706
5707 ENTER();
5708
5709 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
Jeff Johnson295189b2012-06-20 16:38:30 -07005710 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
5711
5712 EXIT();
5713 return halStatus;
5714}
5715
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305716/**---------------------------------------------------------------------------
5717
5718 \brief hdd_set_mac_address() -
5719
5720 Wrapper function to protect __hdd_set_mac_address() function from ssr
5721
5722 \param - dev - Pointer to the net device.
5723 - addr - Pointer to the sockaddr.
5724 \return - 0 for success, non zero for failure
5725
5726 --------------------------------------------------------------------------*/
5727static int hdd_set_mac_address(struct net_device *dev, void *addr)
5728{
5729 int ret;
5730
5731 vos_ssr_protect(__func__);
5732 ret = __hdd_set_mac_address(dev, addr);
5733 vos_ssr_unprotect(__func__);
5734
5735 return ret;
5736}
5737
Jeff Johnson295189b2012-06-20 16:38:30 -07005738tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
5739{
5740 int i;
5741 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5742 {
Abhishek Singheb183782014-02-06 13:37:21 +05305743 if( 0 == ((pHddCtx->cfg_ini->intfAddrMask) & (1 << i)) )
Jeff Johnson295189b2012-06-20 16:38:30 -07005744 break;
5745 }
5746
5747 if( VOS_MAX_CONCURRENCY_PERSONA == i)
5748 return NULL;
5749
5750 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
5751 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
5752}
5753
5754void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
5755{
5756 int i;
5757 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5758 {
5759 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
5760 {
5761 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
5762 break;
5763 }
5764 }
5765 return;
5766}
5767
5768#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
5769 static struct net_device_ops wlan_drv_ops = {
5770 .ndo_open = hdd_open,
5771 .ndo_stop = hdd_stop,
5772 .ndo_uninit = hdd_uninit,
5773 .ndo_start_xmit = hdd_hard_start_xmit,
5774 .ndo_tx_timeout = hdd_tx_timeout,
5775 .ndo_get_stats = hdd_stats,
5776 .ndo_do_ioctl = hdd_ioctl,
5777 .ndo_set_mac_address = hdd_set_mac_address,
5778 .ndo_select_queue = hdd_select_queue,
5779#ifdef WLAN_FEATURE_PACKET_FILTERING
5780#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
5781 .ndo_set_rx_mode = hdd_set_multicast_list,
5782#else
5783 .ndo_set_multicast_list = hdd_set_multicast_list,
5784#endif //LINUX_VERSION_CODE
5785#endif
5786 };
Jeff Johnson295189b2012-06-20 16:38:30 -07005787 static struct net_device_ops wlan_mon_drv_ops = {
5788 .ndo_open = hdd_mon_open,
5789 .ndo_stop = hdd_stop,
5790 .ndo_uninit = hdd_uninit,
5791 .ndo_start_xmit = hdd_mon_hard_start_xmit,
5792 .ndo_tx_timeout = hdd_tx_timeout,
5793 .ndo_get_stats = hdd_stats,
5794 .ndo_do_ioctl = hdd_ioctl,
5795 .ndo_set_mac_address = hdd_set_mac_address,
5796 };
Jeff Johnson295189b2012-06-20 16:38:30 -07005797
5798#endif
5799
5800void hdd_set_station_ops( struct net_device *pWlanDev )
5801{
5802#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
Jeff Johnson295189b2012-06-20 16:38:30 -07005803 pWlanDev->netdev_ops = &wlan_drv_ops;
5804#else
5805 pWlanDev->open = hdd_open;
5806 pWlanDev->stop = hdd_stop;
5807 pWlanDev->uninit = hdd_uninit;
5808 pWlanDev->hard_start_xmit = NULL;
5809 pWlanDev->tx_timeout = hdd_tx_timeout;
5810 pWlanDev->get_stats = hdd_stats;
5811 pWlanDev->do_ioctl = hdd_ioctl;
Jeff Johnson295189b2012-06-20 16:38:30 -07005812 pWlanDev->set_mac_address = hdd_set_mac_address;
5813#endif
5814}
5815
Jeff Johnsoneed415b2013-01-18 16:11:20 -08005816static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07005817{
5818 struct net_device *pWlanDev = NULL;
5819 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005820 /*
5821 * cfg80211 initialization and registration....
5822 */
5823 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
5824
Jeff Johnson295189b2012-06-20 16:38:30 -07005825 if(pWlanDev != NULL)
5826 {
5827
5828 //Save the pointer to the net_device in the HDD adapter
5829 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
5830
Jeff Johnson295189b2012-06-20 16:38:30 -07005831 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
5832
5833 pAdapter->dev = pWlanDev;
5834 pAdapter->pHddCtx = pHddCtx;
5835 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
Agarwal Ashish47d18112014-08-04 19:55:07 +05305836 spin_lock_init(&pAdapter->lock_for_active_session);
Jeff Johnson295189b2012-06-20 16:38:30 -07005837
5838 init_completion(&pAdapter->session_open_comp_var);
5839 init_completion(&pAdapter->session_close_comp_var);
5840 init_completion(&pAdapter->disconnect_comp_var);
5841 init_completion(&pAdapter->linkup_event_var);
5842 init_completion(&pAdapter->cancel_rem_on_chan_var);
5843 init_completion(&pAdapter->rem_on_chan_ready_event);
Vinay Krishna Erannaf0e523b2014-03-01 21:00:16 +05305844 init_completion(&pAdapter->pno_comp_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07005845#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
5846 init_completion(&pAdapter->offchannel_tx_event);
5847#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005848 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005849#ifdef FEATURE_WLAN_TDLS
5850 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07005851 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08005852 init_completion(&pAdapter->tdls_mgmt_comp);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05305853 init_completion(&pAdapter->tdls_link_establish_req_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005854#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005855 init_completion(&pHddCtx->mc_sus_event_var);
5856 init_completion(&pHddCtx->tx_sus_event_var);
Gopichand Nakkala05621412013-06-19 19:37:38 +05305857 init_completion(&pHddCtx->rx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07005858 init_completion(&pAdapter->ula_complete);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07005859 init_completion(&pAdapter->change_country_code);
Jeff Johnson295189b2012-06-20 16:38:30 -07005860
Rajeev79dbe4c2013-10-05 11:03:42 +05305861#ifdef FEATURE_WLAN_BATCH_SCAN
5862 init_completion(&pAdapter->hdd_set_batch_scan_req_var);
5863 init_completion(&pAdapter->hdd_get_batch_scan_req_var);
5864 pAdapter->pBatchScanRsp = NULL;
5865 pAdapter->numScanList = 0;
Rajeev Kumar20140c12013-10-21 19:39:02 -07005866 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
Kiet Lamaa8e15a2014-02-11 23:30:06 -08005867 pAdapter->prev_batch_id = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05305868 mutex_init(&pAdapter->hdd_batch_scan_lock);
5869#endif
5870
Jeff Johnson295189b2012-06-20 16:38:30 -07005871 pAdapter->isLinkUpSvcNeeded = FALSE;
5872 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
5873 //Init the net_device structure
5874 strlcpy(pWlanDev->name, name, IFNAMSIZ);
5875
5876 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
5877 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
5878 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
5879 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
5880
5881 hdd_set_station_ops( pAdapter->dev );
5882
5883 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07005884 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
5885 pAdapter->wdev.wiphy = pHddCtx->wiphy;
5886 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07005887 /* set pWlanDev's parent to underlying device */
5888 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
Kumar Anand82c009f2014-05-29 00:29:42 -07005889
5890 hdd_wmm_init( pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07005891 }
5892
5893 return pAdapter;
5894}
5895
5896VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
5897{
5898 struct net_device *pWlanDev = pAdapter->dev;
5899 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
5900 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
5901 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5902
5903 if( rtnl_lock_held )
5904 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08005905 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07005906 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
5907 {
5908 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
5909 return VOS_STATUS_E_FAILURE;
5910 }
5911 }
5912 if (register_netdevice(pWlanDev))
5913 {
5914 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
5915 return VOS_STATUS_E_FAILURE;
5916 }
5917 }
5918 else
5919 {
5920 if(register_netdev(pWlanDev))
5921 {
5922 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
5923 return VOS_STATUS_E_FAILURE;
5924 }
5925 }
5926 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
5927
5928 return VOS_STATUS_SUCCESS;
5929}
5930
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005931static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07005932{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005933 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07005934
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005935 if (NULL == pAdapter)
5936 {
5937 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
5938 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07005939 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005940
5941 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
5942 {
5943 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
5944 return eHAL_STATUS_NOT_INITIALIZED;
5945 }
5946
5947 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
5948
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005949#ifndef WLAN_OPEN_SOURCE
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005950 /* need to make sure all of our scheduled work has completed.
5951 * This callback is called from MC thread context, so it is safe to
5952 * to call below flush workqueue API from here.
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005953 *
5954 * Even though this is called from MC thread context, if there is a faulty
5955 * work item in the system, that can hang this call forever. So flushing
5956 * this global work queue is not safe; and now we make sure that
5957 * individual work queues are stopped correctly. But the cancel work queue
5958 * is a GPL only API, so the proprietary version of the driver would still
5959 * rely on the global work queue flush.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005960 */
5961 flush_scheduled_work();
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005962#endif
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005963
5964 /* We can be blocked while waiting for scheduled work to be
5965 * flushed, and the adapter structure can potentially be freed, in
5966 * which case the magic will have been reset. So make sure the
5967 * magic is still good, and hence the adapter structure is still
5968 * valid, before signaling completion */
5969 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
5970 {
5971 complete(&pAdapter->session_close_comp_var);
5972 }
5973
Jeff Johnson295189b2012-06-20 16:38:30 -07005974 return eHAL_STATUS_SUCCESS;
5975}
5976
5977VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
5978{
5979 struct net_device *pWlanDev = pAdapter->dev;
5980 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
5981 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
5982 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5983 VOS_STATUS status = VOS_STATUS_E_FAILURE;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305984 long rc = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07005985
5986 INIT_COMPLETION(pAdapter->session_open_comp_var);
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07005987 sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07005988 //Open a SME session for future operation
5989 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07005990 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07005991 if ( !HAL_STATUS_SUCCESS( halStatus ) )
5992 {
5993 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005994 "sme_OpenSession() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005995 halStatus, halStatus );
5996 status = VOS_STATUS_E_FAILURE;
5997 goto error_sme_open;
5998 }
5999
6000 //Block on a completion variable. Can't wait forever though.
Vinay Krishna Eranna0fe2e7c2014-04-09 21:32:08 +05306001 rc = wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07006002 &pAdapter->session_open_comp_var,
6003 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306004 if (rc <= 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07006005 {
6006 hddLog(VOS_TRACE_LEVEL_FATAL,
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306007 "Session is not opened within timeout period code %ld", rc );
Jeff Johnson295189b2012-06-20 16:38:30 -07006008 status = VOS_STATUS_E_FAILURE;
6009 goto error_sme_open;
6010 }
6011
6012 // Register wireless extensions
6013 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
6014 {
6015 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07006016 "hdd_register_wext() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07006017 halStatus, halStatus );
6018 status = VOS_STATUS_E_FAILURE;
6019 goto error_register_wext;
6020 }
6021 //Safe to register the hard_start_xmit function again
6022#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
6023 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
6024#else
6025 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
6026#endif
6027
6028 //Set the Connection State to Not Connected
Abhishek Singhf4669da2014-05-26 15:07:49 +05306029 hddLog(VOS_TRACE_LEVEL_INFO,
6030 "%s: Set HDD connState to eConnectionState_NotConnected",
6031 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006032 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
6033
6034 //Set the default operation channel
6035 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
6036
6037 /* Make the default Auth Type as OPEN*/
6038 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
6039
6040 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
6041 {
6042 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07006043 "hdd_init_tx_rx() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07006044 status, status );
6045 goto error_init_txrx;
6046 }
6047
6048 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
6049
6050 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
6051 {
6052 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07006053 "hdd_wmm_adapter_init() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07006054 status, status );
6055 goto error_wmm_init;
6056 }
6057
6058 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
6059
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006060#ifdef FEATURE_WLAN_TDLS
Agarwal Ashish4b87f922014-06-18 03:03:21 +05306061 if(0 != wlan_hdd_sta_tdls_init(pAdapter))
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006062 {
6063 status = VOS_STATUS_E_FAILURE;
Agarwal Ashish4b87f922014-06-18 03:03:21 +05306064 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_sta_tdls_init failed",__func__);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006065 goto error_tdls_init;
6066 }
6067 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
6068#endif
6069
Jeff Johnson295189b2012-06-20 16:38:30 -07006070 return VOS_STATUS_SUCCESS;
6071
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006072#ifdef FEATURE_WLAN_TDLS
6073error_tdls_init:
6074 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
6075 hdd_wmm_adapter_close(pAdapter);
6076#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006077error_wmm_init:
6078 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
6079 hdd_deinit_tx_rx(pAdapter);
6080error_init_txrx:
6081 hdd_UnregisterWext(pWlanDev);
6082error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07006083 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07006084 {
6085 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07006086 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07006087 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07006088 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07006089 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306090 unsigned long rc;
6091
Jeff Johnson295189b2012-06-20 16:38:30 -07006092 //Block on a completion variable. Can't wait forever though.
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306093 rc = wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07006094 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07006095 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306096 if (rc <= 0)
6097 hddLog(VOS_TRACE_LEVEL_ERROR,
6098 FL("Session is not opened within timeout period code %ld"), rc);
Jeff Johnson295189b2012-06-20 16:38:30 -07006099 }
6100}
6101error_sme_open:
6102 return status;
6103}
6104
Jeff Johnson295189b2012-06-20 16:38:30 -07006105void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
6106{
6107 hdd_cfg80211_state_t *cfgState;
6108
6109 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
6110
6111 if( NULL != cfgState->buf )
6112 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306113 long rc;
Jeff Johnson295189b2012-06-20 16:38:30 -07006114 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
6115 rc = wait_for_completion_interruptible_timeout(
6116 &pAdapter->tx_action_cnf_event,
6117 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306118 if (rc <= 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07006119 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08006120 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306121 "%s ERROR: HDD Wait for Action Confirmation Failed!! %ld"
6122 , __func__, rc);
Jeff Johnson295189b2012-06-20 16:38:30 -07006123 }
6124 }
6125 return;
6126}
Jeff Johnson295189b2012-06-20 16:38:30 -07006127
6128void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
6129{
6130 ENTER();
6131 switch ( pAdapter->device_mode )
6132 {
6133 case WLAN_HDD_INFRA_STATION:
6134 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006135 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07006136 {
6137 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
6138 {
6139 hdd_deinit_tx_rx( pAdapter );
6140 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
6141 }
6142
6143 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
6144 {
6145 hdd_wmm_adapter_close( pAdapter );
6146 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
6147 }
6148
Jeff Johnson295189b2012-06-20 16:38:30 -07006149 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006150#ifdef FEATURE_WLAN_TDLS
6151 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
6152 {
6153 wlan_hdd_tdls_exit(pAdapter);
6154 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
6155 }
6156#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006157
6158 break;
6159 }
6160
6161 case WLAN_HDD_SOFTAP:
6162 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07006163 {
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05306164
6165 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
6166 {
6167 hdd_wmm_adapter_close( pAdapter );
6168 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
6169 }
6170
Jeff Johnson295189b2012-06-20 16:38:30 -07006171 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07006172
6173 hdd_unregister_hostapd(pAdapter);
6174 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07006175 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07006176 break;
6177 }
6178
6179 case WLAN_HDD_MONITOR:
6180 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006181 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07006182 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
6183 {
6184 hdd_deinit_tx_rx( pAdapter );
6185 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
6186 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006187 if(NULL != pAdapterforTx)
6188 {
6189 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
6190 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006191 break;
6192 }
6193
6194
6195 default:
6196 break;
6197 }
6198
6199 EXIT();
6200}
6201
6202void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
6203{
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -08006204 struct net_device *pWlanDev = NULL;
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05306205
6206 ENTER();
6207 if (NULL == pAdapter)
6208 {
6209 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6210 "%s: HDD adapter is Null", __func__);
6211 return;
6212 }
6213
6214 pWlanDev = pAdapter->dev;
Jeff Johnson295189b2012-06-20 16:38:30 -07006215
Rajeev79dbe4c2013-10-05 11:03:42 +05306216#ifdef FEATURE_WLAN_BATCH_SCAN
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05306217 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
6218 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Rajeev Kumarf999e582014-01-09 17:33:29 -08006219 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05306220 || (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)
6221 )
6222 {
Rajeev Kumarf999e582014-01-09 17:33:29 -08006223 if (pAdapter)
Rajeev79dbe4c2013-10-05 11:03:42 +05306224 {
Rajeev Kumarf999e582014-01-09 17:33:29 -08006225 if (eHDD_BATCH_SCAN_STATE_STARTED == pAdapter->batchScanState)
6226 {
6227 hdd_deinit_batch_scan(pAdapter);
6228 }
Rajeev79dbe4c2013-10-05 11:03:42 +05306229 }
Rajeev Kumarf999e582014-01-09 17:33:29 -08006230 }
Rajeev79dbe4c2013-10-05 11:03:42 +05306231#endif
6232
Jeff Johnson295189b2012-06-20 16:38:30 -07006233 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
6234 if( rtnl_held )
6235 {
6236 unregister_netdevice(pWlanDev);
6237 }
6238 else
6239 {
6240 unregister_netdev(pWlanDev);
6241 }
6242 // note that the pAdapter is no longer valid at this point
6243 // since the memory has been reclaimed
6244 }
6245
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05306246 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07006247}
6248
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006249void hdd_set_pwrparams(hdd_context_t *pHddCtx)
6250{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306251 VOS_STATUS status;
6252 hdd_adapter_t *pAdapter = NULL;
6253 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006254
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306255 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006256
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306257 /*loop through all adapters.*/
6258 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006259 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306260 pAdapter = pAdapterNode->pAdapter;
6261 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
6262 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006263
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306264 { // we skip this registration for modes other than STA and P2P client modes.
6265 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6266 pAdapterNode = pNext;
6267 continue;
6268 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006269
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306270 //Apply Dynamic DTIM For P2P
6271 //Only if ignoreDynamicDtimInP2pMode is not set in ini
6272 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
6273 pHddCtx->cfg_ini->enableModulatedDTIM) &&
6274 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
6275 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
6276 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
6277 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
6278 (eConnectionState_Associated ==
6279 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
6280 (pHddCtx->cfg_ini->fIsBmpsEnabled))
6281 {
6282 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006283
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306284 powerRequest.uIgnoreDTIM = 1;
6285 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
6286
6287 if (pHddCtx->cfg_ini->enableModulatedDTIM)
6288 {
6289 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
6290 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
6291 }
6292 else
6293 {
6294 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
6295 }
6296
6297 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
6298 * specified during Enter/Exit BMPS when LCD off*/
6299 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
6300 NULL, eANI_BOOLEAN_FALSE);
6301 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
6302 NULL, eANI_BOOLEAN_FALSE);
6303
6304 /* switch to the DTIM specified in cfg.ini */
6305 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6306 "Switch to DTIM %d", powerRequest.uListenInterval);
6307 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
6308 break;
6309
6310 }
6311
6312 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6313 pAdapterNode = pNext;
6314 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006315}
6316
6317void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
6318{
6319 /*Switch back to DTIM 1*/
6320 tSirSetPowerParamsReq powerRequest = { 0 };
6321
6322 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
6323 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07006324 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006325
6326 /* Update ignoreDTIM and ListedInterval in CFG with default values */
6327 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
6328 NULL, eANI_BOOLEAN_FALSE);
6329 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
6330 NULL, eANI_BOOLEAN_FALSE);
6331
6332 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6333 "Switch to DTIM%d",powerRequest.uListenInterval);
6334 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
6335
6336}
6337
Jeff Johnson295189b2012-06-20 16:38:30 -07006338VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
6339{
6340 VOS_STATUS status = VOS_STATUS_SUCCESS;
6341
6342 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
6343 {
6344 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
6345 }
6346
6347 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
6348 {
6349 sme_StartAutoBmpsTimer(pHddCtx->hHal);
6350 }
6351
6352 if (pHddCtx->cfg_ini->fIsImpsEnabled)
6353 {
6354 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
6355 }
6356
6357 return status;
6358}
6359
6360VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
6361{
6362 hdd_adapter_t *pAdapter = NULL;
6363 eHalStatus halStatus;
6364 VOS_STATUS status = VOS_STATUS_E_INVAL;
6365 v_BOOL_t disableBmps = FALSE;
6366 v_BOOL_t disableImps = FALSE;
6367
6368 switch(session_type)
6369 {
6370 case WLAN_HDD_INFRA_STATION:
6371 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07006372 case WLAN_HDD_P2P_CLIENT:
6373 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07006374 //Exit BMPS -> Is Sta/P2P Client is already connected
6375 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
6376 if((NULL != pAdapter)&&
6377 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
6378 {
6379 disableBmps = TRUE;
6380 }
6381
6382 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
6383 if((NULL != pAdapter)&&
6384 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
6385 {
6386 disableBmps = TRUE;
6387 }
6388
6389 //Exit both Bmps and Imps incase of Go/SAP Mode
6390 if((WLAN_HDD_SOFTAP == session_type) ||
6391 (WLAN_HDD_P2P_GO == session_type))
6392 {
6393 disableBmps = TRUE;
6394 disableImps = TRUE;
6395 }
6396
6397 if(TRUE == disableImps)
6398 {
6399 if (pHddCtx->cfg_ini->fIsImpsEnabled)
6400 {
6401 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
6402 }
6403 }
6404
6405 if(TRUE == disableBmps)
6406 {
6407 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
6408 {
6409 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
6410
6411 if(eHAL_STATUS_SUCCESS != halStatus)
6412 {
6413 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08006414 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006415 VOS_ASSERT(0);
6416 return status;
6417 }
6418 }
6419
6420 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
6421 {
6422 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
6423
6424 if(eHAL_STATUS_SUCCESS != halStatus)
6425 {
6426 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08006427 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006428 VOS_ASSERT(0);
6429 return status;
6430 }
6431 }
6432 }
6433
6434 if((TRUE == disableBmps) ||
6435 (TRUE == disableImps))
6436 {
6437 /* Now, get the chip into Full Power now */
6438 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
6439 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
6440 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
6441
6442 if(halStatus != eHAL_STATUS_SUCCESS)
6443 {
6444 if(halStatus == eHAL_STATUS_PMC_PENDING)
6445 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306446 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07006447 //Block on a completion variable. Can't wait forever though
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306448 ret = wait_for_completion_interruptible_timeout(
6449 &pHddCtx->full_pwr_comp_var,
6450 msecs_to_jiffies(1000));
6451 if (ret <= 0)
6452 {
6453 hddLog(VOS_TRACE_LEVEL_ERROR,
6454 "%s: wait on full_pwr_comp_var failed %ld",
6455 __func__, ret);
6456 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006457 }
6458 else
6459 {
6460 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08006461 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006462 VOS_ASSERT(0);
6463 return status;
6464 }
6465 }
6466
6467 status = VOS_STATUS_SUCCESS;
6468 }
6469
6470 break;
6471 }
6472 return status;
6473}
6474
6475hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08006476 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07006477 tANI_U8 rtnl_held )
6478{
Vinay Krishna Eranna83b0ef72014-11-19 16:56:20 +05306479 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006480 hdd_adapter_t *pAdapter = NULL;
6481 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
6482 VOS_STATUS status = VOS_STATUS_E_FAILURE;
6483 VOS_STATUS exitbmpsStatus;
6484
Arif Hussain6d2a3322013-11-17 19:50:10 -08006485 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d",__func__,iface_name,session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006486
Nirav Shah436658f2014-02-28 17:05:45 +05306487 if(macAddr == NULL)
6488 {
6489 /* Not received valid macAddr */
6490 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6491 "%s:Unable to add virtual intf: Not able to get"
6492 "valid mac address",__func__);
6493 return NULL;
6494 }
6495
Jeff Johnson295189b2012-06-20 16:38:30 -07006496 //Disable BMPS incase of Concurrency
6497 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
6498
6499 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
6500 {
6501 //Fail to Exit BMPS
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306502 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Exit BMPS", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006503 VOS_ASSERT(0);
6504 return NULL;
6505 }
6506
6507 switch(session_type)
6508 {
6509 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07006510 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006511 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07006512 {
6513 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
6514
6515 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306516 {
6517 hddLog(VOS_TRACE_LEVEL_FATAL,
6518 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006519 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306520 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006521
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306522#ifdef FEATURE_WLAN_TDLS
6523 /* A Mutex Lock is introduced while changing/initializing the mode to
6524 * protect the concurrent access for the Adapters by TDLS module.
6525 */
Rajesh Chauhana34c6e62014-03-25 16:37:58 +05306526 mutex_lock(&pHddCtx->tdls_lock);
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306527#endif
6528
Jeff Johnsone7245742012-09-05 17:12:55 -07006529 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
6530 NL80211_IFTYPE_P2P_CLIENT:
6531 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07006532
Jeff Johnson295189b2012-06-20 16:38:30 -07006533 pAdapter->device_mode = session_type;
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306534#ifdef FEATURE_WLAN_TDLS
6535 mutex_unlock(&pHddCtx->tdls_lock);
6536#endif
Sunil Dutt66485cb2013-12-19 19:05:03 +05306537
6538 status = hdd_init_station_mode( pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07006539 if( VOS_STATUS_SUCCESS != status )
6540 goto err_free_netdev;
6541
6542 status = hdd_register_interface( pAdapter, rtnl_held );
6543 if( VOS_STATUS_SUCCESS != status )
6544 {
6545 hdd_deinit_adapter(pHddCtx, pAdapter);
6546 goto err_free_netdev;
6547 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306548
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05306549 // Workqueue which gets scheduled in IPv4 notification callback.
6550 INIT_WORK(&pAdapter->ipv4NotifierWorkQueue, hdd_ipv4_notifier_work_queue);
Vinay Krishna Eranna83b0ef72014-11-19 16:56:20 +05306551 // Register IPv4 notifier to notify if any change in IP
6552 // So that we can reconfigure the offload parameters
6553 pAdapter->ipv4_notifier.notifier_call = wlan_hdd_ipv4_changed;
6554 ret = register_inetaddr_notifier(&pAdapter->ipv4_notifier);
6555 if (ret)
6556 {
6557 hddLog(LOGE, FL("Failed to register IPv4 notifier"));
6558 }
6559 else
6560 {
6561 hddLog(LOG1, FL("Registered IPv4 notifier"));
6562 pAdapter->ipv4_notifier_registered = true;
6563 }
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05306564
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306565#ifdef WLAN_NS_OFFLOAD
6566 // Workqueue which gets scheduled in IPv6 notification callback.
6567 INIT_WORK(&pAdapter->ipv6NotifierWorkQueue, hdd_ipv6_notifier_work_queue);
Vinay Krishna Eranna83b0ef72014-11-19 16:56:20 +05306568 // Register IPv6 notifier to notify if any change in IP
6569 // So that we can reconfigure the offload parameters
6570 pAdapter->ipv6_notifier.notifier_call = wlan_hdd_ipv6_changed;
6571 ret = register_inet6addr_notifier(&pAdapter->ipv6_notifier);
6572 if (ret)
6573 {
6574 hddLog(LOGE, FL("Failed to register IPv6 notifier"));
6575 }
6576 else
6577 {
6578 hddLog(LOG1, FL("Registered IPv6 notifier"));
6579 pAdapter->ipv6_notifier_registered = true;
6580 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306581#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006582 //Stop the Interface TX queue.
6583 netif_tx_disable(pAdapter->dev);
6584 //netif_tx_disable(pWlanDev);
6585 netif_carrier_off(pAdapter->dev);
6586
6587 break;
6588 }
6589
Jeff Johnson295189b2012-06-20 16:38:30 -07006590 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07006591 case WLAN_HDD_SOFTAP:
6592 {
6593 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
6594 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306595 {
6596 hddLog(VOS_TRACE_LEVEL_FATAL,
6597 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006598 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306599 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006600
Jeff Johnson295189b2012-06-20 16:38:30 -07006601 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
6602 NL80211_IFTYPE_AP:
6603 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07006604 pAdapter->device_mode = session_type;
6605
6606 status = hdd_init_ap_mode(pAdapter);
6607 if( VOS_STATUS_SUCCESS != status )
6608 goto err_free_netdev;
6609
6610 status = hdd_register_hostapd( pAdapter, rtnl_held );
6611 if( VOS_STATUS_SUCCESS != status )
6612 {
6613 hdd_deinit_adapter(pHddCtx, pAdapter);
6614 goto err_free_netdev;
6615 }
6616
6617 netif_tx_disable(pAdapter->dev);
6618 netif_carrier_off(pAdapter->dev);
6619
6620 hdd_set_conparam( 1 );
6621 break;
6622 }
6623 case WLAN_HDD_MONITOR:
6624 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006625 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
6626 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306627 {
6628 hddLog(VOS_TRACE_LEVEL_FATAL,
6629 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006630 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306631 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006632
6633 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
6634 pAdapter->device_mode = session_type;
6635 status = hdd_register_interface( pAdapter, rtnl_held );
6636#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
6637 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
6638#else
6639 pAdapter->dev->open = hdd_mon_open;
6640 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
6641#endif
6642 hdd_init_tx_rx( pAdapter );
6643 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
6644 //Set adapter to be used for data tx. It will use either GO or softap.
6645 pAdapter->sessionCtx.monitor.pAdapterForTx =
6646 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07006647 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
6648 {
6649 pAdapter->sessionCtx.monitor.pAdapterForTx =
6650 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
6651 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006652 /* This workqueue will be used to transmit management packet over
6653 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07006654 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
6655 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
6656 return NULL;
6657 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07006658
Jeff Johnson295189b2012-06-20 16:38:30 -07006659 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
6660 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07006661 }
6662 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07006663 case WLAN_HDD_FTM:
6664 {
6665 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
6666
6667 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306668 {
6669 hddLog(VOS_TRACE_LEVEL_FATAL,
6670 FL("failed to allocate adapter for session %d"), session_type);
6671 return NULL;
6672 }
6673
Jeff Johnson295189b2012-06-20 16:38:30 -07006674 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
6675 * message while loading driver in FTM mode. */
6676 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
6677 pAdapter->device_mode = session_type;
6678 status = hdd_register_interface( pAdapter, rtnl_held );
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05306679
6680 hdd_init_tx_rx( pAdapter );
6681
6682 //Stop the Interface TX queue.
6683 netif_tx_disable(pAdapter->dev);
6684 netif_carrier_off(pAdapter->dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07006685 }
6686 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07006687 default:
6688 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306689 hddLog(VOS_TRACE_LEVEL_FATAL,"%s Invalid session type %d",
6690 __func__, session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006691 VOS_ASSERT(0);
6692 return NULL;
6693 }
6694 }
6695
Jeff Johnson295189b2012-06-20 16:38:30 -07006696 if( VOS_STATUS_SUCCESS == status )
6697 {
6698 //Add it to the hdd's session list.
6699 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
6700 if( NULL == pHddAdapterNode )
6701 {
6702 status = VOS_STATUS_E_NOMEM;
6703 }
6704 else
6705 {
6706 pHddAdapterNode->pAdapter = pAdapter;
6707 status = hdd_add_adapter_back ( pHddCtx,
6708 pHddAdapterNode );
6709 }
6710 }
6711
6712 if( VOS_STATUS_SUCCESS != status )
6713 {
6714 if( NULL != pAdapter )
6715 {
6716 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
6717 pAdapter = NULL;
6718 }
6719 if( NULL != pHddAdapterNode )
6720 {
6721 vos_mem_free( pHddAdapterNode );
6722 }
6723
6724 goto resume_bmps;
6725 }
6726
6727 if(VOS_STATUS_SUCCESS == status)
6728 {
6729 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
6730
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07006731 //Initialize the WoWL service
6732 if(!hdd_init_wowl(pAdapter))
6733 {
6734 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
6735 goto err_free_netdev;
6736 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006737 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006738 return pAdapter;
6739
6740err_free_netdev:
6741 free_netdev(pAdapter->dev);
6742 wlan_hdd_release_intf_addr( pHddCtx,
6743 pAdapter->macAddressCurrent.bytes );
6744
6745resume_bmps:
6746 //If bmps disabled enable it
6747 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
6748 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306749 if (pHddCtx->hdd_wlan_suspended)
6750 {
6751 hdd_set_pwrparams(pHddCtx);
6752 }
6753 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07006754 }
6755 return NULL;
6756}
6757
6758VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
6759 tANI_U8 rtnl_held )
6760{
6761 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
6762 VOS_STATUS status;
6763
6764 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
6765 if( VOS_STATUS_SUCCESS != status )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306766 {
6767 hddLog(VOS_TRACE_LEVEL_WARN,"%s: adapter list empty %d",
6768 __func__, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07006769 return status;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306770 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006771
6772 while ( pCurrent->pAdapter != pAdapter )
6773 {
6774 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
6775 if( VOS_STATUS_SUCCESS != status )
6776 break;
6777
6778 pCurrent = pNext;
6779 }
6780 pAdapterNode = pCurrent;
6781 if( VOS_STATUS_SUCCESS == status )
6782 {
6783 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
6784 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306785
6786#ifdef FEATURE_WLAN_TDLS
6787
6788 /* A Mutex Lock is introduced while changing/initializing the mode to
6789 * protect the concurrent access for the Adapters by TDLS module.
6790 */
Rajesh Chauhana34c6e62014-03-25 16:37:58 +05306791 mutex_lock(&pHddCtx->tdls_lock);
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306792#endif
6793
Jeff Johnson295189b2012-06-20 16:38:30 -07006794 hdd_remove_adapter( pHddCtx, pAdapterNode );
6795 vos_mem_free( pAdapterNode );
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08006796 pAdapterNode = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006797
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306798#ifdef FEATURE_WLAN_TDLS
6799 mutex_unlock(&pHddCtx->tdls_lock);
6800#endif
6801
Jeff Johnson295189b2012-06-20 16:38:30 -07006802
6803 /* If there is a single session of STA/P2P client, re-enable BMPS */
Agarwal Ashish51325b52014-06-16 16:50:49 +05306804 if ((!vos_concurrent_open_sessions_running()) &&
6805 ((pHddCtx->no_of_open_sessions[VOS_STA_MODE] >= 1) ||
6806 (pHddCtx->no_of_open_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
Jeff Johnson295189b2012-06-20 16:38:30 -07006807 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306808 if (pHddCtx->hdd_wlan_suspended)
6809 {
6810 hdd_set_pwrparams(pHddCtx);
6811 }
6812 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07006813 }
6814
6815 return VOS_STATUS_SUCCESS;
6816 }
6817
6818 return VOS_STATUS_E_FAILURE;
6819}
6820
6821VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
6822{
6823 hdd_adapter_list_node_t *pHddAdapterNode;
6824 VOS_STATUS status;
6825
6826 ENTER();
6827
6828 do
6829 {
6830 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
6831 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
6832 {
6833 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
6834 vos_mem_free( pHddAdapterNode );
6835 }
6836 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
6837
6838 EXIT();
6839
6840 return VOS_STATUS_SUCCESS;
6841}
6842
6843void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
6844{
6845 v_U8_t addIE[1] = {0};
6846
6847 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6848 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
6849 eANI_BOOLEAN_FALSE) )
6850 {
6851 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006852 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006853 }
6854
6855 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6856 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
6857 eANI_BOOLEAN_FALSE) )
6858 {
6859 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006860 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006861 }
6862
6863 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6864 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
6865 eANI_BOOLEAN_FALSE) )
6866 {
6867 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006868 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006869 }
6870}
6871
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05306872VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
6873 const v_BOOL_t bCloseSession )
Jeff Johnson295189b2012-06-20 16:38:30 -07006874{
6875 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
6876 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
Kaushik, Sushant4975a572014-10-21 16:07:48 +05306877 hdd_scaninfo_t *pScanInfo = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006878 union iwreq_data wrqu;
Kaushik, Sushant7005e372014-04-08 11:36:54 +05306879 v_U8_t retry = 0;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306880 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07006881
6882 ENTER();
Kaushik, Sushant4975a572014-10-21 16:07:48 +05306883 pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07006884 switch(pAdapter->device_mode)
6885 {
6886 case WLAN_HDD_INFRA_STATION:
6887 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006888 case WLAN_HDD_P2P_DEVICE:
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05306889 {
6890 hdd_station_ctx_t *pstation = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6891 if( hdd_connIsConnected(pstation) ||
6892 (pstation->conn_info.connState == eConnectionState_Connecting) )
Jeff Johnson295189b2012-06-20 16:38:30 -07006893 {
6894 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
6895 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
6896 pAdapter->sessionId,
6897 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
6898 else
6899 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
6900 pAdapter->sessionId,
6901 eCSR_DISCONNECT_REASON_UNSPECIFIED);
6902 //success implies disconnect command got queued up successfully
6903 if(halStatus == eHAL_STATUS_SUCCESS)
6904 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306905 ret = wait_for_completion_interruptible_timeout(
6906 &pAdapter->disconnect_comp_var,
6907 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6908 if (ret <= 0)
6909 {
6910 hddLog(VOS_TRACE_LEVEL_ERROR,
6911 "%s: wait on disconnect_comp_var failed %ld",
6912 __func__, ret);
6913 }
6914 }
6915 else
6916 {
6917 hddLog(LOGE, "%s: failed to post disconnect event to SME",
6918 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006919 }
6920 memset(&wrqu, '\0', sizeof(wrqu));
6921 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
6922 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
6923 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
6924 }
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05306925 else if(pstation->conn_info.connState ==
6926 eConnectionState_Disconnecting)
6927 {
6928 ret = wait_for_completion_interruptible_timeout(
6929 &pAdapter->disconnect_comp_var,
6930 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6931 if (ret <= 0)
6932 {
6933 hddLog(VOS_TRACE_LEVEL_ERROR,
6934 FL("wait on disconnect_comp_var failed %ld"), ret);
6935 }
6936 }
Kaushik, Sushant4975a572014-10-21 16:07:48 +05306937 else if(pScanInfo != NULL && pHddCtx->scan_info.mScanPending)
Jeff Johnson295189b2012-06-20 16:38:30 -07006938 {
Kaushik, Sushant4975a572014-10-21 16:07:48 +05306939 hdd_abort_mac_scan(pHddCtx, pScanInfo->sessionId,
Srinivas, Dasari138af4f2014-02-07 11:13:45 +05306940 eCSR_SCAN_ABORT_DEFAULT);
Jeff Johnson295189b2012-06-20 16:38:30 -07006941 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +05306942 if (pAdapter->device_mode != WLAN_HDD_INFRA_STATION)
6943 {
6944 while (pAdapter->is_roc_inprogress)
6945 {
6946 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6947 "%s: ROC in progress for session %d!!!",
6948 __func__, pAdapter->sessionId);
6949 // waiting for ROC to expire
6950 msleep(500);
6951 /* In GO present case , if retry exceeds 3,
6952 it means something went wrong. */
6953 if ( retry++ > MAX_WAIT_FOR_ROC_COMPLETION )
6954 {
6955 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6956 "%s: ROC completion is not received.!!!", __func__);
6957 sme_CancelRemainOnChannel(WLAN_HDD_GET_HAL_CTX(pAdapter),
6958 pAdapter->sessionId);
6959 wait_for_completion_interruptible_timeout(
6960 &pAdapter->cancel_rem_on_chan_var,
6961 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
6962 break;
6963 }
6964 }
6965 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306966#ifdef WLAN_NS_OFFLOAD
Vinay Krishna Eranna941360f2014-01-16 15:38:22 +05306967#ifdef WLAN_OPEN_SOURCE
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306968 cancel_work_sync(&pAdapter->ipv6NotifierWorkQueue);
6969#endif
Vinay Krishna Eranna941360f2014-01-16 15:38:22 +05306970 if (pAdapter->ipv6_notifier_registered)
6971 {
6972 hddLog(LOG1, FL("Unregistered IPv6 notifier"));
6973 unregister_inet6addr_notifier(&pAdapter->ipv6_notifier);
6974 pAdapter->ipv6_notifier_registered = false;
6975 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306976#endif
Vinay Krishna Erannad9cbdb32014-01-16 12:59:10 +05306977 if (pAdapter->ipv4_notifier_registered)
6978 {
6979 hddLog(LOG1, FL("Unregistered IPv4 notifier"));
6980 unregister_inetaddr_notifier(&pAdapter->ipv4_notifier);
6981 pAdapter->ipv4_notifier_registered = false;
6982 }
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05306983#ifdef WLAN_OPEN_SOURCE
6984 cancel_work_sync(&pAdapter->ipv4NotifierWorkQueue);
6985#endif
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05306986 /* It is possible that the caller of this function does not
6987 * wish to close the session
6988 */
6989 if (VOS_TRUE == bCloseSession &&
6990 test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07006991 {
6992 INIT_COMPLETION(pAdapter->session_close_comp_var);
6993 if (eHAL_STATUS_SUCCESS ==
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05306994 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
6995 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07006996 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306997 unsigned long ret;
6998
Jeff Johnson295189b2012-06-20 16:38:30 -07006999 //Block on a completion variable. Can't wait forever though.
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307000 ret = wait_for_completion_timeout(
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307001 &pAdapter->session_close_comp_var,
7002 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307003 if ( 0 >= ret)
7004 {
7005 hddLog(LOGE, "%s: failure waiting for session_close_comp_var %ld",
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307006 __func__, ret);
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307007 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007008 }
7009 }
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05307010 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007011 break;
7012
7013 case WLAN_HDD_SOFTAP:
7014 case WLAN_HDD_P2P_GO:
7015 //Any softap specific cleanup here...
Kaushik, Sushant7005e372014-04-08 11:36:54 +05307016 if (pAdapter->device_mode == WLAN_HDD_P2P_GO) {
7017 while (pAdapter->is_roc_inprogress) {
7018 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7019 "%s: ROC in progress for session %d!!!",
7020 __func__, pAdapter->sessionId);
7021 msleep(500);
7022 if ( retry++ > MAX_WAIT_FOR_ROC_COMPLETION ) {
7023 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7024 "%s: ROC completion is not received.!!!", __func__);
7025 WLANSAP_CancelRemainOnChannel(
7026 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
7027 wait_for_completion_interruptible_timeout(
7028 &pAdapter->cancel_rem_on_chan_var,
7029 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
7030 break;
7031 }
7032 }
7033 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007034 mutex_lock(&pHddCtx->sap_lock);
7035 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
7036 {
7037 VOS_STATUS status;
7038 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7039
7040 //Stop Bss.
7041 status = WLANSAP_StopBss(pHddCtx->pvosContext);
7042 if (VOS_IS_STATUS_SUCCESS(status))
7043 {
7044 hdd_hostapd_state_t *pHostapdState =
7045 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
7046
7047 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
7048
7049 if (!VOS_IS_STATUS_SUCCESS(status))
7050 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307051 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss %d",
7052 __func__, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07007053 }
7054 }
7055 else
7056 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007057 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007058 }
7059 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
Agarwal Ashish51325b52014-06-16 16:50:49 +05307060 wlan_hdd_decr_active_session(pHddCtx, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07007061
7062 if (eHAL_STATUS_FAILURE ==
7063 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
7064 0, NULL, eANI_BOOLEAN_FALSE))
7065 {
7066 hddLog(LOGE,
7067 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007068 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007069 }
7070
7071 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
7072 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
7073 eANI_BOOLEAN_FALSE) )
7074 {
7075 hddLog(LOGE,
7076 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
7077 }
7078
7079 // Reset WNI_CFG_PROBE_RSP Flags
7080 wlan_hdd_reset_prob_rspies(pAdapter);
7081 kfree(pAdapter->sessionCtx.ap.beacon);
7082 pAdapter->sessionCtx.ap.beacon = NULL;
7083 }
7084 mutex_unlock(&pHddCtx->sap_lock);
7085 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07007086
Jeff Johnson295189b2012-06-20 16:38:30 -07007087 case WLAN_HDD_MONITOR:
Sameer Thalappilbee426e2013-10-30 10:30:30 -07007088#ifdef WLAN_OPEN_SOURCE
7089 cancel_work_sync(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue);
7090#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007091 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07007092
Jeff Johnson295189b2012-06-20 16:38:30 -07007093 default:
7094 break;
7095 }
7096
7097 EXIT();
7098 return VOS_STATUS_SUCCESS;
7099}
7100
7101VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
7102{
7103 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7104 VOS_STATUS status;
7105 hdd_adapter_t *pAdapter;
7106
7107 ENTER();
7108
7109 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7110
7111 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7112 {
7113 pAdapter = pAdapterNode->pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07007114
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307115 hdd_stop_adapter( pHddCtx, pAdapter, VOS_TRUE );
Jeff Johnson295189b2012-06-20 16:38:30 -07007116
7117 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7118 pAdapterNode = pNext;
7119 }
7120
7121 EXIT();
7122
7123 return VOS_STATUS_SUCCESS;
7124}
7125
Rajeev Kumarf999e582014-01-09 17:33:29 -08007126
7127#ifdef FEATURE_WLAN_BATCH_SCAN
7128/**---------------------------------------------------------------------------
7129
7130 \brief hdd_deinit_batch_scan () - This function cleans up batch scan data
7131 structures
7132
7133 \param - pAdapter Pointer to HDD adapter
7134
7135 \return - None
7136
7137 --------------------------------------------------------------------------*/
7138void hdd_deinit_batch_scan(hdd_adapter_t *pAdapter)
7139{
7140 tHddBatchScanRsp *pNode;
7141 tHddBatchScanRsp *pPrev;
7142
Siddharth Bhalb3e9b792014-02-24 15:14:16 +05307143 if (NULL == pAdapter)
Rajeev Kumarf999e582014-01-09 17:33:29 -08007144 {
Siddharth Bhalb3e9b792014-02-24 15:14:16 +05307145 hddLog(VOS_TRACE_LEVEL_ERROR,
7146 "%s: Adapter context is Null", __func__);
7147 return;
7148 }
7149
7150 pNode = pAdapter->pBatchScanRsp;
7151 while (pNode)
7152 {
7153 pPrev = pNode;
7154 pNode = pNode->pNext;
7155 vos_mem_free((v_VOID_t * )pPrev);
Rajeev Kumarf999e582014-01-09 17:33:29 -08007156 }
7157
7158 pAdapter->pBatchScanRsp = NULL;
7159 pAdapter->numScanList = 0;
7160 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
7161 pAdapter->prev_batch_id = 0;
7162
7163 return;
7164}
7165#endif
7166
7167
Jeff Johnson295189b2012-06-20 16:38:30 -07007168VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
7169{
7170 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7171 VOS_STATUS status;
7172 hdd_adapter_t *pAdapter;
7173
7174 ENTER();
7175
7176 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7177
7178 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7179 {
7180 pAdapter = pAdapterNode->pAdapter;
7181 netif_tx_disable(pAdapter->dev);
7182 netif_carrier_off(pAdapter->dev);
7183
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07007184 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
7185
Jeff Johnson295189b2012-06-20 16:38:30 -07007186 hdd_deinit_tx_rx(pAdapter);
Agarwal Ashish6267caa2014-08-06 19:16:21 +05307187
7188 wlan_hdd_decr_active_session(pHddCtx, pAdapter->device_mode);
7189
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05307190 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
7191 {
7192 hdd_wmm_adapter_close( pAdapter );
7193 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
7194 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007195
Rajeev Kumarf999e582014-01-09 17:33:29 -08007196#ifdef FEATURE_WLAN_BATCH_SCAN
7197 if (eHDD_BATCH_SCAN_STATE_STARTED == pAdapter->batchScanState)
7198 {
7199 hdd_deinit_batch_scan(pAdapter);
7200 }
7201#endif
7202
Jeff Johnson295189b2012-06-20 16:38:30 -07007203 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7204 pAdapterNode = pNext;
7205 }
7206
7207 EXIT();
7208
7209 return VOS_STATUS_SUCCESS;
7210}
7211
7212VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
7213{
7214 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7215 VOS_STATUS status;
7216 hdd_adapter_t *pAdapter;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05307217 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -07007218
7219 ENTER();
7220
7221 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7222
7223 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7224 {
7225 pAdapter = pAdapterNode->pAdapter;
7226
Kumar Anand82c009f2014-05-29 00:29:42 -07007227 hdd_wmm_init( pAdapter );
7228
Jeff Johnson295189b2012-06-20 16:38:30 -07007229 switch(pAdapter->device_mode)
7230 {
7231 case WLAN_HDD_INFRA_STATION:
7232 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07007233 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05307234
7235 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
7236
Jeff Johnson295189b2012-06-20 16:38:30 -07007237 hdd_init_station_mode(pAdapter);
7238 /* Open the gates for HDD to receive Wext commands */
7239 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07007240 pHddCtx->scan_info.mScanPending = FALSE;
7241 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07007242
7243 //Trigger the initial scan
7244 hdd_wlan_initial_scan(pAdapter);
7245
7246 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05307247 if (eConnectionState_Associated == connState ||
7248 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -07007249 {
7250 union iwreq_data wrqu;
7251 memset(&wrqu, '\0', sizeof(wrqu));
7252 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
7253 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
7254 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07007255 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07007256
Jeff Johnson295189b2012-06-20 16:38:30 -07007257 /* indicate disconnected event to nl80211 */
7258 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
7259 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07007260 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05307261 else if (eConnectionState_Connecting == connState)
7262 {
7263 /*
7264 * Indicate connect failure to supplicant if we were in the
7265 * process of connecting
7266 */
7267 cfg80211_connect_result(pAdapter->dev, NULL,
7268 NULL, 0, NULL, 0,
7269 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
7270 GFP_KERNEL);
7271 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007272 break;
7273
7274 case WLAN_HDD_SOFTAP:
7275 /* softAP can handle SSR */
7276 break;
7277
7278 case WLAN_HDD_P2P_GO:
Sameer Thalappiledf0d792013-08-09 14:31:03 -07007279 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send stop ap to supplicant",
Jeff Johnson295189b2012-06-20 16:38:30 -07007280 __func__);
Sameer Thalappiledf0d792013-08-09 14:31:03 -07007281 cfg80211_ap_stopped(pAdapter->dev, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07007282 break;
7283
7284 case WLAN_HDD_MONITOR:
7285 /* monitor interface start */
7286 break;
7287 default:
7288 break;
7289 }
7290
7291 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7292 pAdapterNode = pNext;
7293 }
7294
7295 EXIT();
7296
7297 return VOS_STATUS_SUCCESS;
7298}
7299
7300VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
7301{
7302 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7303 hdd_adapter_t *pAdapter;
7304 VOS_STATUS status;
7305 v_U32_t roamId;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307306 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07007307
7308 ENTER();
7309
7310 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7311
7312 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7313 {
7314 pAdapter = pAdapterNode->pAdapter;
7315
7316 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
7317 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
7318 {
7319 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7320 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
7321
Abhishek Singhf4669da2014-05-26 15:07:49 +05307322 hddLog(VOS_TRACE_LEVEL_INFO,
7323 "%s: Set HDD connState to eConnectionState_NotConnected",
7324 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007325 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
7326 init_completion(&pAdapter->disconnect_comp_var);
7327 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
7328 eCSR_DISCONNECT_REASON_UNSPECIFIED);
7329
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307330 ret = wait_for_completion_interruptible_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07007331 &pAdapter->disconnect_comp_var,
7332 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307333 if (0 >= ret)
7334 hddLog(LOGE, "%s: failure waiting for disconnect_comp_var %ld",
7335 __func__, ret);
Jeff Johnson295189b2012-06-20 16:38:30 -07007336
7337 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
7338 pHddCtx->isAmpAllowed = VOS_FALSE;
7339 sme_RoamConnect(pHddCtx->hHal,
7340 pAdapter->sessionId, &(pWextState->roamProfile),
7341 &roamId);
7342 }
7343
7344 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7345 pAdapterNode = pNext;
7346 }
7347
7348 EXIT();
7349
7350 return VOS_STATUS_SUCCESS;
7351}
7352
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07007353void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
7354{
7355 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7356 VOS_STATUS status;
7357 hdd_adapter_t *pAdapter;
7358 hdd_station_ctx_t *pHddStaCtx;
7359 hdd_ap_ctx_t *pHddApCtx;
7360 hdd_hostapd_state_t * pHostapdState;
7361 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
7362 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
7363 const char *p2pMode = "DEV";
7364 const char *ccMode = "Standalone";
7365 int n;
7366
7367 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7368 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7369 {
7370 pAdapter = pAdapterNode->pAdapter;
7371 switch (pAdapter->device_mode) {
7372 case WLAN_HDD_INFRA_STATION:
7373 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7374 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
7375 staChannel = pHddStaCtx->conn_info.operationChannel;
7376 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
7377 }
7378 break;
7379 case WLAN_HDD_P2P_CLIENT:
7380 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7381 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
7382 p2pChannel = pHddStaCtx->conn_info.operationChannel;
7383 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
7384 p2pMode = "CLI";
7385 }
7386 break;
7387 case WLAN_HDD_P2P_GO:
7388 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
7389 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
7390 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
7391 p2pChannel = pHddApCtx->operatingChannel;
7392 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
7393 }
7394 p2pMode = "GO";
7395 break;
7396 case WLAN_HDD_SOFTAP:
7397 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
7398 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
7399 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
7400 apChannel = pHddApCtx->operatingChannel;
7401 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
7402 }
7403 break;
7404 default:
7405 break;
7406 }
7407 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7408 pAdapterNode = pNext;
7409 }
7410 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
7411 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
7412 }
7413 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
7414 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
7415 if (p2pChannel > 0) {
7416 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
7417 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
7418 }
7419 if (apChannel > 0) {
7420 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
7421 apChannel, MAC_ADDR_ARRAY(apBssid));
7422 }
7423
7424 if (p2pChannel > 0 && apChannel > 0) {
7425 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
7426 }
7427}
7428
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07007429bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07007430{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07007431 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07007432}
7433
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07007434/* Once SSR is disabled then it cannot be set. */
7435void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07007436{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07007437 if (HDD_SSR_DISABLED == isSsrRequired)
7438 return;
7439
Jeff Johnson295189b2012-06-20 16:38:30 -07007440 isSsrRequired = value;
7441}
7442
7443VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
7444 hdd_adapter_list_node_t** ppAdapterNode)
7445{
7446 VOS_STATUS status;
7447 spin_lock(&pHddCtx->hddAdapters.lock);
7448 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
7449 (hdd_list_node_t**) ppAdapterNode );
7450 spin_unlock(&pHddCtx->hddAdapters.lock);
7451 return status;
7452}
7453
7454VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
7455 hdd_adapter_list_node_t* pAdapterNode,
7456 hdd_adapter_list_node_t** pNextAdapterNode)
7457{
7458 VOS_STATUS status;
7459 spin_lock(&pHddCtx->hddAdapters.lock);
7460 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
7461 (hdd_list_node_t*) pAdapterNode,
7462 (hdd_list_node_t**)pNextAdapterNode );
7463
7464 spin_unlock(&pHddCtx->hddAdapters.lock);
7465 return status;
7466}
7467
7468VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
7469 hdd_adapter_list_node_t* pAdapterNode)
7470{
7471 VOS_STATUS status;
7472 spin_lock(&pHddCtx->hddAdapters.lock);
7473 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
7474 &pAdapterNode->node );
7475 spin_unlock(&pHddCtx->hddAdapters.lock);
7476 return status;
7477}
7478
7479VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
7480 hdd_adapter_list_node_t** ppAdapterNode)
7481{
7482 VOS_STATUS status;
7483 spin_lock(&pHddCtx->hddAdapters.lock);
7484 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
7485 (hdd_list_node_t**) ppAdapterNode );
7486 spin_unlock(&pHddCtx->hddAdapters.lock);
7487 return status;
7488}
7489
7490VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
7491 hdd_adapter_list_node_t* pAdapterNode)
7492{
7493 VOS_STATUS status;
7494 spin_lock(&pHddCtx->hddAdapters.lock);
7495 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
7496 (hdd_list_node_t*) pAdapterNode );
7497 spin_unlock(&pHddCtx->hddAdapters.lock);
7498 return status;
7499}
7500
7501VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
7502 hdd_adapter_list_node_t* pAdapterNode)
7503{
7504 VOS_STATUS status;
7505 spin_lock(&pHddCtx->hddAdapters.lock);
7506 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
7507 (hdd_list_node_t*) pAdapterNode );
7508 spin_unlock(&pHddCtx->hddAdapters.lock);
7509 return status;
7510}
7511
7512hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
7513 tSirMacAddr macAddr )
7514{
7515 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7516 hdd_adapter_t *pAdapter;
7517 VOS_STATUS status;
7518
7519 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7520
7521 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7522 {
7523 pAdapter = pAdapterNode->pAdapter;
7524
7525 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
7526 macAddr, sizeof(tSirMacAddr) ) )
7527 {
7528 return pAdapter;
7529 }
7530 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7531 pAdapterNode = pNext;
7532 }
7533
7534 return NULL;
7535
7536}
7537
7538hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
7539{
7540 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7541 hdd_adapter_t *pAdapter;
7542 VOS_STATUS status;
7543
7544 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7545
7546 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7547 {
7548 pAdapter = pAdapterNode->pAdapter;
7549
7550 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
7551 IFNAMSIZ ) )
7552 {
7553 return pAdapter;
7554 }
7555 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7556 pAdapterNode = pNext;
7557 }
7558
7559 return NULL;
7560
7561}
7562
7563hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
7564{
7565 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7566 hdd_adapter_t *pAdapter;
7567 VOS_STATUS status;
7568
7569 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7570
7571 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7572 {
7573 pAdapter = pAdapterNode->pAdapter;
7574
7575 if( pAdapter && (mode == pAdapter->device_mode) )
7576 {
7577 return pAdapter;
7578 }
7579 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7580 pAdapterNode = pNext;
7581 }
7582
7583 return NULL;
7584
7585}
7586
7587//Remove this function later
7588hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
7589{
7590 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7591 hdd_adapter_t *pAdapter;
7592 VOS_STATUS status;
7593
7594 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7595
7596 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7597 {
7598 pAdapter = pAdapterNode->pAdapter;
7599
7600 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
7601 {
7602 return pAdapter;
7603 }
7604
7605 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7606 pAdapterNode = pNext;
7607 }
7608
7609 return NULL;
7610
7611}
7612
Jeff Johnson295189b2012-06-20 16:38:30 -07007613/**---------------------------------------------------------------------------
7614
7615 \brief hdd_set_monitor_tx_adapter() -
7616
7617 This API initializes the adapter to be used while transmitting on monitor
7618 adapter.
7619
7620 \param - pHddCtx - Pointer to the HDD context.
7621 pAdapter - Adapter that will used for TX. This can be NULL.
7622 \return - None.
7623 --------------------------------------------------------------------------*/
7624void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
7625{
7626 hdd_adapter_t *pMonAdapter;
7627
7628 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
7629
7630 if( NULL != pMonAdapter )
7631 {
7632 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
7633 }
7634}
Jeff Johnson295189b2012-06-20 16:38:30 -07007635/**---------------------------------------------------------------------------
7636
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307637 \brief hdd_get_operating_channel() -
Jeff Johnson295189b2012-06-20 16:38:30 -07007638
7639 This API returns the operating channel of the requested device mode
7640
7641 \param - pHddCtx - Pointer to the HDD context.
7642 - mode - Device mode for which operating channel is required
7643 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
7644 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
7645 \return - channel number. "0" id the requested device is not found OR it is not connected.
7646 --------------------------------------------------------------------------*/
7647v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
7648{
7649 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7650 VOS_STATUS status;
7651 hdd_adapter_t *pAdapter;
7652 v_U8_t operatingChannel = 0;
7653
7654 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7655
7656 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7657 {
7658 pAdapter = pAdapterNode->pAdapter;
7659
7660 if( mode == pAdapter->device_mode )
7661 {
7662 switch(pAdapter->device_mode)
7663 {
7664 case WLAN_HDD_INFRA_STATION:
7665 case WLAN_HDD_P2P_CLIENT:
7666 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
7667 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
7668 break;
7669 case WLAN_HDD_SOFTAP:
7670 case WLAN_HDD_P2P_GO:
7671 /*softap connection info */
7672 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
7673 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
7674 break;
7675 default:
7676 break;
7677 }
7678
7679 break; //Found the device of interest. break the loop
7680 }
7681
7682 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7683 pAdapterNode = pNext;
7684 }
7685 return operatingChannel;
7686}
7687
7688#ifdef WLAN_FEATURE_PACKET_FILTERING
7689/**---------------------------------------------------------------------------
7690
7691 \brief hdd_set_multicast_list() -
7692
7693 This used to set the multicast address list.
7694
7695 \param - dev - Pointer to the WLAN device.
7696 - skb - Pointer to OS packet (sk_buff).
7697 \return - success/fail
7698
7699 --------------------------------------------------------------------------*/
7700static void hdd_set_multicast_list(struct net_device *dev)
7701{
7702 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07007703 int mc_count;
7704 int i = 0;
7705 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307706
7707 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07007708 {
7709 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307710 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007711 return;
7712 }
7713
7714 if (dev->flags & IFF_ALLMULTI)
7715 {
7716 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007717 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307718 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07007719 }
7720 else
7721 {
7722 mc_count = netdev_mc_count(dev);
7723 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007724 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07007725 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
7726 {
7727 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007728 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307729 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07007730 return;
7731 }
7732
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307733 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07007734
7735 netdev_for_each_mc_addr(ha, dev) {
7736 if (i == mc_count)
7737 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307738 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
7739 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
Arif Hussain6d2a3322013-11-17 19:50:10 -08007740 hddLog(VOS_TRACE_LEVEL_INFO, "%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07007741 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307742 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07007743 i++;
7744 }
7745 }
7746 return;
7747}
7748#endif
7749
7750/**---------------------------------------------------------------------------
7751
7752 \brief hdd_select_queue() -
7753
7754 This function is registered with the Linux OS for network
7755 core to decide which queue to use first.
7756
7757 \param - dev - Pointer to the WLAN device.
7758 - skb - Pointer to OS packet (sk_buff).
7759 \return - ac, Queue Index/access category corresponding to UP in IP header
7760
7761 --------------------------------------------------------------------------*/
7762v_U16_t hdd_select_queue(struct net_device *dev,
7763 struct sk_buff *skb)
7764{
7765 return hdd_wmm_select_queue(dev, skb);
7766}
7767
7768
7769/**---------------------------------------------------------------------------
7770
7771 \brief hdd_wlan_initial_scan() -
7772
7773 This function triggers the initial scan
7774
7775 \param - pAdapter - Pointer to the HDD adapter.
7776
7777 --------------------------------------------------------------------------*/
7778void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
7779{
7780 tCsrScanRequest scanReq;
7781 tCsrChannelInfo channelInfo;
7782 eHalStatus halStatus;
Jeff Johnson02797792013-10-26 19:17:13 -07007783 tANI_U32 scanId;
Jeff Johnson295189b2012-06-20 16:38:30 -07007784 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7785
7786 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
7787 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
7788 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
7789
7790 if(sme_Is11dSupported(pHddCtx->hHal))
7791 {
7792 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
7793 if ( HAL_STATUS_SUCCESS( halStatus ) )
7794 {
7795 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
7796 if( !scanReq.ChannelInfo.ChannelList )
7797 {
7798 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
7799 vos_mem_free(channelInfo.ChannelList);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08007800 channelInfo.ChannelList = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007801 return;
7802 }
7803 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
7804 channelInfo.numOfChannels);
7805 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
7806 vos_mem_free(channelInfo.ChannelList);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08007807 channelInfo.ChannelList = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007808 }
7809
7810 scanReq.scanType = eSIR_PASSIVE_SCAN;
7811 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
7812 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
7813 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
7814 }
7815 else
7816 {
7817 scanReq.scanType = eSIR_ACTIVE_SCAN;
7818 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
7819 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
7820 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
7821 }
7822
7823 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
7824 if ( !HAL_STATUS_SUCCESS( halStatus ) )
7825 {
7826 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
7827 __func__, halStatus );
7828 }
7829
7830 if(sme_Is11dSupported(pHddCtx->hHal))
7831 vos_mem_free(scanReq.ChannelInfo.ChannelList);
7832}
7833
Jeff Johnson295189b2012-06-20 16:38:30 -07007834/**---------------------------------------------------------------------------
7835
7836 \brief hdd_full_power_callback() - HDD full power callback function
7837
7838 This is the function invoked by SME to inform the result of a full power
7839 request issued by HDD
7840
7841 \param - callbackcontext - Pointer to cookie
7842 \param - status - result of request
7843
7844 \return - None
7845
7846 --------------------------------------------------------------------------*/
7847static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
7848{
Jeff Johnson72a40512013-12-19 10:14:15 -08007849 struct statsContext *pContext = callbackContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07007850
7851 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307852 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07007853
7854 if (NULL == callbackContext)
7855 {
7856 hddLog(VOS_TRACE_LEVEL_ERROR,
7857 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007858 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07007859 return;
7860 }
7861
Jeff Johnson72a40512013-12-19 10:14:15 -08007862 /* there is a race condition that exists between this callback
7863 function and the caller since the caller could time out either
7864 before or while this code is executing. we use a spinlock to
7865 serialize these actions */
7866 spin_lock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07007867
7868 if (POWER_CONTEXT_MAGIC != pContext->magic)
7869 {
7870 /* the caller presumably timed out so there is nothing we can do */
Jeff Johnson72a40512013-12-19 10:14:15 -08007871 spin_unlock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07007872 hddLog(VOS_TRACE_LEVEL_WARN,
7873 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007874 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07007875 return;
7876 }
7877
Jeff Johnson72a40512013-12-19 10:14:15 -08007878 /* context is valid so caller is still waiting */
7879
7880 /* paranoia: invalidate the magic */
7881 pContext->magic = 0;
7882
7883 /* notify the caller */
Jeff Johnson295189b2012-06-20 16:38:30 -07007884 complete(&pContext->completion);
Jeff Johnson72a40512013-12-19 10:14:15 -08007885
7886 /* serialization is complete */
7887 spin_unlock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07007888}
7889
7890/**---------------------------------------------------------------------------
7891
7892 \brief hdd_wlan_exit() - HDD WLAN exit function
7893
7894 This is the driver exit point (invoked during rmmod)
7895
7896 \param - pHddCtx - Pointer to the HDD Context
7897
7898 \return - None
7899
7900 --------------------------------------------------------------------------*/
7901void hdd_wlan_exit(hdd_context_t *pHddCtx)
7902{
7903 eHalStatus halStatus;
7904 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
7905 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05307906 struct wiphy *wiphy = pHddCtx->wiphy;
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -08007907 hdd_adapter_t* pAdapter = NULL;
Jeff Johnson72a40512013-12-19 10:14:15 -08007908 struct statsContext powerContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07007909 long lrc;
c_hpothu5ab05e92014-06-13 17:34:05 +05307910 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007911
7912 ENTER();
7913
Jeff Johnson88ba7742013-02-27 14:36:02 -08007914 if (VOS_FTM_MODE != hdd_get_conparam())
7915 {
7916 // Unloading, restart logic is no more required.
7917 wlan_hdd_restart_deinit(pHddCtx);
Jeff Johnsone7245742012-09-05 17:12:55 -07007918
c_hpothu5ab05e92014-06-13 17:34:05 +05307919 vosStatus = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7920 while (NULL != pAdapterNode && VOS_STATUS_E_EMPTY != vosStatus)
Jeff Johnson295189b2012-06-20 16:38:30 -07007921 {
c_hpothu5ab05e92014-06-13 17:34:05 +05307922 pAdapter = pAdapterNode->pAdapter;
7923 if (NULL != pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07007924 {
Agarwal Ashish9ffa5b92014-11-18 21:07:02 +05307925 /* Disable TX on the interface, after this hard_start_xmit() will
7926 * not be called on that interface
7927 */
7928 netif_tx_disable(pAdapter->dev);
7929
7930 /* Mark the interface status as "down" for outside world */
7931 netif_carrier_off(pAdapter->dev);
7932
7933 /* DeInit the adapter. This ensures that all data packets
7934 * are freed.
7935 */
7936 hdd_deinit_adapter(pHddCtx, pAdapter);
7937
c_hpothu5ab05e92014-06-13 17:34:05 +05307938 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode ||
7939 WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)
7940 {
7941 wlan_hdd_cfg80211_deregister_frames(pAdapter);
7942 hdd_UnregisterWext(pAdapter->dev);
7943 }
Kaushik, Sushant4975a572014-10-21 16:07:48 +05307944
Jeff Johnson295189b2012-06-20 16:38:30 -07007945 }
c_hpothu5ab05e92014-06-13 17:34:05 +05307946 vosStatus = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7947 pAdapterNode = pNext;
Jeff Johnson295189b2012-06-20 16:38:30 -07007948 }
Kaushik, Sushant4975a572014-10-21 16:07:48 +05307949 // Cancel any outstanding scan requests. We are about to close all
7950 // of our adapters, but an adapter structure is what SME passes back
7951 // to our callback function. Hence if there are any outstanding scan
7952 // requests then there is a race condition between when the adapter
7953 // is closed and when the callback is invoked.We try to resolve that
7954 // race condition here by canceling any outstanding scans before we
7955 // close the adapters.
7956 // Note that the scans may be cancelled in an asynchronous manner,
7957 // so ideally there needs to be some kind of synchronization. Rather
7958 // than introduce a new synchronization here, we will utilize the
7959 // fact that we are about to Request Full Power, and since that is
7960 // synchronized, the expectation is that by the time Request Full
7961 // Power has completed all scans will be cancelled.
7962 if (pHddCtx->scan_info.mScanPending)
7963 {
7964 hddLog(VOS_TRACE_LEVEL_INFO,
7965 FL("abort scan mode: %d sessionId: %d"),
7966 pAdapter->device_mode,
7967 pAdapter->sessionId);
7968 hdd_abort_mac_scan(pHddCtx,
7969 pHddCtx->scan_info.sessionId,
7970 eCSR_SCAN_ABORT_DEFAULT);
7971 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007972 }
c_hpothu5ab05e92014-06-13 17:34:05 +05307973 else
Jeff Johnson88ba7742013-02-27 14:36:02 -08007974 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307975 hddLog(VOS_TRACE_LEVEL_INFO,"%s: FTM MODE",__func__);
Jeff Johnson88ba7742013-02-27 14:36:02 -08007976 wlan_hdd_ftm_close(pHddCtx);
7977 goto free_hdd_ctx;
7978 }
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307979
Jeff Johnson295189b2012-06-20 16:38:30 -07007980 /* DeRegister with platform driver as client for Suspend/Resume */
7981 vosStatus = hddDeregisterPmOps(pHddCtx);
7982 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
7983 {
7984 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
7985 VOS_ASSERT(0);
7986 }
7987
7988 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
7989 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
7990 {
7991 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
7992 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007993
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07007994 //Stop the traffic monitor timer
7995 if ( VOS_TIMER_STATE_RUNNING ==
7996 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr))
7997 {
7998 vos_timer_stop(&pHddCtx->tx_rx_trafficTmr);
7999 }
8000
8001 // Destroy the traffic monitor timer
8002 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
8003 &pHddCtx->tx_rx_trafficTmr)))
8004 {
8005 hddLog(VOS_TRACE_LEVEL_ERROR,
8006 "%s: Cannot deallocate Traffic monitor timer", __func__);
8007 }
8008
Jeff Johnson295189b2012-06-20 16:38:30 -07008009 //Disable IMPS/BMPS as we do not want the device to enter any power
8010 //save mode during shutdown
8011 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
8012 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
8013 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
8014
8015 //Ensure that device is in full power as we will touch H/W during vos_Stop
8016 init_completion(&powerContext.completion);
8017 powerContext.magic = POWER_CONTEXT_MAGIC;
8018
8019 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
8020 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
8021
8022 if (eHAL_STATUS_SUCCESS != halStatus)
8023 {
8024 if (eHAL_STATUS_PMC_PENDING == halStatus)
8025 {
8026 /* request was sent -- wait for the response */
8027 lrc = wait_for_completion_interruptible_timeout(
8028 &powerContext.completion,
8029 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
Jeff Johnson295189b2012-06-20 16:38:30 -07008030 if (lrc <= 0)
8031 {
8032 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008033 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07008034 }
8035 }
8036 else
8037 {
8038 hddLog(VOS_TRACE_LEVEL_ERROR,
8039 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008040 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07008041 /* continue -- need to clean up as much as possible */
8042 }
8043 }
8044
Jeff Johnson72a40512013-12-19 10:14:15 -08008045 /* either we never sent a request, we sent a request and received a
8046 response or we sent a request and timed out. if we never sent a
8047 request or if we sent a request and got a response, we want to
8048 clear the magic out of paranoia. if we timed out there is a
8049 race condition such that the callback function could be
8050 executing at the same time we are. of primary concern is if the
8051 callback function had already verified the "magic" but had not
8052 yet set the completion variable when a timeout occurred. we
8053 serialize these activities by invalidating the magic while
8054 holding a shared spinlock which will cause us to block if the
8055 callback is currently executing */
8056 spin_lock(&hdd_context_lock);
8057 powerContext.magic = 0;
8058 spin_unlock(&hdd_context_lock);
8059
Yue Ma0d4891e2013-08-06 17:01:45 -07008060 hdd_debugfs_exit(pHddCtx);
8061
Jeff Johnson295189b2012-06-20 16:38:30 -07008062 // Unregister the Net Device Notifier
8063 unregister_netdevice_notifier(&hdd_netdev_notifier);
8064
Jeff Johnson295189b2012-06-20 16:38:30 -07008065 hdd_stop_all_adapters( pHddCtx );
8066
Jeff Johnson295189b2012-06-20 16:38:30 -07008067#ifdef WLAN_BTAMP_FEATURE
8068 vosStatus = WLANBAP_Stop(pVosContext);
8069 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
8070 {
8071 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8072 "%s: Failed to stop BAP",__func__);
8073 }
8074#endif //WLAN_BTAMP_FEATURE
8075
8076 //Stop all the modules
8077 vosStatus = vos_stop( pVosContext );
8078 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
8079 {
8080 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8081 "%s: Failed to stop VOSS",__func__);
8082 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
8083 }
8084
Jeff Johnson295189b2012-06-20 16:38:30 -07008085 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07008086 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07008087
8088 //Close the scheduler before calling vos_close to make sure no thread is
8089 // scheduled after the each module close is called i.e after all the data
8090 // structures are freed.
8091 vosStatus = vos_sched_close( pVosContext );
8092 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
8093 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
8094 "%s: Failed to close VOSS Scheduler",__func__);
8095 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
8096 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008097#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07008098#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
8099 /* Destroy the wake lock */
8100 wake_lock_destroy(&pHddCtx->rx_wake_lock);
8101#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08008102 /* Destroy the wake lock */
8103 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008104#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008105
Mihir Shete7a24b5f2013-12-21 12:18:31 +05308106#ifdef CONFIG_ENABLE_LINUX_REG
8107 vosStatus = vos_nv_close();
8108 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
8109 {
8110 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8111 "%s: Failed to close NV", __func__);
8112 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
8113 }
8114#endif
8115
Jeff Johnson295189b2012-06-20 16:38:30 -07008116 //Close VOSS
8117 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
8118 vos_close(pVosContext);
8119
Jeff Johnson295189b2012-06-20 16:38:30 -07008120 //Close Watchdog
8121 if(pHddCtx->cfg_ini->fIsLogpEnabled)
8122 vos_watchdog_close(pVosContext);
8123
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05308124 //Clean up HDD Nlink Service
8125 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05308126
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05308127#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05308128 if (pHddCtx->cfg_ini->wlanLoggingEnable)
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05308129 {
8130 wlan_logging_sock_deactivate_svc();
8131 }
8132#endif
8133
Vinay Krishna Erannaef30b522014-08-26 17:48:16 +05308134#ifdef WLAN_KD_READY_NOTIFIER
8135 nl_srv_exit(pHddCtx->ptt_pid);
8136#else
8137 nl_srv_exit();
8138#endif /* WLAN_KD_READY_NOTIFIER */
8139
8140
Jeff Johnson295189b2012-06-20 16:38:30 -07008141 hdd_close_all_adapters( pHddCtx );
8142
Jeff Johnson295189b2012-06-20 16:38:30 -07008143 /* free the power on lock from platform driver */
8144 if (free_riva_power_on_lock("wlan"))
8145 {
8146 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
8147 __func__);
8148 }
8149
Jeff Johnson88ba7742013-02-27 14:36:02 -08008150free_hdd_ctx:
c_hpothu78c7b602014-05-17 17:35:49 +05308151
8152 //Free up dynamically allocated members inside HDD Adapter
8153 if (pHddCtx->cfg_ini)
8154 {
8155 kfree(pHddCtx->cfg_ini);
8156 pHddCtx->cfg_ini= NULL;
8157 }
8158
Leo Changf04ddad2013-09-18 13:46:38 -07008159 /* FTM mode, WIPHY did not registered
8160 If un-register here, system crash will happen */
8161 if (VOS_FTM_MODE != hdd_get_conparam())
8162 {
8163 wiphy_unregister(wiphy) ;
8164 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008165 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07008166 if (hdd_is_ssr_required())
8167 {
8168 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07008169 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07008170 msleep(5000);
8171 }
8172 hdd_set_ssr_required (VOS_FALSE);
8173}
8174
8175
8176/**---------------------------------------------------------------------------
8177
8178 \brief hdd_update_config_from_nv() - Function to update the contents of
8179 the running configuration with parameters taken from NV storage
8180
8181 \param - pHddCtx - Pointer to the HDD global context
8182
8183 \return - VOS_STATUS_SUCCESS if successful
8184
8185 --------------------------------------------------------------------------*/
8186static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
8187{
Jeff Johnson295189b2012-06-20 16:38:30 -07008188 v_BOOL_t itemIsValid = VOS_FALSE;
8189 VOS_STATUS status;
8190 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
8191 v_U8_t macLoop;
8192
8193 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
8194 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
8195 if(status != VOS_STATUS_SUCCESS)
8196 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08008197 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed");
Jeff Johnson295189b2012-06-20 16:38:30 -07008198 return VOS_STATUS_E_FAILURE;
8199 }
8200
8201 if (itemIsValid == VOS_TRUE)
8202 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08008203 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV");
Jeff Johnson295189b2012-06-20 16:38:30 -07008204 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
8205 VOS_MAX_CONCURRENCY_PERSONA);
8206 if(status != VOS_STATUS_SUCCESS)
8207 {
8208 /* Get MAC from NV fail, not update CFG info
8209 * INI MAC value will be used for MAC setting */
Arif Hussain6d2a3322013-11-17 19:50:10 -08008210 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed");
Jeff Johnson295189b2012-06-20 16:38:30 -07008211 return VOS_STATUS_E_FAILURE;
8212 }
8213
8214 /* If first MAC is not valid, treat all others are not valid
8215 * Then all MACs will be got from ini file */
8216 if(vos_is_macaddr_zero(&macFromNV[0]))
8217 {
8218 /* MAC address in NV file is not configured yet */
8219 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
8220 return VOS_STATUS_E_INVAL;
8221 }
8222
8223 /* Get MAC address from NV, update CFG info */
8224 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
8225 {
8226 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
8227 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308228 hddLog(VOS_TRACE_LEVEL_ERROR,"not valid MAC from NV for %d", macLoop);
Jeff Johnson295189b2012-06-20 16:38:30 -07008229 /* This MAC is not valid, skip it
8230 * This MAC will be got from ini file */
8231 }
8232 else
8233 {
8234 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
8235 (v_U8_t *)&macFromNV[macLoop].bytes[0],
8236 VOS_MAC_ADDR_SIZE);
8237 }
8238 }
8239 }
8240 else
8241 {
8242 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
8243 return VOS_STATUS_E_FAILURE;
8244 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008245
Jeff Johnson295189b2012-06-20 16:38:30 -07008246
8247 return VOS_STATUS_SUCCESS;
8248}
8249
8250/**---------------------------------------------------------------------------
8251
8252 \brief hdd_post_voss_start_config() - HDD post voss start config helper
8253
8254 \param - pAdapter - Pointer to the HDD
8255
8256 \return - None
8257
8258 --------------------------------------------------------------------------*/
8259VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
8260{
8261 eHalStatus halStatus;
8262 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308263 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -07008264
Jeff Johnson295189b2012-06-20 16:38:30 -07008265
8266 // Send ready indication to the HDD. This will kick off the MAC
8267 // into a 'running' state and should kick off an initial scan.
8268 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
8269 if ( !HAL_STATUS_SUCCESS( halStatus ) )
8270 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308271 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07008272 "code %08d [x%08x]",__func__, halStatus, halStatus );
8273 return VOS_STATUS_E_FAILURE;
8274 }
8275
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308276 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -07008277 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
8278 // And RIVA will crash
8279 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
8280 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308281 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
8282 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
8283
8284
Jeff Johnson295189b2012-06-20 16:38:30 -07008285 return VOS_STATUS_SUCCESS;
8286}
8287
Jeff Johnson295189b2012-06-20 16:38:30 -07008288/* wake lock APIs for HDD */
8289void hdd_prevent_suspend(void)
8290{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008291#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008292 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008293#else
8294 wcnss_prevent_suspend();
8295#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008296}
8297
8298void hdd_allow_suspend(void)
8299{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008300#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008301 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008302#else
8303 wcnss_allow_suspend();
8304#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008305}
8306
Mahesh A Saptasagarb9c50402014-01-16 15:49:22 +05308307void hdd_prevent_suspend_timeout(v_U32_t timeout)
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07008308{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008309#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07008310 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07008311#else
8312 /* Do nothing as there is no API in wcnss for timeout*/
8313#endif
8314}
8315
Jeff Johnson295189b2012-06-20 16:38:30 -07008316/**---------------------------------------------------------------------------
8317
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008318 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
8319 information between Host and Riva
8320
8321 This function gets reported version of FW
8322 It also finds the version of Riva headers used to compile the host
8323 It compares the above two and prints a warning if they are different
8324 It gets the SW and HW version string
8325 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
8326 indicating the features they support through a bitmap
8327
8328 \param - pHddCtx - Pointer to HDD context
8329
8330 \return - void
8331
8332 --------------------------------------------------------------------------*/
8333
8334void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
8335{
8336
8337 tSirVersionType versionCompiled;
8338 tSirVersionType versionReported;
8339 tSirVersionString versionString;
8340 tANI_U8 fwFeatCapsMsgSupported = 0;
8341 VOS_STATUS vstatus;
8342
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -08008343 memset(&versionCompiled, 0, sizeof(versionCompiled));
8344 memset(&versionReported, 0, sizeof(versionReported));
8345
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008346 /* retrieve and display WCNSS version information */
8347 do {
8348
8349 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
8350 &versionCompiled);
8351 if (!VOS_IS_STATUS_SUCCESS(vstatus))
8352 {
8353 hddLog(VOS_TRACE_LEVEL_FATAL,
8354 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008355 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008356 break;
8357 }
8358
8359 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
8360 &versionReported);
8361 if (!VOS_IS_STATUS_SUCCESS(vstatus))
8362 {
8363 hddLog(VOS_TRACE_LEVEL_FATAL,
8364 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008365 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008366 break;
8367 }
8368
8369 if ((versionCompiled.major != versionReported.major) ||
8370 (versionCompiled.minor != versionReported.minor) ||
8371 (versionCompiled.version != versionReported.version) ||
8372 (versionCompiled.revision != versionReported.revision))
8373 {
8374 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
8375 "Host expected %u.%u.%u.%u\n",
8376 WLAN_MODULE_NAME,
8377 (int)versionReported.major,
8378 (int)versionReported.minor,
8379 (int)versionReported.version,
8380 (int)versionReported.revision,
8381 (int)versionCompiled.major,
8382 (int)versionCompiled.minor,
8383 (int)versionCompiled.version,
8384 (int)versionCompiled.revision);
8385 }
8386 else
8387 {
8388 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
8389 WLAN_MODULE_NAME,
8390 (int)versionReported.major,
8391 (int)versionReported.minor,
8392 (int)versionReported.version,
8393 (int)versionReported.revision);
8394 }
8395
8396 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
8397 versionString,
8398 sizeof(versionString));
8399 if (!VOS_IS_STATUS_SUCCESS(vstatus))
8400 {
8401 hddLog(VOS_TRACE_LEVEL_FATAL,
8402 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008403 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008404 break;
8405 }
8406
8407 pr_info("%s: WCNSS software version %s\n",
8408 WLAN_MODULE_NAME, versionString);
8409
8410 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
8411 versionString,
8412 sizeof(versionString));
8413 if (!VOS_IS_STATUS_SUCCESS(vstatus))
8414 {
8415 hddLog(VOS_TRACE_LEVEL_FATAL,
8416 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008417 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008418 break;
8419 }
8420
8421 pr_info("%s: WCNSS hardware version %s\n",
8422 WLAN_MODULE_NAME, versionString);
8423
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07008424 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
8425 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008426 send the message only if it the riva is 1.1
8427 minor numbers for different riva branches:
8428 0 -> (1.0)Mainline Build
8429 1 -> (1.1)Mainline Build
8430 2->(1.04) Stability Build
8431 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07008432 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008433 ((versionReported.minor>=1) && (versionReported.version>=1)))
8434 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
8435 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07008436
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008437 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08008438 {
8439#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
8440 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
8441 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
8442#endif
Ravi Joshid2ca7c42013-07-23 08:37:49 -07008443 /* Indicate if IBSS heartbeat monitoring needs to be offloaded */
8444 if (!pHddCtx->cfg_ini->enableIbssHeartBeatOffload)
8445 {
8446 sme_disableFeatureCapablity(IBSS_HEARTBEAT_OFFLOAD);
8447 }
8448
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008449 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08008450 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008451
8452 } while (0);
8453
8454}
Neelansh Mittaledafed22014-09-04 18:54:39 +05308455void wlan_hdd_send_svc_nlink_msg(int type, void *data, int len)
8456{
8457 struct sk_buff *skb;
8458 struct nlmsghdr *nlh;
8459 tAniMsgHdr *ani_hdr;
8460
8461 skb = alloc_skb(NLMSG_SPACE(WLAN_NL_MAX_PAYLOAD), GFP_KERNEL);
8462
8463 if(skb == NULL) {
8464 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8465 "%s: alloc_skb failed", __func__);
8466 return;
8467 }
8468
8469 nlh = (struct nlmsghdr *)skb->data;
8470 nlh->nlmsg_pid = 0; /* from kernel */
8471 nlh->nlmsg_flags = 0;
8472 nlh->nlmsg_seq = 0;
8473 nlh->nlmsg_type = WLAN_NL_MSG_SVC;
8474
8475 ani_hdr = NLMSG_DATA(nlh);
8476 ani_hdr->type = type;
8477
8478 switch(type) {
8479 case WLAN_SVC_SAP_RESTART_IND:
8480 ani_hdr->length = 0;
8481 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr)));
8482 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr)));
8483 break;
8484 default:
8485 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8486 "Attempt to send unknown nlink message %d", type);
8487 kfree_skb(skb);
8488 return;
8489 }
8490
8491 nl_srv_bcast(skb);
8492
8493 return;
8494}
8495
8496
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008497
8498/**---------------------------------------------------------------------------
8499
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308500 \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
8501
8502 \param - pHddCtx - Pointer to the hdd context
8503
8504 \return - true if hardware supports 5GHz
8505
8506 --------------------------------------------------------------------------*/
Vinay Krishna Erannafacf5e22014-02-24 13:16:25 +05308507boolean hdd_is_5g_supported(hdd_context_t * pHddCtx)
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308508{
8509 /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
8510 * then hardware support 5Ghz.
8511 */
8512 if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode())
8513 {
Agarwal Ashish971c2882013-10-30 20:11:12 +05308514 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Hardware supports 5Ghz", __func__);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308515 return true;
8516 }
8517 else
8518 {
Agarwal Ashish971c2882013-10-30 20:11:12 +05308519 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Hardware doesn't supports 5Ghz",
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308520 __func__);
8521 return false;
8522 }
8523}
8524
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308525/**---------------------------------------------------------------------------
8526
8527 \brief hdd_generate_iface_mac_addr_auto() - HDD Mac Interface Auto
8528 generate function
8529
8530 This is generate the random mac address for WLAN interface
8531
8532 \param - pHddCtx - Pointer to HDD context
8533 idx - Start interface index to get auto
8534 generated mac addr.
8535 mac_addr - Mac address
8536
8537 \return - 0 for success, < 0 for failure
8538
8539 --------------------------------------------------------------------------*/
8540
8541static int hdd_generate_iface_mac_addr_auto(hdd_context_t *pHddCtx,
8542 int idx, v_MACADDR_t mac_addr)
8543{
8544 int i;
8545 unsigned int serialno;
8546 serialno = wcnss_get_serial_number();
8547
8548 if (0 != serialno)
8549 {
8550 /* MAC address has 3 bytes of OUI so we have a maximum of 3
8551 bytes of the serial number that can be used to generate
8552 the other 3 bytes of the MAC address. Mask off all but
8553 the lower 3 bytes (this will also make sure we don't
8554 overflow in the next step) */
8555 serialno &= 0x00FFFFFF;
8556
8557 /* we need a unique address for each session */
8558 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
8559
8560 /* autogen other Mac addresses */
8561 for (i = idx; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
8562 {
8563 /* start with the entire default address */
8564 pHddCtx->cfg_ini->intfMacAddr[i] = mac_addr;
8565 /* then replace the lower 3 bytes */
8566 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
8567 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
8568 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
8569
8570 serialno++;
8571 hddLog(VOS_TRACE_LEVEL_ERROR,
8572 "%s: Derived Mac Addr: "
8573 MAC_ADDRESS_STR, __func__,
8574 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[i].bytes));
8575 }
8576
8577 }
8578 else
8579 {
8580 hddLog(LOGE, FL("Failed to Get Serial NO"));
8581 return -1;
8582 }
8583 return 0;
8584}
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308585
8586/**---------------------------------------------------------------------------
8587
Mihir Shetefc7ff5b2014-01-27 11:30:05 +05308588 \brief hdd_11d_scan_done - callback to be executed when 11d scan is
8589 completed to flush out the scan results
8590
8591 11d scan is done during driver load and is a passive scan on all
8592 channels supported by the device, 11d scans may find some APs on
8593 frequencies which are forbidden to be used in the regulatory domain
8594 the device is operating in. If these APs are notified to the supplicant
8595 it may try to connect to these APs, thus flush out all the scan results
8596 which are present in SME after 11d scan is done.
8597
8598 \return - eHalStatus
8599
8600 --------------------------------------------------------------------------*/
8601static eHalStatus hdd_11d_scan_done(tHalHandle halHandle, void *pContext,
8602 tANI_U32 scanId, eCsrScanStatus status)
8603{
8604 ENTER();
8605
8606 sme_ScanFlushResult(halHandle, 0);
8607
8608 EXIT();
8609
8610 return eHAL_STATUS_SUCCESS;
8611}
8612
8613/**---------------------------------------------------------------------------
8614
Jeff Johnson295189b2012-06-20 16:38:30 -07008615 \brief hdd_wlan_startup() - HDD init function
8616
8617 This is the driver startup code executed once a WLAN device has been detected
8618
8619 \param - dev - Pointer to the underlying device
8620
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08008621 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07008622
8623 --------------------------------------------------------------------------*/
8624
8625int hdd_wlan_startup(struct device *dev )
8626{
8627 VOS_STATUS status;
8628 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07008629 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07008630 hdd_context_t *pHddCtx = NULL;
8631 v_CONTEXT_t pVosContext= NULL;
8632#ifdef WLAN_BTAMP_FEATURE
8633 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
8634 WLANBAP_ConfigType btAmpConfig;
8635 hdd_config_t *pConfig;
8636#endif
8637 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07008638 struct wiphy *wiphy;
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308639 v_MACADDR_t mac_addr;
Jeff Johnson295189b2012-06-20 16:38:30 -07008640
8641 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07008642 /*
8643 * cfg80211: wiphy allocation
8644 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308645 wiphy = wlan_hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t)) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07008646
8647 if(wiphy == NULL)
8648 {
8649 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08008650 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07008651 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008652 pHddCtx = wiphy_priv(wiphy);
8653
Jeff Johnson295189b2012-06-20 16:38:30 -07008654 //Initialize the adapter context to zeros.
8655 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
8656
Jeff Johnson295189b2012-06-20 16:38:30 -07008657 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07008658 hdd_prevent_suspend();
Mihir Shete18156292014-03-11 15:38:30 +05308659 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_LOAD_IN_PROGRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -07008660
8661 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
8662
8663 /*Get vos context here bcoz vos_open requires it*/
8664 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
8665
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08008666 if(pVosContext == NULL)
8667 {
8668 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
8669 goto err_free_hdd_context;
8670 }
8671
Jeff Johnson295189b2012-06-20 16:38:30 -07008672 //Save the Global VOSS context in adapter context for future.
8673 pHddCtx->pvosContext = pVosContext;
8674
8675 //Save the adapter context in global context for future.
8676 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
8677
Jeff Johnson295189b2012-06-20 16:38:30 -07008678 pHddCtx->parent_dev = dev;
8679
8680 init_completion(&pHddCtx->full_pwr_comp_var);
8681 init_completion(&pHddCtx->standby_comp_var);
8682 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07008683 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08008684 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Kiet Lam46b8e4e2013-11-06 21:49:53 +05308685 init_completion(&pHddCtx->wiphy_channel_update_event);
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +05308686 init_completion(&pHddCtx->ssr_comp_var);
Amar Singhala49cbc52013-10-08 18:37:44 -07008687
8688#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhalfddc28c2013-09-05 13:03:40 -07008689 init_completion(&pHddCtx->linux_reg_req);
Amar Singhala49cbc52013-10-08 18:37:44 -07008690#else
8691 init_completion(&pHddCtx->driver_crda_req);
8692#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008693
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05308694 spin_lock_init(&pHddCtx->schedScan_lock);
8695
Jeff Johnson295189b2012-06-20 16:38:30 -07008696 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
8697
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05308698#ifdef FEATURE_WLAN_TDLS
8699 /* tdls_lock is initialized before an hdd_open_adapter ( which is
8700 * invoked by other instances also) to protect the concurrent
8701 * access for the Adapters by TDLS module.
8702 */
8703 mutex_init(&pHddCtx->tdls_lock);
8704#endif
Siddharth Bhal76972212014-10-15 16:22:51 +05308705 mutex_init(&pHddCtx->spoofMacAddr.macSpoofingLock);
Agarwal Ashish1f422872014-07-22 00:11:55 +05308706 /* By default Strict Regulatory For FCC should be false */
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05308707
Agarwal Ashish1f422872014-07-22 00:11:55 +05308708 pHddCtx->nEnableStrictRegulatoryForFCC = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07008709 // Load all config first as TL config is needed during vos_open
8710 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
8711 if(pHddCtx->cfg_ini == NULL)
8712 {
8713 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
8714 goto err_free_hdd_context;
8715 }
8716
8717 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
8718
8719 // Read and parse the qcom_cfg.ini file
8720 status = hdd_parse_config_ini( pHddCtx );
8721 if ( VOS_STATUS_SUCCESS != status )
8722 {
8723 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
8724 __func__, WLAN_INI_FILE);
8725 goto err_config;
8726 }
Arif Hussaind5218912013-12-05 01:10:55 -08008727#ifdef MEMORY_DEBUG
8728 if (pHddCtx->cfg_ini->IsMemoryDebugSupportEnabled)
8729 vos_mem_init();
8730
8731 hddLog(VOS_TRACE_LEVEL_INFO, "%s: gEnableMemoryDebug=%d",
8732 __func__, pHddCtx->cfg_ini->IsMemoryDebugSupportEnabled);
8733#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008734
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05308735 /* INI has been read, initialise the configuredMcastBcastFilter with
8736 * INI value as this will serve as the default value
8737 */
8738 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
8739 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
8740 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308741
8742 if (false == hdd_is_5g_supported(pHddCtx))
8743 {
8744 //5Ghz is not supported.
8745 if (1 != pHddCtx->cfg_ini->nBandCapability)
8746 {
8747 hddLog(VOS_TRACE_LEVEL_INFO,
8748 "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__);
8749 pHddCtx->cfg_ini->nBandCapability = 1;
8750 }
8751 }
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05308752
8753 /* If SNR Monitoring is enabled, FW has to parse all beacons
8754 * for calcaluting and storing the average SNR, so set Nth beacon
8755 * filter to 1 to enable FW to parse all the beaocons
8756 */
8757 if (1 == pHddCtx->cfg_ini->fEnableSNRMonitoring)
8758 {
8759 /* The log level is deliberately set to WARN as overriding
8760 * nthBeaconFilter to 1 will increase power cosumption and this
8761 * might just prove helpful to detect the power issue.
8762 */
8763 hddLog(VOS_TRACE_LEVEL_WARN,
8764 "%s: Setting pHddCtx->cfg_ini->nthBeaconFilter = 1", __func__);
8765 pHddCtx->cfg_ini->nthBeaconFilter = 1;
8766 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008767 /*
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308768 * cfg80211: Initialization ...
Jeff Johnson295189b2012-06-20 16:38:30 -07008769 */
Manjunathappa Prakasheec4ddf2014-01-13 18:23:51 -08008770 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07008771 {
Manjunathappa Prakasheec4ddf2014-01-13 18:23:51 -08008772 if (0 < wlan_hdd_cfg80211_init(dev, wiphy, pHddCtx->cfg_ini))
8773 {
8774 hddLog(VOS_TRACE_LEVEL_FATAL,
8775 "%s: wlan_hdd_cfg80211_init return failure", __func__);
8776 goto err_config;
8777 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008778 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008779
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08008780 // Update VOS trace levels based upon the cfg.ini
8781 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
8782 pHddCtx->cfg_ini->vosTraceEnableBAP);
8783 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
8784 pHddCtx->cfg_ini->vosTraceEnableTL);
8785 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
8786 pHddCtx->cfg_ini->vosTraceEnableWDI);
8787 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
8788 pHddCtx->cfg_ini->vosTraceEnableHDD);
8789 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
8790 pHddCtx->cfg_ini->vosTraceEnableSME);
8791 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
8792 pHddCtx->cfg_ini->vosTraceEnablePE);
Katya Nigam70d68332013-09-16 16:49:45 +05308793 hdd_vos_trace_enable(VOS_MODULE_ID_PMC,
8794 pHddCtx->cfg_ini->vosTraceEnablePMC);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08008795 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
8796 pHddCtx->cfg_ini->vosTraceEnableWDA);
8797 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
8798 pHddCtx->cfg_ini->vosTraceEnableSYS);
8799 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
8800 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08008801 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
8802 pHddCtx->cfg_ini->vosTraceEnableSAP);
8803 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
8804 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08008805
Jeff Johnson295189b2012-06-20 16:38:30 -07008806 // Update WDI trace levels based upon the cfg.ini
8807 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
8808 pHddCtx->cfg_ini->wdiTraceEnableDAL);
8809 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
8810 pHddCtx->cfg_ini->wdiTraceEnableCTL);
8811 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
8812 pHddCtx->cfg_ini->wdiTraceEnableDAT);
8813 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
8814 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07008815
Jeff Johnson88ba7742013-02-27 14:36:02 -08008816 if (VOS_FTM_MODE == hdd_get_conparam())
8817 {
Jeff Johnson295189b2012-06-20 16:38:30 -07008818 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
8819 {
8820 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
8821 goto err_free_hdd_context;
8822 }
8823 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
c_hpothu2de0ef62014-04-15 16:16:15 +05308824
8825 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -07008826 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08008827 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008828
Jeff Johnson88ba7742013-02-27 14:36:02 -08008829 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07008830 if(pHddCtx->cfg_ini->fIsLogpEnabled)
8831 {
8832 status = vos_watchdog_open(pVosContext,
8833 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
8834
8835 if(!VOS_IS_STATUS_SUCCESS( status ))
8836 {
8837 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308838 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07008839 }
8840 }
8841
8842 pHddCtx->isLogpInProgress = FALSE;
8843 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
8844
Amar Singhala49cbc52013-10-08 18:37:44 -07008845#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -07008846 /* initialize the NV module. This is required so that
8847 we can initialize the channel information in wiphy
8848 from the NV.bin data. The channel information in
8849 wiphy needs to be initialized before wiphy registration */
8850
8851 status = vos_nv_open();
8852 if (!VOS_IS_STATUS_SUCCESS(status))
8853 {
8854 /* NV module cannot be initialized */
8855 hddLog( VOS_TRACE_LEVEL_FATAL,
8856 "%s: vos_nv_open failed", __func__);
Vinay Krishna Eranna2025d892014-09-18 16:51:42 +05308857 goto err_wdclose;
Amar Singhal0a402232013-10-11 20:57:16 -07008858 }
8859
8860 status = vos_init_wiphy_from_nv_bin();
8861 if (!VOS_IS_STATUS_SUCCESS(status))
8862 {
8863 /* NV module cannot be initialized */
8864 hddLog( VOS_TRACE_LEVEL_FATAL,
8865 "%s: vos_init_wiphy failed", __func__);
8866 goto err_vos_nv_close;
8867 }
8868
Amar Singhala49cbc52013-10-08 18:37:44 -07008869#endif
8870
Arun Kumar Khandavalliebb19482014-03-25 13:56:53 +05308871 status = vos_open( &pVosContext, pHddCtx->parent_dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07008872 if ( !VOS_IS_STATUS_SUCCESS( status ))
8873 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008874 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
Mihir Shetee1093ba2014-01-21 20:13:32 +05308875 goto err_vos_nv_close;
Jeff Johnson295189b2012-06-20 16:38:30 -07008876 }
8877
Jeff Johnson295189b2012-06-20 16:38:30 -07008878 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
8879
8880 if ( NULL == pHddCtx->hHal )
8881 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008882 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008883 goto err_vosclose;
8884 }
8885
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008886 status = vos_preStart( pHddCtx->pvosContext );
8887 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8888 {
8889 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05308890 goto err_vosclose;
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008891 }
Jeff Johnsone7245742012-09-05 17:12:55 -07008892
Arif Hussaineaf68602013-12-30 23:10:44 -08008893 if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan)
8894 {
8895 pHddCtx->cfg_ini->enableDFSChnlScan = enable_dfs_chan_scan;
8896 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_dfs_chan_scan set to %d",
8897 __func__, enable_dfs_chan_scan);
8898 }
8899 if (0 == enable_11d || 1 == enable_11d)
8900 {
8901 pHddCtx->cfg_ini->Is11dSupportEnabled = enable_11d;
8902 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_11d set to %d",
8903 __func__, enable_11d);
8904 }
8905
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008906 /* Note that the vos_preStart() sequence triggers the cfg download.
8907 The cfg download must occur before we update the SME config
8908 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07008909 status = hdd_set_sme_config( pHddCtx );
8910
8911 if ( VOS_STATUS_SUCCESS != status )
8912 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008913 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05308914 goto err_vosclose;
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008915 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008916
Jeff Johnson295189b2012-06-20 16:38:30 -07008917 /* In the integrated architecture we update the configuration from
8918 the INI file and from NV before vOSS has been started so that
8919 the final contents are available to send down to the cCPU */
8920
8921 // Apply the cfg.ini to cfg.dat
8922 if (FALSE == hdd_update_config_dat(pHddCtx))
8923 {
8924 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05308925 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07008926 }
8927
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308928 // Get mac addr from platform driver
8929 ret = wcnss_get_wlan_mac_address((char*)&mac_addr.bytes);
8930
8931 if ((0 == ret) && (!vos_is_macaddr_zero(&mac_addr)))
Jeff Johnson295189b2012-06-20 16:38:30 -07008932 {
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308933 /* Store the mac addr for first interface */
8934 pHddCtx->cfg_ini->intfMacAddr[0] = mac_addr;
8935
8936 hddLog(VOS_TRACE_LEVEL_ERROR,
8937 "%s: WLAN Mac Addr: "
8938 MAC_ADDRESS_STR, __func__,
8939 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
8940
8941 /* Here, passing Arg2 as 1 because we do not want to change the
8942 last 3 bytes (means non OUI bytes) of first interface mac
8943 addr.
8944 */
8945 if (0 != hdd_generate_iface_mac_addr_auto(pHddCtx, 1, mac_addr))
8946 {
8947 hddLog(VOS_TRACE_LEVEL_ERROR,
8948 "%s: Failed to generate wlan interface mac addr "
8949 "using MAC from ini file ", __func__);
8950 }
8951 }
8952 else if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
8953 {
8954 // Apply the NV to cfg.dat
8955 /* Prima Update MAC address only at here */
Jeff Johnson295189b2012-06-20 16:38:30 -07008956#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
8957 /* There was not a valid set of MAC Addresses in NV. See if the
8958 default addresses were modified by the cfg.ini settings. If so,
8959 we'll use them, but if not, we'll autogenerate a set of MAC
8960 addresses based upon the device serial number */
8961
8962 static const v_MACADDR_t default_address =
8963 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
Jeff Johnson295189b2012-06-20 16:38:30 -07008964
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308965 if (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
8966 sizeof(default_address)))
Jeff Johnson295189b2012-06-20 16:38:30 -07008967 {
8968 /* cfg.ini has the default address, invoke autogen logic */
8969
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308970 /* Here, passing Arg2 as 0 because we want to change the
8971 last 3 bytes (means non OUI bytes) of all the interfaces
8972 mac addr.
8973 */
8974 if (0 != hdd_generate_iface_mac_addr_auto(pHddCtx, 0,
8975 default_address))
Jeff Johnson295189b2012-06-20 16:38:30 -07008976 {
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308977 hddLog(VOS_TRACE_LEVEL_ERROR,
8978 "%s: Failed to generate wlan interface mac addr "
8979 "using MAC from ini file " MAC_ADDRESS_STR, __func__,
8980 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
Jeff Johnson295189b2012-06-20 16:38:30 -07008981 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008982 }
8983 else
8984#endif //WLAN_AUTOGEN_MACADDR_FEATURE
8985 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008986 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07008987 "%s: Invalid MAC address in NV, using MAC from ini file "
8988 MAC_ADDRESS_STR, __func__,
8989 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
8990 }
8991 }
8992 {
8993 eHalStatus halStatus;
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308994
8995 /* Set the MAC Address Currently this is used by HAL to
8996 * add self sta. Remove this once self sta is added as
8997 * part of session open.
8998 */
Jeff Johnson295189b2012-06-20 16:38:30 -07008999 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
9000 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
9001 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05309002
Jeff Johnson295189b2012-06-20 16:38:30 -07009003 if (!HAL_STATUS_SUCCESS( halStatus ))
9004 {
9005 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
9006 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05309007 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07009008 }
9009 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009010
9011 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
9012 Note: Firmware image will be read and downloaded inside vos_start API */
9013 status = vos_start( pHddCtx->pvosContext );
9014 if ( !VOS_IS_STATUS_SUCCESS( status ) )
9015 {
9016 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05309017 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07009018 }
9019
Leo Chang6cec3e22014-01-21 15:33:49 -08009020#ifdef FEATURE_WLAN_CH_AVOID
9021 /* Plug in avoid channel notification callback
9022 * This should happen before ADD_SELF_STA
9023 * FW will send first IND with ADD_SELF_STA REQ from host */
Pradeep Reddy POTTETI5c2e16d2014-06-27 16:47:38 +05309024
9025 /* check the Channel Avoidance is enabled */
9026 if (TRUE == pHddCtx->cfg_ini->fenableCHAvoidance)
9027 {
9028 sme_AddChAvoidCallback(pHddCtx->hHal,
9029 hdd_hostapd_ch_avoid_cb);
9030 }
Leo Chang6cec3e22014-01-21 15:33:49 -08009031#endif /* FEATURE_WLAN_CH_AVOID */
9032
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07009033 /* Exchange capability info between Host and FW and also get versioning info from FW */
9034 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07009035
Agarwal Ashishad9281b2014-06-10 14:57:30 +05309036#ifdef CONFIG_ENABLE_LINUX_REG
9037 status = wlan_hdd_init_channels(pHddCtx);
9038 if ( !VOS_IS_STATUS_SUCCESS( status ) )
9039 {
9040 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: wlan_hdd_init_channels failed",
9041 __func__);
9042 goto err_vosstop;
9043 }
9044#endif
9045
Jeff Johnson295189b2012-06-20 16:38:30 -07009046 status = hdd_post_voss_start_config( pHddCtx );
9047 if ( !VOS_IS_STATUS_SUCCESS( status ) )
9048 {
9049 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
9050 __func__);
9051 goto err_vosstop;
9052 }
Amar Singhala49cbc52013-10-08 18:37:44 -07009053
9054#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05309055 wlan_hdd_cfg80211_update_reg_info( wiphy );
9056
9057 /* registration of wiphy dev with cfg80211 */
9058 if (0 > wlan_hdd_cfg80211_register(wiphy))
9059 {
9060 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
9061 goto err_vosstop;
9062 }
Amar Singhala49cbc52013-10-08 18:37:44 -07009063#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009064
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05309065#ifdef CONFIG_ENABLE_LINUX_REG
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05309066 /* registration of wiphy dev with cfg80211 */
9067 if (0 > wlan_hdd_cfg80211_register(wiphy))
9068 {
9069 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
9070 goto err_vosstop;
9071 }
9072
Agarwal Ashish6db9d532014-09-30 18:19:10 +05309073 status = wlan_hdd_init_channels_for_cc(pHddCtx, INIT);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05309074 if ( !VOS_IS_STATUS_SUCCESS( status ) )
9075 {
9076 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: wlan_hdd_init_channels_for_cc failed",
9077 __func__);
9078 goto err_unregister_wiphy;
9079 }
9080#endif
9081
Jeff Johnson295189b2012-06-20 16:38:30 -07009082 if (VOS_STA_SAP_MODE == hdd_get_conparam())
9083 {
9084 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
9085 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
9086 }
9087 else
9088 {
Jeff Johnson295189b2012-06-20 16:38:30 -07009089 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
9090 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
9091 if (pAdapter != NULL)
9092 {
Katya Nigama7d81d72014-11-12 12:44:34 +05309093 if (pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated && !(pHddCtx->cfg_ini->intfMacAddr[0].bytes[0] & 0x02))
Jeff Johnson295189b2012-06-20 16:38:30 -07009094 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05309095 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
9096 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
9097 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07009098
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05309099 /* Generate the P2P Device Address. This consists of the device's
9100 * primary MAC address with the locally administered bit set.
9101 */
9102 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07009103 }
9104 else
9105 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05309106 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
9107 if (p2p_dev_addr != NULL)
9108 {
9109 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
9110 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
9111 }
9112 else
9113 {
9114 hddLog(VOS_TRACE_LEVEL_FATAL,
9115 "%s: Failed to allocate mac_address for p2p_device",
9116 __func__);
9117 goto err_close_adapter;
9118 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009119 }
Jeff Johnsone7245742012-09-05 17:12:55 -07009120
9121 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
9122 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
9123 if ( NULL == pP2pAdapter )
9124 {
9125 hddLog(VOS_TRACE_LEVEL_FATAL,
9126 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07009127 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07009128 goto err_close_adapter;
9129 }
Jeff Johnsone7245742012-09-05 17:12:55 -07009130 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009131 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009132
9133 if( pAdapter == NULL )
9134 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08009135 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
9136 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07009137 }
Jeff Johnsone7245742012-09-05 17:12:55 -07009138
Arif Hussain66559122013-11-21 10:11:40 -08009139 if (country_code)
9140 {
9141 eHalStatus ret;
Arif Hussaincb607082013-12-20 11:57:42 -08009142 INIT_COMPLETION(pAdapter->change_country_code);
Arif Hussain66559122013-11-21 10:11:40 -08009143 hdd_checkandupdate_dfssetting(pAdapter, country_code);
9144#ifndef CONFIG_ENABLE_LINUX_REG
9145 hdd_checkandupdate_phymode(pAdapter, country_code);
9146#endif
Arif Hussaineaf68602013-12-30 23:10:44 -08009147 ret = sme_ChangeCountryCode(pHddCtx->hHal,
9148 (void *)(tSmeChangeCountryCallback)
9149 wlan_hdd_change_country_code_callback,
Arif Hussain66559122013-11-21 10:11:40 -08009150 country_code,
9151 pAdapter, pHddCtx->pvosContext,
Abhishek Singha306a442013-11-07 18:39:01 +05309152 eSIR_TRUE, eSIR_TRUE);
Arif Hussain66559122013-11-21 10:11:40 -08009153 if (eHAL_STATUS_SUCCESS == ret)
9154 {
Arif Hussaincb607082013-12-20 11:57:42 -08009155 ret = wait_for_completion_interruptible_timeout(
9156 &pAdapter->change_country_code,
9157 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
9158
9159 if (0 >= ret)
9160 {
9161 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
9162 "%s: SME while setting country code timed out", __func__);
9163 }
Arif Hussain66559122013-11-21 10:11:40 -08009164 }
9165 else
9166 {
Arif Hussaincb607082013-12-20 11:57:42 -08009167 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
9168 "%s: SME Change Country code from module param fail ret=%d",
9169 __func__, ret);
Arif Hussain66559122013-11-21 10:11:40 -08009170 }
9171 }
9172
Jeff Johnson295189b2012-06-20 16:38:30 -07009173#ifdef WLAN_BTAMP_FEATURE
9174 vStatus = WLANBAP_Open(pVosContext);
9175 if(!VOS_IS_STATUS_SUCCESS(vStatus))
9176 {
9177 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
9178 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07009179 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07009180 }
9181
9182 vStatus = BSL_Init(pVosContext);
9183 if(!VOS_IS_STATUS_SUCCESS(vStatus))
9184 {
9185 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
9186 "%s: Failed to Init BSL",__func__);
9187 goto err_bap_close;
9188 }
9189 vStatus = WLANBAP_Start(pVosContext);
9190 if (!VOS_IS_STATUS_SUCCESS(vStatus))
9191 {
9192 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
9193 "%s: Failed to start TL",__func__);
9194 goto err_bap_close;
9195 }
9196
9197 pConfig = pHddCtx->cfg_ini;
9198 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
9199 status = WLANBAP_SetConfig(&btAmpConfig);
9200
9201#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07009202
Mihir Shete9c238772014-10-15 14:35:16 +05309203 /*
9204 * UapsdMask is 0xf if U-APSD is enbaled for all AC's...
9205 * The value of CFG_QOS_WMM_UAPSD_MASK_DEFAULT is 0xaa(Magic Value)
9206 * which is greater than 0xf. So the below check is safe to make
9207 * sure that there is no entry for UapsdMask in the ini
9208 */
9209 if (CFG_QOS_WMM_UAPSD_MASK_DEFAULT == pHddCtx->cfg_ini->UapsdMask)
9210 {
9211 if(IS_DYNAMIC_WMM_PS_ENABLED)
9212 {
9213 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: Enable UAPSD for VI & VO",
9214 __func__);
9215 pHddCtx->cfg_ini->UapsdMask =
9216 CFG_QOS_WMM_UAPSD_MASK_DYMANIC_WMM_PS_DEFAULT;
9217 }
9218 else
9219 {
9220 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: Do not enable UAPSD",
9221 __func__);
9222 pHddCtx->cfg_ini->UapsdMask =
9223 CFG_QOS_WMM_UAPSD_MASK_LEGACY_WMM_PS_DEFAULT;
9224 }
9225 }
9226
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07009227#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
9228 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
9229 {
9230 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
9231 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
9232 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
9233 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
9234 }
9235#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009236
Agarwal Ashish4b87f922014-06-18 03:03:21 +05309237 wlan_hdd_tdls_init(pHddCtx);
9238
Mihir Shetefc7ff5b2014-01-27 11:30:05 +05309239 sme_Register11dScanDoneCallback(pHddCtx->hHal, hdd_11d_scan_done);
9240
Jeff Johnson295189b2012-06-20 16:38:30 -07009241 /* Register with platform driver as client for Suspend/Resume */
9242 status = hddRegisterPmOps(pHddCtx);
9243 if ( !VOS_IS_STATUS_SUCCESS( status ) )
9244 {
9245 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
9246#ifdef WLAN_BTAMP_FEATURE
9247 goto err_bap_stop;
9248#else
Jeff Johnsone7245742012-09-05 17:12:55 -07009249 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07009250#endif //WLAN_BTAMP_FEATURE
9251 }
9252
Yue Ma0d4891e2013-08-06 17:01:45 -07009253 /* Open debugfs interface */
9254 if (VOS_STATUS_SUCCESS != hdd_debugfs_init(pAdapter))
9255 {
9256 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
9257 "%s: hdd_debugfs_init failed!", __func__);
Yue Ma0d4891e2013-08-06 17:01:45 -07009258 }
9259
Jeff Johnson295189b2012-06-20 16:38:30 -07009260 /* Register TM level change handler function to the platform */
9261 status = hddDevTmRegisterNotifyCallback(pHddCtx);
9262 if ( !VOS_IS_STATUS_SUCCESS( status ) )
9263 {
9264 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
9265 goto err_unregister_pmops;
9266 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009267
9268 /* register for riva power on lock to platform driver */
9269 if (req_riva_power_on_lock("wlan"))
9270 {
9271 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
9272 __func__);
9273 goto err_unregister_pmops;
9274 }
9275
Jeff Johnson295189b2012-06-20 16:38:30 -07009276 // register net device notifier for device change notification
9277 ret = register_netdevice_notifier(&hdd_netdev_notifier);
9278
9279 if(ret < 0)
9280 {
9281 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
9282 goto err_free_power_on_lock;
9283 }
9284
9285 //Initialize the nlink service
9286 if(nl_srv_init() != 0)
9287 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05309288 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009289 goto err_reg_netdev;
9290 }
9291
Leo Chang4ce1cc52013-10-21 18:27:15 -07009292#ifdef WLAN_KD_READY_NOTIFIER
9293 pHddCtx->kd_nl_init = 1;
9294#endif /* WLAN_KD_READY_NOTIFIER */
9295
Jeff Johnson295189b2012-06-20 16:38:30 -07009296 //Initialize the BTC service
9297 if(btc_activate_service(pHddCtx) != 0)
9298 {
9299 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
9300 goto err_nl_srv;
9301 }
9302
9303#ifdef PTT_SOCK_SVC_ENABLE
9304 //Initialize the PTT service
9305 if(ptt_sock_activate_svc(pHddCtx) != 0)
9306 {
9307 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
9308 goto err_nl_srv;
9309 }
9310#endif
9311
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05309312#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9313 if(pHddCtx->cfg_ini && pHddCtx->cfg_ini->wlanLoggingEnable)
9314 {
Deepthi Gowri78083a32014-11-04 12:55:51 +05309315 if(wlan_logging_sock_activate_svc(
9316 pHddCtx->cfg_ini->wlanLoggingFEToConsole,
9317 pHddCtx->cfg_ini->wlanLoggingNumBuf))
9318 {
9319 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wlan_logging_sock_activate_svc"
9320 " failed", __func__);
9321 goto err_nl_srv;
9322 }
9323 //TODO: To Remove enableDhcpDebug and use gEnableDebugLog for
9324 //EAPOL and DHCP
9325 pHddCtx->cfg_ini->enableDhcpDebug = CFG_DEBUG_DHCP_ENABLE;
9326 pHddCtx->cfg_ini->gEnableDebugLog = VOS_PKT_PROTO_TYPE_EAPOL;
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05309327 }
9328#endif
9329
Jeff Johnson295189b2012-06-20 16:38:30 -07009330 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07009331 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07009332 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07009333 /* Action frame registered in one adapter which will
9334 * applicable to all interfaces
9335 */
Agarwal Ashish8fa0e9a2014-05-23 00:40:12 +05309336 wlan_hdd_cfg80211_register_frames(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07009337 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009338
9339 mutex_init(&pHddCtx->sap_lock);
Mahesh A Saptasagar60627942014-10-13 13:55:14 +05309340 mutex_init(&pHddCtx->roc_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07009341
Jeff Johnson295189b2012-06-20 16:38:30 -07009342
Sameer Thalappil50dc0092013-02-19 17:23:33 -08009343#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07009344#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
9345 /* Initialize the wake lcok */
9346 wake_lock_init(&pHddCtx->rx_wake_lock,
9347 WAKE_LOCK_SUSPEND,
9348 "qcom_rx_wakelock");
9349#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08009350 /* Initialize the wake lcok */
9351 wake_lock_init(&pHddCtx->sap_wake_lock,
9352 WAKE_LOCK_SUSPEND,
9353 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08009354#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07009355
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07009356 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
9357 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07009358
Katya Nigam5c306ea2014-06-19 15:39:54 +05309359 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_NO_LOAD_UNLOAD_IN_PROGRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -07009360 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
9361 hdd_allow_suspend();
Katya Nigam5c306ea2014-06-19 15:39:54 +05309362
9363#ifdef FEATURE_WLAN_SCAN_PNO
9364 /*SME must send channel update configuration to RIVA*/
9365 sme_UpdateChannelConfig(pHddCtx->hHal);
9366#endif
Abhishek Singhf644b272014-08-21 02:59:39 +05309367 /* Send the update default channel list to the FW*/
9368 sme_UpdateChannelList(pHddCtx->hHal);
Abhishek Singha306a442013-11-07 18:39:01 +05309369#ifndef CONFIG_ENABLE_LINUX_REG
9370 /*updating wiphy so that regulatory user hints can be processed*/
9371 if (wiphy)
9372 {
9373 regulatory_hint(wiphy, "00");
9374 }
9375#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07009376 // Initialize the restart logic
9377 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05309378
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07009379 //Register the traffic monitor timer now
9380 if ( pHddCtx->cfg_ini->dynSplitscan)
9381 {
9382 vos_timer_init(&pHddCtx->tx_rx_trafficTmr,
9383 VOS_TIMER_TYPE_SW,
9384 hdd_tx_rx_pkt_cnt_stat_timer_handler,
9385 (void *)pHddCtx);
9386 }
Dino Mycle6fb96c12014-06-10 11:52:40 +05309387#ifdef WLAN_FEATURE_EXTSCAN
9388 sme_EXTScanRegisterCallback(pHddCtx->hHal,
9389 wlan_hdd_cfg80211_extscan_callback,
9390 pHddCtx);
9391#endif /* WLAN_FEATURE_EXTSCAN */
Jeff Johnson295189b2012-06-20 16:38:30 -07009392 goto success;
9393
9394err_nl_srv:
Leo Chang59cdc7e2013-07-10 10:08:21 -07009395#ifdef WLAN_KD_READY_NOTIFIER
9396 nl_srv_exit(pHddCtx->ptt_pid);
9397#else
Jeff Johnson295189b2012-06-20 16:38:30 -07009398 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07009399#endif /* WLAN_KD_READY_NOTIFIER */
Jeff Johnson295189b2012-06-20 16:38:30 -07009400err_reg_netdev:
9401 unregister_netdevice_notifier(&hdd_netdev_notifier);
9402
9403err_free_power_on_lock:
9404 free_riva_power_on_lock("wlan");
9405
9406err_unregister_pmops:
9407 hddDevTmUnregisterNotifyCallback(pHddCtx);
9408 hddDeregisterPmOps(pHddCtx);
9409
Yue Ma0d4891e2013-08-06 17:01:45 -07009410 hdd_debugfs_exit(pHddCtx);
9411
Jeff Johnson295189b2012-06-20 16:38:30 -07009412#ifdef WLAN_BTAMP_FEATURE
9413err_bap_stop:
9414 WLANBAP_Stop(pVosContext);
9415#endif
9416
9417#ifdef WLAN_BTAMP_FEATURE
9418err_bap_close:
9419 WLANBAP_Close(pVosContext);
9420#endif
9421
Jeff Johnson295189b2012-06-20 16:38:30 -07009422err_close_adapter:
9423 hdd_close_all_adapters( pHddCtx );
Mahesh A Saptasagar9ecefe42014-07-15 18:43:49 +05309424#ifdef CONFIG_ENABLE_LINUX_REG
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05309425err_unregister_wiphy:
Mahesh A Saptasagar9ecefe42014-07-15 18:43:49 +05309426#endif
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05309427 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07009428err_vosstop:
9429 vos_stop(pVosContext);
9430
Amar Singhala49cbc52013-10-08 18:37:44 -07009431err_vosclose:
Jeff Johnson295189b2012-06-20 16:38:30 -07009432 status = vos_sched_close( pVosContext );
9433 if (!VOS_IS_STATUS_SUCCESS(status)) {
9434 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
9435 "%s: Failed to close VOSS Scheduler", __func__);
9436 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
9437 }
Amar Singhala49cbc52013-10-08 18:37:44 -07009438 vos_close(pVosContext );
9439
Amar Singhal0a402232013-10-11 20:57:16 -07009440err_vos_nv_close:
9441
c_hpothue6a36282014-03-19 12:27:38 +05309442#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -07009443 vos_nv_close();
9444
c_hpothu70f8d812014-03-22 22:59:23 +05309445#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009446
9447err_wdclose:
9448 if(pHddCtx->cfg_ini->fIsLogpEnabled)
9449 vos_watchdog_close(pVosContext);
9450
Jeff Johnson295189b2012-06-20 16:38:30 -07009451err_config:
9452 kfree(pHddCtx->cfg_ini);
9453 pHddCtx->cfg_ini= NULL;
9454
9455err_free_hdd_context:
9456 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07009457 wiphy_free(wiphy) ;
9458 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07009459 VOS_BUG(1);
9460
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08009461 if (hdd_is_ssr_required())
9462 {
9463 /* WDI timeout had happened during load, so SSR is needed here */
9464 subsystem_restart("wcnss");
9465 msleep(5000);
9466 }
9467 hdd_set_ssr_required (VOS_FALSE);
9468
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08009469 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07009470
9471success:
9472 EXIT();
9473 return 0;
9474}
9475
9476/**---------------------------------------------------------------------------
9477
Jeff Johnson32d95a32012-09-10 13:15:23 -07009478 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07009479
Jeff Johnson32d95a32012-09-10 13:15:23 -07009480 This is the driver entry point - called in different timeline depending
9481 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07009482
9483 \param - None
9484
9485 \return - 0 for success, non zero for failure
9486
9487 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07009488static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07009489{
9490 VOS_STATUS status;
9491 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07009492 struct device *dev = NULL;
9493 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07009494#ifdef HAVE_WCNSS_CAL_DOWNLOAD
9495 int max_retries = 0;
9496#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009497
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05309498#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9499 wlan_logging_sock_init_svc();
9500#endif
9501
Jeff Johnson295189b2012-06-20 16:38:30 -07009502 ENTER();
9503
Sameer Thalappil50dc0092013-02-19 17:23:33 -08009504#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07009505 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07009506#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009507
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05309508 hddTraceInit();
Jeff Johnson295189b2012-06-20 16:38:30 -07009509 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
9510 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
9511
Jeff Johnson295189b2012-06-20 16:38:30 -07009512#ifdef ANI_BUS_TYPE_PCI
9513
9514 dev = wcnss_wlan_get_device();
9515
9516#endif // ANI_BUS_TYPE_PCI
9517
9518#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07009519
9520#ifdef HAVE_WCNSS_CAL_DOWNLOAD
9521 /* wait until WCNSS driver downloads NV */
9522 while (!wcnss_device_ready() && 5 >= ++max_retries) {
9523 msleep(1000);
9524 }
9525 if (max_retries >= 5) {
9526 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05309527#ifdef WLAN_OPEN_SOURCE
9528 wake_lock_destroy(&wlan_wake_lock);
9529#endif
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05309530
9531#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9532 wlan_logging_sock_deinit_svc();
9533#endif
9534
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07009535 return -ENODEV;
9536 }
9537#endif
9538
Jeff Johnson295189b2012-06-20 16:38:30 -07009539 dev = wcnss_wlan_get_device();
9540#endif // ANI_BUS_TYPE_PLATFORM
9541
9542
9543 do {
9544 if (NULL == dev) {
9545 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
9546 ret_status = -1;
9547 break;
9548 }
9549
Jeff Johnson295189b2012-06-20 16:38:30 -07009550#ifdef TIMER_MANAGER
9551 vos_timer_manager_init();
9552#endif
9553
9554 /* Preopen VOSS so that it is ready to start at least SAL */
9555 status = vos_preOpen(&pVosContext);
9556
9557 if (!VOS_IS_STATUS_SUCCESS(status))
9558 {
9559 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
9560 ret_status = -1;
9561 break;
9562 }
9563
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009564#ifndef MODULE
9565 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
9566 */
9567 hdd_set_conparam((v_UINT_t)con_mode);
9568#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009569
9570 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08009571 if (hdd_wlan_startup(dev))
9572 {
Jeff Johnson295189b2012-06-20 16:38:30 -07009573 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08009574 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009575 vos_preClose( &pVosContext );
9576 ret_status = -1;
9577 break;
9578 }
9579
Jeff Johnson295189b2012-06-20 16:38:30 -07009580 } while (0);
9581
9582 if (0 != ret_status)
9583 {
Jeff Johnson295189b2012-06-20 16:38:30 -07009584#ifdef TIMER_MANAGER
9585 vos_timer_exit();
9586#endif
9587#ifdef MEMORY_DEBUG
9588 vos_mem_exit();
9589#endif
9590
Sameer Thalappil50dc0092013-02-19 17:23:33 -08009591#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07009592 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07009593#endif
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05309594
9595#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9596 wlan_logging_sock_deinit_svc();
9597#endif
9598
Jeff Johnson295189b2012-06-20 16:38:30 -07009599 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
9600 }
9601 else
9602 {
9603 //Send WLAN UP indication to Nlink Service
9604 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
9605
9606 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Jeff Johnson295189b2012-06-20 16:38:30 -07009607 }
9608
9609 EXIT();
9610
9611 return ret_status;
9612}
9613
Jeff Johnson32d95a32012-09-10 13:15:23 -07009614/**---------------------------------------------------------------------------
9615
9616 \brief hdd_module_init() - Init Function
9617
9618 This is the driver entry point (invoked when module is loaded using insmod)
9619
9620 \param - None
9621
9622 \return - 0 for success, non zero for failure
9623
9624 --------------------------------------------------------------------------*/
9625#ifdef MODULE
9626static int __init hdd_module_init ( void)
9627{
9628 return hdd_driver_init();
9629}
Jeff Johnson32d95a32012-09-10 13:15:23 -07009630#else /* #ifdef MODULE */
9631static int __init hdd_module_init ( void)
9632{
9633 /* Driver initialization is delayed to fwpath_changed_handler */
9634 return 0;
9635}
Jeff Johnson32d95a32012-09-10 13:15:23 -07009636#endif /* #ifdef MODULE */
9637
Jeff Johnson295189b2012-06-20 16:38:30 -07009638
9639/**---------------------------------------------------------------------------
9640
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009641 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07009642
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009643 This is the driver exit point (invoked when module is unloaded using rmmod
9644 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07009645
9646 \param - None
9647
9648 \return - None
9649
9650 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009651static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07009652{
9653 hdd_context_t *pHddCtx = NULL;
9654 v_CONTEXT_t pVosContext = NULL;
Agarwal Ashish5e414792014-06-08 15:25:23 +05309655 v_REGDOMAIN_t regId;
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +05309656 unsigned long rc = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07009657
9658 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
9659
9660 //Get the global vos context
9661 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
9662
9663 if(!pVosContext)
9664 {
9665 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
9666 goto done;
9667 }
9668
9669 //Get the HDD context.
9670 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
9671
9672 if(!pHddCtx)
9673 {
9674 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
9675 }
9676 else
9677 {
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +05309678 INIT_COMPLETION(pHddCtx->ssr_comp_var);
9679
9680 if (pHddCtx->isLogpInProgress)
9681 {
Sameer Thalappil451ebb92013-06-28 15:49:58 -07009682 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +05309683 "%s:SSR in Progress; block rmmod !!!", __func__);
9684 rc = wait_for_completion_timeout(&pHddCtx->ssr_comp_var,
9685 msecs_to_jiffies(30000));
9686 if(!rc)
9687 {
9688 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
9689 "%s:SSR timedout, fatal error", __func__);
9690 VOS_BUG(0);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07009691 }
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +05309692 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009693
Vinay Krishna Erannae362b452014-09-23 13:09:46 +05309694 rtnl_lock();
Mihir Shete18156292014-03-11 15:38:30 +05309695 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_UNLOAD_IN_PROGRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -07009696 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
Vinay Krishna Erannae362b452014-09-23 13:09:46 +05309697 rtnl_unlock();
Jeff Johnson295189b2012-06-20 16:38:30 -07009698
Agarwal Ashish8db39882014-07-30 21:56:07 +05309699 /* Driver Need to send country code 00 in below condition
9700 * 1) If gCountryCodePriority is set to 1; and last country
9701 * code set is through 11d. This needs to be done in case
9702 * when NV country code is 00.
9703 * This Needs to be done as when kernel store last country
9704 * code and if stored country code is not through 11d,
9705 * in sme_HandleChangeCountryCodeByUser we will disable 11d
9706 * in next load/unload as soon as we get any country through
9707 * 11d. In sme_HandleChangeCountryCodeByUser
9708 * pMsg->countryCode will be last countryCode and
9709 * pMac->scan.countryCode11d will be country through 11d so
9710 * due to mismatch driver will disable 11d.
9711 *
Agarwal Ashish8db39882014-07-30 21:56:07 +05309712 */
9713
9714 if ((eANI_BOOLEAN_TRUE == sme_Is11dCountrycode(pHddCtx->hHal) &&
Agarwal Ashish8dcd2862014-07-25 11:58:52 +05309715 pHddCtx->cfg_ini->fSupplicantCountryCodeHasPriority &&
Abhishek Singh2a705962014-10-30 14:47:28 +05309716 sme_Is11dSupported(pHddCtx->hHal)))
Agarwal Ashish5e414792014-06-08 15:25:23 +05309717 {
Agarwal Ashish8dcd2862014-07-25 11:58:52 +05309718 hddLog(VOS_TRACE_LEVEL_INFO,
9719 FL("CountryCode 00 is being set while unloading driver"));
Agarwal Ashish5e414792014-06-08 15:25:23 +05309720 vos_nv_getRegDomainFromCountryCode(&regId , "00", COUNTRY_USER);
9721 }
9722
Jeff Johnson295189b2012-06-20 16:38:30 -07009723 //Do all the cleanup before deregistering the driver
9724 hdd_wlan_exit(pHddCtx);
9725 }
9726
Jeff Johnson295189b2012-06-20 16:38:30 -07009727 vos_preClose( &pVosContext );
9728
9729#ifdef TIMER_MANAGER
9730 vos_timer_exit();
9731#endif
9732#ifdef MEMORY_DEBUG
9733 vos_mem_exit();
9734#endif
9735
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05309736#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9737 wlan_logging_sock_deinit_svc();
9738#endif
9739
Jeff Johnson295189b2012-06-20 16:38:30 -07009740done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08009741#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07009742 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07009743#endif
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05309744
Jeff Johnson295189b2012-06-20 16:38:30 -07009745 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
9746}
9747
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009748/**---------------------------------------------------------------------------
9749
9750 \brief hdd_module_exit() - Exit function
9751
9752 This is the driver exit point (invoked when module is unloaded using rmmod)
9753
9754 \param - None
9755
9756 \return - None
9757
9758 --------------------------------------------------------------------------*/
9759static void __exit hdd_module_exit(void)
9760{
9761 hdd_driver_exit();
9762}
9763
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009764#ifdef MODULE
9765static int fwpath_changed_handler(const char *kmessage,
9766 struct kernel_param *kp)
9767{
Jeff Johnson76052702013-04-16 13:55:05 -07009768 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009769}
9770
9771static int con_mode_handler(const char *kmessage,
9772 struct kernel_param *kp)
9773{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07009774 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009775}
9776#else /* #ifdef MODULE */
9777/**---------------------------------------------------------------------------
9778
Jeff Johnson76052702013-04-16 13:55:05 -07009779 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009780
Jeff Johnson76052702013-04-16 13:55:05 -07009781 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009782 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07009783 - invoked when module parameter fwpath is modified from userspace to signal
9784 initializing the WLAN driver or when con_mode is modified from userspace
9785 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009786
9787 \return - 0 for success, non zero for failure
9788
9789 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07009790static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009791{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07009792 int ret_status;
9793
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009794 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07009795 ret_status = hdd_driver_init();
9796 wlan_hdd_inited = ret_status ? 0 : 1;
9797 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009798 }
9799
9800 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07009801
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009802 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07009803
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07009804 ret_status = hdd_driver_init();
9805 wlan_hdd_inited = ret_status ? 0 : 1;
9806 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009807}
9808
Jeff Johnson295189b2012-06-20 16:38:30 -07009809/**---------------------------------------------------------------------------
9810
Jeff Johnson76052702013-04-16 13:55:05 -07009811 \brief fwpath_changed_handler() - Handler Function
9812
9813 Handle changes to the fwpath parameter
9814
9815 \return - 0 for success, non zero for failure
9816
9817 --------------------------------------------------------------------------*/
9818static int fwpath_changed_handler(const char *kmessage,
9819 struct kernel_param *kp)
9820{
9821 int ret;
9822
9823 ret = param_set_copystring(kmessage, kp);
9824 if (0 == ret)
9825 ret = kickstart_driver();
9826 return ret;
9827}
9828
9829/**---------------------------------------------------------------------------
9830
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009831 \brief con_mode_handler() -
9832
9833 Handler function for module param con_mode when it is changed by userspace
9834 Dynamically linked - do nothing
9835 Statically linked - exit and init driver, as in rmmod and insmod
9836
Jeff Johnson76052702013-04-16 13:55:05 -07009837 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009838
Jeff Johnson76052702013-04-16 13:55:05 -07009839 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009840
9841 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07009842static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009843{
Jeff Johnson76052702013-04-16 13:55:05 -07009844 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009845
Jeff Johnson76052702013-04-16 13:55:05 -07009846 ret = param_set_int(kmessage, kp);
9847 if (0 == ret)
9848 ret = kickstart_driver();
9849 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009850}
9851#endif /* #ifdef MODULE */
9852
9853/**---------------------------------------------------------------------------
9854
Jeff Johnson295189b2012-06-20 16:38:30 -07009855 \brief hdd_get_conparam() -
9856
9857 This is the driver exit point (invoked when module is unloaded using rmmod)
9858
9859 \param - None
9860
9861 \return - tVOS_CON_MODE
9862
9863 --------------------------------------------------------------------------*/
9864tVOS_CON_MODE hdd_get_conparam ( void )
9865{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009866#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07009867 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009868#else
9869 return (tVOS_CON_MODE)curr_con_mode;
9870#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009871}
9872void hdd_set_conparam ( v_UINT_t newParam )
9873{
9874 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009875#ifndef MODULE
9876 curr_con_mode = con_mode;
9877#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009878}
9879/**---------------------------------------------------------------------------
9880
9881 \brief hdd_softap_sta_deauth() - function
9882
9883 This to take counter measure to handle deauth req from HDD
9884
9885 \param - pAdapter - Pointer to the HDD
9886
9887 \param - enable - boolean value
9888
9889 \return - None
9890
9891 --------------------------------------------------------------------------*/
9892
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +05309893VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter,
9894 struct tagCsrDelStaParams *pDelStaParams)
Jeff Johnson295189b2012-06-20 16:38:30 -07009895{
Jeff Johnson295189b2012-06-20 16:38:30 -07009896 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009897 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07009898
9899 ENTER();
9900
Rajesh Chauhan18488fc2013-08-22 10:15:03 -07009901 hddLog(LOG1, "hdd_softap_sta_deauth:(%p, false)",
9902 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07009903
9904 //Ignore request to deauth bcmc station
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +05309905 if (pDelStaParams->peerMacAddr[0] & 0x1)
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009906 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07009907
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +05309908 vosStatus = WLANSAP_DeauthSta(pVosContext, pDelStaParams);
Jeff Johnson295189b2012-06-20 16:38:30 -07009909
9910 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009911 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07009912}
9913
9914/**---------------------------------------------------------------------------
9915
Rashmi Ramanna1f0948d2014-08-28 15:33:48 +05309916 \brief hdd_del_all_sta() - function
9917
9918 This function removes all the stations associated on stopping AP/P2P GO.
9919
9920 \param - pAdapter - Pointer to the HDD
9921
9922 \return - None
9923
9924 --------------------------------------------------------------------------*/
9925
9926int hdd_del_all_sta(hdd_adapter_t *pAdapter)
9927{
9928 v_U16_t i;
9929 VOS_STATUS vos_status;
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +05309930 v_CONTEXT_t pVosContext = ( WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
9931 ptSapContext pSapCtx = NULL;
9932 pSapCtx = VOS_GET_SAP_CB(pVosContext);
9933 if(pSapCtx == NULL){
9934 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9935 FL("psapCtx is NULL"));
9936 return 1;
9937 }
Rashmi Ramanna1f0948d2014-08-28 15:33:48 +05309938 ENTER();
9939
9940 hddLog(VOS_TRACE_LEVEL_INFO,
9941 "%s: Delete all STAs associated.",__func__);
9942 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
9943 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
9944 )
9945 {
9946 for(i = 0; i < WLAN_MAX_STA_COUNT; i++)
9947 {
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +05309948 if ((pSapCtx->aStaInfo[i].isUsed) &&
9949 (!pSapCtx->aStaInfo[i].isDeauthInProgress))
Rashmi Ramanna1f0948d2014-08-28 15:33:48 +05309950 {
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +05309951 struct tagCsrDelStaParams delStaParams;
9952
9953 WLANSAP_PopulateDelStaParams(
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +05309954 pSapCtx->aStaInfo[i].macAddrSTA.bytes,
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +05309955 eCsrForcedDeauthSta, SIR_MAC_MGMT_DEAUTH >> 4,
9956 &delStaParams);
9957 vos_status = hdd_softap_sta_deauth(pAdapter, &delStaParams);
Rashmi Ramanna1f0948d2014-08-28 15:33:48 +05309958 if (VOS_IS_STATUS_SUCCESS(vos_status))
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +05309959 pSapCtx->aStaInfo[i].isDeauthInProgress = TRUE;
Rashmi Ramanna1f0948d2014-08-28 15:33:48 +05309960 }
9961 }
9962 }
9963
9964 EXIT();
9965 return 0;
9966}
9967
9968/**---------------------------------------------------------------------------
9969
Jeff Johnson295189b2012-06-20 16:38:30 -07009970 \brief hdd_softap_sta_disassoc() - function
9971
9972 This to take counter measure to handle deauth req from HDD
9973
9974 \param - pAdapter - Pointer to the HDD
9975
9976 \param - enable - boolean value
9977
9978 \return - None
9979
9980 --------------------------------------------------------------------------*/
9981
9982void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
9983{
9984 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
9985
9986 ENTER();
9987
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05309988 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07009989
9990 //Ignore request to disassoc bcmc station
9991 if( pDestMacAddress[0] & 0x1 )
9992 return;
9993
9994 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
9995}
9996
9997void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
9998{
9999 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
10000
10001 ENTER();
10002
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +053010003 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -070010004
10005 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
10006}
10007
Jeff Johnson295189b2012-06-20 16:38:30 -070010008/**---------------------------------------------------------------------------
10009 *
10010 * \brief hdd_get__concurrency_mode() -
10011 *
10012 *
10013 * \param - None
10014 *
10015 * \return - CONCURRENCY MODE
10016 *
10017 * --------------------------------------------------------------------------*/
10018tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
10019{
10020 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
10021 hdd_context_t *pHddCtx;
10022
10023 if (NULL != pVosContext)
10024 {
10025 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
10026 if (NULL != pHddCtx)
10027 {
10028 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
10029 }
10030 }
10031
10032 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070010033 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -070010034 return VOS_STA;
10035}
Sushant Kaushikabb7ee62014-07-18 16:20:12 +053010036v_BOOL_t
10037wlan_hdd_is_GO_power_collapse_allowed (hdd_context_t* pHddCtx)
10038{
10039 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -070010040
Sushant Kaushikabb7ee62014-07-18 16:20:12 +053010041 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_GO);
10042 if (pAdapter == NULL)
10043 {
10044 hddLog(VOS_TRACE_LEVEL_INFO,
10045 FL("GO doesn't exist"));
10046 return TRUE;
10047 }
10048 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
10049 {
10050 hddLog(VOS_TRACE_LEVEL_INFO,
10051 FL("GO started"));
10052 return TRUE;
10053 }
10054 else
10055 /* wait till GO changes its interface to p2p device */
10056 hddLog(VOS_TRACE_LEVEL_INFO,
10057 FL("Del_bss called, avoid apps suspend"));
10058 return FALSE;
10059
10060}
Jeff Johnson295189b2012-06-20 16:38:30 -070010061/* Decide whether to allow/not the apps power collapse.
10062 * Allow apps power collapse if we are in connected state.
10063 * if not, allow only if we are in IMPS */
10064v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
10065{
10066 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -080010067 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -080010068 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -070010069 hdd_config_t *pConfig = pHddCtx->cfg_ini;
10070 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
10071 hdd_adapter_t *pAdapter = NULL;
10072 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -080010073 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -070010074
Jeff Johnson295189b2012-06-20 16:38:30 -070010075 if (VOS_STA_SAP_MODE == hdd_get_conparam())
10076 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -070010077
Yathish9f22e662012-12-10 14:21:35 -080010078 concurrent_state = hdd_get_concurrency_mode();
10079
Sushant Kaushikabb7ee62014-07-18 16:20:12 +053010080 if ((concurrent_state == (VOS_STA | VOS_P2P_GO)) &&
10081 !(wlan_hdd_is_GO_power_collapse_allowed(pHddCtx)))
10082 return FALSE;
Yathish9f22e662012-12-10 14:21:35 -080010083#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
Sushant Kaushikabb7ee62014-07-18 16:20:12 +053010084
Yathish9f22e662012-12-10 14:21:35 -080010085 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
Sushant Kaushikabb7ee62014-07-18 16:20:12 +053010086 (concurrent_state == (VOS_STA | VOS_P2P_GO)))&&
Yathish9f22e662012-12-10 14:21:35 -080010087 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
10088 return TRUE;
10089#endif
10090
Jeff Johnson295189b2012-06-20 16:38:30 -070010091 /*loop through all adapters. TBD fix for Concurrency */
10092 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10093 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
10094 {
10095 pAdapter = pAdapterNode->pAdapter;
10096 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
10097 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
10098 {
Srikant Kuppafef66a72013-01-30 17:32:44 -080010099 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
c_hpothu4e8faac2014-05-16 17:38:44 +053010100 && (pmcState != IMPS && pmcState != BMPS && pmcState != UAPSD
Srikant Kuppafef66a72013-01-30 17:32:44 -080010101 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -080010102 (eANI_BOOLEAN_TRUE == scanRspPending) ||
10103 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -070010104 {
Srikant Kuppafef66a72013-01-30 17:32:44 -080010105 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -080010106 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
10107 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -070010108 return FALSE;
10109 }
10110 }
10111 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10112 pAdapterNode = pNext;
10113 }
10114 return TRUE;
10115}
10116
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -080010117/* Decides whether to send suspend notification to Riva
10118 * if any adapter is in BMPS; then it is required */
10119v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
10120{
10121 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
10122 hdd_config_t *pConfig = pHddCtx->cfg_ini;
10123
10124 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
10125 {
10126 return TRUE;
10127 }
10128 return FALSE;
10129}
10130
Jeff Johnson295189b2012-06-20 16:38:30 -070010131void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
10132{
10133 switch(mode)
10134 {
Chilam Ngc4244af2013-04-01 15:37:32 -070010135 case VOS_STA_MODE:
10136 case VOS_P2P_CLIENT_MODE:
10137 case VOS_P2P_GO_MODE:
10138 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -070010139 pHddCtx->concurrency_mode |= (1 << mode);
Agarwal Ashish51325b52014-06-16 16:50:49 +053010140 pHddCtx->no_of_open_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -070010141 break;
10142 default:
10143 break;
Jeff Johnson295189b2012-06-20 16:38:30 -070010144 }
Agarwal Ashish51325b52014-06-16 16:50:49 +053010145 hddLog(VOS_TRACE_LEVEL_INFO, FL("concurrency_mode = 0x%x "
10146 "Number of open sessions for mode %d = %d"),
10147 pHddCtx->concurrency_mode, mode,
10148 pHddCtx->no_of_open_sessions[mode]);
Jeff Johnson295189b2012-06-20 16:38:30 -070010149}
10150
10151
10152void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
10153{
10154 switch(mode)
10155 {
Chilam Ngc4244af2013-04-01 15:37:32 -070010156 case VOS_STA_MODE:
10157 case VOS_P2P_CLIENT_MODE:
10158 case VOS_P2P_GO_MODE:
10159 case VOS_STA_SAP_MODE:
Agarwal Ashish51325b52014-06-16 16:50:49 +053010160 pHddCtx->no_of_open_sessions[mode]--;
10161 if (!(pHddCtx->no_of_open_sessions[mode]))
10162 pHddCtx->concurrency_mode &= (~(1 << mode));
Jeff Johnson295189b2012-06-20 16:38:30 -070010163 break;
10164 default:
10165 break;
10166 }
Agarwal Ashish51325b52014-06-16 16:50:49 +053010167 hddLog(VOS_TRACE_LEVEL_INFO, FL("concurrency_mode = 0x%x "
10168 "Number of open sessions for mode %d = %d"),
10169 pHddCtx->concurrency_mode, mode, pHddCtx->no_of_open_sessions[mode]);
10170
10171}
10172/**---------------------------------------------------------------------------
10173 *
10174 * \brief wlan_hdd_incr_active_session()
10175 *
10176 * This function increments the number of active sessions
10177 * maintained per device mode
10178 * Incase of STA/P2P CLI/IBSS upon connection indication it is incremented
10179 * Incase of SAP/P2P GO upon bss start it is incremented
10180 *
10181 * \param pHddCtx - HDD Context
10182 * \param mode - device mode
10183 *
10184 * \return - None
10185 *
10186 * --------------------------------------------------------------------------*/
10187void wlan_hdd_incr_active_session(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
10188{
10189 switch (mode) {
10190 case VOS_STA_MODE:
10191 case VOS_P2P_CLIENT_MODE:
10192 case VOS_P2P_GO_MODE:
10193 case VOS_STA_SAP_MODE:
10194 pHddCtx->no_of_active_sessions[mode]++;
10195 break;
10196 default:
10197 hddLog(VOS_TRACE_LEVEL_INFO, FL("Not Expected Mode %d"), mode);
10198 break;
10199 }
10200 hddLog(VOS_TRACE_LEVEL_INFO, FL("No.# of active sessions for mode %d = %d"),
10201 mode,
10202 pHddCtx->no_of_active_sessions[mode]);
10203}
10204
10205/**---------------------------------------------------------------------------
10206 *
10207 * \brief wlan_hdd_decr_active_session()
10208 *
10209 * This function decrements the number of active sessions
10210 * maintained per device mode
10211 * Incase of STA/P2P CLI/IBSS upon disconnection it is decremented
10212 * Incase of SAP/P2P GO upon bss stop it is decremented
10213 *
10214 * \param pHddCtx - HDD Context
10215 * \param mode - device mode
10216 *
10217 * \return - None
10218 *
10219 * --------------------------------------------------------------------------*/
10220void wlan_hdd_decr_active_session(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
10221{
10222 switch (mode) {
10223 case VOS_STA_MODE:
10224 case VOS_P2P_CLIENT_MODE:
10225 case VOS_P2P_GO_MODE:
10226 case VOS_STA_SAP_MODE:
Agarwal Ashish5325f522014-08-06 00:58:44 +053010227 if (pHddCtx->no_of_active_sessions[mode] > 0)
10228 pHddCtx->no_of_active_sessions[mode]--;
10229 else
10230 hddLog(VOS_TRACE_LEVEL_INFO, FL(" No.# of Active sessions"
10231 "is already Zero"));
Agarwal Ashish51325b52014-06-16 16:50:49 +053010232 break;
10233 default:
10234 hddLog(VOS_TRACE_LEVEL_INFO, FL("Not Expected Mode %d"), mode);
10235 break;
10236 }
10237 hddLog(VOS_TRACE_LEVEL_INFO, FL("No.# of active sessions for mode %d = %d"),
10238 mode,
10239 pHddCtx->no_of_active_sessions[mode]);
Jeff Johnson295189b2012-06-20 16:38:30 -070010240}
10241
Jeff Johnsone7245742012-09-05 17:12:55 -070010242/**---------------------------------------------------------------------------
10243 *
10244 * \brief wlan_hdd_restart_init
10245 *
10246 * This function initalizes restart timer/flag. An internal function.
10247 *
10248 * \param - pHddCtx
10249 *
10250 * \return - None
10251 *
10252 * --------------------------------------------------------------------------*/
10253
10254static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
10255{
10256 /* Initialize */
10257 pHddCtx->hdd_restart_retries = 0;
10258 atomic_set(&pHddCtx->isRestartInProgress, 0);
10259 vos_timer_init(&pHddCtx->hdd_restart_timer,
10260 VOS_TIMER_TYPE_SW,
10261 wlan_hdd_restart_timer_cb,
10262 pHddCtx);
10263}
10264/**---------------------------------------------------------------------------
10265 *
10266 * \brief wlan_hdd_restart_deinit
10267 *
10268 * This function cleans up the resources used. An internal function.
10269 *
10270 * \param - pHddCtx
10271 *
10272 * \return - None
10273 *
10274 * --------------------------------------------------------------------------*/
10275
10276static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
10277{
10278
10279 VOS_STATUS vos_status;
10280 /* Block any further calls */
10281 atomic_set(&pHddCtx->isRestartInProgress, 1);
10282 /* Cleanup */
10283 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
10284 if (!VOS_IS_STATUS_SUCCESS(vos_status))
c_hpothu6ff1c3c2013-10-01 19:01:57 +053010285 hddLog(LOGE, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -070010286 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
10287 if (!VOS_IS_STATUS_SUCCESS(vos_status))
c_hpothu6ff1c3c2013-10-01 19:01:57 +053010288 hddLog(LOGE, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -070010289
10290}
10291
10292/**---------------------------------------------------------------------------
10293 *
10294 * \brief wlan_hdd_framework_restart
10295 *
10296 * This function uses a cfg80211 API to start a framework initiated WLAN
10297 * driver module unload/load.
10298 *
10299 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
10300 *
10301 *
10302 * \param - pHddCtx
10303 *
10304 * \return - VOS_STATUS_SUCCESS: Success
10305 * VOS_STATUS_E_EMPTY: Adapter is Empty
10306 * VOS_STATUS_E_NOMEM: No memory
10307
10308 * --------------------------------------------------------------------------*/
10309
10310static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
10311{
10312 VOS_STATUS status = VOS_STATUS_SUCCESS;
10313 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -070010314 int len = (sizeof (struct ieee80211_mgmt));
10315 struct ieee80211_mgmt *mgmt = NULL;
10316
10317 /* Prepare the DEAUTH managment frame with reason code */
10318 mgmt = kzalloc(len, GFP_KERNEL);
10319 if(mgmt == NULL)
10320 {
10321 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
10322 "%s: memory allocation failed (%d bytes)", __func__, len);
10323 return VOS_STATUS_E_NOMEM;
10324 }
10325 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -070010326
10327 /* Iterate over all adapters/devices */
10328 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10329 do
10330 {
10331 if( (status == VOS_STATUS_SUCCESS) &&
10332 pAdapterNode &&
10333 pAdapterNode->pAdapter)
10334 {
10335 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
10336 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
10337 pAdapterNode->pAdapter->dev->name,
10338 pAdapterNode->pAdapter->device_mode,
10339 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -070010340 /*
10341 * CFG80211 event to restart the driver
10342 *
10343 * 'cfg80211_send_unprot_deauth' sends a
10344 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
10345 * of SME(Linux Kernel) state machine.
10346 *
10347 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
10348 * the driver.
10349 *
10350 */
10351
10352 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -070010353 }
10354 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10355 pAdapterNode = pNext;
10356 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
10357
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -070010358
10359 /* Free the allocated management frame */
10360 kfree(mgmt);
10361
Jeff Johnsone7245742012-09-05 17:12:55 -070010362 /* Retry until we unload or reach max count */
10363 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
10364 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
10365
10366 return status;
10367
10368}
10369/**---------------------------------------------------------------------------
10370 *
10371 * \brief wlan_hdd_restart_timer_cb
10372 *
10373 * Restart timer callback. An internal function.
10374 *
10375 * \param - User data:
10376 *
10377 * \return - None
10378 *
10379 * --------------------------------------------------------------------------*/
10380
10381void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
10382{
10383 hdd_context_t *pHddCtx = usrDataForCallback;
10384 wlan_hdd_framework_restart(pHddCtx);
10385 return;
10386
10387}
10388
10389
10390/**---------------------------------------------------------------------------
10391 *
10392 * \brief wlan_hdd_restart_driver
10393 *
10394 * This function sends an event to supplicant to restart the WLAN driver.
10395 *
10396 * This function is called from vos_wlanRestart.
10397 *
10398 * \param - pHddCtx
10399 *
10400 * \return - VOS_STATUS_SUCCESS: Success
10401 * VOS_STATUS_E_EMPTY: Adapter is Empty
10402 * VOS_STATUS_E_ALREADY: Request already in progress
10403
10404 * --------------------------------------------------------------------------*/
10405VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
10406{
10407 VOS_STATUS status = VOS_STATUS_SUCCESS;
10408
10409 /* A tight check to make sure reentrancy */
10410 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
10411 {
Mihir Shetefd528652014-06-23 19:07:50 +053010412 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnsone7245742012-09-05 17:12:55 -070010413 "%s: WLAN restart is already in progress", __func__);
10414
10415 return VOS_STATUS_E_ALREADY;
10416 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -070010417 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -080010418#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -070010419 wcnss_reset_intr();
10420#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -070010421
Jeff Johnsone7245742012-09-05 17:12:55 -070010422 return status;
10423}
10424
Mihir Shetee1093ba2014-01-21 20:13:32 +053010425/**---------------------------------------------------------------------------
10426 *
10427 * \brief wlan_hdd_init_channels
10428 *
10429 * This function is used to initialize the channel list in CSR
10430 *
10431 * This function is called from hdd_wlan_startup
10432 *
10433 * \param - pHddCtx: HDD context
10434 *
10435 * \return - VOS_STATUS_SUCCESS: Success
10436 * VOS_STATUS_E_FAULT: Failure reported by SME
10437
10438 * --------------------------------------------------------------------------*/
10439static VOS_STATUS wlan_hdd_init_channels(hdd_context_t *pHddCtx)
10440{
10441 eHalStatus status;
10442
10443 status = sme_InitChannels(pHddCtx->hHal);
10444 if (HAL_STATUS_SUCCESS(status))
10445 {
10446 return VOS_STATUS_SUCCESS;
10447 }
10448 else
10449 {
10450 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Channel initialization failed(%d)",
10451 __func__, status);
10452 return VOS_STATUS_E_FAULT;
10453 }
10454}
10455
Mihir Shete04206452014-11-20 17:50:58 +053010456#ifdef CONFIG_ENABLE_LINUX_REG
Agarwal Ashish6db9d532014-09-30 18:19:10 +053010457VOS_STATUS wlan_hdd_init_channels_for_cc(hdd_context_t *pHddCtx, driver_load_type init )
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053010458{
10459 eHalStatus status;
10460
Agarwal Ashish6db9d532014-09-30 18:19:10 +053010461 status = sme_InitChannelsForCC(pHddCtx->hHal, init);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053010462 if (HAL_STATUS_SUCCESS(status))
10463 {
10464 return VOS_STATUS_SUCCESS;
10465 }
10466 else
10467 {
10468 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Issue reg hint failed(%d)",
10469 __func__, status);
10470 return VOS_STATUS_E_FAULT;
10471 }
10472}
Mihir Shete04206452014-11-20 17:50:58 +053010473#endif
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -070010474/*
10475 * API to find if there is any STA or P2P-Client is connected
10476 */
10477VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
10478{
10479 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
10480}
Jeff Johnsone7245742012-09-05 17:12:55 -070010481
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053010482int wlan_hdd_scan_abort(hdd_adapter_t *pAdapter)
10483{
10484 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10485 hdd_scaninfo_t *pScanInfo = NULL;
Girish Gowli4bf7a632014-06-12 13:42:11 +053010486 long status = 0;
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053010487
10488 pScanInfo = &pHddCtx->scan_info;
10489 if (pScanInfo->mScanPending)
10490 {
10491 INIT_COMPLETION(pScanInfo->abortscan_event_var);
Kaushik, Sushant4975a572014-10-21 16:07:48 +053010492 hdd_abort_mac_scan(pHddCtx, pScanInfo->sessionId,
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053010493 eCSR_SCAN_ABORT_DEFAULT);
10494
10495 status = wait_for_completion_interruptible_timeout(
10496 &pScanInfo->abortscan_event_var,
10497 msecs_to_jiffies(5000));
Girish Gowli4bf7a632014-06-12 13:42:11 +053010498 if (0 >= status)
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053010499 {
10500 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Girish Gowli4bf7a632014-06-12 13:42:11 +053010501 "%s: Timeout or Interrupt occurred while waiting for abort"
10502 "scan, status- %ld", __func__, status);
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053010503 return -ETIMEDOUT;
10504 }
10505 }
Girish Gowli4bf7a632014-06-12 13:42:11 +053010506 return 0;
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053010507}
10508
c_hpothu225aa7c2014-10-22 17:45:13 +053010509VOS_STATUS wlan_hdd_cancel_remain_on_channel(hdd_context_t *pHddCtx)
10510{
10511 hdd_adapter_t *pAdapter;
10512 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
10513 VOS_STATUS vosStatus;
10514
10515 vosStatus = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10516 while (NULL != pAdapterNode && VOS_STATUS_E_EMPTY != vosStatus)
10517 {
10518 pAdapter = pAdapterNode->pAdapter;
10519 if (NULL != pAdapter)
10520 {
10521 if (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode ||
10522 WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ||
10523 WLAN_HDD_P2P_GO == pAdapter->device_mode)
10524 {
10525 hddLog(LOG1, FL("abort ROC deviceMode: %d"),
10526 pAdapter->device_mode);
10527 if (VOS_STATUS_SUCCESS !=
10528 wlan_hdd_cancel_existing_remain_on_channel(pAdapter))
10529 {
10530 hddLog(LOGE, FL("failed to abort ROC"));
10531 return VOS_STATUS_E_FAILURE;
10532 }
10533 }
10534 }
10535 vosStatus = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10536 pAdapterNode = pNext;
10537 }
10538 return VOS_STATUS_SUCCESS;
10539}
Jeff Johnson295189b2012-06-20 16:38:30 -070010540//Register the module init/exit functions
10541module_init(hdd_module_init);
10542module_exit(hdd_module_exit);
10543
10544MODULE_LICENSE("Dual BSD/GPL");
10545MODULE_AUTHOR("Qualcomm Atheros, Inc.");
10546MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
10547
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070010548module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
10549 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -070010550
Jeff Johnson76052702013-04-16 13:55:05 -070010551module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -070010552 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Arif Hussain66559122013-11-21 10:11:40 -080010553
10554module_param(enable_dfs_chan_scan, int,
10555 S_IRUSR | S_IRGRP | S_IROTH);
10556
10557module_param(enable_11d, int,
10558 S_IRUSR | S_IRGRP | S_IROTH);
10559
10560module_param(country_code, charp,
10561 S_IRUSR | S_IRGRP | S_IROTH);