blob: d62ec5ebe92a75ad65b71c902f357cbe11bb8fc8 [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Rajeev Kumar Sirasanagandlaa74e1222018-01-09 17:38:55 +05302 * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved.
Kiet Lam842dad02014-02-18 18:44:02 -08003 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
Kiet Lama7f454d2014-07-24 12:04:06 -070023 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
Gopichand Nakkala92f07d82013-01-08 21:16:34 -080026 */
Kiet Lam842dad02014-02-18 18:44:02 -080027
28
Kiet Lama7f454d2014-07-24 12:04:06 -070029
30
Jeff Johnson295189b2012-06-20 16:38:30 -070031/*========================================================================
32
33 \file wlan_hdd_main.c
34
35 \brief WLAN Host Device Driver implementation
36
Jeff Johnson295189b2012-06-20 16:38:30 -070037
38 ========================================================================*/
39
40/**=========================================================================
41
42 EDIT HISTORY FOR FILE
43
44
45 This section contains comments describing changes made to the module.
46 Notice that changes are listed in reverse chronological order.
47
48
49 $Header:$ $DateTime: $ $Author: $
50
51
52 when who what, where, why
53 -------- --- --------------------------------------------------------
54 04/5/09 Shailender Created module.
55 02/24/10 Sudhir.S.Kohalli Added to support param for SoftAP module
56 06/03/10 js - Added support to hostapd driven deauth/disassoc/mic failure
57 ==========================================================================*/
58
59/*--------------------------------------------------------------------------
60 Include Files
61 ------------------------------------------------------------------------*/
62//#include <wlan_qct_driver.h>
63#include <wlan_hdd_includes.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070064#include <vos_api.h>
65#include <vos_sched.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070066#include <linux/etherdevice.h>
67#include <linux/firmware.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070068#ifdef ANI_BUS_TYPE_PLATFORM
69#include <linux/wcnss_wlan.h>
70#endif //ANI_BUS_TYPE_PLATFORM
71#ifdef ANI_BUS_TYPE_PCI
72#include "wcnss_wlan.h"
73#endif /* ANI_BUS_TYPE_PCI */
74#include <wlan_hdd_tx_rx.h>
75#include <palTimer.h>
76#include <wniApi.h>
77#include <wlan_nlink_srv.h>
78#include <wlan_btc_svc.h>
79#include <wlan_hdd_cfg.h>
80#include <wlan_ptt_sock_svc.h>
Vinay Krishna Erannad938c422014-03-10 17:14:21 +053081#include <wlan_logging_sock_svc.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070082#include <wlan_hdd_wowl.h>
83#include <wlan_hdd_misc.h>
84#include <wlan_hdd_wext.h>
85#ifdef WLAN_BTAMP_FEATURE
86#include <bap_hdd_main.h>
87#include <bapInternal.h>
88#endif // WLAN_BTAMP_FEATURE
Sushant Kaushik4b7cb302014-01-06 17:45:01 +053089#include "wlan_hdd_trace.h"
90#include "vos_types.h"
91#include "vos_trace.h"
Jeff Johnson295189b2012-06-20 16:38:30 -070092#include <linux/wireless.h>
93#include <net/cfg80211.h>
Vinay Krishna Erannad9cbdb32014-01-16 12:59:10 +053094#include <linux/inetdevice.h>
95#include <net/addrconf.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070096#include "wlan_hdd_cfg80211.h"
97#include "wlan_hdd_p2p.h"
Jeff Johnson295189b2012-06-20 16:38:30 -070098#include <linux/rtnetlink.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070099int wlan_hdd_ftm_start(hdd_context_t *pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700100#include "sapApi.h"
101#include <linux/semaphore.h>
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -0700102#include <linux/ctype.h>
Arun Kumar Khandavalli74fe3032014-03-17 20:35:34 +0530103#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0))
104#include <soc/qcom/subsystem_restart.h>
105#else
Jeff Johnson295189b2012-06-20 16:38:30 -0700106#include <mach/subsystem_restart.h>
Arun Kumar Khandavalli74fe3032014-03-17 20:35:34 +0530107#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700108#include <wlan_hdd_hostapd.h>
109#include <wlan_hdd_softap_tx_rx.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700110#include "cfgApi.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700111#include "wlan_hdd_dev_pwr.h"
112#ifdef WLAN_BTAMP_FEATURE
113#include "bap_hdd_misc.h"
114#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700115#include "wlan_qct_pal_trace.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700116#include "qwlan_version.h"
Yathish9f22e662012-12-10 14:21:35 -0800117#include "wlan_qct_wda.h"
Chilam NG571c65a2013-01-19 12:27:36 +0530118#ifdef FEATURE_WLAN_TDLS
119#include "wlan_hdd_tdls.h"
120#endif
Yue Ma0d4891e2013-08-06 17:01:45 -0700121#include "wlan_hdd_debugfs.h"
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +0530122#include "sapInternal.h"
Hanumanth Reddy Pothula1efcd162018-03-14 14:32:27 +0530123#include "wlan_hdd_request_manager.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700124
125#ifdef MODULE
126#define WLAN_MODULE_NAME module_name(THIS_MODULE)
127#else
128#define WLAN_MODULE_NAME "wlan"
129#endif
130
131#ifdef TIMER_MANAGER
132#define TIMER_MANAGER_STR " +TIMER_MANAGER"
133#else
134#define TIMER_MANAGER_STR ""
135#endif
136
137#ifdef MEMORY_DEBUG
138#define MEMORY_DEBUG_STR " +MEMORY_DEBUG"
139#else
140#define MEMORY_DEBUG_STR ""
141#endif
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530142#define MAX_WAIT_FOR_ROC_COMPLETION 3
Jeff Johnson295189b2012-06-20 16:38:30 -0700143/* the Android framework expects this param even though we don't use it */
144#define BUF_LEN 20
Jeff Johnson76052702013-04-16 13:55:05 -0700145static char fwpath_buffer[BUF_LEN];
146static struct kparam_string fwpath = {
147 .string = fwpath_buffer,
148 .maxlen = BUF_LEN,
149};
Arif Hussain66559122013-11-21 10:11:40 -0800150
151static char *country_code;
152static int enable_11d = -1;
153static int enable_dfs_chan_scan = -1;
c_hpothu92367912014-05-01 15:18:17 +0530154static int gbcnMissRate = -1;
Arif Hussain66559122013-11-21 10:11:40 -0800155
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700156#ifndef MODULE
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700157static int wlan_hdd_inited;
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700158#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700159
Jeff Johnsone7245742012-09-05 17:12:55 -0700160/*
Jeff Johnson72a40512013-12-19 10:14:15 -0800161 * spinlock for synchronizing asynchronous request/response
162 * (full description of use in wlan_hdd_main.h)
163 */
164DEFINE_SPINLOCK(hdd_context_lock);
165
166/*
Jeff Johnsone7245742012-09-05 17:12:55 -0700167 * The rate at which the driver sends RESTART event to supplicant
168 * once the function 'vos_wlanRestart()' is called
169 *
170 */
171#define WLAN_HDD_RESTART_RETRY_DELAY_MS 5000 /* 5 second */
172#define WLAN_HDD_RESTART_RETRY_MAX_CNT 5 /* 5 retries */
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -0700173
174/*
175 * Size of Driver command strings from upper layer
176 */
177#define SIZE_OF_SETROAMMODE 11 /* size of SETROAMMODE */
178#define SIZE_OF_GETROAMMODE 11 /* size of GETROAMMODE */
179
Abhishek Singh00b71972016-01-07 10:51:04 +0530180#ifdef WLAN_FEATURE_RMC
181/*
182 * Ibss prop IE from command will be of size:
183 * size = sizeof(oui) + sizeof(oui_data) + 1(Element ID) + 1(EID Length)
184 * OUI_DATA should be at least 3 bytes long
185 */
186#define WLAN_HDD_IBSS_MIN_OUI_DATA_LENGTH (3)
187#endif
188
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -0800189#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda5cecb202013-10-08 09:13:25 -0700190#define TID_MIN_VALUE 0
191#define TID_MAX_VALUE 15
192static VOS_STATUS hdd_get_tsm_stats(hdd_adapter_t *pAdapter, const tANI_U8 tid,
193 tAniTrafStrmMetrics* pTsmMetrics);
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -0800194static VOS_STATUS hdd_parse_ese_beacon_req(tANI_U8 *pValue,
195 tCsrEseBeaconReq *pEseBcnReq);
196#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -0700197
Atul Mittal1d722422014-03-19 11:15:07 +0530198/*
199 * Maximum buffer size used for returning the data back to user space
200 */
201#define WLAN_MAX_BUF_SIZE 1024
202#define WLAN_PRIV_DATA_MAX_LEN 8192
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -0700203
Abhishek Singh00b71972016-01-07 10:51:04 +0530204/*
205 * When ever we need to print IBSSPEERINFOALL for morethan 16 STA
206 * we will split the printing.
207 */
208#define NUM_OF_STA_DATA_TO_PRINT 16
209
210#ifdef WLAN_FEATURE_RMC
211#define WLAN_NLINK_CESIUM 30
212#endif
213
c_hpothu92367912014-05-01 15:18:17 +0530214//wait time for beacon miss rate.
215#define BCN_MISS_RATE_TIME 500
216
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +0530217/*
218 * Android DRIVER command structures
219 */
220struct android_wifi_reassoc_params {
221 unsigned char bssid[18];
222 int channel;
223};
224
Sushant Kaushik83392fa2015-05-05 17:44:40 +0530225static vos_wake_lock_t wlan_wake_lock;
226
Jeff Johnson295189b2012-06-20 16:38:30 -0700227/* set when SSR is needed after unload */
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -0700228static e_hdd_ssr_required isSsrRequired = HDD_SSR_NOT_REQUIRED;
Jeff Johnson295189b2012-06-20 16:38:30 -0700229
230//internal function declaration
Jeff Johnsone7245742012-09-05 17:12:55 -0700231static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx);
232static void wlan_hdd_restart_init(hdd_context_t *pHddCtx);
233static void wlan_hdd_restart_deinit(hdd_context_t *pHddCtx);
Abhishek Singh00b71972016-01-07 10:51:04 +0530234
235#ifdef WLAN_FEATURE_RMC
236static void hdd_tx_fail_ind_callback(v_U8_t *MacAddr, v_U8_t seqNo);
237
238static int hdd_open_cesium_nl_sock(void);
239static void hdd_close_cesium_nl_sock(void);
240static struct sock *cesium_nl_srv_sock;
241static v_U16_t cesium_pid;
242
243static int hdd_ParseIBSSTXFailEventParams(tANI_U8 *pValue,
244 tANI_U8 *tx_fail_count,
245 tANI_U16 *pid);
246
247static int hdd_ParseUserParams(tANI_U8 *pValue, tANI_U8 **ppArg);
248
249#endif /* WLAN_FEATURE_RMC */
Jeff Johnsone7245742012-09-05 17:12:55 -0700250void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback);
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800251void hdd_set_wlan_suspend_mode(bool suspend);
Jeff Johnsone7245742012-09-05 17:12:55 -0700252
Jeff Johnson295189b2012-06-20 16:38:30 -0700253v_U16_t hdd_select_queue(struct net_device *dev,
Anand N Sunkade9adb1b2015-07-29 09:56:45 +0530254 struct sk_buff *skb
255#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0))
256 , void *accel_priv
257#endif
258#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0))
259 , select_queue_fallback_t fallback
260#endif
261);
Jeff Johnson295189b2012-06-20 16:38:30 -0700262
263#ifdef WLAN_FEATURE_PACKET_FILTERING
264static void hdd_set_multicast_list(struct net_device *dev);
265#endif
266
267void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter);
268
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -0800269#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -0800270void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand);
271static VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels);
Srinivas Girigowda100eb322013-03-15 16:48:20 -0700272static VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid,
273 tANI_U8 *pChannel, tANI_U8 *pDwellTime,
274 tANI_U8 **pBuf, tANI_U8 *pBufLen);
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +0530275static int hdd_parse_reassoc_command_v1_data(const tANI_U8 *pValue,
276 tANI_U8 *pTargetApBssid, tANI_U8 *pChannel);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800277#endif
Ratheesh S P21280412015-05-19 14:21:52 +0530278
279/* Store WLAN driver info in a global variable such that crash debugger
280 can extract it from driver debug symbol and crashdump for post processing */
281tANI_U8 g_wlan_driver[ ] = "pronto_driver";
282
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -0800283#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda5cecb202013-10-08 09:13:25 -0700284VOS_STATUS hdd_parse_get_cckm_ie(tANI_U8 *pValue, tANI_U8 **pCckmIe, tANI_U8 *pCckmIeLen);
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -0800285#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -0700286
Mihir Shetee1093ba2014-01-21 20:13:32 +0530287static VOS_STATUS wlan_hdd_init_channels(hdd_context_t *pHddCtx);
Sushant Kaushik8bc7df22014-04-09 17:55:29 +0530288const char * hdd_device_modetoString(v_U8_t device_mode)
289{
290 switch(device_mode)
291 {
292 CASE_RETURN_STRING( WLAN_HDD_INFRA_STATION );
293 CASE_RETURN_STRING( WLAN_HDD_SOFTAP );
294 CASE_RETURN_STRING( WLAN_HDD_P2P_CLIENT );
295 CASE_RETURN_STRING( WLAN_HDD_P2P_GO );
296 CASE_RETURN_STRING( WLAN_HDD_MONITOR);
297 CASE_RETURN_STRING( WLAN_HDD_FTM );
298 CASE_RETURN_STRING( WLAN_HDD_IBSS );
299 CASE_RETURN_STRING( WLAN_HDD_P2P_DEVICE );
300 default:
301 return "device_mode Unknown";
302 }
303}
Mihir Shetee1093ba2014-01-21 20:13:32 +0530304
Mukul Sharmaa78cf6b2015-02-24 16:59:01 +0530305static int __hdd_netdev_notifier_call(struct notifier_block * nb,
Jeff Johnson295189b2012-06-20 16:38:30 -0700306 unsigned long state,
307 void *ndev)
308{
309 struct net_device *dev = ndev;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700310 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson27cee452013-03-27 11:10:24 -0700311 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700312#ifdef WLAN_BTAMP_FEATURE
313 VOS_STATUS status;
Jeff Johnson295189b2012-06-20 16:38:30 -0700314#endif
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +0530315 long result;
Jeff Johnson295189b2012-06-20 16:38:30 -0700316
317 //Make sure that this callback corresponds to our device.
Jeff Johnson27cee452013-03-27 11:10:24 -0700318 if ((strncmp(dev->name, "wlan", 4)) &&
Amar Singhal4c723bd2013-03-25 18:14:15 -0700319 (strncmp(dev->name, "p2p", 3)))
320 return NOTIFY_DONE;
321
Jeff Johnson295189b2012-06-20 16:38:30 -0700322 if (!dev->ieee80211_ptr)
Jeff Johnson27cee452013-03-27 11:10:24 -0700323 return NOTIFY_DONE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700324
Jeff Johnson27cee452013-03-27 11:10:24 -0700325 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -0700326 {
Jeff Johnsona8a1a482012-12-12 16:49:33 -0800327 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Adapter Null Pointer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700328 VOS_ASSERT(0);
329 return NOTIFY_DONE;
330 }
331
Jeff Johnson27cee452013-03-27 11:10:24 -0700332 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
333 if (NULL == pHddCtx)
334 {
335 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Context Null Pointer", __func__);
336 VOS_ASSERT(0);
337 return NOTIFY_DONE;
338 }
Sameer Thalappil14067972014-01-23 14:54:54 -0800339 if (pHddCtx->isLogpInProgress)
340 return NOTIFY_DONE;
341
Jeff Johnson27cee452013-03-27 11:10:24 -0700342
343 hddLog(VOS_TRACE_LEVEL_INFO, "%s: %s New Net Device State = %lu",
344 __func__, dev->name, state);
Jeff Johnson295189b2012-06-20 16:38:30 -0700345
346 switch (state) {
347 case NETDEV_REGISTER:
348 break;
349
350 case NETDEV_UNREGISTER:
351 break;
352
353 case NETDEV_UP:
354 break;
355
356 case NETDEV_DOWN:
357 break;
358
359 case NETDEV_CHANGE:
Jeff Johnsone7245742012-09-05 17:12:55 -0700360 if(TRUE == pAdapter->isLinkUpSvcNeeded)
361 complete(&pAdapter->linkup_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700362 break;
363
364 case NETDEV_GOING_DOWN:
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +0530365 result = wlan_hdd_scan_abort(pAdapter);
Girish Gowli4bf7a632014-06-12 13:42:11 +0530366 if (result < 0)
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +0530367 {
368 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
369 "%s: Timeout occurred while waiting for abortscan %ld",
370 __func__, result);
Jeff Johnson295189b2012-06-20 16:38:30 -0700371 }
372 else
373 {
374 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +0530375 "%s: Scan Abort Successful" , __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700376 }
377#ifdef WLAN_BTAMP_FEATURE
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700378 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: disabling AMP", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700379 status = WLANBAP_StopAmp();
380 if(VOS_STATUS_SUCCESS != status )
381 {
382 pHddCtx->isAmpAllowed = VOS_TRUE;
383 hddLog(VOS_TRACE_LEVEL_FATAL,
384 "%s: Failed to stop AMP", __func__);
385 }
386 else
387 {
388 //a state m/c implementation in PAL is TBD to avoid this delay
389 msleep(500);
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700390 if ( pHddCtx->isAmpAllowed )
391 {
392 WLANBAP_DeregisterFromHCI();
393 pHddCtx->isAmpAllowed = VOS_FALSE;
394 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700395 }
396#endif //WLAN_BTAMP_FEATURE
397 break;
398
399 default:
400 break;
401 }
402
403 return NOTIFY_DONE;
404}
405
Mukul Sharmaa78cf6b2015-02-24 16:59:01 +0530406static int hdd_netdev_notifier_call(struct notifier_block * nb,
407 unsigned long state,
408 void *ndev)
409{
410 int ret;
411 vos_ssr_protect(__func__);
412 ret = __hdd_netdev_notifier_call( nb, state, ndev);
413 vos_ssr_unprotect(__func__);
414 return ret;
415}
416
Jeff Johnson295189b2012-06-20 16:38:30 -0700417struct notifier_block hdd_netdev_notifier = {
418 .notifier_call = hdd_netdev_notifier_call,
419};
420
421/*---------------------------------------------------------------------------
422 * Function definitions
423 *-------------------------------------------------------------------------*/
Jeff Johnson295189b2012-06-20 16:38:30 -0700424void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx);
425void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -0700426//variable to hold the insmod parameters
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700427static int con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -0700428#ifndef MODULE
429/* current con_mode - used only for statically linked driver
430 * con_mode is changed by userspace to indicate a mode change which will
431 * result in calling the module exit and init functions. The module
432 * exit function will clean up based on the value of con_mode prior to it
433 * being changed by userspace. So curr_con_mode records the current con_mode
434 * for exit when con_mode becomes the next mode for init
435 */
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700436static int curr_con_mode;
Jeff Johnson295189b2012-06-20 16:38:30 -0700437#endif
438
Srinivas Girigowda8bf64cb2015-09-30 19:50:09 +0530439#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
440/**
441 * hdd_init_offloaded_packets_ctx() - Initialize offload packets context
442 * @hdd_ctx: hdd global context
443 *
444 * Return: none
445 */
446static void hdd_init_offloaded_packets_ctx(hdd_context_t *hdd_ctx)
447{
448 uint8_t i;
449
450 mutex_init(&hdd_ctx->op_ctx.op_lock);
451 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++)
452 {
453 hdd_ctx->op_ctx.op_table[i].request_id = 0;
454 hdd_ctx->op_ctx.op_table[i].pattern_id = i;
455 }
456}
457#else
458static void hdd_init_offloaded_packets_ctx(hdd_context_t *hdd_ctx)
459{
460}
461#endif
462
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -0800463/**---------------------------------------------------------------------------
464
465 \brief hdd_vos_trace_enable() - Configure initial VOS Trace enable
466
467 Called immediately after the cfg.ini is read in order to configure
468 the desired trace levels.
469
470 \param - moduleId - module whose trace level is being configured
471 \param - bitmask - bitmask of log levels to be enabled
472
473 \return - void
474
475 --------------------------------------------------------------------------*/
476static void hdd_vos_trace_enable(VOS_MODULE_ID moduleId, v_U32_t bitmask)
477{
478 wpt_tracelevel level;
479
480 /* if the bitmask is the default value, then a bitmask was not
481 specified in cfg.ini, so leave the logging level alone (it
482 will remain at the "compiled in" default value) */
483 if (CFG_VOS_TRACE_ENABLE_DEFAULT == bitmask)
484 {
485 return;
486 }
487
488 /* a mask was specified. start by disabling all logging */
489 vos_trace_setValue(moduleId, VOS_TRACE_LEVEL_NONE, 0);
490
491 /* now cycle through the bitmask until all "set" bits are serviced */
492 level = VOS_TRACE_LEVEL_FATAL;
493 while (0 != bitmask)
494 {
495 if (bitmask & 1)
496 {
497 vos_trace_setValue(moduleId, level, 1);
498 }
499 level++;
500 bitmask >>= 1;
501 }
502}
503
504
Jeff Johnson295189b2012-06-20 16:38:30 -0700505/**---------------------------------------------------------------------------
506
507 \brief hdd_wdi_trace_enable() - Configure initial WDI Trace enable
508
509 Called immediately after the cfg.ini is read in order to configure
510 the desired trace levels in the WDI.
511
512 \param - moduleId - module whose trace level is being configured
513 \param - bitmask - bitmask of log levels to be enabled
514
515 \return - void
516
517 --------------------------------------------------------------------------*/
518static void hdd_wdi_trace_enable(wpt_moduleid moduleId, v_U32_t bitmask)
519{
520 wpt_tracelevel level;
521
522 /* if the bitmask is the default value, then a bitmask was not
523 specified in cfg.ini, so leave the logging level alone (it
524 will remain at the "compiled in" default value) */
525 if (CFG_WDI_TRACE_ENABLE_DEFAULT == bitmask)
526 {
527 return;
528 }
529
530 /* a mask was specified. start by disabling all logging */
531 wpalTraceSetLevel(moduleId, eWLAN_PAL_TRACE_LEVEL_NONE, 0);
532
533 /* now cycle through the bitmask until all "set" bits are serviced */
534 level = eWLAN_PAL_TRACE_LEVEL_FATAL;
535 while (0 != bitmask)
536 {
537 if (bitmask & 1)
538 {
539 wpalTraceSetLevel(moduleId, level, 1);
540 }
541 level++;
542 bitmask >>= 1;
543 }
544}
Jeff Johnson295189b2012-06-20 16:38:30 -0700545
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530546/*
547 * FUNCTION: wlan_hdd_validate_context
548 * This function is used to check the HDD context
549 */
550int wlan_hdd_validate_context(hdd_context_t *pHddCtx)
551{
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530552
553 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
554 {
Mahesh A Saptasagar886997a2015-03-04 13:15:51 +0530555 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530556 "%s: HDD context is Null", __func__);
557 return -ENODEV;
558 }
559
560 if (pHddCtx->isLogpInProgress)
561 {
Mahesh A Saptasagar886997a2015-03-04 13:15:51 +0530562 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
c_hpothu8adb97b2014-12-08 19:38:20 +0530563 "%s: LOGP %s. Ignore!!", __func__,
564 vos_is_wlan_in_badState(VOS_MODULE_ID_HDD, NULL)
565 ?"failed":"in Progress");
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530566 return -EAGAIN;
567 }
568
Mihir Shete18156292014-03-11 15:38:30 +0530569 if (WLAN_HDD_IS_LOAD_UNLOAD_IN_PROGRESS(pHddCtx))
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530570 {
Mahesh A Saptasagar886997a2015-03-04 13:15:51 +0530571 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530572 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
573 return -EAGAIN;
574 }
575 return 0;
576}
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700577#ifdef CONFIG_ENABLE_LINUX_REG
578void hdd_checkandupdate_phymode( hdd_context_t *pHddCtx)
579{
580 hdd_adapter_t *pAdapter = NULL;
581 hdd_station_ctx_t *pHddStaCtx = NULL;
582 eCsrPhyMode phyMode;
583 hdd_config_t *cfg_param = NULL;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530584
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700585 if (NULL == pHddCtx)
586 {
587 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
588 "HDD Context is null !!");
589 return ;
590 }
591
592 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
593 if (NULL == pAdapter)
594 {
595 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
596 "pAdapter is null !!");
597 return ;
598 }
599
600 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
601 if (NULL == pHddStaCtx)
602 {
603 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
604 "pHddStaCtx is null !!");
605 return ;
606 }
607
608 cfg_param = pHddCtx->cfg_ini;
609 if (NULL == cfg_param)
610 {
611 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
612 "cfg_params not available !!");
613 return ;
614 }
615
616 phyMode = sme_GetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter));
617
618 if (!pHddCtx->isVHT80Allowed)
619 {
620 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
621 (eCSR_DOT11_MODE_11ac == phyMode) ||
622 (eCSR_DOT11_MODE_11ac_ONLY == phyMode))
623 {
624 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
625 "Setting phymode to 11n!!");
626 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter), eCSR_DOT11_MODE_11n);
627 }
628 }
629 else
630 {
631 /*New country Supports 11ac as well resetting value back from .ini*/
632 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter),
633 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->dot11Mode));
634 return ;
635 }
636
637 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
638 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode) ||
639 (eCSR_CFG_DOT11_MODE_11AC == pHddStaCtx->conn_info.dot11Mode)))
640 {
641 VOS_STATUS vosStatus;
642
643 // need to issue a disconnect to CSR.
644 INIT_COMPLETION(pAdapter->disconnect_comp_var);
645 vosStatus = sme_RoamDisconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
646 pAdapter->sessionId,
647 eCSR_DISCONNECT_REASON_UNSPECIFIED );
648
649 if (VOS_STATUS_SUCCESS == vosStatus)
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530650 {
651 long ret;
652
653 ret = wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700654 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530655 if (0 >= ret)
656 hddLog(LOGE, FL("failure waiting for disconnect_comp_var %ld"),
657 ret);
658 }
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700659
660 }
661}
662#else
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530663void hdd_checkandupdate_phymode( hdd_adapter_t *pAdapter, char *country_code)
664{
665 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
666 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
667 hdd_config_t *cfg_param;
668 eCsrPhyMode phyMode;
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530669 long ret;
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530670
671 if (NULL == pHddCtx)
672 {
673 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
674 "HDD Context is null !!");
675 return ;
676 }
677
678 cfg_param = pHddCtx->cfg_ini;
679
680 if (NULL == cfg_param)
681 {
682 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
683 "cfg_params not available !!");
684 return ;
685 }
686
687 phyMode = sme_GetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter));
688
689 if (NULL != strstr(cfg_param->listOfNon11acCountryCode, country_code))
690 {
691 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
692 (eCSR_DOT11_MODE_11ac == phyMode) ||
693 (eCSR_DOT11_MODE_11ac_ONLY == phyMode))
694 {
695 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
696 "Setting phymode to 11n!!");
697 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter), eCSR_DOT11_MODE_11n);
698 }
699 }
700 else
701 {
702 /*New country Supports 11ac as well resetting value back from .ini*/
703 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter),
704 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->dot11Mode));
705 return ;
706 }
707
708 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
709 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode) ||
710 (eCSR_CFG_DOT11_MODE_11AC == pHddStaCtx->conn_info.dot11Mode)))
711 {
712 VOS_STATUS vosStatus;
713
714 // need to issue a disconnect to CSR.
715 INIT_COMPLETION(pAdapter->disconnect_comp_var);
716 vosStatus = sme_RoamDisconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
717 pAdapter->sessionId,
718 eCSR_DISCONNECT_REASON_UNSPECIFIED );
719
720 if (VOS_STATUS_SUCCESS == vosStatus)
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530721 {
722 ret = wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530723 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530724 if (ret <= 0)
725 {
726 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
727 "wait on disconnect_comp_var is failed %ld", ret);
728 }
729 }
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530730
731 }
732}
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700733#endif //CONFIG_ENABLE_LINUX_REG
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530734
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700735void hdd_checkandupdate_dfssetting( hdd_adapter_t *pAdapter, char *country_code)
736{
737 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
738 hdd_config_t *cfg_param;
739
740 if (NULL == pHddCtx)
741 {
742 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
743 "HDD Context is null !!");
744 return ;
745 }
746
747 cfg_param = pHddCtx->cfg_ini;
748
749 if (NULL == cfg_param)
750 {
751 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
752 "cfg_params not available !!");
753 return ;
754 }
755
Agarwal Ashish738843c2014-09-25 12:27:56 +0530756 if (NULL != strstr(cfg_param->listOfNonDfsCountryCode, country_code) ||
757 pHddCtx->disable_dfs_flag == TRUE)
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700758 {
759 /*New country doesn't support DFS */
760 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), 0);
761 }
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700762
763}
764
Abhishek Singh00b71972016-01-07 10:51:04 +0530765#ifdef WLAN_FEATURE_RMC
766static int hdd_parse_setrmcenable_command(tANI_U8 *pValue, tANI_U8 *pRmcEnable)
767{
768 tANI_U8 *inPtr = pValue;
769 int tempInt;
770 int v = 0;
771 char buf[32];
772 *pRmcEnable = 0;
773
774 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
775 /*no argument after the command*/
776 if (NULL == inPtr)
777 {
778 return 0;
779 }
780
781 /*no space after the command*/
782 else if (SPACE_ASCII_VALUE != *inPtr)
783 {
784 return 0;
785 }
786
787 /*removing empty spaces*/
788 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
789
790 /*no argument followed by spaces*/
791 if ('\0' == *inPtr)
792 {
793 return 0;
794 }
795
796 /* getting the first argument which enables or disables RMC
797 * for input IP v4 address*/
Ashish Kumar Dhanotiya54d31a32017-08-04 17:12:44 +0530798 sscanf(inPtr, "%31s ", buf);
Abhishek Singh00b71972016-01-07 10:51:04 +0530799 v = kstrtos32(buf, 10, &tempInt);
800 if ( v < 0)
801 {
802 return -EINVAL;
803 }
804
805 *pRmcEnable = tempInt;
806
807 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
808 "ucRmcEnable: %d", *pRmcEnable);
809
810 return 0;
811}
812
813/* Function header left blank Intentionally */
814static int hdd_parse_setrmcactionperiod_command(tANI_U8 *pValue,
815 tANI_U32 *pActionPeriod)
816{
817 tANI_U8 *inPtr = pValue;
818 int tempInt;
819 int v = 0;
820 char buf[32];
821 *pActionPeriod = 0;
822
823 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
824 /*no argument after the command*/
825 if (NULL == inPtr)
826 {
827 return -EINVAL;
828 }
829
830 /*no space after the command*/
831 else if (SPACE_ASCII_VALUE != *inPtr)
832 {
833 return -EINVAL;
834 }
835
836 /*removing empty spaces*/
837 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
838
839 /*no argument followed by spaces*/
840 if ('\0' == *inPtr)
841 {
842 return 0;
843 }
844
845 /* getting the first argument which enables or disables RMC
846 * for input IP v4 address*/
Ashish Kumar Dhanotiya54d31a32017-08-04 17:12:44 +0530847 sscanf(inPtr, "%31s ", buf);
Abhishek Singh00b71972016-01-07 10:51:04 +0530848 v = kstrtos32(buf, 10, &tempInt);
849 if ( v < 0)
850 {
851 return -EINVAL;
852 }
853
854 /* Range checking for passed paramter */
855 if (tempInt < WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY_STAMIN ||
856 tempInt > WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY_STAMAX)
857 {
858 return -EINVAL;
859 }
860
861 *pActionPeriod = tempInt;
862
863 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
864 "uActionPeriod: %d", *pActionPeriod);
865
866 return 0;
867}
868
869/* Function header left blank Intentionally */
870static int hdd_parse_setrmcrate_command(tANI_U8 *pValue,
871 tANI_U32 *pRate, tTxrateinfoflags *pTxFlags)
872{
873 tANI_U8 *inPtr = pValue;
874 int tempInt;
875 int v = 0;
876 char buf[32];
877 *pRate = 0;
878 *pTxFlags = 0;
879
880 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
881 /*no argument after the command*/
882 if (NULL == inPtr)
883 {
884 return -EINVAL;
885 }
886
887 /*no space after the command*/
888 else if (SPACE_ASCII_VALUE != *inPtr)
889 {
890 return -EINVAL;
891 }
892
893 /*removing empty spaces*/
894 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
895
896 /*no argument followed by spaces*/
897 if ('\0' == *inPtr)
898 {
899 return 0;
900 }
901
902 /*
903 * getting the first argument which sets multicast rate.
904 */
Ashish Kumar Dhanotiya06f9f202017-08-04 15:26:27 +0530905 sscanf(inPtr, "%31s ", buf);
Abhishek Singh00b71972016-01-07 10:51:04 +0530906 v = kstrtos32(buf, 10, &tempInt);
907 if ( v < 0)
908 {
909 return -EINVAL;
910 }
911
912 /*
913 * Validate the multicast rate.
914 */
915 switch (tempInt)
916 {
917 default:
918 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
919 "Unsupported rate: %d", tempInt);
920 return -EINVAL;
921 case 0:
922 case 6:
923 case 9:
924 case 12:
925 case 18:
926 case 24:
927 case 36:
928 case 48:
929 case 54:
930 *pTxFlags = eHAL_TX_RATE_LEGACY;
931 *pRate = tempInt * 10;
932 break;
933 case 65:
934 *pTxFlags = eHAL_TX_RATE_HT20;
935 *pRate = tempInt * 10;
936 break;
937 case 72:
938 *pTxFlags = eHAL_TX_RATE_HT20 | eHAL_TX_RATE_SGI;
939 *pRate = 722; /* fractional rate 72.2 Mbps */
940 break;
941 }
942
943 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
944 "Rate: %d", *pRate);
945
946 return 0;
947}
948
949/**---------------------------------------------------------------------------
950
951 \brief hdd_cfg80211_get_ibss_peer_info_cb() - Callback function for IBSS
952 Peer Info request
953
954 This is an asynchronous callback function from SME when the peer info
955 is received
956
957 \pUserData -> Adapter private data
958 \pPeerInfoRsp -> Peer info response
959
960 \return - 0 for success non-zero for failure
961 --------------------------------------------------------------------------*/
962static void
963hdd_cfg80211_get_ibss_peer_info_cb(v_VOID_t *pUserData, v_VOID_t *pPeerInfoRsp)
964{
965 hdd_adapter_t *pAdapter = (hdd_adapter_t *)pUserData;
966 tSirPeerInfoRspParams *pPeerInfo = (tSirPeerInfoRspParams *)pPeerInfoRsp;
967 hdd_station_ctx_t *pStaCtx;
968 v_U8_t i;
969
970 /*Sanity check*/
971 if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
972 {
973 hddLog(LOGE,
974 FL("invalid adapter or adapter has invalid magic"));
975 return;
976 }
977
978 pStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
979 if (NULL != pStaCtx && NULL != pPeerInfo &&
980 eHAL_STATUS_SUCCESS == pPeerInfo->status)
981 {
982 pStaCtx->ibss_peer_info.status = pPeerInfo->status;
983 pStaCtx->ibss_peer_info.numIBSSPeers = pPeerInfo->numPeers;
984
985 /* Paranoia check */
986 if (pPeerInfo->numPeers < HDD_MAX_NUM_IBSS_STA)
987 {
988 for (i = 0; i < pPeerInfo->numPeers; i++)
989 {
990 memcpy(&pStaCtx->ibss_peer_info.ibssPeerList[i],
991 &pPeerInfo->peerInfoParams[i],
992 sizeof(hdd_ibss_peer_info_params_t));
993 }
994 hddLog(LOG1,
995 FL("Peer Info copied in HDD"));
996 }
997 else
998 {
999 hddLog(LOGE,
1000 FL(" Number of peers %d returned is more than limit %d"),
1001 pPeerInfo->numPeers, HDD_MAX_NUM_IBSS_STA);
1002 }
1003 }
1004 else
1005 {
1006 hddLog(LOG1,
1007 FL("peerInfo returned is NULL"));
1008 }
1009
1010 complete(&pAdapter->ibss_peer_info_comp);
1011}
1012
1013/**---------------------------------------------------------------------------
1014
1015 \brief hdd_cfg80211_get_ibss_peer_info_all() -
1016
1017 Request function to get IBSS peer info from lower layers
1018
1019 \pAdapter -> Adapter context
1020
1021 \return - 0 for success non-zero for failure
1022 --------------------------------------------------------------------------*/
1023static
1024VOS_STATUS hdd_cfg80211_get_ibss_peer_info_all(hdd_adapter_t *pAdapter)
1025{
1026 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1027 long status;
1028 VOS_STATUS retStatus = VOS_STATUS_E_FAILURE;
1029
1030 INIT_COMPLETION(pAdapter->ibss_peer_info_comp);
1031
1032 retStatus = sme_RequestIBSSPeerInfo(hHal, pAdapter,
1033 hdd_cfg80211_get_ibss_peer_info_cb,
1034 VOS_TRUE, 0xFF);
1035
1036 if (VOS_STATUS_SUCCESS == retStatus)
1037 {
1038 status = wait_for_completion_interruptible_timeout
1039 (&pAdapter->ibss_peer_info_comp,
1040 msecs_to_jiffies(IBSS_PEER_INFO_REQ_TIMOEUT));
1041
1042 /* status will be 0 if timed out */
1043 if (status <= 0)
1044 {
1045 hddLog(VOS_TRACE_LEVEL_WARN, "%s: Warning: IBSS_PEER_INFO_TIMEOUT %ld",
1046 __func__, status);
1047 retStatus = VOS_STATUS_E_FAILURE;
1048 return retStatus;
1049 }
1050 }
1051 else
1052 {
1053 hddLog(VOS_TRACE_LEVEL_WARN,
1054 "%s: Warning: sme_RequestIBSSPeerInfo Request failed", __func__);
1055 }
1056
1057 return retStatus;
1058}
1059
1060/**---------------------------------------------------------------------------
1061
1062 \brief hdd_cfg80211_get_ibss_peer_info() -
1063
1064 Request function to get IBSS peer info from lower layers
1065
1066 \pAdapter -> Adapter context
1067 \staIdx -> Sta index for which the peer info is requested
1068
1069 \return - 0 for success non-zero for failure
1070 --------------------------------------------------------------------------*/
1071static VOS_STATUS
1072hdd_cfg80211_get_ibss_peer_info(hdd_adapter_t *pAdapter, v_U8_t staIdx)
1073{
1074 long status;
1075 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1076 VOS_STATUS retStatus = VOS_STATUS_E_FAILURE;
1077
1078 INIT_COMPLETION(pAdapter->ibss_peer_info_comp);
1079
1080 retStatus = sme_RequestIBSSPeerInfo(hHal, pAdapter,
1081 hdd_cfg80211_get_ibss_peer_info_cb,
1082 VOS_FALSE, staIdx);
1083
1084 if (VOS_STATUS_SUCCESS == retStatus)
1085 {
1086 status = wait_for_completion_interruptible_timeout
1087 (&pAdapter->ibss_peer_info_comp,
1088 msecs_to_jiffies(IBSS_PEER_INFO_REQ_TIMOEUT));
1089
1090 /* status = 0 on timeout */
1091 if (status <= 0)
1092 {
1093 hddLog(VOS_TRACE_LEVEL_WARN, "%s: Warning: IBSS_PEER_INFO_TIMEOUT %ld",
1094 __func__, status);
1095 retStatus = VOS_STATUS_E_FAILURE;
1096 return retStatus;
1097 }
1098 }
1099 else
1100 {
1101 hddLog(VOS_TRACE_LEVEL_WARN,
1102 "%s: Warning: sme_RequestIBSSPeerInfo Request failed", __func__);
1103 }
1104
1105 return retStatus;
1106}
1107
1108/* Function header left blank Intentionally */
1109VOS_STATUS
1110hdd_parse_get_ibss_peer_info(tANI_U8 *pValue, v_MACADDR_t *pPeerMacAddr)
1111{
1112 tANI_U8 *inPtr = pValue;
1113 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
1114
1115 /*no argument after the command*/
1116 if (NULL == inPtr)
1117 {
1118 return VOS_STATUS_E_FAILURE;;
1119 }
1120
1121 /*no space after the command*/
1122 else if (SPACE_ASCII_VALUE != *inPtr)
1123 {
1124 return VOS_STATUS_E_FAILURE;;
1125 }
1126
1127 /*removing empty spaces*/
1128 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
1129
1130 /*no argument followed by spaces*/
1131 if ('\0' == *inPtr)
1132 {
1133 return VOS_STATUS_E_FAILURE;;
1134 }
1135
1136 /*getting the first argument ie the peer mac address */
1137 if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' ||
1138 inPtr[11] != ':' || inPtr[14] != ':')
1139 {
1140 return VOS_STATUS_E_FAILURE;;
1141 }
1142 sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x",
1143 (unsigned int *)&pPeerMacAddr->bytes[0],
1144 (unsigned int *)&pPeerMacAddr->bytes[1],
1145 (unsigned int *)&pPeerMacAddr->bytes[2],
1146 (unsigned int *)&pPeerMacAddr->bytes[3],
1147 (unsigned int *)&pPeerMacAddr->bytes[4],
1148 (unsigned int *)&pPeerMacAddr->bytes[5]);
1149
1150 /* The command buffer seems to be fine */
1151 return VOS_STATUS_SUCCESS;
1152}
1153
1154/* Function header left blank Intentionally */
1155static int hdd_parse_set_ibss_oui_data_command(tANI_U8 *command, tANI_U8 *ie,
1156 tANI_U32 limit)
1157{
1158 tANI_U8 len;
1159 tANI_U8 data;
1160
1161 /* skip white space */
1162 while ((SPACE_ASCII_VALUE == *command) && ('\0' != *command))
1163 {
1164 command++;
1165 limit--;
1166 }
1167
1168 /* skip element id and element length */
1169 len = 2;
1170
1171 /* extract oui */
1172 while ((SPACE_ASCII_VALUE != *command) && ('\0' != *command) &&
1173 (limit > 1))
1174 {
1175 /* Convert ASCII to decimal */
1176 data = ((*command -'0') << 4) | (*(command + 1) - '0');
1177 ie[len++] = data;
1178 command += 2;
1179 limit -= 2;
1180 }
1181
1182 /* skip white space */
1183 while ((SPACE_ASCII_VALUE == *command) && ('\0' != *command))
1184 {
1185 command++;
1186 limit--;
1187 }
1188
1189 /* extract data */
1190 while ((SPACE_ASCII_VALUE != *command) && ('\0' != *command) &&
1191 (limit > 1))
1192 {
1193 /* Convert ASCII to decimal */
1194 data = ((*command -'0') << 4) | (*(command + 1) - '0');
1195 ie[len++] = data;
1196 command += 2;
1197 limit -= 2;
1198 }
1199
1200 /* fill element id and element length */
1201 ie[0] = IE_EID_VENDOR;
1202 ie[1] = len - 2;
1203
1204 return len;
1205}
1206
1207static tANI_U32 hdd_find_ibss_wpa_ie_pos(tANI_U8 *addIePtr, tANI_U32 addIeLen)
1208{
1209 tANI_U32 ieLenPresent = 0;
1210 int left = addIeLen;
1211 v_U8_t *ptr = addIePtr;
1212 v_U8_t elem_id,elem_len;
1213
1214 while(left >= 2)
1215 {
1216 elem_id = ptr[0];
1217 elem_len = ptr[1];
1218 left -= 2;
1219 if(elem_len > left)
1220 {
1221 hddLog(LOGE,
1222 FL("****Invalid elem_len=%d left=%d*****"),
1223 elem_len,left);
1224 return 0;
1225 }
1226 if ((elem_id == IE_EID_VENDOR) &&
1227 (left >= WPA_OUI_TYPE_SIZE))
1228 {
1229 if (!memcmp(&ptr[2], WPA_OUI_TYPE,
1230 WPA_OUI_TYPE_SIZE))
1231 {
1232 ieLenPresent += elem_len + 2;
1233 return ieLenPresent;
1234 }
1235 }
1236 ieLenPresent += (elem_len + 2);
1237 left -= elem_len;
1238 ptr += (elem_len + 2);
1239 }
1240 return 0;
1241}
1242
1243#endif /* WLAN_FEATURE_RMC */
1244
Rajeev79dbe4c2013-10-05 11:03:42 +05301245#ifdef FEATURE_WLAN_BATCH_SCAN
1246
1247/**---------------------------------------------------------------------------
1248
1249 \brief hdd_extract_assigned_int_from_str() - Extracts assigned integer from
1250 input string
1251
1252 This function extracts assigned integer from string in below format:
1253 "STRING=10" : extracts integer 10 from this string
1254
1255 \param - pInPtr Pointer to input string
1256 \param - base Base for string to int conversion(10 for decimal 16 for hex)
1257 \param - pOutPtr Pointer to variable in which extracted integer needs to be
1258 assigned
1259 \param - pLastArg to tell whether it is last arguement in input string or
1260 not
1261
1262 \return - NULL for failure cases
1263 pointer to next arguement in input string for success cases
1264 --------------------------------------------------------------------------*/
1265static tANI_U8 *
1266hdd_extract_assigned_int_from_str
1267(
1268 tANI_U8 *pInPtr,
1269 tANI_U8 base,
1270 tANI_U32 *pOutPtr,
1271 tANI_U8 *pLastArg
1272)
1273{
1274 int tempInt;
1275 int v = 0;
1276 char buf[32];
1277 int val = 0;
1278 *pLastArg = FALSE;
1279
1280 pInPtr = strnchr(pInPtr, strlen(pInPtr), EQUALS_TO_ASCII_VALUE);
1281 if (NULL == pInPtr)
1282 {
1283 return NULL;
1284 }
1285
1286 pInPtr++;
1287
1288 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
1289
1290 val = sscanf(pInPtr, "%32s ", buf);
1291 if (val < 0 && val > strlen(pInPtr))
1292 {
1293 return NULL;
1294 }
1295 pInPtr += val;
1296 v = kstrtos32(buf, base, &tempInt);
1297 if (v < 0)
1298 {
1299 return NULL;
1300 }
Rajeev Kumar4d93d842014-01-02 18:31:21 -08001301 if (tempInt < 0)
1302 {
1303 tempInt = 0;
1304 }
Rajeev79dbe4c2013-10-05 11:03:42 +05301305 *pOutPtr = tempInt;
1306
1307 pInPtr = strnchr(pInPtr, strlen(pInPtr), SPACE_ASCII_VALUE);
1308 if (NULL == pInPtr)
1309 {
1310 *pLastArg = TRUE;
1311 return NULL;
1312 }
1313 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
1314
1315 return pInPtr;
1316}
1317
1318/**---------------------------------------------------------------------------
1319
1320 \brief hdd_extract_assigned_char_from_str() - Extracts assigned char from
1321 input string
1322
1323 This function extracts assigned character from string in below format:
1324 "STRING=A" : extracts char 'A' from this string
1325
1326 \param - pInPtr Pointer to input string
1327 \param - pOutPtr Pointer to variable in which extracted char needs to be
1328 assigned
1329 \param - pLastArg to tell whether it is last arguement in input string or
1330 not
1331
1332 \return - NULL for failure cases
1333 pointer to next arguement in input string for success cases
1334 --------------------------------------------------------------------------*/
1335static tANI_U8 *
1336hdd_extract_assigned_char_from_str
1337(
1338 tANI_U8 *pInPtr,
1339 tANI_U8 *pOutPtr,
1340 tANI_U8 *pLastArg
1341)
1342{
1343 *pLastArg = FALSE;
1344
1345 pInPtr = strnchr(pInPtr, strlen(pInPtr), EQUALS_TO_ASCII_VALUE);
1346 if (NULL == pInPtr)
1347 {
1348 return NULL;
1349 }
1350
1351 pInPtr++;
1352
1353 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
1354
1355 *pOutPtr = *pInPtr;
1356
1357 pInPtr = strnchr(pInPtr, strlen(pInPtr), SPACE_ASCII_VALUE);
1358 if (NULL == pInPtr)
1359 {
1360 *pLastArg = TRUE;
1361 return NULL;
1362 }
1363 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
1364
1365 return pInPtr;
1366}
1367
1368
1369/**---------------------------------------------------------------------------
1370
1371 \brief hdd_parse_set_batchscan_command () - HDD parse set batch scan command
1372
1373 This function parses set batch scan command in below format:
1374 WLS_BATCHING_SET <space> followed by below arguements
1375 "SCANFREQ=XX" : Optional defaults to 30 sec
1376 "MSCAN=XX" : Required number of scans to attempt to batch
1377 "BESTN=XX" : Best Network (RSSI) defaults to 16
1378 "CHANNEL=<X,Y>" : optional defaults to all channels, can list 'A'or` B.
1379 A. implies only 5 GHz , B. implies only 2.4GHz
1380 "RTT=X" : optional defaults to 0
1381 returns the MIN of MSCAN or the max # of scans firmware can cache or -1 on
1382 error
1383
1384 For example input commands:
1385 1) WLS_BATCHING_SET SCANFREQ=60 MSCAN=10 BESTN=20 CHANNEL=A RTT=0 -> This is
1386 translated into set batch scan with following parameters:
1387 a) Frequence 60 seconds
1388 b) Batch 10 scans together
1389 c) Best RSSI to be 20
1390 d) 5GHz band only
1391 e) RTT is equal to 0
1392
1393 \param - pValue Pointer to input channel list
1394 \param - pHddSetBatchScanReq Pointer to HDD batch scan request structure
1395
1396 \return - 0 for success non-zero for failure
1397
1398 --------------------------------------------------------------------------*/
1399static int
1400hdd_parse_set_batchscan_command
1401(
1402 tANI_U8 *pValue,
1403 tSirSetBatchScanReq *pHddSetBatchScanReq
1404)
1405{
1406 tANI_U8 *inPtr = pValue;
1407 tANI_U8 val = 0;
1408 tANI_U8 lastArg = 0;
Abhishek Singh00b71972016-01-07 10:51:04 +05301409 tANI_U32 nScanFreq = HDD_SET_BATCH_SCAN_DEFAULT_FREQ;
Rajeev Kumar45e64a72013-11-18 19:48:15 -08001410 tANI_U32 nMscan;
Abhishek Singh00b71972016-01-07 10:51:04 +05301411 tANI_U32 nBestN = HDD_SET_BATCH_SCAN_BEST_NETWORK;
1412 tANI_U8 ucRfBand = HDD_SET_BATCH_SCAN_DEFAULT_BAND;
1413 tANI_U32 nRtt = 0;
Rajeev Kumarc933d982013-11-18 20:04:20 -08001414 tANI_U32 temp;
Rajeev79dbe4c2013-10-05 11:03:42 +05301415
Rajeev79dbe4c2013-10-05 11:03:42 +05301416 /*go to space after WLS_BATCHING_SET command*/
1417 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
1418 /*no argument after the command*/
1419 if (NULL == inPtr)
1420 {
1421 return -EINVAL;
1422 }
1423
1424 /*no space after the command*/
1425 else if (SPACE_ASCII_VALUE != *inPtr)
1426 {
1427 return -EINVAL;
1428 }
1429
1430 /*removing empty spaces*/
1431 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
1432
1433 /*no argument followed by spaces*/
1434 if ('\0' == *inPtr)
1435 {
1436 return -EINVAL;
1437 }
1438
1439 /*check and parse SCANFREQ*/
1440 if ((strncmp(inPtr, "SCANFREQ", 8) == 0))
1441 {
1442 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumarc933d982013-11-18 20:04:20 -08001443 &temp, &lastArg);
Rajeev Kumar45e64a72013-11-18 19:48:15 -08001444
Rajeev Kumarc933d982013-11-18 20:04:20 -08001445 if (0 != temp)
Rajeev Kumar45e64a72013-11-18 19:48:15 -08001446 {
Rajeev Kumarc933d982013-11-18 20:04:20 -08001447 nScanFreq = temp;
Rajeev Kumar45e64a72013-11-18 19:48:15 -08001448 }
1449
Rajeev79dbe4c2013-10-05 11:03:42 +05301450 if ( (NULL == inPtr) || (TRUE == lastArg))
1451 {
1452 return -EINVAL;
1453 }
1454 }
1455
1456 /*check and parse MSCAN*/
1457 if ((strncmp(inPtr, "MSCAN", 5) == 0))
1458 {
1459 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumar45e64a72013-11-18 19:48:15 -08001460 &nMscan, &lastArg);
1461
1462 if (0 == nMscan)
1463 {
1464 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1465 "invalid MSCAN=%d", nMscan);
1466 return -EINVAL;
1467 }
1468
Rajeev79dbe4c2013-10-05 11:03:42 +05301469 if (TRUE == lastArg)
1470 {
1471 goto done;
1472 }
1473 else if (NULL == inPtr)
1474 {
1475 return -EINVAL;
1476 }
1477 }
1478 else
1479 {
1480 return -EINVAL;
1481 }
1482
1483 /*check and parse BESTN*/
1484 if ((strncmp(inPtr, "BESTN", 5) == 0))
1485 {
1486 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumarc933d982013-11-18 20:04:20 -08001487 &temp, &lastArg);
Rajeev Kumar45e64a72013-11-18 19:48:15 -08001488
Rajeev Kumarc933d982013-11-18 20:04:20 -08001489 if (0 != temp)
Rajeev Kumar45e64a72013-11-18 19:48:15 -08001490 {
Rajeev Kumarc933d982013-11-18 20:04:20 -08001491 nBestN = temp;
Rajeev Kumar45e64a72013-11-18 19:48:15 -08001492 }
1493
Rajeev79dbe4c2013-10-05 11:03:42 +05301494 if (TRUE == lastArg)
1495 {
1496 goto done;
1497 }
1498 else if (NULL == inPtr)
1499 {
1500 return -EINVAL;
1501 }
1502 }
1503
1504 /*check and parse CHANNEL*/
1505 if ((strncmp(inPtr, "CHANNEL", 7) == 0))
1506 {
1507 inPtr = hdd_extract_assigned_char_from_str(inPtr, &val, &lastArg);
Rajeev Kumarc933d982013-11-18 20:04:20 -08001508
Rajeev79dbe4c2013-10-05 11:03:42 +05301509 if (('A' == val) || ('a' == val))
1510 {
c_hpothuebf89732014-02-25 13:00:24 +05301511 ucRfBand = HDD_SET_BATCH_SCAN_5GHz_BAND_ONLY;
Rajeev79dbe4c2013-10-05 11:03:42 +05301512 }
1513 else if (('B' == val) || ('b' == val))
1514 {
c_hpothuebf89732014-02-25 13:00:24 +05301515 ucRfBand = HDD_SET_BATCH_SCAN_24GHz_BAND_ONLY;
Rajeev79dbe4c2013-10-05 11:03:42 +05301516 }
1517 else
1518 {
Rajeev Kumarc933d982013-11-18 20:04:20 -08001519 ucRfBand = HDD_SET_BATCH_SCAN_DEFAULT_BAND;
1520 }
1521
1522 if (TRUE == lastArg)
1523 {
1524 goto done;
1525 }
1526 else if (NULL == inPtr)
1527 {
Rajeev79dbe4c2013-10-05 11:03:42 +05301528 return -EINVAL;
1529 }
1530 }
1531
1532 /*check and parse RTT*/
1533 if ((strncmp(inPtr, "RTT", 3) == 0))
1534 {
1535 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumar45e64a72013-11-18 19:48:15 -08001536 &nRtt, &lastArg);
Rajeev79dbe4c2013-10-05 11:03:42 +05301537 if (TRUE == lastArg)
1538 {
1539 goto done;
1540 }
1541 if (NULL == inPtr)
1542 {
1543 return -EINVAL;
1544 }
1545 }
1546
1547
1548done:
1549
Rajeev Kumar45e64a72013-11-18 19:48:15 -08001550 pHddSetBatchScanReq->scanFrequency = nScanFreq;
1551 pHddSetBatchScanReq->numberOfScansToBatch = nMscan;
1552 pHddSetBatchScanReq->bestNetwork = nBestN;
1553 pHddSetBatchScanReq->rfBand = ucRfBand;
1554 pHddSetBatchScanReq->rtt = nRtt;
1555
Rajeev79dbe4c2013-10-05 11:03:42 +05301556 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1557 "Received WLS_BATCHING_SET with SCANFREQ=%d "
1558 "MSCAN=%d BESTN=%d CHANNEL=%d RTT=%d",
1559 pHddSetBatchScanReq->scanFrequency,
1560 pHddSetBatchScanReq->numberOfScansToBatch,
1561 pHddSetBatchScanReq->bestNetwork,
1562 pHddSetBatchScanReq->rfBand,
1563 pHddSetBatchScanReq->rtt);
1564
1565 return 0;
1566}/*End of hdd_parse_set_batchscan_command*/
1567
1568/**---------------------------------------------------------------------------
1569
1570 \brief hdd_set_batch_scan_req_callback () - This function is called after
1571 receiving set batch scan response from FW and it saves set batch scan
1572 response data FW to HDD context and sets the completion event on
1573 which hdd_ioctl is waiting
1574
1575 \param - callbackContext Pointer to HDD adapter
1576 \param - pRsp Pointer to set batch scan response data received from FW
1577
1578 \return - nothing
1579
1580 --------------------------------------------------------------------------*/
1581static void hdd_set_batch_scan_req_callback
1582(
1583 void *callbackContext,
1584 tSirSetBatchScanRsp *pRsp
1585)
1586{
1587 hdd_adapter_t* pAdapter = (hdd_adapter_t*)callbackContext;
1588 tSirSetBatchScanRsp *pHddSetBatchScanRsp;
1589
1590 /*sanity check*/
1591 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
1592 {
1593 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1594 "%s: Invalid pAdapter magic", __func__);
1595 VOS_ASSERT(0);
1596 return;
1597 }
1598 pHddSetBatchScanRsp = &pAdapter->hddSetBatchScanRsp;
1599
1600 /*save set batch scan response*/
1601 pHddSetBatchScanRsp->nScansToBatch = pRsp->nScansToBatch;
1602
1603 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1604 "Received set batch scan rsp from FW with nScansToBatch=%d",
1605 pHddSetBatchScanRsp->nScansToBatch);
1606
1607 pAdapter->hdd_wait_for_set_batch_scan_rsp = FALSE;
1608 complete(&pAdapter->hdd_set_batch_scan_req_var);
1609
1610 return;
1611}/*End of hdd_set_batch_scan_req_callback*/
1612
1613
1614/**---------------------------------------------------------------------------
1615
1616 \brief hdd_populate_batch_scan_rsp_queue () - This function stores AP meta
1617 info in hdd batch scan response queue
1618
1619 \param - pAdapter Pointer to hdd adapter
1620 \param - pAPMetaInfo Pointer to access point meta info
1621 \param - scanId scan ID of batch scan response
1622 \param - isLastAp tells whether AP is last AP in batch scan response or not
1623
1624 \return - nothing
1625
1626 --------------------------------------------------------------------------*/
1627static void hdd_populate_batch_scan_rsp_queue( hdd_adapter_t* pAdapter,
1628 tpSirBatchScanNetworkInfo pApMetaInfo, tANI_U32 scanId, v_BOOL_t isLastAp)
1629{
1630 tHddBatchScanRsp *pHead;
1631 tHddBatchScanRsp *pNode;
1632 tHddBatchScanRsp *pPrev;
1633 tHddBatchScanRsp *pTemp;
1634 tANI_U8 ssidLen;
1635
1636 /*head of hdd batch scan response queue*/
1637 pHead = pAdapter->pBatchScanRsp;
1638
1639 pNode = (tHddBatchScanRsp *)vos_mem_malloc(sizeof(tHddBatchScanRsp));
1640 if (NULL == pNode)
1641 {
1642 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1643 "%s: Could not allocate memory", __func__);
1644 VOS_ASSERT(0);
1645 return;
1646 }
1647
1648 vos_mem_copy(pNode->ApInfo.bssid, pApMetaInfo->bssid,
1649 sizeof(pNode->ApInfo.bssid));
1650 ssidLen = strlen(pApMetaInfo->ssid);
1651 if (SIR_MAX_SSID_SIZE < ssidLen)
1652 {
1653 /*invalid scan result*/
1654 vos_mem_free(pNode);
1655 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1656 "%s: Invalid AP meta info ssidlen %d", __func__, ssidLen);
1657 return;
1658 }
1659 vos_mem_copy(pNode->ApInfo.ssid, pApMetaInfo->ssid, ssidLen);
1660 /*null terminate ssid*/
1661 pNode->ApInfo.ssid[ssidLen] = '\0';
1662 pNode->ApInfo.ch = pApMetaInfo->ch;
1663 pNode->ApInfo.rssi = pApMetaInfo->rssi;
1664 pNode->ApInfo.age = pApMetaInfo->timestamp;
1665 pNode->ApInfo.batchId = scanId;
1666 pNode->ApInfo.isLastAp = isLastAp;
1667
1668 pNode->pNext = NULL;
1669 if (NULL == pHead)
1670 {
1671 pAdapter->pBatchScanRsp = pNode;
1672 }
1673 else
1674 {
1675 pTemp = pHead;
1676 while (NULL != pTemp)
1677 {
1678 pPrev = pTemp;
1679 pTemp = pTemp->pNext;
1680 }
1681 pPrev->pNext = pNode;
1682 }
1683
1684 return;
1685}/*End of hdd_populate_batch_scan_rsp_queue*/
1686
1687/**---------------------------------------------------------------------------
1688
1689 \brief hdd_batch_scan_result_ind_callback () - This function is called after
1690 receiving batch scan response indication from FW. It saves get batch scan
1691 response data in HDD batch scan response queue. This callback sets the
1692 completion event on which hdd_ioctl is waiting only after getting complete
1693 batch scan response data from FW
1694
1695 \param - callbackContext Pointer to HDD adapter
1696 \param - pRsp Pointer to get batch scan response data received from FW
1697
1698 \return - nothing
1699
1700 --------------------------------------------------------------------------*/
1701static void hdd_batch_scan_result_ind_callback
1702(
1703 void *callbackContext,
1704 void *pRsp
1705)
1706{
1707 v_BOOL_t isLastAp;
1708 tANI_U32 numApMetaInfo;
Rajeev Kumarce651e42013-10-21 18:57:15 -07001709 tANI_U32 numNetworkInScanList;
Rajeev79dbe4c2013-10-05 11:03:42 +05301710 tANI_U32 numberScanList;
1711 tANI_U32 nextScanListOffset;
1712 tANI_U32 nextApMetaInfoOffset;
1713 hdd_adapter_t* pAdapter;
1714 tpSirBatchScanList pScanList;
1715 tpSirBatchScanNetworkInfo pApMetaInfo;
1716 tpSirBatchScanResultIndParam pBatchScanRsp;/*batch scan rsp data from FW*/
1717 tSirSetBatchScanReq *pReq;
1718
1719 pAdapter = (hdd_adapter_t *)callbackContext;
1720 /*sanity check*/
Rajeev Kumar5286bb92013-12-05 11:52:10 -08001721 if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
Rajeev79dbe4c2013-10-05 11:03:42 +05301722 {
1723 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1724 "%s: Invalid pAdapter magic", __func__);
1725 VOS_ASSERT(0);
1726 return;
1727 }
1728
1729 /*initialize locals*/
1730 pReq = &pAdapter->hddSetBatchScanReq;
1731 pBatchScanRsp = (tpSirBatchScanResultIndParam)pRsp;
1732 isLastAp = FALSE;
1733 numApMetaInfo = 0;
Rajeev Kumarce651e42013-10-21 18:57:15 -07001734 numNetworkInScanList = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05301735 numberScanList = 0;
1736 nextScanListOffset = 0;
1737 nextApMetaInfoOffset = 0;
1738 pScanList = NULL;
1739 pApMetaInfo = NULL;
1740
1741 if ((NULL == pBatchScanRsp) || (NULL == pReq))
1742 {
1743 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnsonc135a9a2017-09-19 08:37:24 -07001744 "%s: pBatchScanRsp is %pK pReq %pK", __func__, pBatchScanRsp, pReq);
Rajeev79dbe4c2013-10-05 11:03:42 +05301745 isLastAp = TRUE;
1746 goto done;
1747 }
1748
1749 pAdapter->numScanList = numberScanList = pBatchScanRsp->numScanLists;
1750 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1751 "Batch scan rsp: numberScalList %d", numberScanList);
1752
1753 if ((!numberScanList) || (numberScanList > pReq->numberOfScansToBatch))
1754 {
1755 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1756 "%s: numberScanList %d", __func__, numberScanList);
1757 isLastAp = TRUE;
1758 goto done;
1759 }
1760
1761 while (numberScanList)
1762 {
Rajeev Kumarce651e42013-10-21 18:57:15 -07001763 pScanList = (tpSirBatchScanList)((tANI_U8 *)pBatchScanRsp->scanResults +
Rajeev79dbe4c2013-10-05 11:03:42 +05301764 nextScanListOffset);
1765 if (NULL == pScanList)
1766 {
1767 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnsonc135a9a2017-09-19 08:37:24 -07001768 "%s: pScanList is %pK", __func__, pScanList);
Rajeev79dbe4c2013-10-05 11:03:42 +05301769 isLastAp = TRUE;
1770 goto done;
1771 }
Rajeev Kumarce651e42013-10-21 18:57:15 -07001772 numNetworkInScanList = numApMetaInfo = pScanList->numNetworksInScanList;
Rajeev79dbe4c2013-10-05 11:03:42 +05301773 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumarce651e42013-10-21 18:57:15 -07001774 "Batch scan rsp: numApMetaInfo %d scanId %d",
1775 numApMetaInfo, pScanList->scanId);
Rajeev79dbe4c2013-10-05 11:03:42 +05301776
1777 if ((!numApMetaInfo) || (numApMetaInfo > pReq->bestNetwork))
1778 {
1779 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1780 "%s: numApMetaInfo %d", __func__, numApMetaInfo);
1781 isLastAp = TRUE;
1782 goto done;
1783 }
1784
Rajeev Kumarce651e42013-10-21 18:57:15 -07001785 /*Initialize next AP meta info offset for next scan list*/
1786 nextApMetaInfoOffset = 0;
1787
Rajeev79dbe4c2013-10-05 11:03:42 +05301788 while (numApMetaInfo)
1789 {
1790 pApMetaInfo = (tpSirBatchScanNetworkInfo)(pScanList->scanList +
1791 nextApMetaInfoOffset);
1792 if (NULL == pApMetaInfo)
1793 {
1794 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnsonc135a9a2017-09-19 08:37:24 -07001795 "%s: pApMetaInfo is %pK", __func__, pApMetaInfo);
Rajeev79dbe4c2013-10-05 11:03:42 +05301796 isLastAp = TRUE;
1797 goto done;
1798 }
1799 /*calculate AP age*/
1800 pApMetaInfo->timestamp =
1801 pBatchScanRsp->timestamp - pApMetaInfo->timestamp;
1802
1803 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
Arif Hussaina7c8e412013-11-20 11:06:42 -08001804 "%s: bssId "MAC_ADDRESS_STR
1805 " ch %d rssi %d timestamp %d", __func__,
1806 MAC_ADDR_ARRAY(pApMetaInfo->bssid),
1807 pApMetaInfo->ch, pApMetaInfo->rssi,
1808 pApMetaInfo->timestamp);
Rajeev79dbe4c2013-10-05 11:03:42 +05301809
1810 /*mark last AP in batch scan response*/
1811 if ((TRUE == pBatchScanRsp->isLastResult) &&
1812 (1 == numberScanList) && (1 == numApMetaInfo))
1813 {
1814 isLastAp = TRUE;
1815 }
1816
1817 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1818 /*store batch scan repsonse in hdd queue*/
1819 hdd_populate_batch_scan_rsp_queue(pAdapter, pApMetaInfo,
1820 pScanList->scanId, isLastAp);
1821 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1822
1823 nextApMetaInfoOffset += sizeof(tSirBatchScanNetworkInfo);
1824 numApMetaInfo--;
1825 }
1826
Rajeev Kumarce651e42013-10-21 18:57:15 -07001827 nextScanListOffset += ((sizeof(tSirBatchScanList) - sizeof(tANI_U8))
1828 + (sizeof(tSirBatchScanNetworkInfo)
1829 * numNetworkInScanList));
Rajeev79dbe4c2013-10-05 11:03:42 +05301830 numberScanList--;
1831 }
1832
1833done:
1834
1835 /*notify hdd_ioctl only if complete batch scan rsp is received and it was
1836 requested from hdd_ioctl*/
1837 if ((TRUE == pAdapter->hdd_wait_for_get_batch_scan_rsp) &&
1838 (TRUE == isLastAp))
1839 {
1840 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
1841 complete(&pAdapter->hdd_get_batch_scan_req_var);
1842 }
1843
1844 return;
1845}/*End of hdd_batch_scan_result_ind_callback*/
1846
1847/**---------------------------------------------------------------------------
1848
1849 \brief hdd_format_batch_scan_rsp () - This function formats batch scan
1850 response as per batch scan FR request format by putting proper markers
1851
1852 \param - pDest pointer to destination buffer
1853 \param - cur_len current length
1854 \param - tot_len total remaining size which can be written to user space
1855 \param - pApMetaInfo Pointer to get batch scan response AP meta info
1856 \param - pAdapter Pointer to HDD adapter
1857
1858 \return - ret no of characters written
1859
1860 --------------------------------------------------------------------------*/
1861static tANI_U32
1862hdd_format_batch_scan_rsp
1863(
1864 tANI_U8 *pDest,
1865 tANI_U32 cur_len,
1866 tANI_U32 tot_len,
1867 tHddBatchScanRsp *pApMetaInfo,
1868 hdd_adapter_t* pAdapter
1869)
1870{
1871 tANI_U32 ret = 0;
1872 tANI_U32 rem_len = 0;
1873 tANI_U8 temp_len = 0;
1874 tANI_U8 temp_total_len = 0;
1875 tANI_U8 temp[HDD_BATCH_SCAN_AP_META_INFO_SIZE];
1876 tANI_U8 *pTemp = temp;
1877
1878 /*Batch scan reponse needs to be returned to user space in
1879 following format:
1880 "scancount=X\n" where X is the number of scans in current batch
1881 batch
1882 "trunc\n" optional present if current scan truncated
1883 "bssid=XX:XX:XX:XX:XX:XX\n"
1884 "ssid=XXXX\n"
1885 "freq=X\n" frequency in Mhz
1886 "level=XX\n"
1887 "age=X\n" ms
1888 "dist=X\n" cm (-1 if not available)
1889 "errror=X\n" (-1if not available)
1890 "====\n" (end of ap marker)
1891 "####\n" (end of scan marker)
1892 "----\n" (end of results)*/
1893 /*send scan result in above format to user space based on
1894 available length*/
1895 /*The GET response may have more data than the driver can return in its
1896 buffer. In that case the buffer should be filled to the nearest complete
1897 scan, ending with "%%%%".Subsequent callsshould return the remaining data
1898 starting with the next scan (optional .trunc\n., .apcount=X\n., etc).
1899 The final buffer should end with "----\n"*/
1900
1901 /*sanity*/
1902 if (cur_len > tot_len)
1903 {
1904 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1905 "%s: invaid cur_len %d tot_len %d", __func__, cur_len, tot_len);
1906 return 0;
1907 }
1908 else
1909 {
1910 rem_len = (tot_len - cur_len);
1911 }
1912
1913 /*end scan marker*/
1914 if (pApMetaInfo->ApInfo.batchId != pAdapter->prev_batch_id)
1915 {
1916 temp_len = snprintf(pTemp, sizeof(temp), "####\n");
1917 pTemp += temp_len;
1918 temp_total_len += temp_len;
1919 }
1920
1921 /*bssid*/
1922 temp_len = snprintf(pTemp, sizeof(temp),
1923 "bssid=0x%x:0x%x:0x%x:0x%x:0x%x:0x%x\n",
1924 pApMetaInfo->ApInfo.bssid[0], pApMetaInfo->ApInfo.bssid[1],
1925 pApMetaInfo->ApInfo.bssid[2], pApMetaInfo->ApInfo.bssid[3],
1926 pApMetaInfo->ApInfo.bssid[4], pApMetaInfo->ApInfo.bssid[5]);
1927 pTemp += temp_len;
1928 temp_total_len += temp_len;
1929
1930 /*ssid*/
1931 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "ssid=%s\n",
1932 pApMetaInfo->ApInfo.ssid);
1933 pTemp += temp_len;
1934 temp_total_len += temp_len;
1935
1936 /*freq*/
1937 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "freq=%d\n",
Rajeev Kumarc40f7512013-11-04 14:13:23 -08001938 sme_ChnToFreq(pApMetaInfo->ApInfo.ch));
Rajeev79dbe4c2013-10-05 11:03:42 +05301939 pTemp += temp_len;
1940 temp_total_len += temp_len;
1941
1942 /*level*/
1943 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "level=%d\n",
1944 pApMetaInfo->ApInfo.rssi);
1945 pTemp += temp_len;
1946 temp_total_len += temp_len;
1947
1948 /*age*/
Jeff Johnson02797792013-10-26 19:17:13 -07001949 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "age=%d\n",
Rajeev79dbe4c2013-10-05 11:03:42 +05301950 pApMetaInfo->ApInfo.age);
1951 pTemp += temp_len;
1952 temp_total_len += temp_len;
1953
1954 /*dist*/
1955 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "dist=-1\n");
1956 pTemp += temp_len;
1957 temp_total_len += temp_len;
1958
1959 /*error*/
1960 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "error=-1\n");
1961 pTemp += temp_len;
1962 temp_total_len += temp_len;
1963
1964 /*end AP marker*/
1965 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "====\n");
1966 pTemp += temp_len;
1967 temp_total_len += temp_len;
1968
1969 /*last AP in batch scan response*/
1970 if(TRUE == pApMetaInfo->ApInfo.isLastAp)
1971 {
1972 /*end scan marker*/
1973 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "####\n");
1974 pTemp += temp_len;
1975 temp_total_len += temp_len;
1976
1977 /*end batch scan result marker*/
1978 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "----\n");
1979 pTemp += temp_len;
1980 temp_total_len += temp_len;
Kiet Lamaa8e15a2014-02-11 23:30:06 -08001981
Rajeev79dbe4c2013-10-05 11:03:42 +05301982 }
1983
1984 if (temp_total_len < rem_len)
1985 {
1986 ret = temp_total_len + 1;
1987 strlcpy(pDest, temp, ret);
1988 pAdapter->isTruncated = FALSE;
1989 }
1990 else
1991 {
1992 pAdapter->isTruncated = TRUE;
1993 if (rem_len >= strlen("%%%%"))
1994 {
Rajeev Kumarc933d982013-11-18 20:04:20 -08001995 ret = snprintf(pDest, sizeof(temp), "%%%%");
Rajeev79dbe4c2013-10-05 11:03:42 +05301996 }
Rajeev Kumarc933d982013-11-18 20:04:20 -08001997 else
Rajeev79dbe4c2013-10-05 11:03:42 +05301998 {
1999 ret = 0;
2000 }
2001 }
2002
2003 return ret;
2004
2005}/*End of hdd_format_batch_scan_rsp*/
2006
2007/**---------------------------------------------------------------------------
2008
2009 \brief hdd_populate_user_batch_scan_rsp() - This function populates user data
2010 buffer starting with head of hdd batch scan response queue
2011
2012 \param - pAdapter Pointer to HDD adapter
2013 \param - pDest Pointer to user data buffer
2014 \param - cur_len current offset in user buffer
2015 \param - rem_len remaining no of bytes in user buffer
2016
2017 \return - number of bytes written in user buffer
2018
2019 --------------------------------------------------------------------------*/
2020
2021tANI_U32 hdd_populate_user_batch_scan_rsp
2022(
2023 hdd_adapter_t* pAdapter,
2024 tANI_U8 *pDest,
2025 tANI_U32 cur_len,
2026 tANI_U32 rem_len
2027)
2028{
2029 tHddBatchScanRsp *pHead;
2030 tHddBatchScanRsp *pPrev;
2031 tANI_U32 len;
2032
Rajeev79dbe4c2013-10-05 11:03:42 +05302033 pAdapter->isTruncated = FALSE;
2034
2035 /*head of hdd batch scan response queue*/
2036 pHead = pAdapter->pBatchScanRsp;
2037 while (pHead)
2038 {
2039 len = hdd_format_batch_scan_rsp(pDest, cur_len, rem_len, pHead,
2040 pAdapter);
2041 pDest += len;
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07002042 pDest--;
Rajeev79dbe4c2013-10-05 11:03:42 +05302043 cur_len += len;
2044 if(TRUE == pAdapter->isTruncated)
2045 {
2046 /*result is truncated return rest of scan rsp in next req*/
2047 cur_len = rem_len;
2048 break;
2049 }
2050 pPrev = pHead;
2051 pHead = pHead->pNext;
2052 pAdapter->pBatchScanRsp = pHead;
Rajeev Kumarbe17d8b2014-01-10 15:39:45 -08002053 if (TRUE == pPrev->ApInfo.isLastAp)
2054 {
2055 pAdapter->prev_batch_id = 0;
2056 }
2057 else
2058 {
2059 pAdapter->prev_batch_id = pPrev->ApInfo.batchId;
2060 }
Rajeev79dbe4c2013-10-05 11:03:42 +05302061 vos_mem_free(pPrev);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002062 pPrev = NULL;
Rajeev79dbe4c2013-10-05 11:03:42 +05302063 }
2064
2065 return cur_len;
2066}/*End of hdd_populate_user_batch_scan_rsp*/
2067
2068/**---------------------------------------------------------------------------
2069
2070 \brief hdd_return_batch_scan_rsp_to_user () - This function returns batch
2071 scan response data from HDD queue to user space
2072 It does following in detail:
2073 a) if HDD has enough data in its queue then it 1st copies data to user
2074 space and then send get batch scan indication message to FW. In this
2075 case it does not wait on any event and batch scan response data will
2076 be populated in HDD response queue in MC thread context after receiving
2077 indication from FW
2078 b) else send get batch scan indication message to FW and wait on an event
2079 which will be set once HDD receives complete batch scan response from
2080 FW and then this function returns batch scan response to user space
2081
2082 \param - pAdapter Pointer to HDD adapter
2083 \param - pPrivData Pointer to priv_data
2084
2085 \return - 0 for success -EFAULT for failure
2086
2087 --------------------------------------------------------------------------*/
2088
2089int hdd_return_batch_scan_rsp_to_user
2090(
2091 hdd_adapter_t* pAdapter,
2092 hdd_priv_data_t *pPrivData,
2093 tANI_U8 *command
2094)
2095{
2096 tANI_U8 *pDest;
2097 tANI_U32 count = 0;
2098 tANI_U32 len = 0;
2099 tANI_U32 cur_len = 0;
2100 tANI_U32 rem_len = 0;
2101 eHalStatus halStatus;
2102 unsigned long rc;
2103 tSirTriggerBatchScanResultInd *pReq;
2104
2105 pReq = &pAdapter->hddTriggerBatchScanResultInd;
2106 pReq->param = 0;/*batch scan client*/
2107 pDest = (tANI_U8 *)(command + pPrivData->used_len);
2108 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
2109
2110 cur_len = pPrivData->used_len;
2111 if (pPrivData->total_len > pPrivData->used_len)
2112 {
2113 rem_len = pPrivData->total_len - pPrivData->used_len;
2114 }
2115 else
2116 {
2117 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2118 "%s: Invalid user data buffer total_len %d used_len %d",
2119 __func__, pPrivData->total_len, pPrivData->used_len);
2120 return -EFAULT;
2121 }
2122
2123 mutex_lock(&pAdapter->hdd_batch_scan_lock);
2124 len = hdd_populate_user_batch_scan_rsp(pAdapter, pDest,
2125 cur_len, rem_len);
2126 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
2127
2128 /*enough scan result available in cache to return to user space or
2129 scan result needs to be fetched 1st from fw and then return*/
Rajeev Kumar99db6262013-11-11 15:23:36 -08002130 if (len == cur_len)
Rajeev79dbe4c2013-10-05 11:03:42 +05302131 {
2132 pAdapter->hdd_wait_for_get_batch_scan_rsp = TRUE;
2133 halStatus = sme_TriggerBatchScanResultInd(
2134 WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
2135 pAdapter->sessionId, hdd_batch_scan_result_ind_callback,
2136 pAdapter);
2137 if ( eHAL_STATUS_SUCCESS == halStatus )
2138 {
2139 if (TRUE == pAdapter->hdd_wait_for_get_batch_scan_rsp)
2140 {
2141 INIT_COMPLETION(pAdapter->hdd_get_batch_scan_req_var);
2142 rc = wait_for_completion_timeout(
2143 &pAdapter->hdd_get_batch_scan_req_var,
2144 msecs_to_jiffies(HDD_GET_BATCH_SCAN_RSP_TIME_OUT));
Abhishek Singh00b71972016-01-07 10:51:04 +05302145 if (0 >= rc)
Rajeev79dbe4c2013-10-05 11:03:42 +05302146 {
2147 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Abhishek Singh00b71972016-01-07 10:51:04 +05302148 "%s: wait on hdd_get_batch_scan_req_var failed %ld",
2149 __func__, rc);
Rajeev79dbe4c2013-10-05 11:03:42 +05302150 return -EFAULT;
2151 }
2152 }
2153
2154 len = snprintf(pDest, HDD_BATCH_SCAN_AP_META_INFO_SIZE,
Jeff Johnson02797792013-10-26 19:17:13 -07002155 "scancount=%u\n", pAdapter->numScanList);
Rajeev79dbe4c2013-10-05 11:03:42 +05302156 pDest += len;
2157 cur_len += len;
2158
2159 mutex_lock(&pAdapter->hdd_batch_scan_lock);
2160 len = hdd_populate_user_batch_scan_rsp(pAdapter, pDest,
2161 cur_len, rem_len);
2162 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
2163
2164 count = 0;
2165 len = (len - pPrivData->used_len);
2166 pDest = (command + pPrivData->used_len);
2167 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar99db6262013-11-11 15:23:36 -08002168 "NEW BATCH SCAN RESULT:");
Rajeev79dbe4c2013-10-05 11:03:42 +05302169 while(count < len)
2170 {
2171 printk("%c", *(pDest + count));
2172 count++;
2173 }
2174 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2175 "%s: copy %d data to user buffer", __func__, len);
2176 if (copy_to_user(pPrivData->buf, pDest, len))
2177 {
2178 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2179 "%s: failed to copy data to user buffer", __func__);
2180 return -EFAULT;
2181 }
2182 }
2183 else
2184 {
2185 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2186 "sme_GetBatchScanScan returned failure halStatus %d",
2187 halStatus);
2188 return -EINVAL;
2189 }
2190 }
2191 else
2192 {
Rajeev79dbe4c2013-10-05 11:03:42 +05302193 count = 0;
2194 len = (len - pPrivData->used_len);
2195 pDest = (command + pPrivData->used_len);
2196 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar99db6262013-11-11 15:23:36 -08002197 "REMAINING TRUNCATED BATCH SCAN RESULT:");
Rajeev79dbe4c2013-10-05 11:03:42 +05302198 while(count < len)
2199 {
2200 printk("%c", *(pDest + count));
2201 count++;
2202 }
Rajeev Kumar99db6262013-11-11 15:23:36 -08002203 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2204 "%s: copy %d data to user buffer", __func__, len);
Rajeev79dbe4c2013-10-05 11:03:42 +05302205 if (copy_to_user(pPrivData->buf, pDest, len))
2206 {
2207 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2208 "%s: failed to copy data to user buffer", __func__);
2209 return -EFAULT;
2210 }
Rajeev79dbe4c2013-10-05 11:03:42 +05302211 }
2212
2213 return 0;
2214} /*End of hdd_return_batch_scan_rsp_to_user*/
2215
Rajeev Kumar8b373292014-01-08 20:36:55 -08002216/**---------------------------------------------------------------------------
2217
2218 \brief hdd_handle_batch_scan_ioctl () - This function handles WLS_BATCHING
2219 IOCTLs from user space. Following BATCH SCAN DEV IOCTs are handled:
2220 WLS_BATCHING VERSION
2221 WLS_BATCHING SET
2222 WLS_BATCHING GET
2223 WLS_BATCHING STOP
2224
2225 \param - pAdapter Pointer to HDD adapter
2226 \param - pPrivdata Pointer to priv_data
2227 \param - command Pointer to command
2228
2229 \return - 0 for success -EFAULT for failure
2230
2231 --------------------------------------------------------------------------*/
2232
2233int hdd_handle_batch_scan_ioctl
2234(
2235 hdd_adapter_t *pAdapter,
2236 hdd_priv_data_t *pPrivdata,
2237 tANI_U8 *command
2238)
2239{
2240 int ret = 0;
Yue Mae36e3552014-03-05 17:06:20 -08002241 hdd_context_t *pHddCtx;
2242
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05302243 ENTER();
2244
Yue Mae36e3552014-03-05 17:06:20 -08002245 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2246 ret = wlan_hdd_validate_context(pHddCtx);
2247 if (ret)
2248 {
Yue Mae36e3552014-03-05 17:06:20 -08002249 goto exit;
2250 }
Rajeev Kumar8b373292014-01-08 20:36:55 -08002251
2252 if (strncmp(command, "WLS_BATCHING VERSION", 20) == 0)
2253 {
2254 char extra[32];
2255 tANI_U8 len = 0;
2256 tANI_U8 version = HDD_BATCH_SCAN_VERSION;
2257
2258 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
2259 {
2260 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2261 "%s: Batch scan feature is not supported by FW", __func__);
2262 ret = -EINVAL;
2263 goto exit;
2264 }
2265
2266 len = scnprintf(extra, sizeof(extra), "WLS_BATCHING_VERSION %d",
2267 version);
2268 if (copy_to_user(pPrivdata->buf, &extra, len + 1))
2269 {
2270 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2271 "%s: failed to copy data to user buffer", __func__);
2272 ret = -EFAULT;
2273 goto exit;
2274 }
2275 ret = HDD_BATCH_SCAN_VERSION;
2276 }
2277 else if (strncmp(command, "WLS_BATCHING SET", 16) == 0)
2278 {
2279 int status;
2280 tANI_U8 *value = (command + 16);
2281 eHalStatus halStatus;
2282 unsigned long rc;
2283 tSirSetBatchScanReq *pReq = &pAdapter->hddSetBatchScanReq;
2284 tSirSetBatchScanRsp *pRsp = &pAdapter->hddSetBatchScanRsp;
2285
2286 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
2287 {
2288 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2289 "%s: Batch scan feature is not supported by FW", __func__);
2290 ret = -EINVAL;
2291 goto exit;
2292 }
2293
2294 if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) &&
2295 (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) &&
2296 (WLAN_HDD_P2P_GO != pAdapter->device_mode) &&
2297 (WLAN_HDD_P2P_DEVICE != pAdapter->device_mode))
2298 {
2299 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Sushant Kaushik8bc7df22014-04-09 17:55:29 +05302300 "Received WLS_BATCHING SET command in invalid mode %s (%d) "
Rajeev Kumar8b373292014-01-08 20:36:55 -08002301 "WLS_BATCHING_SET is only allowed in infra STA/P2P client mode",
Sushant Kaushik8bc7df22014-04-09 17:55:29 +05302302 hdd_device_modetoString(pAdapter->device_mode),
2303 pAdapter->device_mode);
Rajeev Kumar8b373292014-01-08 20:36:55 -08002304 ret = -EINVAL;
2305 goto exit;
2306 }
2307
2308 status = hdd_parse_set_batchscan_command(value, pReq);
2309 if (status)
2310 {
2311 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2312 "Invalid WLS_BATCHING SET command");
2313 ret = -EINVAL;
2314 goto exit;
2315 }
2316
2317
2318 pAdapter->hdd_wait_for_set_batch_scan_rsp = TRUE;
2319 halStatus = sme_SetBatchScanReq(WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
2320 pAdapter->sessionId, hdd_set_batch_scan_req_callback,
2321 pAdapter);
2322
2323 if ( eHAL_STATUS_SUCCESS == halStatus )
2324 {
Mahesh A Saptasagar5f568172014-05-14 17:02:33 +05302325 char extra[32];
2326 tANI_U8 len = 0;
2327 tANI_U8 mScan = 0;
2328
Rajeev Kumar8b373292014-01-08 20:36:55 -08002329 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2330 "sme_SetBatchScanReq returned success halStatus %d",
2331 halStatus);
2332 if (TRUE == pAdapter->hdd_wait_for_set_batch_scan_rsp)
2333 {
2334 INIT_COMPLETION(pAdapter->hdd_set_batch_scan_req_var);
2335 rc = wait_for_completion_timeout(
2336 &pAdapter->hdd_set_batch_scan_req_var,
2337 msecs_to_jiffies(HDD_SET_BATCH_SCAN_REQ_TIME_OUT));
2338 if (0 == rc)
2339 {
2340 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2341 "%s: Timeout waiting for set batch scan to complete",
2342 __func__);
2343 ret = -EINVAL;
2344 goto exit;
2345 }
2346 }
2347 if ( !pRsp->nScansToBatch )
2348 {
2349 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2350 "%s: Received set batch scan failure response from FW",
2351 __func__);
2352 ret = -EINVAL;
2353 goto exit;
2354 }
2355 /*As per the Batch Scan Framework API we should return the MIN of
2356 either MSCAN or the max # of scans firmware can cache*/
Mahesh A Saptasagar5f568172014-05-14 17:02:33 +05302357 mScan = MIN(pReq->numberOfScansToBatch , pRsp->nScansToBatch);
Rajeev Kumar8b373292014-01-08 20:36:55 -08002358
2359 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STARTED;
2360
2361 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2362 "%s: request MSCAN %d response MSCAN %d ret %d",
Mahesh A Saptasagar5f568172014-05-14 17:02:33 +05302363 __func__, pReq->numberOfScansToBatch, pRsp->nScansToBatch, mScan);
2364 len = scnprintf(extra, sizeof(extra), "%d", mScan);
2365 if (copy_to_user(pPrivdata->buf, &extra, len + 1))
2366 {
2367 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2368 "%s: failed to copy MSCAN value to user buffer", __func__);
2369 ret = -EFAULT;
2370 goto exit;
2371 }
Rajeev Kumar8b373292014-01-08 20:36:55 -08002372 }
2373 else
2374 {
2375 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2376 "sme_SetBatchScanReq returned failure halStatus %d",
2377 halStatus);
2378 ret = -EINVAL;
2379 goto exit;
2380 }
2381 }
2382 else if (strncmp(command, "WLS_BATCHING STOP", 17) == 0)
2383 {
2384 eHalStatus halStatus;
2385 tSirStopBatchScanInd *pInd = &pAdapter->hddStopBatchScanInd;
2386 pInd->param = 0;
2387
2388 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
2389 {
2390 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2391 "%s: Batch scan feature is not supported by FW", __func__);
2392 ret = -EINVAL;
2393 goto exit;
2394 }
2395
2396 if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState)
2397 {
Deepthi Gowribfd17132014-11-14 17:59:04 +05302398 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Rajeev Kumar8b373292014-01-08 20:36:55 -08002399 "Batch scan is not yet enabled batch scan state %d",
2400 pAdapter->batchScanState);
2401 ret = -EINVAL;
2402 goto exit;
2403 }
2404
Kiet Lamaa8e15a2014-02-11 23:30:06 -08002405 mutex_lock(&pAdapter->hdd_batch_scan_lock);
2406 hdd_deinit_batch_scan(pAdapter);
2407 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
2408
Rajeev Kumar8b373292014-01-08 20:36:55 -08002409 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
2410
2411 halStatus = sme_StopBatchScanInd(WLAN_HDD_GET_HAL_CTX(pAdapter), pInd,
2412 pAdapter->sessionId);
2413 if ( eHAL_STATUS_SUCCESS == halStatus )
2414 {
2415 ret = 0;
2416 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2417 "sme_StopBatchScanInd returned success halStatus %d",
2418 halStatus);
2419 }
2420 else
2421 {
2422 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2423 "sme_StopBatchScanInd returned failure halStatus %d",
2424 halStatus);
2425 ret = -EINVAL;
2426 goto exit;
2427 }
2428 }
2429 else if (strncmp(command, "WLS_BATCHING GET", 16) == 0)
2430 {
2431 tANI_U32 remain_len;
2432
2433 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
2434 {
2435 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2436 "%s: Batch scan feature is not supported by FW", __func__);
2437 ret = -EINVAL;
2438 goto exit;
2439 }
2440
2441 if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState)
2442 {
Deepthi Gowribfd17132014-11-14 17:59:04 +05302443 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Rajeev Kumar8b373292014-01-08 20:36:55 -08002444 "Batch scan is not yet enabled could not return results"
2445 "Batch Scan state %d",
2446 pAdapter->batchScanState);
2447 ret = -EINVAL;
2448 goto exit;
2449 }
2450
2451 pPrivdata->used_len = 16;
2452 remain_len = pPrivdata->total_len - pPrivdata->used_len;
2453 if (remain_len < pPrivdata->total_len)
2454 {
2455 /*Clear previous batch scan response data if any*/
2456 vos_mem_zero((tANI_U8 *)(command + pPrivdata->used_len), remain_len);
2457 }
2458 else
2459 {
2460 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2461 "Invalid total length from user space can't fetch batch"
2462 " scan response total_len %d used_len %d remain len %d",
2463 pPrivdata->total_len, pPrivdata->used_len, remain_len);
2464 ret = -EINVAL;
2465 goto exit;
2466 }
2467 ret = hdd_return_batch_scan_rsp_to_user(pAdapter, pPrivdata, command);
2468 }
2469
2470exit:
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05302471 EXIT();
Rajeev Kumar8b373292014-01-08 20:36:55 -08002472 return ret;
2473}
2474
2475
Rajeev79dbe4c2013-10-05 11:03:42 +05302476#endif/*End of FEATURE_WLAN_BATCH_SCAN*/
2477
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05302478#if defined(WLAN_FEATURE_VOWIFI_11R) || defined(FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
2479/**
2480 * hdd_assign_handoff_src_reassoc - Set handoff source as REASSOC
2481 * to Handoff request
2482 * @handoffInfo: Pointer to Handoff request
2483 * @src: enum of handoff_src
2484 * Return: None
2485 */
2486#ifndef QCA_WIFI_ISOC
2487static inline void hdd_assign_handoff_src_reassoc(tCsrHandoffRequest
2488 *handoffInfo, handoff_src src)
2489{
2490 handoffInfo->src = src;
2491}
2492#else
2493static inline void hdd_assign_handoff_src_reassoc(tCsrHandoffRequest
2494 *handoffInfo, handoff_src src)
2495{
2496}
2497#endif
2498
2499/**
Selvaraj, Sridhar4fa15232016-06-18 12:27:25 +05302500 * hdd_reassoc() - perform a user space-directed reassoc
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05302501 *
2502 * @pAdapter: Adapter upon which the command was received
2503 * @bssid: BSSID with which to reassociate
2504 * @channel: channel upon which to reassociate
Selvaraj, Sridhar4fa15232016-06-18 12:27:25 +05302505 * @src: The source for the trigger of this action
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05302506 *
2507 * Return: 0 for success non-zero for failure
2508 */
2509#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
Selvaraj, Sridhar8ecb4192016-06-23 17:50:49 +05302510int hdd_reassoc(hdd_adapter_t *pAdapter, const tANI_U8 *bssid,
Selvaraj, Sridhar4fa15232016-06-18 12:27:25 +05302511 const tANI_U8 channel, const handoff_src src)
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05302512{
2513 hdd_station_ctx_t *pHddStaCtx;
2514 tCsrHandoffRequest handoffInfo;
2515 hdd_context_t *pHddCtx = NULL;
2516 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2517
2518 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2519
2520 /* if not associated, no need to proceed with reassoc */
2521 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
2522 hddLog(LOG1, FL("Not associated"));
2523 return -EINVAL;
2524 }
2525
2526 /* if the target bssid is same as currently associated AP,
2527 then no need to proceed with reassoc */
2528 if (!memcmp(bssid, pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr))) {
2529 hddLog(LOG1, FL("Reassoc BSSID is same as currently associated AP bssid"));
2530 return -EINVAL;
2531 }
2532
2533 /* Check channel number is a valid channel number */
2534 if (VOS_STATUS_SUCCESS !=
2535 wlan_hdd_validate_operation_channel(pAdapter, channel)) {
2536 hddLog(LOGE, FL("Invalid Channel %d"), channel);
2537 return -EINVAL;
2538 }
2539
2540 /* Proceed with reassoc */
2541 handoffInfo.channel = channel;
Selvaraj, Sridhar4fa15232016-06-18 12:27:25 +05302542 hdd_assign_handoff_src_reassoc(&handoffInfo, src);
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05302543 memcpy(handoffInfo.bssid, bssid, sizeof(tSirMacAddr));
2544 sme_HandoffRequest(pHddCtx->hHal, &handoffInfo);
2545 return 0;
2546}
2547#else
Selvaraj, Sridhar8ecb4192016-06-23 17:50:49 +05302548int hdd_reassoc(hdd_adapter_t *pAdapter, const tANI_U8 *bssid,
Selvaraj, Sridhar4fa15232016-06-18 12:27:25 +05302549 const tANI_U8 channel, const handoff_src src)
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05302550{
2551 return -EPERM;
2552}
2553#endif
2554
2555/**
2556 * hdd_parse_reassoc_v1() - parse version 1 of the REASSOC command
2557 * This function parses the v1 REASSOC command with the format
2558 * REASSOC xx:xx:xx:xx:xx:xx CH where "xx:xx:xx:xx:xx:xx" is the
2559 * Hex-ASCII representation of the BSSID and CH is the ASCII
2560 * representation of the channel. For example
2561 * REASSOC 00:0a:0b:11:22:33 48
2562 *
2563 * @pAdapter: Adapter upon which the command was received
2564 * @command: ASCII text command that was received
2565 *
2566 * Return: 0 for success non-zero for failure
2567 */
2568static int
2569hdd_parse_reassoc_v1(hdd_adapter_t *pAdapter, const char *command)
2570{
2571 tANI_U8 channel = 0;
2572 tSirMacAddr bssid;
2573 int ret;
2574
2575 ret = hdd_parse_reassoc_command_v1_data(command, bssid, &channel);
2576 if (ret)
2577 hddLog(LOGE, FL("Failed to parse reassoc command data"));
2578 else
Selvaraj, Sridhar4fa15232016-06-18 12:27:25 +05302579 ret = hdd_reassoc(pAdapter, bssid, channel, REASSOC);
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05302580
2581 return ret;
2582}
2583
2584/**
2585 * hdd_parse_reassoc_v2() - parse version 2 of the REASSOC command
2586 * This function parses the v2 REASSOC command with the format
2587 * REASSOC <android_wifi_reassoc_params>
2588 *
2589 * @pAdapter: Adapter upon which the command was received
2590 * @command: command that was received, ASCII command followed
2591 * by binary data
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05302592 * @total_len: Total length of the command received
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05302593 *
2594 * Return: 0 for success non-zero for failure
2595 */
2596static int
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05302597hdd_parse_reassoc_v2(hdd_adapter_t *pAdapter, const char *command,
2598 int total_len)
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05302599{
2600 struct android_wifi_reassoc_params params;
2601 tSirMacAddr bssid;
2602 int ret;
2603
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05302604 if (total_len < sizeof(params) + 8) {
2605 hddLog(LOGE, FL("Invalid command length"));
2606 return -EINVAL;
2607 }
2608
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05302609 /* The params are located after "REASSOC " */
2610 memcpy(&params, command + 8, sizeof(params));
2611
2612 if (!mac_pton(params.bssid, (u8 *)&bssid)) {
2613 hddLog(LOGE, FL("MAC address parsing failed"));
2614 ret = -EINVAL;
2615 } else {
Selvaraj, Sridhar4fa15232016-06-18 12:27:25 +05302616 ret = hdd_reassoc(pAdapter, bssid, params.channel, REASSOC);
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05302617 }
2618 return ret;
2619}
2620
2621/**
2622 * hdd_parse_reassoc() - parse the REASSOC command
2623 * There are two different versions of the REASSOC command.Version 1
2624 * of the command contains a parameter list that is ASCII characters
2625 * whereas version 2 contains a combination of ASCII and binary
2626 * payload. Determine if a version 1 or a version 2 command is being
2627 * parsed by examining the parameters, and then dispatch the parser
2628 * that is appropriate for the command.
2629 *
2630 * @pAdapter: Adapter upon which the command was received
2631 * @command: command that was received
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05302632 * @total_len: Total length of the command received
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05302633 *
2634 * Return: 0 for success non-zero for failure
2635 */
2636static int
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05302637hdd_parse_reassoc(hdd_adapter_t *pAdapter, const char *command, int total_len)
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05302638{
2639 int ret;
2640
2641 /*
2642 * both versions start with "REASSOC"
2643 * v1 has a bssid and channel # as an ASCII string
2644 * REASSOC xx:xx:xx:xx:xx:xx CH
2645 * v2 has a C struct
2646 * REASSOC <binary c struct>
2647 *
2648 * The first field in the v2 struct is also the bssid in ASCII.
2649 * But in the case of a v2 message the BSSID is NUL-terminated.
2650 * Hence we can peek at that offset to see if this is V1 or V2
2651 * REASSOC xx:xx:xx:xx:xx:xx*
2652 * 1111111111222222
2653 * 01234567890123456789012345
2654 */
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05302655
2656 if (total_len < 26) {
2657 hddLog(LOGE, FL("Invalid command (total_len=%d)"), total_len);
2658 return -EINVAL;
2659 }
2660
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05302661 if (command[25])
2662 ret = hdd_parse_reassoc_v1(pAdapter, command);
2663 else
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05302664 ret = hdd_parse_reassoc_v2(pAdapter, command, total_len);
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05302665
2666 return ret;
2667}
2668#endif /* WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_ESE FEATURE_WLAN_LFR */
2669
c_hpothu92367912014-05-01 15:18:17 +05302670static void getBcnMissRateCB(VOS_STATUS status, int bcnMissRate, void *data)
2671{
c_hpothu39eb1e32014-06-26 16:31:50 +05302672 bcnMissRateContext_t *pCBCtx;
2673
2674 if (NULL == data)
2675 {
2676 hddLog(VOS_TRACE_LEVEL_ERROR, FL("argument data is NULL"));
2677 return;
2678 }
c_hpothu92367912014-05-01 15:18:17 +05302679
2680 /* there is a race condition that exists between this callback
2681 function and the caller since the caller could time out either
2682 before or while this code is executing. we use a spinlock to
2683 serialize these actions */
2684 spin_lock(&hdd_context_lock);
2685
c_hpothu39eb1e32014-06-26 16:31:50 +05302686 pCBCtx = (bcnMissRateContext_t *)data;
c_hpothu92367912014-05-01 15:18:17 +05302687 gbcnMissRate = -1;
2688
c_hpothu39eb1e32014-06-26 16:31:50 +05302689 if (pCBCtx->magic != BCN_MISS_RATE_CONTEXT_MAGIC)
c_hpothu92367912014-05-01 15:18:17 +05302690 {
2691 hddLog(VOS_TRACE_LEVEL_ERROR,
c_hpothu39eb1e32014-06-26 16:31:50 +05302692 FL("invalid context magic: %08x"), pCBCtx->magic);
c_hpothu92367912014-05-01 15:18:17 +05302693 spin_unlock(&hdd_context_lock);
2694 return ;
2695 }
2696
2697 if (VOS_STATUS_SUCCESS == status)
2698 {
c_hpothu39eb1e32014-06-26 16:31:50 +05302699 gbcnMissRate = bcnMissRate;
c_hpothu92367912014-05-01 15:18:17 +05302700 }
c_hpothu39eb1e32014-06-26 16:31:50 +05302701 else
2702 {
2703 hddLog(VOS_TRACE_LEVEL_ERROR, FL("failed to get bcnMissRate"));
2704 }
2705
c_hpothu92367912014-05-01 15:18:17 +05302706 complete(&(pCBCtx->completion));
2707 spin_unlock(&hdd_context_lock);
2708
2709 return;
2710}
2711
Abhishek Singh08aa7762014-12-16 13:59:03 +05302712void hdd_FWStatisCB( VOS_STATUS status,
2713 tSirFwStatsResult *fwStatsResult, void *pContext )
Satyanarayana Dash72806012014-12-02 14:30:08 +05302714{
2715 fwStatsContext_t *fwStatsCtx;
Satyanarayana Dash72806012014-12-02 14:30:08 +05302716 hdd_adapter_t *pAdapter;
2717
2718 hddLog(VOS_TRACE_LEVEL_INFO, FL(" with status = %d"),status);
2719
Abhishek Singh08aa7762014-12-16 13:59:03 +05302720 if (NULL == pContext)
Satyanarayana Dash72806012014-12-02 14:30:08 +05302721 {
2722 hddLog(VOS_TRACE_LEVEL_ERROR, FL("argument data is NULL"));
2723 return;
2724 }
2725 /* there is a race condition that exists between this callback
2726 function and the caller since the caller could time out either
2727 before or while this code is executing. we use a spinlock to
2728 serialize these actions */
2729 spin_lock(&hdd_context_lock);
Abhishek Singh08aa7762014-12-16 13:59:03 +05302730 fwStatsCtx = (fwStatsContext_t *) pContext;
Satyanarayana Dash72806012014-12-02 14:30:08 +05302731 if (fwStatsCtx->magic != FW_STATS_CONTEXT_MAGIC)
2732 {
2733 hddLog(VOS_TRACE_LEVEL_ERROR,
2734 FL("invalid context magic: %08x"), fwStatsCtx->magic);
2735 spin_unlock(&hdd_context_lock);
2736 return;
2737 }
2738 pAdapter = fwStatsCtx->pAdapter;
2739 if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
2740 {
2741 hddLog(VOS_TRACE_LEVEL_ERROR,
2742 FL("pAdapter returned is NULL or invalid"));
2743 spin_unlock(&hdd_context_lock);
2744 return;
2745 }
2746 pAdapter->fwStatsRsp.type = 0;
Abhishek Singh08aa7762014-12-16 13:59:03 +05302747 if ((VOS_STATUS_SUCCESS == status) && (NULL != fwStatsResult))
Satyanarayana Dash72806012014-12-02 14:30:08 +05302748 {
Satyanarayana Dash72806012014-12-02 14:30:08 +05302749 switch( fwStatsResult->type )
2750 {
2751 case FW_UBSP_STATS:
2752 {
Abhishek Singh08aa7762014-12-16 13:59:03 +05302753 memcpy(&pAdapter->fwStatsRsp,fwStatsResult,sizeof(tSirFwStatsResult));
Satyanarayana Dash72806012014-12-02 14:30:08 +05302754 hddLog(VOS_TRACE_LEVEL_INFO,
2755 FL("ubsp_enter_cnt = %d ubsp_jump_ddr_cnt = %d"),
Abhishek Singh08aa7762014-12-16 13:59:03 +05302756 pAdapter->fwStatsRsp.fwStatsData.ubspStats.ubsp_enter_cnt,
2757 pAdapter->fwStatsRsp.fwStatsData.ubspStats.ubsp_jump_ddr_cnt);
Satyanarayana Dash72806012014-12-02 14:30:08 +05302758 }
2759 break;
2760 default:
2761 {
2762 hddLog(VOS_TRACE_LEVEL_ERROR,
2763 FL(" No handling for stats type %d"),fwStatsResult->type);
2764 }
2765 }
2766 }
2767 complete(&(fwStatsCtx->completion));
2768 spin_unlock(&hdd_context_lock);
2769 return;
2770}
2771
jge35567202017-06-21 16:39:38 +08002772/*
2773 *hdd_parse_setmaxtxpower_command() - HDD Parse MAXTXPOWER command
2774 *@pValue Pointer to MAXTXPOWER command
2775 *@pTxPower Pointer to tx power
2776 *
2777 *This function parses the MAXTXPOWER command passed in the format
2778 * MAXTXPOWER<space>X(Tx power in dbm)
2779 * For example input commands:
2780 * 1) MAXTXPOWER -8 -> This is translated into set max TX power to -8 dbm
2781 * 2) MAXTXPOWER -23 -> This is translated into set max TX power to -23 dbm
2782 *
2783 *return - 0 for success non-zero for failure
2784 */
2785static int hdd_parse_setmaxtxpower_command(unsigned char *pValue, int *pTxPower)
2786{
2787 unsigned char *inPtr = pValue;
2788 int tempInt;
2789 int v = 0;
2790 *pTxPower = 0;
2791
2792 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2793 /* no argument after the command */
2794 if (NULL == inPtr)
2795 return -EINVAL;
2796 /* no space after the command */
2797 else if (SPACE_ASCII_VALUE != *inPtr)
2798 return -EINVAL;
2799
2800 /* removing empty spaces */
2801 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
2802
2803 /* no argument followed by spaces */
2804 if ('\0' == *inPtr)
2805 return 0;
2806
2807 v = kstrtos32(inPtr, 10, &tempInt);
2808
2809 /* Range checking for passed parameter */
2810 if ((tempInt < HDD_MIN_TX_POWER) || (tempInt > HDD_MAX_TX_POWER))
2811 return -EINVAL;
2812
2813 *pTxPower = tempInt;
2814
2815 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2816 "SETMAXTXPOWER: %d", *pTxPower);
2817
2818 return 0;
2819}
2820
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302821static int hdd_get_dwell_time(hdd_config_t *pCfg, tANI_U8 *command, char *extra, tANI_U8 n, tANI_U8 *len)
2822{
2823 int ret = 0;
2824
2825 if (!pCfg || !command || !extra || !len)
2826 {
2827 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2828 "%s: argument passsed for GETDWELLTIME is incorrect", __func__);
2829 ret = -EINVAL;
2830 return ret;
2831 }
2832
2833 if (strncmp(command, "GETDWELLTIME ACTIVE MAX", 23) == 0)
2834 {
2835 *len = scnprintf(extra, n, "GETDWELLTIME ACTIVE MAX %u\n",
2836 (int)pCfg->nActiveMaxChnTime);
2837 return ret;
2838 }
2839 else if (strncmp(command, "GETDWELLTIME ACTIVE MIN", 23) == 0)
2840 {
2841 *len = scnprintf(extra, n, "GETDWELLTIME ACTIVE MIN %u\n",
2842 (int)pCfg->nActiveMinChnTime);
2843 return ret;
2844 }
2845 else if (strncmp(command, "GETDWELLTIME PASSIVE MAX", 24) == 0)
2846 {
2847 *len = scnprintf(extra, n, "GETDWELLTIME PASSIVE MAX %u\n",
2848 (int)pCfg->nPassiveMaxChnTime);
2849 return ret;
2850 }
2851 else if (strncmp(command, "GETDWELLTIME PASSIVE MIN", 24) == 0)
2852 {
2853 *len = scnprintf(extra, n, "GETDWELLTIME PASSIVE MIN %u\n",
2854 (int)pCfg->nPassiveMinChnTime);
2855 return ret;
2856 }
Rajesh Babu Prathipati0fd227e2014-07-05 12:50:00 +05302857 else if (strncmp(command, "GETDWELLTIME", 12) == 0)
2858 {
2859 *len = scnprintf(extra, n, "GETDWELLTIME %u \n",
2860 (int)pCfg->nActiveMaxChnTime);
2861 return ret;
2862 }
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302863 else
2864 {
2865 ret = -EINVAL;
2866 }
2867
2868 return ret;
2869}
2870
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05302871int hdd_drv_cmd_validate(tANI_U8 *command, int len)
2872{
2873 if (command[len] != ' ')
2874 return -EINVAL;
2875
2876 return 0;
2877}
2878
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302879static int hdd_set_dwell_time(hdd_adapter_t *pAdapter, tANI_U8 *command)
2880{
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302881 tHalHandle hHal;
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302882 hdd_config_t *pCfg;
2883 tANI_U8 *value = command;
2884 int val = 0, ret = 0, temp = 0;
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302885 tSmeConfigParams smeConfig;
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302886
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302887 if (!pAdapter || !command || !(pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini)
2888 || !(hHal = (WLAN_HDD_GET_HAL_CTX(pAdapter))))
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302889 {
2890 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2891 "%s: argument passed for SETDWELLTIME is incorrect", __func__);
2892 ret = -EINVAL;
2893 return ret;
2894 }
2895
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302896 vos_mem_zero(&smeConfig, sizeof(smeConfig));
2897 sme_GetConfigParam(hHal, &smeConfig);
2898
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302899 if (strncmp(command, "SETDWELLTIME ACTIVE MAX", 23) == 0 )
2900 {
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05302901 if (hdd_drv_cmd_validate(command, 23))
2902 return -EINVAL;
2903
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302904 value = value + 24;
2905 temp = kstrtou32(value, 10, &val);
2906 if (temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_MIN ||
2907 val > CFG_ACTIVE_MAX_CHANNEL_TIME_MAX )
2908 {
2909 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2910 "%s: argument passed for SETDWELLTIME ACTIVE MAX is incorrect", __func__);
2911 ret = -EFAULT;
2912 return ret;
2913 }
2914 pCfg->nActiveMaxChnTime = val;
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302915 smeConfig.csrConfig.nActiveMaxChnTime = val;
2916 sme_UpdateConfig(hHal, &smeConfig);
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302917 }
2918 else if (strncmp(command, "SETDWELLTIME ACTIVE MIN", 23) == 0)
2919 {
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05302920 if (hdd_drv_cmd_validate(command, 23))
2921 return -EINVAL;
2922
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302923 value = value + 24;
2924 temp = kstrtou32(value, 10, &val);
2925 if (temp !=0 || val < CFG_ACTIVE_MIN_CHANNEL_TIME_MIN ||
2926 val > CFG_ACTIVE_MIN_CHANNEL_TIME_MAX )
2927 {
2928 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2929 "%s: argument passsed for SETDWELLTIME ACTIVE MIN is incorrect", __func__);
2930 ret = -EFAULT;
2931 return ret;
2932 }
2933 pCfg->nActiveMinChnTime = val;
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302934 smeConfig.csrConfig.nActiveMinChnTime = val;
2935 sme_UpdateConfig(hHal, &smeConfig);
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302936 }
2937 else if (strncmp(command, "SETDWELLTIME PASSIVE MAX", 24) == 0)
2938 {
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05302939 if (hdd_drv_cmd_validate(command, 24))
2940 return -EINVAL;
2941
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302942 value = value + 25;
2943 temp = kstrtou32(value, 10, &val);
2944 if (temp != 0 || val < CFG_PASSIVE_MAX_CHANNEL_TIME_MIN ||
2945 val > CFG_PASSIVE_MAX_CHANNEL_TIME_MAX )
2946 {
2947 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2948 "%s: argument passed for SETDWELLTIME PASSIVE MAX is incorrect", __func__);
2949 ret = -EFAULT;
2950 return ret;
2951 }
2952 pCfg->nPassiveMaxChnTime = val;
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302953 smeConfig.csrConfig.nPassiveMaxChnTime = val;
2954 sme_UpdateConfig(hHal, &smeConfig);
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302955 }
2956 else if (strncmp(command, "SETDWELLTIME PASSIVE MIN", 24) == 0)
2957 {
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05302958 if (hdd_drv_cmd_validate(command, 24))
2959 return -EINVAL;
2960
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302961 value = value + 25;
2962 temp = kstrtou32(value, 10, &val);
2963 if (temp != 0 || val < CFG_PASSIVE_MIN_CHANNEL_TIME_MIN ||
2964 val > CFG_PASSIVE_MIN_CHANNEL_TIME_MAX )
2965 {
2966 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2967 "%s: argument passed for SETDWELLTIME PASSIVE MIN is incorrect", __func__);
2968 ret = -EFAULT;
2969 return ret;
2970 }
2971 pCfg->nPassiveMinChnTime = val;
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302972 smeConfig.csrConfig.nPassiveMinChnTime = val;
2973 sme_UpdateConfig(hHal, &smeConfig);
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302974 }
Rajesh Babu Prathipati0fd227e2014-07-05 12:50:00 +05302975 else if (strncmp(command, "SETDWELLTIME", 12) == 0)
2976 {
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05302977 if (hdd_drv_cmd_validate(command, 12))
2978 return -EINVAL;
2979
Rajesh Babu Prathipati0fd227e2014-07-05 12:50:00 +05302980 value = value + 13;
2981 temp = kstrtou32(value, 10, &val);
2982 if (temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_MIN ||
2983 val > CFG_ACTIVE_MAX_CHANNEL_TIME_MAX )
2984 {
2985 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2986 "%s: argument passed for SETDWELLTIME is incorrect", __func__);
2987 ret = -EFAULT;
2988 return ret;
2989 }
2990 pCfg->nActiveMaxChnTime = val;
2991 smeConfig.csrConfig.nActiveMaxChnTime = val;
2992 sme_UpdateConfig(hHal, &smeConfig);
2993 }
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302994 else
2995 {
2996 ret = -EINVAL;
2997 }
2998
2999 return ret;
3000}
Agarwal Ashish8bd53ae2015-06-12 18:03:45 +05303001static int hdd_cmd_setFccChannel(hdd_context_t *pHddCtx, tANI_U8 *cmd,
3002 tANI_U8 cmd_len)
3003{
3004 tANI_U8 *value;
3005 tANI_U8 fcc_constraint;
3006
3007 eHalStatus status;
3008 int ret = 0;
3009 value = cmd + cmd_len + 1;
3010
3011 ret = kstrtou8(value, 10, &fcc_constraint);
3012 if ((ret < 0) || (fcc_constraint > 1)) {
3013 /*
3014 * If the input value is greater than max value of datatype,
3015 * then also it is a failure
3016 */
3017 hddLog(VOS_TRACE_LEVEL_ERROR,
3018 "%s: value out of range", __func__);
3019 return -EINVAL;
3020 }
3021
Agrawal Ashish842eea82016-02-04 17:56:16 +05303022 status = sme_handleSetFccChannel(pHddCtx->hHal, fcc_constraint,
3023 pHddCtx->scan_info.mScanPending);
Agarwal Ashish8bd53ae2015-06-12 18:03:45 +05303024 if (status != eHAL_STATUS_SUCCESS)
3025 ret = -EPERM;
3026
3027 return ret;
3028}
3029
Mahesh A Saptasagarbeca12c2015-09-07 16:21:06 +05303030/**---------------------------------------------------------------------------
Agarwal Ashish8bd53ae2015-06-12 18:03:45 +05303031
Mahesh A Saptasagarbeca12c2015-09-07 16:21:06 +05303032 \brief hdd_enable_disable_ca_event() - When Host sends IOCTL (enabled),
3033 FW will send *ONE* CA ind to Host(even though it is duplicate).
3034 When Host send IOCTL (disable), FW doesn't perform any action.
3035 Whenever any change in CA *and* WLAN is in SAP/P2P-GO mode, FW
3036 sends CA ind to host. (regard less of IOCTL status)
3037 \param - pHddCtx - HDD context
3038 \param - command - command received from framework
3039 \param - cmd_len - len of the command
3040
3041 \return - 0 on success, appropriate error values on failure.
3042
3043 --------------------------------------------------------------------------*/
3044int hdd_enable_disable_ca_event(hdd_context_t *pHddCtx, tANI_U8* command, tANI_U8 cmd_len)
3045{
3046 tANI_U8 set_value;
3047 int ret = 0;
3048 eHalStatus status;
3049
3050 ret = wlan_hdd_validate_context(pHddCtx);
3051 if (0 != ret)
3052 {
3053 ret = -EINVAL;
3054 goto exit;
3055 }
3056
3057 if (pHddCtx->cfg_ini->gOptimizeCAevent == 0)
3058 {
3059 hddLog(VOS_TRACE_LEVEL_ERROR, "Enable gOptimizeCAevent"
3060 " ini param to control channel avooidance indication");
3061 ret = 0;
3062 goto exit;
3063 }
3064
3065 set_value = command[cmd_len + 1] - '0';
3066 status = sme_enableDisableChanAvoidIndEvent(pHddCtx->hHal, set_value);
3067 if (status != eHAL_STATUS_SUCCESS)
3068 {
3069 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to send"
3070 " enableDisableChanAoidance command to SME\n", __func__);
3071 ret = -EINVAL;
3072 }
3073
3074exit:
3075 return ret;
3076}
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05303077
Selvaraj, Sridhar3714c4d2016-06-22 15:19:12 +05303078/**
3079 * wlan_hdd_fastreassoc_handoff_request() - Post Handoff request to SME
3080 * @pHddCtx: Pointer to the HDD context
3081 * @channel: channel to reassociate
3082 * @targetApBssid: Target AP/BSSID to reassociate
3083 *
3084 * Return: None
3085 */
3086#if defined(WLAN_FEATURE_ROAM_SCAN_OFFLOAD) && !defined(QCA_WIFI_ISOC)
3087static void wlan_hdd_fastreassoc_handoff_request(hdd_context_t *pHddCtx,
3088 uint8_t channel, tSirMacAddr targetApBssid)
3089{
3090 tCsrHandoffRequest handoffInfo;
3091 handoffInfo.channel = channel;
3092 handoffInfo.src = FASTREASSOC;
3093 vos_mem_copy(handoffInfo.bssid, targetApBssid, sizeof(tSirMacAddr));
3094 sme_HandoffRequest(pHddCtx->hHal, &handoffInfo);
3095}
3096#else
3097static void wlan_hdd_fastreassoc_handoff_request(hdd_context_t *pHddCtx,
3098 uint8_t channel, tSirMacAddr targetApBssid)
3099{
3100}
3101#endif
3102
3103/**
3104 * csr_fastroam_neighbor_ap_event() - Function to trigger scan/roam
3105 * @pAdapter: Pointer to HDD adapter
3106 * @channel: Channel to scan/roam
3107 * @targetApBssid: BSSID to roam
3108 *
3109 * Return: None
3110 */
3111#ifdef QCA_WIFI_ISOC
3112static void csr_fastroam_neighbor_ap_event(hdd_adapter_t *pAdapter,
3113 uint8_t channel, tSirMacAddr targetApBssid)
3114{
3115 smeIssueFastRoamNeighborAPEvent(WLAN_HDD_GET_HAL_CTX(pAdapter),
3116 &targetApBssid[0], eSME_ROAM_TRIGGER_SCAN, channel);
3117}
3118#else
3119static void csr_fastroam_neighbor_ap_event(hdd_adapter_t *pAdapter,
3120 uint8_t channel, tSirMacAddr targetApBssid)
3121{
3122}
3123#endif
3124
3125/**
3126 * wlan_hdd_handle_fastreassoc() - Handle fastreassoc command
3127 * @pAdapter: pointer to hdd adapter
3128 * @command: pointer to the command received
3129 *
3130 * Return: VOS_STATUS enum
3131 */
3132static VOS_STATUS wlan_hdd_handle_fastreassoc(hdd_adapter_t *pAdapter,
3133 uint8_t *command)
3134{
3135 tANI_U8 *value = command;
3136 tANI_U8 channel = 0;
3137 tSirMacAddr targetApBssid;
Selvaraj, Sridhar3714c4d2016-06-22 15:19:12 +05303138 hdd_station_ctx_t *pHddStaCtx = NULL;
3139 hdd_context_t *pHddCtx = NULL;
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05303140 int ret;
Selvaraj, Sridhar349b8fe2017-01-18 13:11:25 +05303141 tCsrRoamModifyProfileFields mod_profile_fields;
3142 uint32_t roam_id = 0;
Selvaraj, Sridhar3714c4d2016-06-22 15:19:12 +05303143 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3144 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3145
3146 /* if not associated, no need to proceed with reassoc */
3147 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
3148 hddLog(LOG1, FL("Not associated!"));
3149 return eHAL_STATUS_FAILURE;
3150 }
3151
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05303152 ret = hdd_parse_reassoc_command_v1_data(value, targetApBssid, &channel);
3153 if (ret) {
Selvaraj, Sridhar3714c4d2016-06-22 15:19:12 +05303154 hddLog(LOGE, FL("Failed to parse reassoc command data"));
3155 return eHAL_STATUS_FAILURE;
3156 }
3157
3158 /* if the target bssid is same as currently associated AP,
3159 then no need to proceed with reassoc */
3160 if (vos_mem_compare(targetApBssid,
3161 pHddStaCtx->conn_info.bssId,
3162 sizeof(tSirMacAddr))) {
Selvaraj, Sridhar349b8fe2017-01-18 13:11:25 +05303163 sme_GetModifyProfileFields(pHddCtx->hHal, pAdapter->sessionId,
3164 &mod_profile_fields);
3165 sme_RoamReassoc(pHddCtx->hHal, pAdapter->sessionId, NULL,
3166 mod_profile_fields, &roam_id, 1);
Selvaraj, Sridhar3714c4d2016-06-22 15:19:12 +05303167 hddLog(LOG1, FL("Reassoc BSSID is same as currently associated AP bssid"));
Selvaraj, Sridhar349b8fe2017-01-18 13:11:25 +05303168 return eHAL_STATUS_SUCCESS;
Selvaraj, Sridhar3714c4d2016-06-22 15:19:12 +05303169 }
3170
3171 /* Check channel number is a valid channel number */
3172 if (VOS_STATUS_SUCCESS !=
3173 wlan_hdd_validate_operation_channel(pAdapter, channel)) {
3174 hddLog(LOGE, FL("Invalid Channel [%d]"), channel);
3175 return eHAL_STATUS_FAILURE;
3176 }
3177
3178 /* Proceed with reassoc */
3179 wlan_hdd_fastreassoc_handoff_request(pHddCtx, channel, targetApBssid);
3180
3181 /* Proceed with scan/roam */
3182 csr_fastroam_neighbor_ap_event(pAdapter, channel, targetApBssid);
3183
3184 return eHAL_STATUS_SUCCESS;
3185}
3186
3187/**
3188 * hdd_assign_reassoc_handoff - Set handoff source as REASSOC
3189 * @handoffInfo: Pointer to the csr Handoff Request.
3190 *
3191 * Return: None
3192 */
3193#ifndef QCA_WIFI_ISOC
3194static inline void hdd_assign_reassoc_handoff(tCsrHandoffRequest *handoffInfo)
3195{
3196 handoffInfo->src = REASSOC;
3197}
3198#else
3199static inline void hdd_assign_reassoc_handoff(tCsrHandoffRequest *handoffInfo)
3200{
3201}
3202#endif
3203
Ashish Kumar Dhanotiya32d092b2018-02-20 21:43:57 +05303204/**
3205 * wlan_hdd_free_cache_channels() - Free the cache channels list
3206 * @hdd_ctx: Pointer to HDD context
3207 *
3208 * Return: None
3209 */
3210
3211static void wlan_hdd_free_cache_channels(hdd_context_t *hdd_ctx)
3212{
3213 mutex_lock(&hdd_ctx->cache_channel_lock);
3214 hdd_ctx->orginal_channels->num_channels = 0;
3215 vos_mem_free(hdd_ctx->orginal_channels->channel_info);
3216 hdd_ctx->orginal_channels->channel_info = NULL;
3217 vos_mem_free(hdd_ctx->orginal_channels);
3218 hdd_ctx->orginal_channels = NULL;
3219 mutex_unlock(&hdd_ctx->cache_channel_lock);
3220}
3221
3222/**
3223 * hdd_alloc_chan_cache() - Allocate the memory to cache the channel
3224 * info for the channels received in command SET_DISABLE_CHANNEL_LIST
3225 * @hdd_ctx: Pointer to HDD context
3226 * @num_chan: Number of channels for which memory needs to
3227 * be allocated
3228 *
3229 * Return: 0 on success and error code on failure
3230 */
3231
3232int hdd_alloc_chan_cache(hdd_context_t *hdd_ctx, int num_chan)
3233{
3234 if (NULL == hdd_ctx->orginal_channels) {
3235 hdd_ctx->orginal_channels =
3236 vos_mem_malloc(sizeof(struct hdd_cache_channels));
3237 if (NULL == hdd_ctx->orginal_channels) {
3238 hddLog(VOS_TRACE_LEVEL_ERROR,
3239 "In %s, VOS_MALLOC_ERR", __func__);
3240 return -EINVAL;
3241 }
3242 hdd_ctx->orginal_channels->num_channels = num_chan;
3243 hdd_ctx->orginal_channels->channel_info =
3244 vos_mem_malloc(num_chan *
3245 sizeof(struct hdd_cache_channel_info));
3246 if (NULL == hdd_ctx->orginal_channels->channel_info) {
3247 hddLog(VOS_TRACE_LEVEL_ERROR,
3248 "In %s, VOS_MALLOC_ERR", __func__);
3249 hdd_ctx->orginal_channels->num_channels = 0;
3250 vos_mem_free(hdd_ctx->orginal_channels);
3251 hdd_ctx->orginal_channels = NULL;
3252 return -EINVAL;
3253 }
3254 } else {
3255 /* Same command comes multiple times */
3256 struct hdd_cache_channel_info *temp_chan_info;
3257
3258 if (hdd_ctx->orginal_channels->num_channels + num_chan >
3259 MAX_CHANNEL) {
3260 hddLog(VOS_TRACE_LEVEL_ERROR,
3261 "%s: Invalid Number of channel received",
3262 __func__);
3263 return -EINVAL;
3264 }
3265
3266 temp_chan_info = vos_mem_malloc((
3267 hdd_ctx->orginal_channels->
3268 num_channels + num_chan) *
3269 sizeof(struct hdd_cache_channel_info));
3270 if (NULL == temp_chan_info) {
3271 hddLog(VOS_TRACE_LEVEL_ERROR,
3272 "In %s, VOS_MALLOC_ERR",
3273 __func__);
3274 return -EINVAL;
3275 }
3276
3277 vos_mem_copy(temp_chan_info, hdd_ctx->orginal_channels->
3278 channel_info, hdd_ctx->orginal_channels->
3279 num_channels *
3280 sizeof(struct hdd_cache_channel_info));
3281
3282 hdd_ctx->orginal_channels->num_channels += num_chan;
3283 vos_mem_free(hdd_ctx->orginal_channels->channel_info);
3284 hdd_ctx->orginal_channels->channel_info = temp_chan_info;
3285 temp_chan_info = NULL;
3286 }
3287 return 0;
3288
3289}
3290
3291
3292int hdd_parse_disable_chan_cmd(hdd_adapter_t *adapter, tANI_U8 *ptr)
3293{
3294 v_PVOID_t pvosGCtx = vos_get_global_context(VOS_MODULE_ID_HDD, NULL);
3295 hdd_context_t *hdd_ctx = vos_get_context(VOS_MODULE_ID_HDD, pvosGCtx);
3296 tANI_U8 *param;
3297 int j, tempInt, index = 0, ret = 0;
3298
3299 if (NULL == pvosGCtx) {
3300 hddLog(VOS_TRACE_LEVEL_FATAL,
3301 "VOS Global Context is NULL");
3302 return -EINVAL;
3303 }
3304
3305 if (NULL == hdd_ctx) {
3306 hddLog(VOS_TRACE_LEVEL_FATAL, "HDD Context is NULL");
3307 return -EINVAL;
3308 }
3309
3310 param = strchr(ptr, ' ');
3311 /*no argument after the command*/
3312 if (NULL == param)
3313 return -EINVAL;
3314
3315 /*no space after the command*/
3316 else if (SPACE_ASCII_VALUE != *param)
3317 return -EINVAL;
3318
3319 param++;
3320
3321 /*removing empty spaces*/
3322 while ((SPACE_ASCII_VALUE == *param) && ('\0' != *param))
3323 param++;
3324
3325 /*no argument followed by spaces*/
3326 if ('\0' == *param)
3327 return -EINVAL;
3328
3329 /*getting the first argument ie the number of channels*/
3330 if (sscanf(param, "%d ", &tempInt) != 1) {
3331 hddLog(VOS_TRACE_LEVEL_ERROR,
3332 "%s: Cannot get number of channels from input",
3333 __func__);
3334 return -EINVAL;
3335 }
3336
3337 if (tempInt < 0 || tempInt > MAX_CHANNEL) {
3338 hddLog(VOS_TRACE_LEVEL_ERROR,
3339 "%s: Invalid Number of channel received", __func__);
3340 return -EINVAL;
3341 }
3342
3343 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
3344 "%s: Number of channel to disable are: %d",
3345 __func__, tempInt);
3346
3347 if (!tempInt) {
3348 if (!wlan_hdd_restore_channels(hdd_ctx)) {
3349 /*
3350 * Free the cache channels only when the command is
3351 * received with num channels as 0
3352 */
3353 wlan_hdd_free_cache_channels(hdd_ctx);
3354 }
3355 return 0;
3356 }
3357
3358 mutex_lock(&hdd_ctx->cache_channel_lock);
3359 if (hdd_alloc_chan_cache(hdd_ctx, tempInt)) {
3360 ret = -ENOMEM;
3361 goto parse_done;
3362 }
3363 index = hdd_ctx->orginal_channels->num_channels - tempInt;
3364
3365 for (j = index; j < hdd_ctx->orginal_channels->num_channels; j++) {
3366 /*
3367 * param pointing to the beginning of first space
3368 * after number of channels
3369 */
3370 param = strpbrk(param, " ");
3371 /*no channel list after the number of channels argument*/
3372 if (NULL == param) {
3373 hddLog(VOS_TRACE_LEVEL_ERROR,
3374 "%s, Invalid No of channel provided in the list",
3375 __func__);
3376 ret = -EINVAL;
3377 goto parse_done;
3378 }
3379
3380 param++;
3381
3382 /*removing empty space*/
3383 while ((SPACE_ASCII_VALUE == *param) && ('\0' != *param))
3384 param++;
3385
3386 if ('\0' == *param) {
3387 hddLog(VOS_TRACE_LEVEL_ERROR,
3388 "%s, No channel is provided in the list",
3389 __func__);
3390 ret = -EINVAL;
3391 goto parse_done;
3392
3393 }
3394
3395 if (sscanf(param, "%d ", &tempInt) != 1) {
3396 hddLog(VOS_TRACE_LEVEL_ERROR,
3397 "%s: Cannot read channel number",
3398 __func__);
3399 ret = -EINVAL;
3400 goto parse_done;
3401
3402 }
3403
3404 if (!IS_CHANNEL_VALID(tempInt)) {
3405 hddLog(VOS_TRACE_LEVEL_ERROR,
3406 "%s: Invalid channel number received",
3407 __func__);
3408 ret = -EINVAL;
3409 goto parse_done;
3410
3411 }
3412
3413 hddLog(VOS_TRACE_LEVEL_INFO, "%s: channel[%d] = %d", __func__,
3414 j, tempInt);
3415 hdd_ctx->orginal_channels->channel_info[j].channel_num =
3416 tempInt;
3417 }
3418
3419 /*extra arguments check*/
3420 param = strchr(param, ' ');
3421 if (NULL != param) {
3422 while ((SPACE_ASCII_VALUE == *param) && ('\0' != *param))
3423 param++;
3424
3425 if ('\0' != *param) {
3426 hddLog(VOS_TRACE_LEVEL_ERROR,
3427 "%s: Invalid argument received", __func__);
3428 ret = -EINVAL;
3429 goto parse_done;
3430 }
3431 }
3432
3433parse_done:
3434 mutex_unlock(&hdd_ctx->cache_channel_lock);
3435 EXIT();
3436
3437 return ret;
3438}
3439
Hanumanth Reddy Pothula8ae38bb2018-03-07 18:59:30 +05303440int hdd_get_disable_ch_list(hdd_context_t *hdd_ctx, tANI_U8 *buf,
3441 tANI_U8 buf_len)
3442{
3443 struct hdd_cache_channel_info *ch_list;
3444 unsigned char i, num_ch;
3445 int len = 0;
3446
3447 mutex_lock(&hdd_ctx->cache_channel_lock);
3448 if (hdd_ctx->orginal_channels &&
3449 hdd_ctx->orginal_channels->num_channels) {
3450 num_ch = hdd_ctx->orginal_channels->num_channels;
3451
3452 if (num_ch == 0) {
3453 mutex_unlock(&hdd_ctx->cache_channel_lock);
3454 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3455 FL("no disable channels programed"));
3456 return 0;
3457 }
3458
3459 len = scnprintf(buf, buf_len, "%s %hhu",
3460 "GET_DISABLE_CHANNEL_LIST", num_ch);
3461
3462 ch_list = hdd_ctx->orginal_channels->channel_info;
3463 if (!ch_list) {
3464 mutex_unlock(&hdd_ctx->cache_channel_lock);
3465 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3466 FL("disable channel list is NULL"));
3467 return 0;
3468 }
3469
3470 for (i = 0; (i < num_ch) && len <= buf_len; i++) {
3471 len += scnprintf(buf + len, buf_len - len,
3472 " %d", ch_list[i].channel_num);
3473 }
3474 }
3475 mutex_unlock(&hdd_ctx->cache_channel_lock);
3476
3477 return len;
3478}
3479
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003480static int hdd_driver_command(hdd_adapter_t *pAdapter,
3481 hdd_priv_data_t *ppriv_data)
Jeff Johnson295189b2012-06-20 16:38:30 -07003482{
Jeff Johnson295189b2012-06-20 16:38:30 -07003483 hdd_priv_data_t priv_data;
3484 tANI_U8 *command = NULL;
Kaushik, Sushant96122442014-10-21 16:40:18 +05303485 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3486 hdd_scaninfo_t *pScanInfo = NULL;
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003487 int ret = 0;
Kaushik, Sushant96122442014-10-21 16:40:18 +05303488 int status;
Anand N Sunkade9adb1b2015-07-29 09:56:45 +05303489#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0))
3490 struct cfg80211_mgmt_tx_params params;
3491#endif
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05303492
3493 ENTER();
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003494 /*
3495 * Note that valid pointers are provided by caller
3496 */
Jeff Johnson295189b2012-06-20 16:38:30 -07003497
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003498 /* copy to local struct to avoid numerous changes to legacy code */
3499 priv_data = *ppriv_data;
Jeff Johnson295189b2012-06-20 16:38:30 -07003500
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003501 if (priv_data.total_len <= 0 ||
3502 priv_data.total_len > WLAN_PRIV_DATA_MAX_LEN)
Sameer Thalappil8ef3a0e2013-04-05 14:36:04 -07003503 {
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003504 hddLog(VOS_TRACE_LEVEL_WARN,
3505 "%s:invalid priv_data.total_len(%d)!!!", __func__,
3506 priv_data.total_len);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003507 ret = -EINVAL;
3508 goto exit;
3509 }
Kaushik, Sushant96122442014-10-21 16:40:18 +05303510 status = wlan_hdd_validate_context(pHddCtx);
3511 if (0 != status)
3512 {
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05303513 ret = -EINVAL;
3514 goto exit;
Kaushik, Sushant96122442014-10-21 16:40:18 +05303515 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003516 /* Allocate +1 for '\0' */
3517 command = kmalloc(priv_data.total_len + 1, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07003518 if (!command)
3519 {
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003520 hddLog(VOS_TRACE_LEVEL_ERROR,
3521 "%s: failed to allocate memory", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003522 ret = -ENOMEM;
3523 goto exit;
3524 }
3525
3526 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
3527 {
3528 ret = -EFAULT;
3529 goto exit;
3530 }
3531
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003532 /* Make sure the command is NUL-terminated */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003533 command[priv_data.total_len] = '\0';
3534
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003535 /* at one time the following block of code was conditional. braces
3536 * have been retained to avoid re-indenting the legacy code
3537 */
Jeff Johnson295189b2012-06-20 16:38:30 -07003538 {
3539 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
3540
3541 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07003542 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -07003543
3544 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
3545 {
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303546 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3547 TRACE_CODE_HDD_P2P_DEV_ADDR_IOCTL,
3548 pAdapter->sessionId, (unsigned)
3549 (*(pHddCtx->p2pDeviceAddress.bytes+2)<<24 |
3550 *(pHddCtx->p2pDeviceAddress.bytes+3)<<16 |
3551 *(pHddCtx->p2pDeviceAddress.bytes+4)<<8 |
3552 *(pHddCtx->p2pDeviceAddress.bytes+5))));
Jeff Johnson295189b2012-06-20 16:38:30 -07003553 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
3554 sizeof(tSirMacAddr)))
3555 {
3556 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Arif Hussain6d2a3322013-11-17 19:50:10 -08003557 "%s: failed to copy data to user buffer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003558 ret = -EFAULT;
3559 }
3560 }
Amar Singhal0974e402013-02-12 14:27:46 -08003561 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07003562 {
Amar Singhal0974e402013-02-12 14:27:46 -08003563 tANI_U8 *ptr = command ;
Srinivas Girigowdade697412013-02-14 16:31:48 -08003564
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05303565 ret = hdd_drv_cmd_validate(command, 7);
3566 if (ret)
3567 goto exit;
3568
Jeff Johnson295189b2012-06-20 16:38:30 -07003569 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -08003570
3571 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -07003572 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07003573 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -08003574 "%s: SetBandCommand Info comm %s UL %d, TL %d", __func__, command, priv_data.used_len, priv_data.total_len);
Anand N Sunkad27354cf2015-07-13 14:39:11 +05303575 if(VOS_FTM_MODE != hdd_get_conparam())
3576 {
3577 /* Change band request received */
3578 ret = hdd_setBand_helper(pAdapter->dev, ptr);
3579 if(ret < 0)
3580 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
3581 "%s: failed to set band ret=%d", __func__, ret);
3582 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08003583 }
Kiet Lamf040f472013-11-20 21:15:23 +05303584 else if(strncmp(command, "SETWMMPS", 8) == 0)
3585 {
3586 tANI_U8 *ptr = command;
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05303587
3588 ret = hdd_drv_cmd_validate(command, 8);
3589 if (ret)
3590 goto exit;
3591
Kiet Lamf040f472013-11-20 21:15:23 +05303592 ret = hdd_wmmps_helper(pAdapter, ptr);
3593 }
Agarwal Ashishef54a182014-12-16 15:07:31 +05303594
3595 else if(strncmp(command, "TDLSSCAN", 8) == 0)
3596 {
3597 tANI_U8 *ptr = command;
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05303598
3599 ret = hdd_drv_cmd_validate(command, 8);
3600 if (ret)
3601 goto exit;
3602
Agarwal Ashishef54a182014-12-16 15:07:31 +05303603 ret = hdd_set_tdls_scan_type(pAdapter, ptr);
3604 }
3605
Jeff Johnson32d95a32012-09-10 13:15:23 -07003606 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
3607 {
3608 char *country_code;
3609
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05303610 ret = hdd_drv_cmd_validate(command, 7);
3611 if (ret)
3612 goto exit;
3613
Jeff Johnson32d95a32012-09-10 13:15:23 -07003614 country_code = command + 8;
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07003615
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07003616 INIT_COMPLETION(pAdapter->change_country_code);
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07003617 hdd_checkandupdate_dfssetting(pAdapter, country_code);
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -07003618#ifndef CONFIG_ENABLE_LINUX_REG
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +05303619 hdd_checkandupdate_phymode(pAdapter, country_code);
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -07003620#endif
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07003621 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal,
3622 (void *)(tSmeChangeCountryCallback)
3623 wlan_hdd_change_country_code_callback,
Abhishek Singha306a442013-11-07 18:39:01 +05303624 country_code, pAdapter, pHddCtx->pvosContext, eSIR_TRUE, eSIR_TRUE);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07003625 if (eHAL_STATUS_SUCCESS == ret)
3626 {
3627 ret = wait_for_completion_interruptible_timeout(
3628 &pAdapter->change_country_code,
3629 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
3630 if (0 >= ret)
3631 {
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003632 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: SME while setting country code timed out %d",
c_hpothu6ff1c3c2013-10-01 19:01:57 +05303633 __func__, ret);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07003634 }
3635 }
3636 else
Jeff Johnson32d95a32012-09-10 13:15:23 -07003637 {
3638 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003639 "%s: SME Change Country code fail ret=%d", __func__, ret);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07003640 ret = -EINVAL;
Jeff Johnson32d95a32012-09-10 13:15:23 -07003641 }
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07003642
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07003643 }
3644 /*
3645 command should be a string having format
3646 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
3647 */
Amar Singhal0974e402013-02-12 14:27:46 -08003648 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07003649 {
Amar Singhal0974e402013-02-12 14:27:46 -08003650 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07003651
3652 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003653 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07003654
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -08003655 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -07003656 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -08003657 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
3658 {
3659 int suspend = 0;
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05303660 tANI_U8 *ptr;
3661
3662 ret = hdd_drv_cmd_validate(command, 14);
3663 if (ret)
3664 goto exit;
3665
3666 ptr = (tANI_U8*)command + 15;
Sameer Thalappil45931fb2013-02-01 11:18:05 -08003667
3668 suspend = *ptr - '0';
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303669 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3670 TRACE_CODE_HDD_SETSUSPENDMODE_IOCTL,
3671 pAdapter->sessionId, suspend));
Sameer Thalappil45931fb2013-02-01 11:18:05 -08003672 hdd_set_wlan_suspend_mode(suspend);
3673 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08003674#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
3675 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
3676 {
3677 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003678 tANI_S8 rssi = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08003679 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
3680 eHalStatus status = eHAL_STATUS_SUCCESS;
3681
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05303682 ret = hdd_drv_cmd_validate(command, 14);
3683 if (ret)
3684 goto exit;
3685
Srinivas Girigowdade697412013-02-14 16:31:48 -08003686 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
3687 value = value + 15;
3688
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003689 /* Convert the value from ascii to integer */
3690 ret = kstrtos8(value, 10, &rssi);
3691 if (ret < 0)
3692 {
3693 /* If the input value is greater than max value of datatype, then also
3694 kstrtou8 fails */
3695 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3696 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdafa7157d2013-10-31 10:14:22 -07003697 __func__,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003698 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
3699 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
3700 ret = -EINVAL;
3701 goto exit;
3702 }
3703
Srinivas Girigowdade697412013-02-14 16:31:48 -08003704 lookUpThreshold = abs(rssi);
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003705
Srinivas Girigowdade697412013-02-14 16:31:48 -08003706 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
3707 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
3708 {
3709 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3710 "Neighbor lookup threshold value %d is out of range"
3711 " (Min: %d Max: %d)", lookUpThreshold,
3712 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
3713 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
3714 ret = -EINVAL;
3715 goto exit;
3716 }
3717
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303718 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3719 TRACE_CODE_HDD_SETROAMTRIGGER_IOCTL,
3720 pAdapter->sessionId, lookUpThreshold));
Srinivas Girigowdade697412013-02-14 16:31:48 -08003721 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3722 "%s: Received Command to Set Roam trigger"
3723 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
3724
3725 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
3726 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
3727 if (eHAL_STATUS_SUCCESS != status)
3728 {
3729 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3730 "%s: Failed to set roam trigger, try again", __func__);
3731 ret = -EPERM;
3732 goto exit;
3733 }
3734
3735 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
mukul sharmad6e1fdd2014-06-23 19:19:09 +05303736 pHddCtx->cfg_ini->nNeighborReassocRssiThreshold = lookUpThreshold + 5;
Srinivas Girigowdade697412013-02-14 16:31:48 -08003737 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
3738 }
3739 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
3740 {
3741 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
3742 int rssi = (-1) * lookUpThreshold;
3743 char extra[32];
3744 tANI_U8 len = 0;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303745 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3746 TRACE_CODE_HDD_GETROAMTRIGGER_IOCTL,
3747 pAdapter->sessionId, lookUpThreshold));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003748 len = scnprintf(extra, sizeof(extra), "%s %d", command, rssi);
Srinivas Girigowda91719232015-07-13 15:10:10 +05303749 len = VOS_MIN(priv_data.total_len, len + 1);
3750 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdade697412013-02-14 16:31:48 -08003751 {
3752 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3753 "%s: failed to copy data to user buffer", __func__);
3754 ret = -EFAULT;
3755 goto exit;
3756 }
3757 }
3758 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
3759 {
3760 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003761 tANI_U8 roamScanPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003762 tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003763
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05303764 ret = hdd_drv_cmd_validate(command, 17);
3765 if (ret)
3766 goto exit;
3767
Srinivas Girigowdade697412013-02-14 16:31:48 -08003768 /* input refresh period is in terms of seconds */
3769 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
3770 value = value + 18;
3771 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003772 ret = kstrtou8(value, 10, &roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08003773 if (ret < 0)
3774 {
3775 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003776 kstrtou8 fails */
Srinivas Girigowdade697412013-02-14 16:31:48 -08003777 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003778 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdade697412013-02-14 16:31:48 -08003779 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07003780 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
3781 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08003782 ret = -EINVAL;
3783 goto exit;
3784 }
3785
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003786 if ((roamScanPeriod < (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000)) ||
3787 (roamScanPeriod > (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000)))
Srinivas Girigowdade697412013-02-14 16:31:48 -08003788 {
3789 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003790 "Roam scan period value %d is out of range"
3791 " (Min: %d Max: %d)", roamScanPeriod,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07003792 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
3793 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08003794 ret = -EINVAL;
3795 goto exit;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303796 }
3797 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3798 TRACE_CODE_HDD_SETROAMSCANPERIOD_IOCTL,
3799 pAdapter->sessionId, roamScanPeriod));
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003800 neighborEmptyScanRefreshPeriod = roamScanPeriod * 1000;
Srinivas Girigowdade697412013-02-14 16:31:48 -08003801
3802 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3803 "%s: Received Command to Set roam scan period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003804 " (Empty Scan refresh period) = %d", __func__, roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08003805
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003806 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod;
3807 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08003808 }
3809 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
3810 {
3811 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
3812 char extra[32];
3813 tANI_U8 len = 0;
3814
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303815 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3816 TRACE_CODE_HDD_GETROAMSCANPERIOD_IOCTL,
3817 pAdapter->sessionId, nEmptyScanRefreshPeriod));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003818 len = scnprintf(extra, sizeof(extra), "%s %d",
3819 "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08003820 /* Returned value is in units of seconds */
Ratnam Rachuria72ba112015-07-17 13:27:03 +05303821 len = VOS_MIN(priv_data.total_len, len + 1);
3822 if (copy_to_user(priv_data.buf, &extra, len)) {
Srinivas Girigowdade697412013-02-14 16:31:48 -08003823 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3824 "%s: failed to copy data to user buffer", __func__);
3825 ret = -EFAULT;
3826 goto exit;
3827 }
3828 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003829 else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0)
3830 {
3831 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003832 tANI_U8 roamScanRefreshPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003833 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003834
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05303835 ret = hdd_drv_cmd_validate(command, 24);
3836 if (ret)
3837 goto exit;
3838
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003839 /* input refresh period is in terms of seconds */
3840 /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */
3841 value = value + 25;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003842
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003843 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003844 ret = kstrtou8(value, 10, &roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003845 if (ret < 0)
3846 {
3847 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003848 kstrtou8 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003849 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003850 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003851 __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003852 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
3853 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
3854 ret = -EINVAL;
3855 goto exit;
3856 }
3857
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003858 if ((roamScanRefreshPeriod < (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000)) ||
3859 (roamScanRefreshPeriod > (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000)))
3860 {
3861 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3862 "Neighbor scan results refresh period value %d is out of range"
3863 " (Min: %d Max: %d)", roamScanRefreshPeriod,
3864 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
3865 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
3866 ret = -EINVAL;
3867 goto exit;
3868 }
3869 neighborScanRefreshPeriod = roamScanRefreshPeriod * 1000;
3870
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003871 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3872 "%s: Received Command to Set roam scan refresh period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003873 " (Scan refresh period) = %d", __func__, roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003874
3875 pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod;
3876 sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
3877 }
3878 else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0)
3879 {
3880 tANI_U16 value = sme_getNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
3881 char extra[32];
3882 tANI_U8 len = 0;
3883
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003884 len = scnprintf(extra, sizeof(extra), "%s %d",
3885 "GETROAMSCANREFRESHPERIOD", (value/1000));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003886 /* Returned value is in units of seconds */
Ratnam Rachuri2c9d6702015-07-17 13:25:16 +05303887 len = VOS_MIN(priv_data.total_len, len + 1);
3888 if (copy_to_user(priv_data.buf, &extra, len)) {
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003889 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3890 "%s: failed to copy data to user buffer", __func__);
3891 ret = -EFAULT;
3892 goto exit;
3893 }
3894 }
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07003895#ifdef FEATURE_WLAN_LFR
3896 /* SETROAMMODE */
3897 else if (strncmp(command, "SETROAMMODE", SIZE_OF_SETROAMMODE) == 0)
3898 {
3899 tANI_U8 *value = command;
3900 tANI_BOOLEAN roamMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
3901
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05303902 if (pHddCtx->concurrency_mode == VOS_STA_MON) {
3903 hddLog(LOGE,
3904 FL("Roaming is always disabled in STA + MON concurrency"));
3905 ret = -EINVAL;
3906 goto exit;
3907 }
3908
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05303909 ret = hdd_drv_cmd_validate(command, SIZE_OF_SETROAMMODE);
3910 if (ret)
3911 goto exit;
3912
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07003913 /* Move pointer to ahead of SETROAMMODE<delimiter> */
3914 value = value + SIZE_OF_SETROAMMODE + 1;
3915
3916 /* Convert the value from ascii to integer */
3917 ret = kstrtou8(value, SIZE_OF_SETROAMMODE, &roamMode);
3918 if (ret < 0)
3919 {
3920 /* If the input value is greater than max value of datatype, then also
3921 kstrtou8 fails */
3922 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3923 "%s: kstrtou8 failed range [%d - %d]", __func__,
3924 CFG_LFR_FEATURE_ENABLED_MIN,
3925 CFG_LFR_FEATURE_ENABLED_MAX);
3926 ret = -EINVAL;
3927 goto exit;
3928 }
3929 if ((roamMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
3930 (roamMode > CFG_LFR_FEATURE_ENABLED_MAX))
3931 {
3932 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3933 "Roam Mode value %d is out of range"
3934 " (Min: %d Max: %d)", roamMode,
3935 CFG_LFR_FEATURE_ENABLED_MIN,
3936 CFG_LFR_FEATURE_ENABLED_MAX);
3937 ret = -EINVAL;
3938 goto exit;
3939 }
3940
3941 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3942 "%s: Received Command to Set Roam Mode = %d", __func__, roamMode);
3943 /*
3944 * Note that
3945 * SETROAMMODE 0 is to enable LFR while
3946 * SETROAMMODE 1 is to disable LFR, but
3947 * NotifyIsFastRoamIniFeatureEnabled 0/1 is to enable/disable.
3948 * So, we have to invert the value to call sme_UpdateIsFastRoamIniFeatureEnabled.
3949 */
3950 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
3951 roamMode = CFG_LFR_FEATURE_ENABLED_MAX; /* Roam enable */
3952 else
3953 roamMode = CFG_LFR_FEATURE_ENABLED_MIN; /* Roam disable */
3954
3955 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = roamMode;
3956 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), roamMode);
3957 }
3958 /* GETROAMMODE */
Mahesh A Saptasagarec7d1092015-04-02 13:41:34 +05303959 else if (strncmp(command, "GETROAMMODE", SIZE_OF_GETROAMMODE) == 0)
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07003960 {
3961 tANI_BOOLEAN roamMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
3962 char extra[32];
3963 tANI_U8 len = 0;
3964
3965 /*
3966 * roamMode value shall be inverted because the sementics is different.
3967 */
3968 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
3969 roamMode = CFG_LFR_FEATURE_ENABLED_MAX;
3970 else
3971 roamMode = CFG_LFR_FEATURE_ENABLED_MIN;
3972
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003973 len = scnprintf(extra, sizeof(extra), "%s %d", command, roamMode);
Ratnam Rachuri28693eb2015-07-17 13:23:42 +05303974 len = VOS_MIN(priv_data.total_len, len + 1);
3975 if (copy_to_user(priv_data.buf, &extra, len)) {
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07003976 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3977 "%s: failed to copy data to user buffer", __func__);
3978 ret = -EFAULT;
3979 goto exit;
3980 }
3981 }
3982#endif
Srinivas Girigowdade697412013-02-14 16:31:48 -08003983#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003984#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -08003985 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
3986 {
3987 tANI_U8 *value = command;
3988 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
3989
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05303990 ret = hdd_drv_cmd_validate(command, 12);
3991 if (ret)
3992 goto exit;
3993
Srinivas Girigowdade697412013-02-14 16:31:48 -08003994 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
3995 value = value + 13;
3996 /* Convert the value from ascii to integer */
3997 ret = kstrtou8(value, 10, &roamRssiDiff);
3998 if (ret < 0)
3999 {
4000 /* If the input value is greater than max value of datatype, then also
4001 kstrtou8 fails */
4002 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4003 "%s: kstrtou8 failed range [%d - %d]", __func__,
4004 CFG_ROAM_RSSI_DIFF_MIN,
4005 CFG_ROAM_RSSI_DIFF_MAX);
4006 ret = -EINVAL;
4007 goto exit;
4008 }
4009
4010 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
4011 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
4012 {
4013 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4014 "Roam rssi diff value %d is out of range"
4015 " (Min: %d Max: %d)", roamRssiDiff,
4016 CFG_ROAM_RSSI_DIFF_MIN,
4017 CFG_ROAM_RSSI_DIFF_MAX);
4018 ret = -EINVAL;
4019 goto exit;
4020 }
4021
4022 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4023 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
4024
4025 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
4026 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
4027 }
Mahesh A Saptasagarec7d1092015-04-02 13:41:34 +05304028 else if (strncmp(command, "GETROAMDELTA", 12) == 0)
Srinivas Girigowdade697412013-02-14 16:31:48 -08004029 {
4030 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
4031 char extra[32];
4032 tANI_U8 len = 0;
4033
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05304034 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
4035 TRACE_CODE_HDD_GETROAMDELTA_IOCTL,
4036 pAdapter->sessionId, roamRssiDiff));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004037 len = scnprintf(extra, sizeof(extra), "%s %d",
4038 command, roamRssiDiff);
Ratnam Rachuri22a3b402015-07-17 13:21:49 +05304039 len = VOS_MIN(priv_data.total_len, len + 1);
4040 if (copy_to_user(priv_data.buf, &extra, len)) {
Srinivas Girigowdade697412013-02-14 16:31:48 -08004041 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4042 "%s: failed to copy data to user buffer", __func__);
4043 ret = -EFAULT;
4044 goto exit;
4045 }
4046 }
4047#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004048#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -08004049 else if (strncmp(command, "GETBAND", 7) == 0)
4050 {
4051 int band = -1;
4052 char extra[32];
4053 tANI_U8 len = 0;
4054 hdd_getBand_helper(pHddCtx, &band);
4055
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05304056 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
4057 TRACE_CODE_HDD_GETBAND_IOCTL,
4058 pAdapter->sessionId, band));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004059 len = scnprintf(extra, sizeof(extra), "%s %d", command, band);
Ratnam Rachuri52139592015-07-17 13:17:29 +05304060 len = VOS_MIN(priv_data.total_len, len + 1);
4061 if (copy_to_user(priv_data.buf, &extra, len)) {
Srinivas Girigowdade697412013-02-14 16:31:48 -08004062 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4063 "%s: failed to copy data to user buffer", __func__);
4064 ret = -EFAULT;
4065 goto exit;
4066 }
4067 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004068 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
4069 {
4070 tANI_U8 *value = command;
4071 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
4072 tANI_U8 numChannels = 0;
4073 eHalStatus status = eHAL_STATUS_SUCCESS;
4074
4075 status = hdd_parse_channellist(value, ChannelList, &numChannels);
4076 if (eHAL_STATUS_SUCCESS != status)
4077 {
4078 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4079 "%s: Failed to parse channel list information", __func__);
4080 ret = -EINVAL;
4081 goto exit;
4082 }
4083
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05304084 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
4085 TRACE_CODE_HDD_SETROAMSCANCHANNELS_IOCTL,
4086 pAdapter->sessionId, numChannels));
Srinivas Girigowdade697412013-02-14 16:31:48 -08004087 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
4088 {
4089 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4090 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
4091 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
4092 ret = -EINVAL;
4093 goto exit;
4094 }
4095 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
4096 numChannels);
4097 if (eHAL_STATUS_SUCCESS != status)
4098 {
4099 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4100 "%s: Failed to update channel list information", __func__);
4101 ret = -EINVAL;
4102 goto exit;
4103 }
4104 }
4105 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
4106 {
4107 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
4108 tANI_U8 numChannels = 0;
Jeff Johnson51b67782013-04-05 12:35:41 -07004109 tANI_U8 j = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08004110 char extra[128] = {0};
Jeff Johnson51b67782013-04-05 12:35:41 -07004111 int len;
Srinivas Girigowdade697412013-02-14 16:31:48 -08004112
4113 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
4114 ChannelList, &numChannels ))
4115 {
4116 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4117 "%s: failed to get roam scan channel list", __func__);
4118 ret = -EFAULT;
4119 goto exit;
4120 }
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05304121 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
4122 TRACE_CODE_HDD_GETROAMSCANCHANNELS_IOCTL,
4123 pAdapter->sessionId, numChannels));
Srinivas Girigowdade697412013-02-14 16:31:48 -08004124 /* output channel list is of the format
4125 [Number of roam scan channels][Channel1][Channel2]... */
4126 /* copy the number of channels in the 0th index */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004127 len = scnprintf(extra, sizeof(extra), "%s %d", command, numChannels);
Sushant Kaushika08ca192015-09-16 15:52:04 +05304128 for (j = 0; (j < numChannels) && len <= sizeof(extra); j++)
Srinivas Girigowdade697412013-02-14 16:31:48 -08004129 {
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004130 len += scnprintf(extra + len, sizeof(extra) - len, " %d",
4131 ChannelList[j]);
Srinivas Girigowdade697412013-02-14 16:31:48 -08004132 }
4133
Sushant Kaushikc9b8be52015-07-15 16:41:27 +05304134 len = VOS_MIN(priv_data.total_len, len + 1);
4135 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdade697412013-02-14 16:31:48 -08004136 {
4137 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4138 "%s: failed to copy data to user buffer", __func__);
4139 ret = -EFAULT;
4140 goto exit;
4141 }
4142 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004143 else if (strncmp(command, "GETCCXMODE", 10) == 0)
4144 {
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004145 tANI_BOOLEAN eseMode = sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004146 char extra[32];
4147 tANI_U8 len = 0;
4148
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004149 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07004150 then this operation is not permitted (return FAILURE) */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004151 if (eseMode &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07004152 hdd_is_okc_mode_enabled(pHddCtx) &&
4153 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
4154 {
4155 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004156 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07004157 " hence this operation is not permitted!", __func__);
4158 ret = -EPERM;
4159 goto exit;
4160 }
4161
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004162 len = scnprintf(extra, sizeof(extra), "%s %d",
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004163 "GETCCXMODE", eseMode);
Sushant Kaushikf8abd352015-07-15 16:37:49 +05304164 len = VOS_MIN(priv_data.total_len, len + 1);
4165 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004166 {
4167 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4168 "%s: failed to copy data to user buffer", __func__);
4169 ret = -EFAULT;
4170 goto exit;
4171 }
4172 }
4173 else if (strncmp(command, "GETOKCMODE", 10) == 0)
4174 {
4175 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
4176 char extra[32];
4177 tANI_U8 len = 0;
4178
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004179 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07004180 then this operation is not permitted (return FAILURE) */
4181 if (okcMode &&
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004182 sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07004183 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
4184 {
4185 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004186 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07004187 " hence this operation is not permitted!", __func__);
4188 ret = -EPERM;
4189 goto exit;
4190 }
4191
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004192 len = scnprintf(extra, sizeof(extra), "%s %d",
4193 "GETOKCMODE", okcMode);
Sushant Kaushikbc2fb5c2015-07-15 16:43:16 +05304194 len = VOS_MIN(priv_data.total_len, len + 1);
4195 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004196 {
4197 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4198 "%s: failed to copy data to user buffer", __func__);
4199 ret = -EFAULT;
4200 goto exit;
4201 }
4202 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07004203 else if (strncmp(command, "GETFASTROAM", 11) == 0)
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004204 {
4205 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
4206 char extra[32];
4207 tANI_U8 len = 0;
4208
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004209 len = scnprintf(extra, sizeof(extra), "%s %d",
4210 "GETFASTROAM", lfrMode);
Sushant Kaushik4da7ec92015-07-15 16:39:32 +05304211 len = VOS_MIN(priv_data.total_len, len + 1);
4212 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004213 {
4214 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4215 "%s: failed to copy data to user buffer", __func__);
4216 ret = -EFAULT;
4217 goto exit;
4218 }
4219 }
4220 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
4221 {
4222 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
4223 char extra[32];
4224 tANI_U8 len = 0;
4225
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004226 len = scnprintf(extra, sizeof(extra), "%s %d",
4227 "GETFASTTRANSITION", ft);
Sushant Kaushik231a4452015-07-15 16:23:56 +05304228 len = VOS_MIN(priv_data.total_len, len + 1);
4229 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004230 {
4231 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4232 "%s: failed to copy data to user buffer", __func__);
4233 ret = -EFAULT;
4234 goto exit;
4235 }
4236 }
4237 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
4238 {
4239 tANI_U8 *value = command;
4240 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
4241
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304242 ret = hdd_drv_cmd_validate(command, 25);
4243 if (ret)
4244 goto exit;
4245
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004246 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
4247 value = value + 26;
4248 /* Convert the value from ascii to integer */
4249 ret = kstrtou8(value, 10, &minTime);
4250 if (ret < 0)
4251 {
4252 /* If the input value is greater than max value of datatype, then also
4253 kstrtou8 fails */
4254 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4255 "%s: kstrtou8 failed range [%d - %d]", __func__,
4256 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
4257 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
4258 ret = -EINVAL;
4259 goto exit;
4260 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004261 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
4262 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
4263 {
4264 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4265 "scan min channel time value %d is out of range"
4266 " (Min: %d Max: %d)", minTime,
4267 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
4268 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
4269 ret = -EINVAL;
4270 goto exit;
4271 }
4272
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05304273 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
4274 TRACE_CODE_HDD_SETROAMSCANCHANNELMINTIME_IOCTL,
4275 pAdapter->sessionId, minTime));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004276 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4277 "%s: Received Command to change channel min time = %d", __func__, minTime);
4278
4279 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
4280 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
4281 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004282 else if (strncmp(command, "SENDACTIONFRAME", 15) == 0)
4283 {
4284 tANI_U8 *value = command;
4285 tANI_U8 channel = 0;
4286 tANI_U8 dwellTime = 0;
4287 tANI_U8 bufLen = 0;
4288 tANI_U8 *buf = NULL;
4289 tSirMacAddr targetApBssid;
4290 eHalStatus status = eHAL_STATUS_SUCCESS;
4291 struct ieee80211_channel chan;
4292 tANI_U8 finalLen = 0;
4293 tANI_U8 *finalBuf = NULL;
4294 tANI_U8 temp = 0;
4295 u64 cookie;
4296 hdd_station_ctx_t *pHddStaCtx = NULL;
4297 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4298
4299 /* if not associated, no need to send action frame */
4300 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
4301 {
4302 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
4303 ret = -EINVAL;
4304 goto exit;
4305 }
4306
4307 status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel,
4308 &dwellTime, &buf, &bufLen);
4309 if (eHAL_STATUS_SUCCESS != status)
4310 {
4311 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4312 "%s: Failed to parse send action frame data", __func__);
4313 ret = -EINVAL;
4314 goto exit;
4315 }
4316
4317 /* if the target bssid is different from currently associated AP,
4318 then no need to send action frame */
4319 if (VOS_TRUE != vos_mem_compare(targetApBssid,
4320 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
4321 {
4322 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__);
4323 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07004324 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08004325 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004326 goto exit;
4327 }
4328
4329 /* if the channel number is different from operating channel then
4330 no need to send action frame */
4331 if (channel != pHddStaCtx->conn_info.operationChannel)
4332 {
4333 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4334 "%s: channel(%d) is different from operating channel(%d)",
4335 __func__, channel, pHddStaCtx->conn_info.operationChannel);
4336 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07004337 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08004338 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004339 goto exit;
4340 }
4341 chan.center_freq = sme_ChnToFreq(channel);
4342
4343 finalLen = bufLen + 24;
4344 finalBuf = vos_mem_malloc(finalLen);
4345 if (NULL == finalBuf)
4346 {
4347 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__);
4348 ret = -ENOMEM;
Jeff Johnson11c33152013-04-16 17:52:40 -07004349 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08004350 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004351 goto exit;
4352 }
4353 vos_mem_zero(finalBuf, finalLen);
4354
4355 /* Fill subtype */
4356 temp = SIR_MAC_MGMT_ACTION << 4;
4357 vos_mem_copy(finalBuf + 0, &temp, sizeof(temp));
4358
4359 /* Fill type */
4360 temp = SIR_MAC_MGMT_FRAME;
4361 vos_mem_copy(finalBuf + 2, &temp, sizeof(temp));
4362
4363 /* Fill destination address (bssid of the AP) */
4364 vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid));
4365
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07004366 /* Fill source address (STA mac address) */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004367 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
4368
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07004369 /* Fill BSSID (AP mac address) */
4370 vos_mem_copy(finalBuf + 16, targetApBssid, sizeof(targetApBssid));
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004371
4372 /* Fill received buffer from 24th address */
4373 vos_mem_copy(finalBuf + 24, buf, bufLen);
4374
Jeff Johnson11c33152013-04-16 17:52:40 -07004375 /* done with the parsed buffer */
4376 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08004377 buf = NULL;
Jeff Johnson11c33152013-04-16 17:52:40 -07004378
Anand N Sunkade9adb1b2015-07-29 09:56:45 +05304379#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0))
4380 params.chan = &chan;
4381 params.offchan = 0;
4382 params.wait = dwellTime;
4383 params.buf = finalBuf;
4384 params.len = finalLen;
4385 params.no_cck = 1;
4386 params.dont_wait_for_ack = 1;
4387 ret = wlan_hdd_mgmt_tx(NULL, &pAdapter->wdev, &params, &cookie);
4388#else
DARAM SUDHA39eede62014-02-12 11:16:40 +05304389 wlan_hdd_mgmt_tx( NULL,
Yue Maf49ba872013-08-19 12:04:25 -07004390#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
4391 &(pAdapter->wdev),
4392#else
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07004393 pAdapter->dev,
Yue Maf49ba872013-08-19 12:04:25 -07004394#endif
4395 &chan, 0,
4396#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
4397 NL80211_CHAN_HT20, 1,
4398#endif
4399 dwellTime, finalBuf, finalLen, 1,
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004400 1, &cookie );
Anand N Sunkade9adb1b2015-07-29 09:56:45 +05304401#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0)*/
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004402 vos_mem_free(finalBuf);
4403 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004404 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
4405 {
4406 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
4407 char extra[32];
4408 tANI_U8 len = 0;
4409
4410 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004411 len = scnprintf(extra, sizeof(extra), "%s %d",
4412 "GETROAMSCANCHANNELMINTIME", val);
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05304413 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
4414 TRACE_CODE_HDD_GETROAMSCANCHANNELMINTIME_IOCTL,
4415 pAdapter->sessionId, val));
Sushant Kaushikbb8c52c2015-07-15 16:36:23 +05304416 len = VOS_MIN(priv_data.total_len, len + 1);
4417 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004418 {
4419 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4420 "%s: failed to copy data to user buffer", __func__);
4421 ret = -EFAULT;
4422 goto exit;
4423 }
4424 }
4425 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
4426 {
4427 tANI_U8 *value = command;
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07004428 tANI_U16 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004429
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304430 ret = hdd_drv_cmd_validate(command, 18);
4431 if (ret)
4432 goto exit;
4433
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004434 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
4435 value = value + 19;
4436 /* Convert the value from ascii to integer */
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07004437 ret = kstrtou16(value, 10, &maxTime);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004438 if (ret < 0)
4439 {
4440 /* If the input value is greater than max value of datatype, then also
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07004441 kstrtou16 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004442 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07004443 "%s: kstrtou16 failed range [%d - %d]", __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004444 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
4445 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
4446 ret = -EINVAL;
4447 goto exit;
4448 }
4449
4450 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
4451 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
4452 {
4453 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4454 "lfr mode value %d is out of range"
4455 " (Min: %d Max: %d)", maxTime,
4456 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
4457 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
4458 ret = -EINVAL;
4459 goto exit;
4460 }
4461
4462 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4463 "%s: Received Command to change channel max time = %d", __func__, maxTime);
4464
4465 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
4466 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
4467 }
4468 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
4469 {
4470 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
4471 char extra[32];
4472 tANI_U8 len = 0;
4473
4474 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004475 len = scnprintf(extra, sizeof(extra), "%s %d",
4476 "GETSCANCHANNELTIME", val);
Ratheesh S Pacbfa932015-07-16 15:27:18 +05304477 len = VOS_MIN(priv_data.total_len, len + 1);
4478 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004479 {
4480 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4481 "%s: failed to copy data to user buffer", __func__);
4482 ret = -EFAULT;
4483 goto exit;
4484 }
4485 }
4486 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
4487 {
4488 tANI_U8 *value = command;
4489 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
4490
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304491 ret = hdd_drv_cmd_validate(command, 15);
4492 if (ret)
4493 goto exit;
4494
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004495 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
4496 value = value + 16;
4497 /* Convert the value from ascii to integer */
4498 ret = kstrtou16(value, 10, &val);
4499 if (ret < 0)
4500 {
4501 /* If the input value is greater than max value of datatype, then also
4502 kstrtou16 fails */
4503 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4504 "%s: kstrtou16 failed range [%d - %d]", __func__,
4505 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
4506 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
4507 ret = -EINVAL;
4508 goto exit;
4509 }
4510
4511 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
4512 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
4513 {
4514 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4515 "scan home time value %d is out of range"
4516 " (Min: %d Max: %d)", val,
4517 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
4518 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
4519 ret = -EINVAL;
4520 goto exit;
4521 }
4522
4523 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4524 "%s: Received Command to change scan home time = %d", __func__, val);
4525
4526 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
4527 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
4528 }
4529 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
4530 {
4531 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
4532 char extra[32];
4533 tANI_U8 len = 0;
4534
4535 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004536 len = scnprintf(extra, sizeof(extra), "%s %d",
4537 "GETSCANHOMETIME", val);
Ratheesh S P728d7c62015-07-16 15:38:58 +05304538 len = VOS_MIN(priv_data.total_len, len + 1);
4539 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004540 {
4541 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4542 "%s: failed to copy data to user buffer", __func__);
4543 ret = -EFAULT;
4544 goto exit;
4545 }
4546 }
4547 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
4548 {
4549 tANI_U8 *value = command;
4550 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
4551
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304552 ret = hdd_drv_cmd_validate(command, 16);
4553 if (ret)
4554 goto exit;
4555
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004556 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
4557 value = value + 17;
4558 /* Convert the value from ascii to integer */
4559 ret = kstrtou8(value, 10, &val);
4560 if (ret < 0)
4561 {
4562 /* If the input value is greater than max value of datatype, then also
4563 kstrtou8 fails */
4564 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4565 "%s: kstrtou8 failed range [%d - %d]", __func__,
4566 CFG_ROAM_INTRA_BAND_MIN,
4567 CFG_ROAM_INTRA_BAND_MAX);
4568 ret = -EINVAL;
4569 goto exit;
4570 }
4571
4572 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
4573 (val > CFG_ROAM_INTRA_BAND_MAX))
4574 {
4575 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4576 "intra band mode value %d is out of range"
4577 " (Min: %d Max: %d)", val,
4578 CFG_ROAM_INTRA_BAND_MIN,
4579 CFG_ROAM_INTRA_BAND_MAX);
4580 ret = -EINVAL;
4581 goto exit;
4582 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004583 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4584 "%s: Received Command to change intra band = %d", __func__, val);
4585
4586 pHddCtx->cfg_ini->nRoamIntraBand = val;
4587 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
4588 }
4589 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
4590 {
4591 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
4592 char extra[32];
4593 tANI_U8 len = 0;
4594
4595 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004596 len = scnprintf(extra, sizeof(extra), "%s %d",
4597 "GETROAMINTRABAND", val);
Ratheesh S P2dd2a3e2015-07-16 15:34:23 +05304598 len = VOS_MIN(priv_data.total_len, len + 1);
4599 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004600 {
4601 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4602 "%s: failed to copy data to user buffer", __func__);
4603 ret = -EFAULT;
4604 goto exit;
4605 }
4606 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004607 else if (strncmp(command, "SETSCANNPROBES", 14) == 0)
4608 {
4609 tANI_U8 *value = command;
4610 tANI_U8 nProbes = CFG_ROAM_SCAN_N_PROBES_DEFAULT;
4611
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304612 ret = hdd_drv_cmd_validate(command, 14);
4613 if (ret)
4614 goto exit;
4615
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004616 /* Move pointer to ahead of SETSCANNPROBES<delimiter> */
4617 value = value + 15;
4618 /* Convert the value from ascii to integer */
4619 ret = kstrtou8(value, 10, &nProbes);
4620 if (ret < 0)
4621 {
4622 /* If the input value is greater than max value of datatype, then also
4623 kstrtou8 fails */
4624 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4625 "%s: kstrtou8 failed range [%d - %d]", __func__,
4626 CFG_ROAM_SCAN_N_PROBES_MIN,
4627 CFG_ROAM_SCAN_N_PROBES_MAX);
4628 ret = -EINVAL;
4629 goto exit;
4630 }
4631
4632 if ((nProbes < CFG_ROAM_SCAN_N_PROBES_MIN) ||
4633 (nProbes > CFG_ROAM_SCAN_N_PROBES_MAX))
4634 {
4635 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4636 "NProbes value %d is out of range"
4637 " (Min: %d Max: %d)", nProbes,
4638 CFG_ROAM_SCAN_N_PROBES_MIN,
4639 CFG_ROAM_SCAN_N_PROBES_MAX);
4640 ret = -EINVAL;
4641 goto exit;
4642 }
4643
4644 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4645 "%s: Received Command to Set nProbes = %d", __func__, nProbes);
4646
4647 pHddCtx->cfg_ini->nProbes = nProbes;
4648 sme_UpdateRoamScanNProbes((tHalHandle)(pHddCtx->hHal), nProbes);
4649 }
Mahesh A Saptasagarec7d1092015-04-02 13:41:34 +05304650 else if (strncmp(command, "GETSCANNPROBES", 14) == 0)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004651 {
4652 tANI_U8 val = sme_getRoamScanNProbes((tHalHandle)(pHddCtx->hHal));
4653 char extra[32];
4654 tANI_U8 len = 0;
4655
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004656 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Ratnam Rachuri6da525d2015-08-07 13:55:54 +05304657 len = VOS_MIN(priv_data.total_len, len + 1);
4658 if (copy_to_user(priv_data.buf, &extra, len)) {
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004659 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4660 "%s: failed to copy data to user buffer", __func__);
4661 ret = -EFAULT;
4662 goto exit;
4663 }
4664 }
4665 else if (strncmp(command, "SETSCANHOMEAWAYTIME", 19) == 0)
4666 {
4667 tANI_U8 *value = command;
4668 tANI_U16 homeAwayTime = CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT;
4669
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304670 ret = hdd_drv_cmd_validate(command, 19);
4671 if (ret)
4672 goto exit;
4673
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004674 /* Move pointer to ahead of SETSCANHOMEAWAYTIME<delimiter> */
4675 /* input value is in units of msec */
4676 value = value + 20;
4677 /* Convert the value from ascii to integer */
4678 ret = kstrtou16(value, 10, &homeAwayTime);
4679 if (ret < 0)
4680 {
4681 /* If the input value is greater than max value of datatype, then also
4682 kstrtou8 fails */
4683 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4684 "%s: kstrtou8 failed range [%d - %d]", __func__,
4685 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
4686 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
4687 ret = -EINVAL;
4688 goto exit;
4689 }
4690
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004691 if ((homeAwayTime < CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN) ||
4692 (homeAwayTime > CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX))
4693 {
4694 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4695 "homeAwayTime value %d is out of range"
4696 " (Min: %d Max: %d)", homeAwayTime,
4697 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
4698 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
4699 ret = -EINVAL;
4700 goto exit;
4701 }
4702
4703 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4704 "%s: Received Command to Set scan away time = %d", __func__, homeAwayTime);
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07004705 if (pHddCtx->cfg_ini->nRoamScanHomeAwayTime != homeAwayTime)
4706 {
4707 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
4708 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_TRUE);
4709 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004710 }
Mahesh A Saptasagarec7d1092015-04-02 13:41:34 +05304711 else if (strncmp(command, "GETSCANHOMEAWAYTIME", 19) == 0)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004712 {
4713 tANI_U16 val = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
4714 char extra[32];
4715 tANI_U8 len = 0;
4716
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004717 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Ratnam Rachuri51a5ad12015-08-07 14:06:37 +05304718 len = VOS_MIN(priv_data.total_len, len + 1);
4719 if (copy_to_user(priv_data.buf, &extra, len)) {
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004720 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4721 "%s: failed to copy data to user buffer", __func__);
4722 ret = -EFAULT;
4723 goto exit;
4724 }
4725 }
4726 else if (strncmp(command, "REASSOC", 7) == 0)
4727 {
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304728 ret = hdd_drv_cmd_validate(command, 7);
4729 if (ret)
4730 goto exit;
4731
4732 ret = hdd_parse_reassoc(pAdapter, command, priv_data.total_len);
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05304733 if (!ret)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004734 goto exit;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004735 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07004736 else if (strncmp(command, "SETWESMODE", 10) == 0)
4737 {
4738 tANI_U8 *value = command;
4739 tANI_BOOLEAN wesMode = CFG_ENABLE_WES_MODE_NAME_DEFAULT;
4740
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304741 ret = hdd_drv_cmd_validate(command, 10);
4742 if (ret)
4743 goto exit;
4744
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07004745 /* Move pointer to ahead of SETWESMODE<delimiter> */
4746 value = value + 11;
4747 /* Convert the value from ascii to integer */
4748 ret = kstrtou8(value, 10, &wesMode);
4749 if (ret < 0)
4750 {
4751 /* If the input value is greater than max value of datatype, then also
4752 kstrtou8 fails */
4753 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4754 "%s: kstrtou8 failed range [%d - %d]", __func__,
4755 CFG_ENABLE_WES_MODE_NAME_MIN,
4756 CFG_ENABLE_WES_MODE_NAME_MAX);
4757 ret = -EINVAL;
4758 goto exit;
4759 }
4760
4761 if ((wesMode < CFG_ENABLE_WES_MODE_NAME_MIN) ||
4762 (wesMode > CFG_ENABLE_WES_MODE_NAME_MAX))
4763 {
4764 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4765 "WES Mode value %d is out of range"
4766 " (Min: %d Max: %d)", wesMode,
4767 CFG_ENABLE_WES_MODE_NAME_MIN,
4768 CFG_ENABLE_WES_MODE_NAME_MAX);
4769 ret = -EINVAL;
4770 goto exit;
4771 }
4772 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4773 "%s: Received Command to Set WES Mode rssi diff = %d", __func__, wesMode);
4774
4775 pHddCtx->cfg_ini->isWESModeEnabled = wesMode;
4776 sme_UpdateWESMode((tHalHandle)(pHddCtx->hHal), wesMode);
4777 }
Mahesh A Saptasagarec7d1092015-04-02 13:41:34 +05304778 else if (strncmp(command, "GETWESMODE", 10) == 0)
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07004779 {
4780 tANI_BOOLEAN wesMode = sme_GetWESMode((tHalHandle)(pHddCtx->hHal));
4781 char extra[32];
4782 tANI_U8 len = 0;
4783
Arif Hussain826d9412013-11-12 16:44:54 -08004784 len = scnprintf(extra, sizeof(extra), "%s %d", command, wesMode);
Ratnam Rachuri8fe90c62015-08-07 14:03:26 +05304785 len = VOS_MIN(priv_data.total_len, len + 1);
4786 if (copy_to_user(priv_data.buf, &extra, len)) {
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07004787 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4788 "%s: failed to copy data to user buffer", __func__);
4789 ret = -EFAULT;
4790 goto exit;
4791 }
4792 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004793#endif /* WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_ESE || FEATURE_WLAN_LFR */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004794#ifdef FEATURE_WLAN_LFR
4795 else if (strncmp(command, "SETFASTROAM", 11) == 0)
4796 {
4797 tANI_U8 *value = command;
4798 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
4799
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05304800 if (pHddCtx->concurrency_mode == VOS_STA_MON) {
4801 hddLog(LOGE,
4802 FL("Roaming is always disabled in STA + MON concurrency"));
4803 ret = -EINVAL;
4804 goto exit;
4805 }
4806
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304807 ret = hdd_drv_cmd_validate(command, 11);
4808 if (ret)
4809 goto exit;
4810
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004811 /* Move pointer to ahead of SETFASTROAM<delimiter> */
4812 value = value + 12;
4813 /* Convert the value from ascii to integer */
4814 ret = kstrtou8(value, 10, &lfrMode);
4815 if (ret < 0)
4816 {
4817 /* If the input value is greater than max value of datatype, then also
4818 kstrtou8 fails */
4819 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4820 "%s: kstrtou8 failed range [%d - %d]", __func__,
4821 CFG_LFR_FEATURE_ENABLED_MIN,
4822 CFG_LFR_FEATURE_ENABLED_MAX);
4823 ret = -EINVAL;
4824 goto exit;
4825 }
4826
4827 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
4828 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
4829 {
4830 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4831 "lfr mode value %d is out of range"
4832 " (Min: %d Max: %d)", lfrMode,
4833 CFG_LFR_FEATURE_ENABLED_MIN,
4834 CFG_LFR_FEATURE_ENABLED_MAX);
4835 ret = -EINVAL;
4836 goto exit;
4837 }
4838
4839 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4840 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
4841
4842 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
4843 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
4844 }
4845#endif
4846#ifdef WLAN_FEATURE_VOWIFI_11R
4847 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
4848 {
4849 tANI_U8 *value = command;
4850 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
4851
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304852 ret = hdd_drv_cmd_validate(command, 17);
4853 if (ret)
4854 goto exit;
4855
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004856 /* Move pointer to ahead of SETFASTROAM<delimiter> */
4857 value = value + 18;
4858 /* Convert the value from ascii to integer */
4859 ret = kstrtou8(value, 10, &ft);
4860 if (ret < 0)
4861 {
4862 /* If the input value is greater than max value of datatype, then also
4863 kstrtou8 fails */
4864 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4865 "%s: kstrtou8 failed range [%d - %d]", __func__,
4866 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
4867 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
4868 ret = -EINVAL;
4869 goto exit;
4870 }
4871
4872 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
4873 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
4874 {
4875 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4876 "ft mode value %d is out of range"
4877 " (Min: %d Max: %d)", ft,
4878 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
4879 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
4880 ret = -EINVAL;
4881 goto exit;
4882 }
4883
4884 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4885 "%s: Received Command to change ft mode = %d", __func__, ft);
4886
4887 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
4888 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
4889 }
Padma, Santhosh Kumar778d8382015-03-04 17:41:22 +05304890 else if (strncmp(command, "SETDFSSCANMODE", 14) == 0)
4891 {
4892 tANI_U8 *value = command;
4893 tANI_U8 dfsScanMode = DFS_CHNL_SCAN_ENABLED_NORMAL;
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05304894
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304895 ret = hdd_drv_cmd_validate(command, 14);
4896 if (ret)
4897 goto exit;
4898
Padma, Santhosh Kumar778d8382015-03-04 17:41:22 +05304899 /* Move pointer to ahead of SETDFSSCANMODE<delimiter> */
4900 value = value + 15;
4901 /* Convert the value from ascii to integer */
4902 ret = kstrtou8(value, 10, &dfsScanMode);
4903 if (ret < 0)
4904 {
4905 /* If the input value is greater than max value of
4906 datatype, then also kstrtou8 fails
4907 */
4908 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4909 "%s: kstrtou8 failed range [%d - %d]", __func__,
4910 CFG_ENABLE_DFS_CHNL_SCAN_MIN,
4911 CFG_ENABLE_DFS_CHNL_SCAN_MAX);
4912 ret = -EINVAL;
4913 goto exit;
4914 }
4915
4916 if ((dfsScanMode < CFG_ENABLE_DFS_CHNL_SCAN_MIN) ||
4917 (dfsScanMode > CFG_ENABLE_DFS_CHNL_SCAN_MAX))
4918 {
4919 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4920 "dfsScanMode value %d is out of range"
4921 " (Min: %d Max: %d)", dfsScanMode,
4922 CFG_ENABLE_DFS_CHNL_SCAN_MIN,
4923 CFG_ENABLE_DFS_CHNL_SCAN_MAX);
4924 ret = -EINVAL;
4925 goto exit;
4926 }
4927 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4928 "%s: Received Command to Set DFS Scan Mode = %d",
4929 __func__, dfsScanMode);
4930
4931 ret = wlan_hdd_handle_dfs_chan_scan(pHddCtx, dfsScanMode);
4932 }
4933 else if (strncmp(command, "GETDFSSCANMODE", 14) == 0)
4934 {
4935 tANI_U8 dfsScanMode = sme_GetDFSScanMode(pHddCtx->hHal);
4936 char extra[32];
4937 tANI_U8 len = 0;
4938
4939 len = scnprintf(extra, sizeof(extra), "%s %d", command, dfsScanMode);
Ratheesh S P767224e2015-07-16 15:35:51 +05304940 len = VOS_MIN(priv_data.total_len, len + 1);
4941 if (copy_to_user(priv_data.buf, &extra, len))
Padma, Santhosh Kumar778d8382015-03-04 17:41:22 +05304942 {
4943 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4944 "%s: failed to copy data to user buffer", __func__);
4945 ret = -EFAULT;
4946 goto exit;
4947 }
4948 }
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05304949 else if (strncmp(command, "FASTREASSOC", 11) == 0)
4950 {
Selvaraj, Sridhar3714c4d2016-06-22 15:19:12 +05304951 ret = wlan_hdd_handle_fastreassoc(pAdapter, command);
4952 if (!ret)
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05304953 goto exit;
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05304954 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004955#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004956#ifdef FEATURE_WLAN_ESE
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004957 else if (strncmp(command, "SETCCXMODE", 10) == 0)
4958 {
4959 tANI_U8 *value = command;
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004960 tANI_U8 eseMode = CFG_ESE_FEATURE_ENABLED_DEFAULT;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004961
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304962 ret = hdd_drv_cmd_validate(command, 10);
4963 if (ret)
4964 goto exit;
4965
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004966 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07004967 then this operation is not permitted (return FAILURE) */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004968 if (sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07004969 hdd_is_okc_mode_enabled(pHddCtx) &&
4970 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
4971 {
4972 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004973 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07004974 " hence this operation is not permitted!", __func__);
4975 ret = -EPERM;
4976 goto exit;
4977 }
4978
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004979 /* Move pointer to ahead of SETCCXMODE<delimiter> */
4980 value = value + 11;
4981 /* Convert the value from ascii to integer */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004982 ret = kstrtou8(value, 10, &eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004983 if (ret < 0)
4984 {
4985 /* If the input value is greater than max value of datatype, then also
4986 kstrtou8 fails */
4987 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4988 "%s: kstrtou8 failed range [%d - %d]", __func__,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004989 CFG_ESE_FEATURE_ENABLED_MIN,
4990 CFG_ESE_FEATURE_ENABLED_MAX);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004991 ret = -EINVAL;
4992 goto exit;
4993 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004994 if ((eseMode < CFG_ESE_FEATURE_ENABLED_MIN) ||
4995 (eseMode > CFG_ESE_FEATURE_ENABLED_MAX))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004996 {
4997 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004998 "Ese mode value %d is out of range"
4999 " (Min: %d Max: %d)", eseMode,
5000 CFG_ESE_FEATURE_ENABLED_MIN,
5001 CFG_ESE_FEATURE_ENABLED_MAX);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07005002 ret = -EINVAL;
5003 goto exit;
5004 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07005005 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08005006 "%s: Received Command to change ese mode = %d", __func__, eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07005007
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08005008 pHddCtx->cfg_ini->isEseIniFeatureEnabled = eseMode;
5009 sme_UpdateIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal), eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07005010 }
5011#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07005012 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
5013 {
5014 tANI_U8 *value = command;
5015 tANI_BOOLEAN roamScanControl = 0;
5016
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05305017 ret = hdd_drv_cmd_validate(command, 18);
5018 if (ret)
5019 goto exit;
5020
Srinivas Girigowda100eb322013-03-15 16:48:20 -07005021 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
5022 value = value + 19;
5023 /* Convert the value from ascii to integer */
5024 ret = kstrtou8(value, 10, &roamScanControl);
5025 if (ret < 0)
5026 {
5027 /* If the input value is greater than max value of datatype, then also
5028 kstrtou8 fails */
5029 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5030 "%s: kstrtou8 failed ", __func__);
5031 ret = -EINVAL;
5032 goto exit;
5033 }
5034
5035 if (0 != roamScanControl)
5036 {
5037 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5038 "roam scan control invalid value = %d",
5039 roamScanControl);
5040 ret = -EINVAL;
5041 goto exit;
5042 }
5043 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5044 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
5045
5046 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
5047 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07005048#ifdef FEATURE_WLAN_OKC
5049 else if (strncmp(command, "SETOKCMODE", 10) == 0)
5050 {
5051 tANI_U8 *value = command;
5052 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
5053
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05305054 ret = hdd_drv_cmd_validate(command, 10);
5055 if (ret)
5056 goto exit;
5057
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08005058 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07005059 then this operation is not permitted (return FAILURE) */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08005060 if (sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07005061 hdd_is_okc_mode_enabled(pHddCtx) &&
5062 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
5063 {
5064 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08005065 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07005066 " hence this operation is not permitted!", __func__);
5067 ret = -EPERM;
5068 goto exit;
5069 }
5070
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07005071 /* Move pointer to ahead of SETOKCMODE<delimiter> */
5072 value = value + 11;
5073 /* Convert the value from ascii to integer */
5074 ret = kstrtou8(value, 10, &okcMode);
5075 if (ret < 0)
5076 {
5077 /* If the input value is greater than max value of datatype, then also
5078 kstrtou8 fails */
5079 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5080 "%s: kstrtou8 failed range [%d - %d]", __func__,
5081 CFG_OKC_FEATURE_ENABLED_MIN,
5082 CFG_OKC_FEATURE_ENABLED_MAX);
5083 ret = -EINVAL;
5084 goto exit;
5085 }
5086
5087 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
5088 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
5089 {
5090 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5091 "Okc mode value %d is out of range"
5092 " (Min: %d Max: %d)", okcMode,
5093 CFG_OKC_FEATURE_ENABLED_MIN,
5094 CFG_OKC_FEATURE_ENABLED_MAX);
5095 ret = -EINVAL;
5096 goto exit;
5097 }
5098
5099 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5100 "%s: Received Command to change okc mode = %d", __func__, okcMode);
5101
5102 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
5103 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07005104#endif /* FEATURE_WLAN_OKC */
Mahesh A Saptasagarec7d1092015-04-02 13:41:34 +05305105 else if (strncmp(command, "GETROAMSCANCONTROL", 18) == 0)
Srinivas Girigowda100eb322013-03-15 16:48:20 -07005106 {
5107 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
5108 char extra[32];
5109 tANI_U8 len = 0;
5110
Sameer Thalappilb0a30232013-09-27 15:37:48 -07005111 len = scnprintf(extra, sizeof(extra), "%s %d",
5112 command, roamScanControl);
Ratnam Rachuri083ada82015-08-07 14:01:05 +05305113 len = VOS_MIN(priv_data.total_len, len + 1);
5114 if (copy_to_user(priv_data.buf, &extra, len)) {
Srinivas Girigowda100eb322013-03-15 16:48:20 -07005115 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5116 "%s: failed to copy data to user buffer", __func__);
5117 ret = -EFAULT;
5118 goto exit;
5119 }
5120 }
Gopichand Nakkala227c7f32013-06-26 22:44:57 +05305121#ifdef WLAN_FEATURE_PACKET_FILTERING
5122 else if (strncmp(command, "ENABLE_PKTFILTER_IPV6", 21) == 0)
5123 {
5124 tANI_U8 filterType = 0;
5125 tANI_U8 *value = command;
5126
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05305127 ret = hdd_drv_cmd_validate(command, 21);
5128 if (ret)
5129 goto exit;
5130
Gopichand Nakkala227c7f32013-06-26 22:44:57 +05305131 /* Move pointer to ahead of ENABLE_PKTFILTER_IPV6<delimiter> */
5132 value = value + 22;
5133
5134 /* Convert the value from ascii to integer */
5135 ret = kstrtou8(value, 10, &filterType);
5136 if (ret < 0)
5137 {
5138 /* If the input value is greater than max value of datatype,
5139 * then also kstrtou8 fails
5140 */
5141 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5142 "%s: kstrtou8 failed range ", __func__);
5143 ret = -EINVAL;
5144 goto exit;
5145 }
5146
5147 if (filterType != 0 && filterType != 1)
5148 {
5149 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5150 "%s: Accepted Values are 0 and 1 ", __func__);
5151 ret = -EINVAL;
5152 goto exit;
5153 }
5154 wlan_hdd_setIPv6Filter(WLAN_HDD_GET_CTX(pAdapter), filterType,
5155 pAdapter->sessionId);
5156 }
5157#endif
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05305158 else if (strncmp(command, "BTCOEXMODE", 10) == 0 )
5159 {
Kiet Lamad161252014-07-22 11:23:32 -07005160 char *dhcpPhase;
Satyanarayana Dash1faea4f2014-09-22 16:21:04 +05305161 int ret;
5162
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05305163 ret = hdd_drv_cmd_validate(command, 10);
5164 if (ret)
5165 goto exit;
5166
Kiet Lamad161252014-07-22 11:23:32 -07005167 dhcpPhase = command + 11;
5168 if ('1' == *dhcpPhase)
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05305169 {
Deepthi Gowribfd17132014-11-14 17:59:04 +05305170 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Kiet Lamad161252014-07-22 11:23:32 -07005171 FL("send DHCP START indication"));
c_hpothu9b781ba2013-12-30 20:57:45 +05305172
5173 pHddCtx->btCoexModeSet = TRUE;
Kiet Lamad161252014-07-22 11:23:32 -07005174
Satyanarayana Dash1faea4f2014-09-22 16:21:04 +05305175 ret = wlan_hdd_scan_abort(pAdapter);
5176 if (ret < 0)
5177 {
5178 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5179 FL("failed to abort existing scan %d"), ret);
5180 }
5181
Kiet Lamad161252014-07-22 11:23:32 -07005182 sme_DHCPStartInd(pHddCtx->hHal, pAdapter->device_mode,
5183 pAdapter->sessionId);
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05305184 }
Kiet Lamad161252014-07-22 11:23:32 -07005185 else if ('2' == *dhcpPhase)
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05305186 {
Deepthi Gowribfd17132014-11-14 17:59:04 +05305187 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Kiet Lamad161252014-07-22 11:23:32 -07005188 FL("send DHCP STOP indication"));
c_hpothu9b781ba2013-12-30 20:57:45 +05305189
5190 pHddCtx->btCoexModeSet = FALSE;
Kiet Lamad161252014-07-22 11:23:32 -07005191
5192 sme_DHCPStopInd(pHddCtx->hHal, pAdapter->device_mode,
5193 pAdapter->sessionId);
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05305194 }
5195 }
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07005196 else if (strncmp(command, "SCAN-ACTIVE", 11) == 0)
5197 {
Abhishek Singh58749d62016-02-03 15:27:20 +05305198 hddLog(LOG1,
5199 FL("making default scan to ACTIVE"));
c_hpothudbefd3e2014-04-28 15:59:47 +05305200 pHddCtx->scan_info.scan_mode = eSIR_ACTIVE_SCAN;
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07005201 }
5202 else if (strncmp(command, "SCAN-PASSIVE", 12) == 0)
5203 {
Abhishek Singh58749d62016-02-03 15:27:20 +05305204 hddLog(LOG1,
5205 FL("making default scan to PASSIVE"));
c_hpothudbefd3e2014-04-28 15:59:47 +05305206 pHddCtx->scan_info.scan_mode = eSIR_PASSIVE_SCAN;
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07005207 }
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05305208 else if (strncmp(command, "GETDWELLTIME", 12) == 0)
5209 {
5210 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
5211 char extra[32];
5212 tANI_U8 len = 0;
5213
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05305214 memset(extra, 0, sizeof(extra));
5215 ret = hdd_get_dwell_time(pCfg, command, extra, sizeof(extra), &len);
Ratnam Rachuri12d5d462015-08-07 14:10:23 +05305216 len = VOS_MIN(priv_data.total_len, len + 1);
5217 if (ret != 0 || copy_to_user(priv_data.buf, &extra, len)) {
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05305218 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5219 "%s: failed to copy data to user buffer", __func__);
5220 ret = -EFAULT;
5221 goto exit;
5222 }
5223 ret = len;
5224 }
5225 else if (strncmp(command, "SETDWELLTIME", 12) == 0)
5226 {
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05305227 ret = hdd_set_dwell_time(pAdapter, command);
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05305228 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07005229 else if ( strncasecmp(command, "MIRACAST", 8) == 0 )
5230 {
5231 tANI_U8 filterType = 0;
5232 tANI_U8 *value;
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05305233
5234 ret = hdd_drv_cmd_validate(command, 8);
5235 if (ret)
5236 goto exit;
5237
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07005238 value = command + 9;
5239
5240 /* Convert the value from ascii to integer */
5241 ret = kstrtou8(value, 10, &filterType);
5242 if (ret < 0)
5243 {
5244 /* If the input value is greater than max value of datatype,
5245 * then also kstrtou8 fails
5246 */
5247 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5248 "%s: kstrtou8 failed range ", __func__);
5249 ret = -EINVAL;
5250 goto exit;
5251 }
5252 if ((filterType < WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL ) ||
5253 (filterType > WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL))
5254 {
5255 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5256 "%s: Accepted Values are 0 to 2. 0-Disabled, 1-Source,"
5257 " 2-Sink ", __func__);
5258 ret = -EINVAL;
5259 goto exit;
5260 }
5261 //Filtertype value should be either 0-Disabled, 1-Source, 2-sink
5262 pHddCtx->drvr_miracast = filterType;
Kaushik, Sushant96122442014-10-21 16:40:18 +05305263 pScanInfo = &pHddCtx->scan_info;
5264 if (filterType && pScanInfo != NULL &&
5265 pHddCtx->scan_info.mScanPending)
5266 {
5267 /*Miracast Session started. Abort Scan */
5268 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5269 "%s, Aborting Scan For Miracast",__func__);
5270 hdd_abort_mac_scan(pHddCtx, pScanInfo->sessionId,
5271 eCSR_SCAN_ABORT_DEFAULT);
5272 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07005273 hdd_tx_rx_pkt_cnt_stat_timer_handler(pHddCtx);
Ganesh Kondabattini8f6e3b32014-08-25 16:07:54 +05305274 sme_SetMiracastMode(pHddCtx->hHal, pHddCtx->drvr_miracast);
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07005275 }
Leo Chang614d2072013-08-22 14:59:44 -07005276 else if (strncmp(command, "SETMCRATE", 9) == 0)
5277 {
Leo Chang614d2072013-08-22 14:59:44 -07005278 tANI_U8 *value = command;
5279 int targetRate;
Leo Chang1f98cbd2013-10-17 15:03:52 -07005280 tSirRateUpdateInd *rateUpdate;
5281 eHalStatus status;
Leo Chang614d2072013-08-22 14:59:44 -07005282
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05305283 ret = hdd_drv_cmd_validate(command, 9);
5284 if (ret)
5285 goto exit;
5286
Leo Chang614d2072013-08-22 14:59:44 -07005287 /* Only valid for SAP mode */
5288 if (WLAN_HDD_SOFTAP != pAdapter->device_mode)
5289 {
5290 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5291 "%s: SAP mode is not running", __func__);
5292 ret = -EFAULT;
5293 goto exit;
5294 }
5295
5296 /* Move pointer to ahead of SETMCRATE<delimiter> */
5297 /* input value is in units of hundred kbps */
5298 value = value + 10;
5299 /* Convert the value from ascii to integer, decimal base */
5300 ret = kstrtouint(value, 10, &targetRate);
5301
Leo Chang1f98cbd2013-10-17 15:03:52 -07005302 rateUpdate = (tSirRateUpdateInd *)vos_mem_malloc(sizeof(tSirRateUpdateInd));
5303 if (NULL == rateUpdate)
Leo Chang614d2072013-08-22 14:59:44 -07005304 {
Leo Chang1f98cbd2013-10-17 15:03:52 -07005305 hddLog(VOS_TRACE_LEVEL_ERROR,
5306 "%s: SETMCRATE indication alloc fail", __func__);
5307 ret = -EFAULT;
5308 goto exit;
5309 }
5310 vos_mem_zero(rateUpdate, sizeof(tSirRateUpdateInd ));
5311
5312 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5313 "MC Target rate %d", targetRate);
5314 /* Ignore unicast */
5315 rateUpdate->ucastDataRate = -1;
5316 rateUpdate->mcastDataRate24GHz = targetRate;
5317 rateUpdate->mcastDataRate5GHz = targetRate;
5318 rateUpdate->mcastDataRate24GHzTxFlag = 0;
5319 rateUpdate->mcastDataRate5GHzTxFlag = 0;
5320 status = sme_SendRateUpdateInd(pHddCtx->hHal, rateUpdate);
5321 if (eHAL_STATUS_SUCCESS != status)
5322 {
5323 hddLog(VOS_TRACE_LEVEL_ERROR,
5324 "%s: SET_MC_RATE failed", __func__);
5325 vos_mem_free(rateUpdate);
5326 ret = -EFAULT;
5327 goto exit;
Leo Chang614d2072013-08-22 14:59:44 -07005328 }
5329 }
jge35567202017-06-21 16:39:38 +08005330 else if (strncmp(command, "MAXTXPOWER", 10) == 0)
5331 {
5332 int status;
5333 int txPower;
5334 eHalStatus smeStatus;
5335 tANI_U8 *value = command;
5336 tSirMacAddr bssid = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
5337 tSirMacAddr selfMac = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
5338
5339 status = hdd_parse_setmaxtxpower_command(value, &txPower);
5340 if (status)
5341 {
5342 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5343 "Invalid MAXTXPOWER command ");
5344 ret = -EINVAL;
5345 goto exit;
5346 }
5347
5348 hddLog(VOS_TRACE_LEVEL_INFO, "max tx power %d selfMac: "
5349 MAC_ADDRESS_STR " bssId: " MAC_ADDRESS_STR " ",
5350 txPower, MAC_ADDR_ARRAY(selfMac),
5351 MAC_ADDR_ARRAY(bssid));
5352 smeStatus = sme_SetMaxTxPower((tHalHandle)(pHddCtx->hHal),
5353 bssid, selfMac, txPower) ;
5354 if( smeStatus != eHAL_STATUS_SUCCESS )
5355 {
5356 hddLog(VOS_TRACE_LEVEL_ERROR, "%s:Set max tx power failed",
5357 __func__);
5358 ret = -EINVAL;
5359 goto exit;
5360 }
5361
5362 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Set max tx power success",
5363 __func__);
5364 }
Rajeev79dbe4c2013-10-05 11:03:42 +05305365#ifdef FEATURE_WLAN_BATCH_SCAN
Rajeev Kumar8b373292014-01-08 20:36:55 -08005366 else if (strncmp(command, "WLS_BATCHING", 12) == 0)
Rajeev79dbe4c2013-10-05 11:03:42 +05305367 {
Rajeev Kumar8b373292014-01-08 20:36:55 -08005368 ret = hdd_handle_batch_scan_ioctl(pAdapter, &priv_data, command);
Rajeev79dbe4c2013-10-05 11:03:42 +05305369 }
5370#endif
Abhishek Singh00b71972016-01-07 10:51:04 +05305371#ifdef WLAN_FEATURE_RMC
5372 else if ((strncasecmp(command, "SETIBSSBEACONOUIDATA", 20) == 0) &&
5373 (WLAN_HDD_IBSS == pAdapter->device_mode))
5374 {
5375 int i = 0;
5376 tANI_U8 *ibss_ie;
5377 tANI_U32 command_len;
5378 tANI_U8 *value = command;
5379 tHalHandle hHal = pHddCtx->hHal;
5380 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
5381 tANI_U32 ibss_ie_length;
5382 tANI_U32 len, present;
5383 tANI_U8 *addIE;
5384 tANI_U8 *addIEData;
5385
5386 hddLog(LOG1,
5387 FL(" received command %s"),((char *) value));
5388 /* validate argument of command */
5389 if (strlen(value) <= 21)
5390 {
5391 hddLog(LOGE,
5392 FL("No arguements in command length %zu"), strlen(value));
5393 ret = -EFAULT;
5394 goto exit;
5395 }
5396
5397 /* moving to arguments of commands */
5398 value = value + 21;
5399 command_len = strlen(value);
5400
5401 /* oui_data can't be less than 3 bytes */
5402 if (command_len <= (2 * WLAN_HDD_IBSS_MIN_OUI_DATA_LENGTH))
5403 {
5404 hddLog(LOGE,
5405 FL("Invalid SETIBSSBEACONOUIDATA command length %d"),
5406 command_len);
5407 ret = -EFAULT;
5408 goto exit;
5409 }
5410 ibss_ie = vos_mem_malloc(command_len);
5411 if (!ibss_ie) {
5412 hddLog(LOGE,
5413 FL("Could not allocate memory for command length %d"),
5414 command_len);
5415 ret = -ENOMEM;
5416 goto exit;
5417 }
5418 vos_mem_zero(ibss_ie, command_len);
5419
5420 ibss_ie_length = hdd_parse_set_ibss_oui_data_command(value, ibss_ie,
5421 command_len);
5422 if (ibss_ie_length < (2 * WLAN_HDD_IBSS_MIN_OUI_DATA_LENGTH)) {
5423 hddLog(LOGE, FL("Could not parse command %s return length %d"),
5424 value, ibss_ie_length);
5425 ret = -EFAULT;
5426 vos_mem_free(ibss_ie);
5427 goto exit;
5428 }
5429
5430 hddLog(LOG1, FL("ibss_ie length %d ibss_ie:"), ibss_ie_length);
5431 while (i < ibss_ie_length)
5432 hddLog(LOG1, FL("0x%x"), ibss_ie[i++]);
5433
5434 /* Populate Vendor IE in Beacon */
5435 if ((ccmCfgGetInt(hHal,
5436 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
5437 &present)) != eHAL_STATUS_SUCCESS)
5438 {
5439 hddLog(LOGE,
5440 FL("unable to ftch WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG"));
5441 ret = -EFAULT;
5442 vos_mem_free(ibss_ie);
5443 goto exit;
5444 }
5445
5446 addIE = vos_mem_malloc(WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN);
5447 if (!addIE) {
5448 hddLog(LOGE,
5449 FL("Could not allocate memory for command length %d"),
5450 command_len);
5451 vos_mem_free(ibss_ie);
5452 ret = -ENOMEM;
5453 goto exit;
5454 }
5455 vos_mem_zero(addIE, WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN);
5456
5457 if (present)
5458 {
5459 if ((wlan_cfgGetStrLen(pMac,
5460 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, &len)) != eSIR_SUCCESS)
5461 {
5462 hddLog(LOGE,
5463 FL("unable to fetch WNI_CFG_PROBE_RSP_BCN_ADDNIE_LEN"));
5464 ret = -EFAULT;
5465 vos_mem_free(ibss_ie);
5466 vos_mem_free(addIE);
5467 goto exit;
5468 }
5469
5470 if (len <= WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN && len &&
5471 ((len + ibss_ie_length) <=
5472 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN))
5473 {
5474 if ((ccmCfgGetStr(hHal,
5475 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, addIE, &len))
5476 != eHAL_STATUS_SUCCESS)
5477 {
5478 hddLog(LOGE,
5479 FL("unable to fetch WNI_PROBE_RSP_BCN_ADDNIE_DATA"));
5480 ret = -EFAULT;
5481 vos_mem_free(ibss_ie);
5482 vos_mem_free(addIE);
5483 goto exit;
5484 }
5485 else
5486 {
5487 /* Curruntly only WPA IE is added before Vendor IE
5488 * so we can blindly place the Vendor IE after WPA
5489 * IE. If no WPA IE found replace all with Vendor IE.
5490 */
5491 len = hdd_find_ibss_wpa_ie_pos(addIE, len);
5492 }
5493 }
5494 else
5495 {
5496 hddLog(LOGE,
5497 FL("IE len exceed limit len %d,ibss_ie_length %d "),
5498 len, ibss_ie_length);
5499 ret = -EFAULT;
5500 vos_mem_free(addIE);
5501 vos_mem_free(ibss_ie);
5502 goto exit;
5503 }
5504 }
5505 else {
5506 len = 0;
5507 }
5508
5509 vos_mem_copy (addIE + len , ibss_ie, ibss_ie_length);
5510 len += ibss_ie_length;
5511
5512 if (ccmCfgSetStr(hHal,
5513 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, addIE, len, NULL,
5514 eANI_BOOLEAN_FALSE) != eHAL_STATUS_SUCCESS)
5515 {
5516 hddLog(LOGE,
5517 FL("unable to set WNI_CFG_PRBE_RSP_BCN_ADDNIE_DATA"));
5518 ret = -EFAULT;
5519 vos_mem_free(ibss_ie);
5520 vos_mem_free(addIE);
5521 goto exit;
5522 }
5523 vos_mem_free(addIE);
5524 if (ccmCfgSetInt(hHal,
5525 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 1,NULL,
5526 eANI_BOOLEAN_FALSE) != eHAL_STATUS_SUCCESS)
5527 {
5528 hddLog(LOGE,
5529 FL("unble to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG"));
5530 ret = -EFAULT;
5531 vos_mem_free(ibss_ie);
5532 goto exit;
5533 }
5534
5535 /* Populate Vendor IE in probe resp */
5536 if ((ccmCfgGetInt(hHal,
5537 WNI_CFG_PROBE_RSP_ADDNIE_FLAG,
5538 &present)) != eHAL_STATUS_SUCCESS)
5539 {
5540 hddLog(LOGE,
5541 FL("unable to fetch WNI_CFG_PROBE_RSP_ADDNIE_FLAG"));
5542 ret = -EFAULT;
5543 vos_mem_free(ibss_ie);
5544 goto exit;
5545 }
5546
5547 addIEData = vos_mem_malloc(WNI_CFG_PROBE_RSP_ADDNIE_DATA1_LEN);
5548 if (!addIEData) {
5549 hddLog(LOGE,
5550 FL("Could not allocate memory for command length %d"),
5551 command_len);
5552 vos_mem_free(ibss_ie);
5553 ret = -ENOMEM;
5554 goto exit;
5555 }
5556 vos_mem_zero(addIEData, WNI_CFG_PROBE_RSP_ADDNIE_DATA1_LEN);
5557
5558 if (present) {
5559 if (eSIR_SUCCESS != wlan_cfgGetStrLen(pMac,
5560 WNI_CFG_PROBE_RSP_ADDNIE_DATA1, &len)) {
5561 hddLog(LOGE,
5562 FL("unable to fetch WNI_CFG_PROBE_RSP_ADDNIE_DATA1"));
5563 ret = -EFAULT;
5564 vos_mem_free(ibss_ie);
5565 vos_mem_free(addIEData);
5566 goto exit;
5567 }
5568 if (len < WNI_CFG_PROBE_RSP_ADDNIE_DATA1_LEN && len &&
5569 (ibss_ie_length + len) <=
5570 WNI_CFG_PROBE_RSP_ADDNIE_DATA1_LEN) {
5571
5572 if ((ccmCfgGetStr(hHal,
5573 WNI_CFG_PROBE_RSP_ADDNIE_DATA1, addIEData, &len))
5574 != eHAL_STATUS_SUCCESS) {
5575 hddLog(LOGE,
5576 FL("unable fetch WNI_CFG_PROBE_RSP_ADDNIE_DATA1"));
5577 ret = -EFAULT;
5578 vos_mem_free(ibss_ie);
5579 vos_mem_free(addIEData);
5580 goto exit;
5581 }
5582 else {
5583 /* Curruntly only WPA IE is added before Vendor IE
5584 * so we can blindly place the Vendor IE after WPA
5585 * IE. If no WPA IE found replace all with Vendor IE.
5586 */
5587 len = hdd_find_ibss_wpa_ie_pos(addIEData, len);
5588 }
5589 }
5590 else
5591 {
5592 hddLog(LOGE,
5593 FL("IE len exceed limit len %d,ibss_ie_length %d "),
5594 len, ibss_ie_length);
5595 ret = -EFAULT;
5596 vos_mem_free(addIEData);
5597 vos_mem_free(ibss_ie);
5598 goto exit;
5599 }
5600 } /* probe rsp ADD IE present */
5601 else {
5602 /* probe rsp add IE is not present */
5603 len = 0;
5604 }
5605
5606 vos_mem_copy(addIEData +len , ibss_ie, ibss_ie_length);
5607 len += ibss_ie_length;
5608
5609 vos_mem_free(ibss_ie);
5610
5611 if (ccmCfgSetStr(hHal,
5612 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,
5613 (tANI_U8*)(addIEData),
5614 len, NULL,
5615 eANI_BOOLEAN_FALSE)
5616 == eHAL_STATUS_FAILURE) {
5617 hddLog(LOGE,
5618 FL("unable to copy to WNI_CFG_PROBE_RSP_ADDNIE_DATA1"));
5619 ret = -EFAULT;
5620 vos_mem_free(addIEData);
5621 goto exit;
5622 }
5623 vos_mem_free(addIEData);
5624 if (ccmCfgSetInt(WLAN_HDD_GET_HAL_CTX(pAdapter),
5625 WNI_CFG_PROBE_RSP_ADDNIE_FLAG, 1,NULL,
5626 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
5627 {
5628 hddLog(LOGE,
5629 FL("unable to copy WNI_CFG_PROBE_RSP_ADDNIE_FLAG"));
5630 ret = -EFAULT;
5631 goto exit;
5632 }
5633 }
5634 else if (strncasecmp(command, "SETRMCENABLE", 12) == 0)
5635 {
5636 tANI_U8 *value = command;
5637 tANI_U8 ucRmcEnable = 0;
5638 int status;
5639
5640 if ((WLAN_HDD_IBSS != pAdapter->device_mode) &&
5641 (WLAN_HDD_SOFTAP != pAdapter->device_mode))
5642 {
5643 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5644 "Received SETRMCENABLE command in invalid mode %d "
5645 "SETRMCENABLE command is only allowed in IBSS or SOFTAP mode",
5646 pAdapter->device_mode);
5647 ret = -EINVAL;
5648 goto exit;
5649 }
5650
5651 status = hdd_parse_setrmcenable_command(value, &ucRmcEnable);
5652 if (status)
5653 {
5654 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5655 "Invalid SETRMCENABLE command ");
5656 ret = -EINVAL;
5657 goto exit;
5658 }
5659
5660 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5661 "%s: ucRmcEnable %d ", __func__, ucRmcEnable);
5662
5663 if (TRUE == ucRmcEnable)
5664 {
5665 status = sme_EnableRMC( (tHalHandle)(pHddCtx->hHal),
5666 pAdapter->sessionId );
5667 }
5668 else if(FALSE == ucRmcEnable)
5669 {
5670 status = sme_DisableRMC( (tHalHandle)(pHddCtx->hHal),
5671 pAdapter->sessionId );
5672 }
5673 else
5674 {
5675 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5676 "Invalid SETRMCENABLE command %d", ucRmcEnable);
5677 ret = -EINVAL;
5678 goto exit;
5679 }
5680
5681 if (VOS_STATUS_SUCCESS != status)
5682 {
5683 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5684 "%s: SETRMC %d failed status %d", __func__, ucRmcEnable,
5685 status);
5686 ret = -EINVAL;
5687 goto exit;
5688 }
5689 }
5690 else if (strncasecmp(command, "SETRMCACTIONPERIOD", 18) == 0)
5691 {
5692 tANI_U8 *value = command;
5693 tANI_U32 uActionPeriod = 0;
5694 int status;
5695
5696 if ((WLAN_HDD_IBSS != pAdapter->device_mode) &&
5697 (WLAN_HDD_SOFTAP != pAdapter->device_mode))
5698 {
5699 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5700 "Received SETRMC command in invalid mode %d "
5701 "SETRMC command is only allowed in IBSS or SOFTAP mode",
5702 pAdapter->device_mode);
5703 ret = -EINVAL;
5704 goto exit;
5705 }
5706
5707 status = hdd_parse_setrmcactionperiod_command(value, &uActionPeriod);
5708 if (status)
5709 {
5710 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5711 "Invalid SETRMCACTIONPERIOD command ");
5712 ret = -EINVAL;
5713 goto exit;
5714 }
5715
5716 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5717 "%s: uActionPeriod %d ", __func__, uActionPeriod);
5718
5719 if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY,
5720 uActionPeriod, NULL, eANI_BOOLEAN_FALSE))
5721 {
5722 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5723 "%s: Could not set SETRMCACTIONPERIOD %d", __func__, uActionPeriod);
5724 ret = -EINVAL;
5725 goto exit;
5726 }
5727
5728 }
5729 else if (strncasecmp(command, "GETIBSSPEERINFOALL", 18) == 0)
5730 {
5731 /* Peer Info All Command */
5732 int status = eHAL_STATUS_SUCCESS;
5733 hdd_station_ctx_t *pHddStaCtx = NULL;
5734 char *extra = NULL;
5735 int idx = 0, length = 0;
5736 v_MACADDR_t *macAddr;
5737 v_U32_t txRateMbps = 0, numOfBytestoPrint = 0;
5738
5739 if (WLAN_HDD_IBSS == pAdapter->device_mode)
5740 {
5741 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5742 }
5743 else
5744 {
5745 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5746 "%s: pAdapter is not valid for this device mode",
5747 __func__);
5748 ret = -EINVAL;
5749 goto exit;
5750 }
5751
5752 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5753 "%s: Received GETIBSSPEERINFOALL Command", __func__);
5754
5755
5756 /* Handle the command */
5757 status = hdd_cfg80211_get_ibss_peer_info_all(pAdapter);
5758 if (VOS_STATUS_SUCCESS == status)
5759 {
5760 /* The variable extra needed to be allocated on the heap since
5761 * amount of memory required to copy the data for 32 devices
5762 * exceeds the size of 1024 bytes of default stack size. On
5763 * 64 bit devices, the default max stack size of 2048 bytes
5764 */
5765 extra = kmalloc(WLAN_MAX_BUF_SIZE, GFP_KERNEL);
5766
5767 if (NULL == extra)
5768 {
5769 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5770 "%s:kmalloc failed", __func__);
5771 ret = -EINVAL;
5772 goto exit;
5773 }
5774
5775 /* Copy number of stations */
5776 length = scnprintf( extra, WLAN_MAX_BUF_SIZE, "%d ",
5777 pHddStaCtx->ibss_peer_info.numIBSSPeers);
5778 numOfBytestoPrint = length;
5779 for (idx = 0; idx < pHddStaCtx->ibss_peer_info.numIBSSPeers; idx++)
5780 {
5781 macAddr =
5782 hdd_wlan_get_ibss_mac_addr_from_staid(pAdapter,
5783 pHddStaCtx->ibss_peer_info.ibssPeerList[idx].staIdx);
5784 if (NULL != macAddr)
5785 {
5786 txRateMbps =
5787 ((pHddStaCtx->ibss_peer_info.ibssPeerList[idx].txRate)*500*1000)/1000000;
5788
5789 length += scnprintf( (extra + length), WLAN_MAX_BUF_SIZE - length,
5790 "%02x:%02x:%02x:%02x:%02x:%02x %d %d ",
5791 macAddr->bytes[0], macAddr->bytes[1], macAddr->bytes[2],
5792 macAddr->bytes[3], macAddr->bytes[4], macAddr->bytes[5],
5793 (int)txRateMbps,
5794 (int)pHddStaCtx->ibss_peer_info.ibssPeerList[idx].rssi);
5795 }
5796 else
5797 {
5798 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5799 "%s: MAC ADDR is NULL for staIdx: %d", __func__,
5800 pHddStaCtx->ibss_peer_info.ibssPeerList[idx].staIdx);
5801 }
5802
5803 /*
5804 * VOS_TRACE() macro has limitation of 512 bytes for the print
5805 * buffer. Hence printing the data in two chunks. The first chunk
5806 * will have the data for 16 devices and the second chunk will
5807 * have the rest.
5808 */
5809 if (idx < NUM_OF_STA_DATA_TO_PRINT)
5810 {
5811 numOfBytestoPrint = length;
5812 }
5813 }
5814
5815 /*
5816 * Copy the data back into buffer, if the data to copy is
5817 * morethan 512 bytes than we will split the data and do
5818 * it in two shots
5819 */
5820 if (copy_to_user(priv_data.buf, extra, numOfBytestoPrint))
5821 {
5822 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5823 "%s: Copy into user data buffer failed ", __func__);
5824 ret = -EFAULT;
5825 kfree(extra);
5826 goto exit;
5827 }
5828 priv_data.buf[numOfBytestoPrint] = '\0';
5829 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED,
5830 "%s", priv_data.buf);
5831
5832 if (length > numOfBytestoPrint)
5833 {
5834 if (copy_to_user(priv_data.buf + numOfBytestoPrint,
5835 extra + numOfBytestoPrint,
5836 length - numOfBytestoPrint + 1))
5837 {
5838 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5839 "%s: Copy into user data buffer failed ", __func__);
5840 ret = -EFAULT;
5841 kfree(extra);
5842 goto exit;
5843 }
5844 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED,
5845 "%s", &priv_data.buf[numOfBytestoPrint]);
5846 }
5847
5848 /* Free temporary buffer */
5849 kfree(extra);
5850 }
5851
5852 else
5853 {
5854 /* Command failed, log error */
5855 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5856 "%s: GETIBSSPEERINFOALL command failed with status code %d",
5857 __func__, status);
5858 ret = -EINVAL;
5859 goto exit;
5860 }
5861 ret = 0;
5862 }
5863 else if(strncasecmp(command, "GETIBSSPEERINFO", 15) == 0)
5864 {
5865 /* Peer Info <Peer Addr> command */
5866 tANI_U8 *value = command;
5867 VOS_STATUS status;
5868 hdd_station_ctx_t *pHddStaCtx = NULL;
5869 char extra[128] = { 0 };
5870 v_U32_t length = 0;
5871 v_U8_t staIdx = 0;
5872 v_U32_t txRateMbps = 0;
5873 v_MACADDR_t peerMacAddr;
5874
5875 if (WLAN_HDD_IBSS == pAdapter->device_mode)
5876 {
5877 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5878 }
5879 else
5880 {
5881 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5882 "%s: pAdapter is not valid for this device mode",
5883 __func__);
5884 ret = -EINVAL;
5885 goto exit;
5886 }
5887
5888 /* if there are no peers, no need to continue with the command */
5889 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5890 "%s: Received GETIBSSPEERINFO Command", __func__);
5891
5892 if (eConnectionState_IbssConnected != pHddStaCtx->conn_info.connState)
5893 {
5894 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5895 "%s:No IBSS Peers coalesced", __func__);
5896 ret = -EINVAL;
5897 goto exit;
5898 }
5899
5900 /* Parse the incoming command buffer */
5901 status = hdd_parse_get_ibss_peer_info(value, &peerMacAddr);
5902 if (VOS_STATUS_SUCCESS != status)
5903 {
5904 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5905 "%s: Invalid GETIBSSPEERINFO command", __func__);
5906 ret = -EINVAL;
5907 goto exit;
5908 }
5909
5910 /* Get station index for the peer mac address */
5911 hdd_Ibss_GetStaId(pHddStaCtx, &peerMacAddr, &staIdx);
5912
5913 if (staIdx > HDD_MAX_NUM_IBSS_STA)
5914 {
5915 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5916 "%s: Invalid StaIdx %d returned", __func__, staIdx);
5917 ret = -EINVAL;
5918 goto exit;
5919 }
5920
5921 /* Handle the command */
5922 status = hdd_cfg80211_get_ibss_peer_info(pAdapter, staIdx);
5923 if (VOS_STATUS_SUCCESS == status)
5924 {
5925 v_U32_t txRate = pHddStaCtx->ibss_peer_info.ibssPeerList[0].txRate;
5926 txRateMbps = (txRate * 500 * 1000)/1000000;
5927
5928 length = scnprintf( extra, sizeof(extra), "%d %d", (int)txRateMbps,
5929 (int)pHddStaCtx->ibss_peer_info.ibssPeerList[0].rssi);
5930
5931 /* Copy the data back into buffer */
5932 if (copy_to_user(priv_data.buf, &extra, length+ 1))
5933 {
5934 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5935 "%s: copy data to user buffer failed GETIBSSPEERINFO command",
5936 __func__);
5937 ret = -EFAULT;
5938 goto exit;
5939 }
5940 }
5941 else
5942 {
5943 /* Command failed, log error */
5944 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5945 "%s: GETIBSSPEERINFO command failed with status code %d",
5946 __func__, status);
5947 ret = -EINVAL;
5948 goto exit;
5949 }
5950
5951 /* Success ! */
5952 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED,
5953 "%s", priv_data.buf);
5954 ret = 0;
5955 }
5956 else if (strncasecmp(command, "SETRMCTXRATE", 12) == 0)
5957 {
5958 tANI_U8 *value = command;
5959 tANI_U32 uRate = 0;
5960 tTxrateinfoflags txFlags = 0;
5961 tSirRateUpdateInd *rateUpdateParams;
5962 int status;
5963
5964 if ((WLAN_HDD_IBSS != pAdapter->device_mode) &&
5965 (WLAN_HDD_SOFTAP != pAdapter->device_mode))
5966 {
5967 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5968 "Received SETRMCTXRATE command in invalid mode %d "
5969 "SETRMC command is only allowed in IBSS or SOFTAP mode",
5970 pAdapter->device_mode);
5971 ret = -EINVAL;
5972 goto exit;
5973 }
5974
5975 status = hdd_parse_setrmcrate_command(value, &uRate, &txFlags);
5976 if (status)
5977 {
5978 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5979 "Invalid SETRMCTXRATE command ");
5980 ret = -EINVAL;
5981 goto exit;
5982 }
5983
5984 rateUpdateParams = vos_mem_malloc(sizeof(tSirRateUpdateInd));
5985 if (NULL == rateUpdateParams)
5986 {
5987 ret = -EINVAL;
5988 goto exit;
5989 }
5990
5991 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5992 "%s: uRate %d ", __func__, uRate);
5993
5994 vos_mem_zero(rateUpdateParams, sizeof(tSirRateUpdateInd ));
5995
5996 /* -1 implies ignore this param */
5997 rateUpdateParams->ucastDataRate = -1;
5998
5999 /*
6000 * Fill the user specifieed RMC rate param
6001 * and the derived tx flags.
6002 */
6003 rateUpdateParams->rmcDataRate = uRate;
6004 rateUpdateParams->rmcDataRateTxFlag = txFlags;
6005
6006 status = sme_SendRateUpdateInd((tHalHandle)(pHddCtx->hHal), rateUpdateParams);
6007 }
6008 else if (strncasecmp(command, "SETIBSSTXFAILEVENT", 18) == 0 )
6009 {
6010 char *value;
6011 tANI_U8 tx_fail_count = 0;
6012 tANI_U16 pid = 0;
6013
6014 value = command;
6015
6016 ret = hdd_ParseIBSSTXFailEventParams(value, &tx_fail_count, &pid);
6017
6018 if (0 != ret)
6019 {
6020 hddLog(VOS_TRACE_LEVEL_INFO,
6021 "%s: Failed to parse SETIBSSTXFAILEVENT arguments",
6022 __func__);
6023 goto exit;
6024 }
6025
6026 hddLog(VOS_TRACE_LEVEL_INFO, "%s: tx_fail_cnt=%hhu, pid=%hu",
6027 __func__, tx_fail_count, pid);
6028
6029 if (0 == tx_fail_count)
6030 {
6031 // Disable TX Fail Indication
6032 if (eHAL_STATUS_SUCCESS ==
6033 sme_TXFailMonitorStartStopInd(pHddCtx->hHal,
6034 tx_fail_count,
6035 NULL))
6036 {
6037 cesium_pid = 0;
6038 }
6039 else
6040 {
6041 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6042 "%s: failed to disable TX Fail Event ", __func__);
6043 ret = -EINVAL;
6044 }
6045 }
6046 else
6047 {
6048 if (eHAL_STATUS_SUCCESS ==
6049 sme_TXFailMonitorStartStopInd(pHddCtx->hHal,
6050 tx_fail_count,
6051 (void*)hdd_tx_fail_ind_callback))
6052 {
6053 cesium_pid = pid;
6054 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6055 "%s: Registered Cesium pid %u", __func__,
6056 cesium_pid);
6057 }
6058 else
6059 {
6060 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6061 "%s: Failed to enable TX Fail Monitoring", __func__);
6062 ret = -EINVAL;
6063 }
6064 }
6065 }
6066
6067#endif /* WLAN_FEATURE_RMC */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006068#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006069 else if (strncmp(command, "SETCCXROAMSCANCHANNELS", 22) == 0)
6070 {
6071 tANI_U8 *value = command;
6072 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
6073 tANI_U8 numChannels = 0;
6074 eHalStatus status = eHAL_STATUS_SUCCESS;
6075
6076 status = hdd_parse_channellist(value, ChannelList, &numChannels);
6077 if (eHAL_STATUS_SUCCESS != status)
6078 {
6079 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6080 "%s: Failed to parse channel list information", __func__);
6081 ret = -EINVAL;
6082 goto exit;
6083 }
6084
6085 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
6086 {
6087 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6088 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
6089 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
6090 ret = -EINVAL;
6091 goto exit;
6092 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006093 status = sme_SetEseRoamScanChannelList((tHalHandle)(pHddCtx->hHal),
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006094 ChannelList,
6095 numChannels);
6096 if (eHAL_STATUS_SUCCESS != status)
6097 {
6098 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6099 "%s: Failed to update channel list information", __func__);
6100 ret = -EINVAL;
6101 goto exit;
6102 }
6103 }
6104 else if (strncmp(command, "GETTSMSTATS", 11) == 0)
6105 {
6106 tANI_U8 *value = command;
6107 char extra[128] = {0};
6108 int len = 0;
6109 tANI_U8 tid = 0;
6110 hdd_station_ctx_t *pHddStaCtx = NULL;
6111 tAniTrafStrmMetrics tsmMetrics;
6112 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6113
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05306114 ret = hdd_drv_cmd_validate(command, 11);
6115 if (ret)
6116 goto exit;
6117
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006118 /* if not associated, return error */
6119 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
6120 {
6121 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:Not associated!",__func__);
6122 ret = -EINVAL;
6123 goto exit;
6124 }
6125
6126 /* Move pointer to ahead of GETTSMSTATS<delimiter> */
6127 value = value + 12;
6128 /* Convert the value from ascii to integer */
6129 ret = kstrtou8(value, 10, &tid);
6130 if (ret < 0)
6131 {
6132 /* If the input value is greater than max value of datatype, then also
6133 kstrtou8 fails */
6134 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6135 "%s: kstrtou8 failed range [%d - %d]", __func__,
6136 TID_MIN_VALUE,
6137 TID_MAX_VALUE);
6138 ret = -EINVAL;
6139 goto exit;
6140 }
6141
6142 if ((tid < TID_MIN_VALUE) || (tid > TID_MAX_VALUE))
6143 {
6144 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6145 "tid value %d is out of range"
6146 " (Min: %d Max: %d)", tid,
6147 TID_MIN_VALUE,
6148 TID_MAX_VALUE);
6149 ret = -EINVAL;
6150 goto exit;
6151 }
6152
6153 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6154 "%s: Received Command to get tsm stats tid = %d", __func__, tid);
6155
6156 if (VOS_STATUS_SUCCESS != hdd_get_tsm_stats(pAdapter, tid, &tsmMetrics))
6157 {
6158 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6159 "%s: failed to get tsm stats", __func__);
6160 ret = -EFAULT;
6161 goto exit;
6162 }
6163
6164 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6165 "UplinkPktQueueDly(%d)\n"
6166 "UplinkPktQueueDlyHist[0](%d)\n"
6167 "UplinkPktQueueDlyHist[1](%d)\n"
6168 "UplinkPktQueueDlyHist[2](%d)\n"
6169 "UplinkPktQueueDlyHist[3](%d)\n"
Arun Kumar Khandavallie8768212014-02-17 16:43:34 +05306170 "UplinkPktTxDly(%u)\n"
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006171 "UplinkPktLoss(%d)\n"
6172 "UplinkPktCount(%d)\n"
6173 "RoamingCount(%d)\n"
6174 "RoamingDly(%d)", tsmMetrics.UplinkPktQueueDly,
6175 tsmMetrics.UplinkPktQueueDlyHist[0],
6176 tsmMetrics.UplinkPktQueueDlyHist[1],
6177 tsmMetrics.UplinkPktQueueDlyHist[2],
6178 tsmMetrics.UplinkPktQueueDlyHist[3],
6179 tsmMetrics.UplinkPktTxDly, tsmMetrics.UplinkPktLoss,
6180 tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount, tsmMetrics.RoamingDly);
6181
6182 /* Output TSM stats is of the format
6183 GETTSMSTATS [PktQueueDly] [PktQueueDlyHist[0]]:[PktQueueDlyHist[1]] ...[RoamingDly]
6184 eg., GETTSMSTATS 10 1:0:0:161 20 1 17 8 39800 */
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006185 len = scnprintf(extra, sizeof(extra), "%s %d %d:%d:%d:%d %u %d %d %d %d", command,
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006186 tsmMetrics.UplinkPktQueueDly, tsmMetrics.UplinkPktQueueDlyHist[0],
6187 tsmMetrics.UplinkPktQueueDlyHist[1], tsmMetrics.UplinkPktQueueDlyHist[2],
6188 tsmMetrics.UplinkPktQueueDlyHist[3], tsmMetrics.UplinkPktTxDly,
6189 tsmMetrics.UplinkPktLoss, tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount,
6190 tsmMetrics.RoamingDly);
6191
Ratnam Rachurid53009c2015-08-07 13:59:00 +05306192 len = VOS_MIN(priv_data.total_len, len + 1);
6193 if (copy_to_user(priv_data.buf, &extra, len)) {
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006194 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6195 "%s: failed to copy data to user buffer", __func__);
6196 ret = -EFAULT;
6197 goto exit;
6198 }
6199 }
6200 else if (strncmp(command, "SETCCKMIE", 9) == 0)
6201 {
6202 tANI_U8 *value = command;
6203 tANI_U8 *cckmIe = NULL;
6204 tANI_U8 cckmIeLen = 0;
6205 eHalStatus status = eHAL_STATUS_SUCCESS;
6206
6207 status = hdd_parse_get_cckm_ie(value, &cckmIe, &cckmIeLen);
6208 if (eHAL_STATUS_SUCCESS != status)
6209 {
6210 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6211 "%s: Failed to parse cckm ie data", __func__);
6212 ret = -EINVAL;
6213 goto exit;
6214 }
6215
6216 if (cckmIeLen > DOT11F_IE_RSN_MAX_LEN)
6217 {
6218 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6219 "%s: CCKM Ie input length is more than max[%d]", __func__,
6220 DOT11F_IE_RSN_MAX_LEN);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08006221 vos_mem_free(cckmIe);
6222 cckmIe = NULL;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006223 ret = -EINVAL;
6224 goto exit;
6225 }
6226 sme_SetCCKMIe((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, cckmIe, cckmIeLen);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08006227 vos_mem_free(cckmIe);
6228 cckmIe = NULL;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006229 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006230 else if (strncmp(command, "CCXBEACONREQ", 12) == 0)
6231 {
6232 tANI_U8 *value = command;
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006233 tCsrEseBeaconReq eseBcnReq;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006234 eHalStatus status = eHAL_STATUS_SUCCESS;
Srinivas Girigowda0c6d7fe2014-05-28 18:18:10 -07006235
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006236 status = hdd_parse_ese_beacon_req(value, &eseBcnReq);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006237 if (eHAL_STATUS_SUCCESS != status)
6238 {
6239 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006240 "%s: Failed to parse ese beacon req", __func__);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006241 ret = -EINVAL;
6242 goto exit;
6243 }
Srinivas Girigowda0c6d7fe2014-05-28 18:18:10 -07006244 if (!hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))) {
6245 hddLog(VOS_TRACE_LEVEL_INFO, FL("Not associated"));
6246 hdd_indicateEseBcnReportNoResults (pAdapter,
6247 eseBcnReq.bcnReq[0].measurementToken,
6248 0x02, //BIT(1) set for measurement done
6249 0); // no BSS
6250 goto exit;
6251 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006252
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006253 status = sme_SetEseBeaconRequest((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, &eseBcnReq);
6254 if (eHAL_STATUS_SUCCESS != status)
6255 {
6256 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6257 "%s: sme_SetEseBeaconRequest failed (%d)", __func__, status);
6258 ret = -EINVAL;
6259 goto exit;
6260 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006261 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006262#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
c_hpothu92367912014-05-01 15:18:17 +05306263 else if (strncmp(command, "GETBCNMISSRATE", 14) == 0)
6264 {
6265 eHalStatus status;
6266 char buf[32], len;
6267 long waitRet;
6268 bcnMissRateContext_t getBcnMissRateCtx;
6269
6270 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6271
6272 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
6273 {
6274 hddLog(VOS_TRACE_LEVEL_WARN,
6275 FL("GETBCNMISSRATE: STA is not in connected state"));
6276 ret = -1;
6277 goto exit;
6278 }
6279
6280 init_completion(&(getBcnMissRateCtx.completion));
6281 getBcnMissRateCtx.magic = BCN_MISS_RATE_CONTEXT_MAGIC;
6282
6283 status = sme_getBcnMissRate((tHalHandle)(pHddCtx->hHal),
6284 pAdapter->sessionId,
6285 (void *)getBcnMissRateCB,
6286 (void *)(&getBcnMissRateCtx));
6287 if( eHAL_STATUS_SUCCESS != status)
6288 {
6289 hddLog(VOS_TRACE_LEVEL_INFO,
6290 FL("GETBCNMISSRATE: fail to post WDA cmd"));
6291 ret = -EINVAL;
6292 goto exit;
6293 }
6294
6295 waitRet = wait_for_completion_interruptible_timeout
6296 (&getBcnMissRateCtx.completion, BCN_MISS_RATE_TIME);
6297 if(waitRet <= 0)
6298 {
6299 hddLog(VOS_TRACE_LEVEL_ERROR,
6300 FL("failed to wait on bcnMissRateComp %d"), ret);
6301
6302 //Make magic number to zero so that callback is not called.
6303 spin_lock(&hdd_context_lock);
6304 getBcnMissRateCtx.magic = 0x0;
6305 spin_unlock(&hdd_context_lock);
6306 ret = -EINVAL;
6307 goto exit;
6308 }
6309
6310 hddLog(VOS_TRACE_LEVEL_INFO,
6311 FL("GETBCNMISSRATE: bcnMissRate: %d"), gbcnMissRate);
6312
6313 len = snprintf(buf, sizeof(buf), "GETBCNMISSRATE %d", gbcnMissRate);
6314 if (copy_to_user(priv_data.buf, &buf, len + 1))
6315 {
6316 hddLog(VOS_TRACE_LEVEL_ERROR,
6317 "%s: failed to copy data to user buffer", __func__);
6318 ret = -EFAULT;
6319 goto exit;
6320 }
6321 ret = len;
6322 }
Atul Mittal87ec2422014-09-24 13:12:50 +05306323#ifdef FEATURE_WLAN_TDLS
6324 else if (strncmp(command, "TDLSSECONDARYCHANNELOFFSET", 26) == 0) {
6325 tANI_U8 *value = command;
6326 int set_value;
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05306327
6328 ret = hdd_drv_cmd_validate(command, 26);
6329 if (ret)
6330 goto exit;
6331
Atul Mittal87ec2422014-09-24 13:12:50 +05306332 /* Move pointer to ahead of TDLSOFFCH*/
6333 value += 26;
c_manjeebbc40212015-12-08 13:52:59 +05306334 if (!(sscanf(value, "%d", &set_value))) {
6335 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6336 FL("No input identified"));
6337 ret = -EINVAL;
6338 goto exit;
6339 }
6340
Atul Mittal87ec2422014-09-24 13:12:50 +05306341 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6342 "%s: Tdls offchannel offset:%d",
6343 __func__, set_value);
6344 ret = iw_set_tdlssecoffchanneloffset(pHddCtx, set_value);
6345 if (ret < 0)
6346 {
6347 ret = -EINVAL;
6348 goto exit;
6349 }
6350
6351 } else if (strncmp(command, "TDLSOFFCHANNELMODE", 18) == 0) {
6352 tANI_U8 *value = command;
6353 int set_value;
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05306354
6355 ret = hdd_drv_cmd_validate(command, 18);
6356 if (ret)
6357 goto exit;
6358
Atul Mittal87ec2422014-09-24 13:12:50 +05306359 /* Move pointer to ahead of tdlsoffchnmode*/
6360 value += 18;
c_manjee82323892015-12-08 12:40:34 +05306361 ret = sscanf(value, "%d", &set_value);
6362 if (ret != 1) {
6363 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6364 FL("No input identified"));
6365 ret = -EINVAL;
6366 goto exit;
6367 }
Atul Mittal87ec2422014-09-24 13:12:50 +05306368 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6369 "%s: Tdls offchannel mode:%d",
6370 __func__, set_value);
6371 ret = iw_set_tdlsoffchannelmode(pAdapter, set_value);
6372 if (ret < 0)
6373 {
6374 ret = -EINVAL;
6375 goto exit;
6376 }
6377 } else if (strncmp(command, "TDLSOFFCHANNEL", 14) == 0) {
6378 tANI_U8 *value = command;
6379 int set_value;
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05306380
6381 ret = hdd_drv_cmd_validate(command, 14);
6382 if (ret)
6383 goto exit;
6384
Atul Mittal87ec2422014-09-24 13:12:50 +05306385 /* Move pointer to ahead of TDLSOFFCH*/
6386 value += 14;
c_manjeef6ccaf52015-12-08 11:52:11 +05306387 ret = sscanf(value, "%d", &set_value);
6388 if (ret != 1) {
6389 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6390 "Wrong value is given for hdd_set_tdls_offchannel");
6391 ret = -EINVAL;
6392 goto exit;
6393 }
6394
Atul Mittal87ec2422014-09-24 13:12:50 +05306395 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6396 "%s: Tdls offchannel num: %d",
6397 __func__, set_value);
6398 ret = iw_set_tdlsoffchannel(pHddCtx, set_value);
6399 if (ret < 0)
6400 {
6401 ret = -EINVAL;
6402 goto exit;
6403 }
6404 }
6405#endif
Satyanarayana Dash72806012014-12-02 14:30:08 +05306406 else if (strncmp(command, "GETFWSTATS", 10) == 0)
6407 {
6408 eHalStatus status;
6409 char *buf = NULL;
6410 char len;
6411 long waitRet;
6412 fwStatsContext_t fwStatsCtx;
Abhishek Singh08aa7762014-12-16 13:59:03 +05306413 tSirFwStatsResult *fwStatsRsp = &(pAdapter->fwStatsRsp);
Satyanarayana Dash72806012014-12-02 14:30:08 +05306414 tANI_U8 *ptr = command;
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05306415 int stats;
Satyanarayana Dash72806012014-12-02 14:30:08 +05306416
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05306417 ret = hdd_drv_cmd_validate(command, 10);
6418 if (ret)
6419 goto exit;
6420
6421 stats = *(ptr + 11) - '0';
Satyanarayana Dash72806012014-12-02 14:30:08 +05306422 hddLog(VOS_TRACE_LEVEL_INFO, FL("stats = %d "),stats);
6423 if (!IS_FEATURE_FW_STATS_ENABLE)
6424 {
6425 hddLog(VOS_TRACE_LEVEL_INFO,
6426 FL("Get Firmware stats feature not supported"));
6427 ret = -EINVAL;
6428 goto exit;
6429 }
6430
6431 if (FW_STATS_MAX <= stats || 0 >= stats)
6432 {
6433 hddLog(VOS_TRACE_LEVEL_INFO,
6434 FL(" stats %d not supported"),stats);
6435 ret = -EINVAL;
6436 goto exit;
6437 }
6438
6439 init_completion(&(fwStatsCtx.completion));
6440 fwStatsCtx.magic = FW_STATS_CONTEXT_MAGIC;
6441 fwStatsCtx.pAdapter = pAdapter;
6442 fwStatsRsp->type = 0;
6443 status = sme_GetFwStats( (tHalHandle)pHddCtx->hHal, stats,
Abhishek Singh08aa7762014-12-16 13:59:03 +05306444 &fwStatsCtx, hdd_FWStatisCB);
Satyanarayana Dash72806012014-12-02 14:30:08 +05306445 if (eHAL_STATUS_SUCCESS != status)
6446 {
6447 hddLog(VOS_TRACE_LEVEL_ERROR,
6448 FL(" fail to post WDA cmd status = %d"), status);
6449 ret = -EINVAL;
6450 goto exit;
6451 }
6452 waitRet = wait_for_completion_timeout
6453 (&(fwStatsCtx.completion), FW_STATE_WAIT_TIME);
6454 if (waitRet <= 0)
6455 {
6456 hddLog(VOS_TRACE_LEVEL_ERROR,
6457 FL("failed to wait on GwtFwstats"));
6458 //Make magic number to zero so that callback is not executed.
6459 spin_lock(&hdd_context_lock);
6460 fwStatsCtx.magic = 0x0;
6461 spin_unlock(&hdd_context_lock);
6462 ret = -EINVAL;
6463 goto exit;
6464 }
6465 if (fwStatsRsp->type)
6466 {
6467 buf = kmalloc(FW_STATE_RSP_LEN, GFP_KERNEL);
6468 if (!buf)
6469 {
6470 hddLog(VOS_TRACE_LEVEL_ERROR,
6471 FL(" failed to allocate memory"));
6472 ret = -ENOMEM;
6473 goto exit;
6474 }
6475 switch( fwStatsRsp->type )
6476 {
6477 case FW_UBSP_STATS:
6478 {
6479 len = snprintf(buf, FW_STATE_RSP_LEN,
6480 "GETFWSTATS: ubsp_enter_cnt %d ubsp_jump_ddr_cnt %d",
Abhishek Singh08aa7762014-12-16 13:59:03 +05306481 fwStatsRsp->fwStatsData.ubspStats.ubsp_enter_cnt,
6482 fwStatsRsp->fwStatsData.ubspStats.ubsp_jump_ddr_cnt);
Satyanarayana Dash72806012014-12-02 14:30:08 +05306483 }
6484 break;
6485 default:
6486 {
6487 hddLog(VOS_TRACE_LEVEL_ERROR, FL( "No handling for stats type %d"),fwStatsRsp->type);
6488 ret = -EFAULT;
6489 kfree(buf);
6490 goto exit;
6491 }
6492 }
6493 if (copy_to_user(priv_data.buf, buf, len + 1))
6494 {
6495 hddLog(VOS_TRACE_LEVEL_ERROR,
6496 FL(" failed to copy data to user buffer"));
6497 ret = -EFAULT;
6498 kfree(buf);
6499 goto exit;
6500 }
6501 ret = len;
6502 kfree(buf);
6503 }
6504 else
6505 {
6506 hddLog(VOS_TRACE_LEVEL_ERROR,
6507 FL("failed to fetch the stats"));
6508 ret = -EFAULT;
6509 goto exit;
6510 }
6511
6512 }
Agarwal Ashish8bd53ae2015-06-12 18:03:45 +05306513 else if (strncasecmp(command, "SET_FCC_CHANNEL", 15) == 0)
6514 {
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05306515 ret = hdd_drv_cmd_validate(command, 15);
6516 if (ret)
6517 goto exit;
6518
Agarwal Ashish8bd53ae2015-06-12 18:03:45 +05306519 /*
6520 * this command wld be called by user-space when it detects WLAN
6521 * ON after airplane mode is set. When APM is set, WLAN turns off.
6522 * But it can be turned back on. Otherwise; when APM is turned back
6523 * off, WLAN wld turn back on. So at that point the command is
6524 * expected to come down. 0 means disable, 1 means enable. The
6525 * constraint is removed when parameter 1 is set or different
6526 * country code is set
6527 */
6528 ret = hdd_cmd_setFccChannel(pHddCtx, command, 15);
6529 }
Mahesh A Saptasagarbeca12c2015-09-07 16:21:06 +05306530 else if (strncasecmp(command, "DISABLE_CA_EVENT", 16) == 0)
6531 {
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05306532 ret = hdd_drv_cmd_validate(command, 16);
6533 if (ret)
6534 goto exit;
6535
Mahesh A Saptasagarbeca12c2015-09-07 16:21:06 +05306536 ret = hdd_enable_disable_ca_event(pHddCtx, command, 16);
6537 }
Ashish Kumar Dhanotiya32d092b2018-02-20 21:43:57 +05306538 /*
6539 * command should be a string having format
6540 * SET_DISABLE_CHANNEL_LIST <num of channels>
6541 * <channels separated by spaces>
6542 */
6543 else if (strncmp(command, "SET_DISABLE_CHANNEL_LIST", 24) == 0) {
6544 tANI_U8 *ptr = command;
6545 ret = hdd_drv_cmd_validate(command, 24);
6546 if (ret)
6547 goto exit;
6548
6549 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6550 " Received Command to disable Channels %s",
6551 __func__);
6552 ret = hdd_parse_disable_chan_cmd(pAdapter, ptr);
6553 if (ret)
6554 goto exit;
6555 }
Hanumanth Reddy Pothula8ae38bb2018-03-07 18:59:30 +05306556 else if (strncmp(command, "GET_DISABLE_CHANNEL_LIST", 24) == 0) {
6557 char extra[128] = {0};
6558 int len;
Ashish Kumar Dhanotiya32d092b2018-02-20 21:43:57 +05306559
Hanumanth Reddy Pothula8ae38bb2018-03-07 18:59:30 +05306560 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6561 " Received Command to get disable Channels list %s",
6562 __func__);
6563
6564 len = hdd_get_disable_ch_list(pHddCtx, extra, sizeof(extra));
6565 if (len == 0) {
6566 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6567 FL("disable channel list are not yet programed"));
6568 ret = -EINVAL;
6569 goto exit;
6570 }
6571
6572 len = VOS_MIN(priv_data.total_len, len + 1);
6573 if (copy_to_user(priv_data.buf, &extra, len)) {
6574 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6575 "%s: failed to copy data to user buffer", __func__);
6576 ret = -EFAULT;
6577 goto exit;
6578 }
6579
6580 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6581 FL("data:%s"), extra);
6582 }
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07006583 else {
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05306584 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
6585 TRACE_CODE_HDD_UNSUPPORTED_IOCTL,
6586 pAdapter->sessionId, 0));
Satyanarayana Dash72806012014-12-02 14:30:08 +05306587 hddLog( VOS_TRACE_LEVEL_WARN, FL("Unsupported GUI command %s"),
6588 command);
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07006589 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006590 }
6591exit:
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05306592 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07006593 if (command)
6594 {
6595 kfree(command);
6596 }
6597 return ret;
6598}
6599
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07006600#ifdef CONFIG_COMPAT
6601static int hdd_driver_compat_ioctl(hdd_adapter_t *pAdapter, struct ifreq *ifr)
6602{
6603 struct {
6604 compat_uptr_t buf;
6605 int used_len;
6606 int total_len;
6607 } compat_priv_data;
6608 hdd_priv_data_t priv_data;
6609 int ret = 0;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006610
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07006611 /*
6612 * Note that pAdapter and ifr have already been verified by caller,
6613 * and HDD context has also been validated
6614 */
6615 if (copy_from_user(&compat_priv_data, ifr->ifr_data,
6616 sizeof(compat_priv_data))) {
6617 ret = -EFAULT;
6618 goto exit;
6619 }
6620 priv_data.buf = compat_ptr(compat_priv_data.buf);
6621 priv_data.used_len = compat_priv_data.used_len;
6622 priv_data.total_len = compat_priv_data.total_len;
6623 ret = hdd_driver_command(pAdapter, &priv_data);
6624 exit:
6625 return ret;
6626}
6627#else /* CONFIG_COMPAT */
6628static int hdd_driver_compat_ioctl(hdd_adapter_t *pAdapter, struct ifreq *ifr)
6629{
6630 /* will never be invoked */
6631 return 0;
6632}
6633#endif /* CONFIG_COMPAT */
6634
6635static int hdd_driver_ioctl(hdd_adapter_t *pAdapter, struct ifreq *ifr)
6636{
6637 hdd_priv_data_t priv_data;
6638 int ret = 0;
6639
6640 /*
6641 * Note that pAdapter and ifr have already been verified by caller,
6642 * and HDD context has also been validated
6643 */
6644 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(priv_data))) {
6645 ret = -EFAULT;
6646 } else {
6647 ret = hdd_driver_command(pAdapter, &priv_data);
6648 }
6649 return ret;
6650}
6651
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05306652int __hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07006653{
6654 hdd_adapter_t *pAdapter;
6655 hdd_context_t *pHddCtx;
6656 int ret;
6657
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05306658 ENTER();
6659
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07006660 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6661 if (NULL == pAdapter) {
6662 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6663 "%s: HDD adapter context is Null", __func__);
6664 ret = -ENODEV;
6665 goto exit;
6666 }
6667 if (dev != pAdapter->dev) {
6668 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6669 "%s: HDD adapter/dev inconsistency", __func__);
6670 ret = -ENODEV;
6671 goto exit;
6672 }
6673
6674 if ((!ifr) || (!ifr->ifr_data)) {
6675 ret = -EINVAL;
6676 goto exit;
6677 }
6678
6679 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6680 ret = wlan_hdd_validate_context(pHddCtx);
6681 if (ret) {
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07006682 ret = -EBUSY;
6683 goto exit;
6684 }
6685
6686 switch (cmd) {
6687 case (SIOCDEVPRIVATE + 1):
6688 if (is_compat_task())
6689 ret = hdd_driver_compat_ioctl(pAdapter, ifr);
6690 else
6691 ret = hdd_driver_ioctl(pAdapter, ifr);
6692 break;
6693 default:
6694 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unknown ioctl %d",
6695 __func__, cmd);
6696 ret = -EINVAL;
6697 break;
6698 }
6699 exit:
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05306700 EXIT();
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07006701 return ret;
6702}
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006703
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05306704int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
6705{
6706 int ret;
6707
6708 vos_ssr_protect(__func__);
6709 ret = __hdd_ioctl(dev, ifr, cmd);
6710 vos_ssr_unprotect(__func__);
6711
6712 return ret;
6713}
6714
Katya Nigame7b69a82015-04-28 15:24:06 +05306715int hdd_mon_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
6716{
6717 return 0;
6718}
6719
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006720#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006721/**---------------------------------------------------------------------------
6722
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006723 \brief hdd_parse_ese_beacon_req() - Parse ese beacon request
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006724
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006725 This function parses the ese beacon request passed in the format
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006726 CCXBEACONREQ<space><Number of fields><space><Measurement token>
6727 <space>Channel 1<space>Scan Mode <space>Meas Duration<space>Channel N
6728 <space>Scan Mode N<space>Meas Duration N
6729 if the Number of bcn req fields (N) does not match with the actual number of fields passed
6730 then take N.
6731 <Meas Token><Channel><Scan Mode> and <Meas Duration> are treated as one pair
6732 For example, CCXBEACONREQ 2 1 1 1 30 2 44 0 40.
6733 This function does not take care of removing duplicate channels from the list
6734
6735 \param - pValue Pointer to data
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006736 \param - pEseBcnReq output pointer to store parsed ie information
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006737
6738 \return - 0 for success non-zero for failure
6739
6740 --------------------------------------------------------------------------*/
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006741static VOS_STATUS hdd_parse_ese_beacon_req(tANI_U8 *pValue,
6742 tCsrEseBeaconReq *pEseBcnReq)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006743{
6744 tANI_U8 *inPtr = pValue;
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306745 uint8_t input = 0;
6746 uint32_t tempInt = 0;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006747 int j = 0, i = 0, v = 0;
6748 char buf[32];
6749
6750 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
6751 /*no argument after the command*/
6752 if (NULL == inPtr)
6753 {
6754 return -EINVAL;
6755 }
6756 /*no space after the command*/
6757 else if (SPACE_ASCII_VALUE != *inPtr)
6758 {
6759 return -EINVAL;
6760 }
6761
6762 /*removing empty spaces*/
6763 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
6764
6765 /*no argument followed by spaces*/
6766 if ('\0' == *inPtr) return -EINVAL;
6767
6768 /*getting the first argument ie measurement token*/
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08006769 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006770 if (1 != v) return -EINVAL;
6771
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306772 v = kstrtos8(buf, 10, &input);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006773 if ( v < 0) return -EINVAL;
6774
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306775 input = VOS_MIN(input, SIR_ESE_MAX_MEAS_IE_REQS);
6776 pEseBcnReq->numBcnReqIe = input;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006777
Srinivas Girigowda725a88e2016-03-31 19:24:25 +05306778 hddLog(LOG1, "Number of Bcn Req Ie fields: %d", pEseBcnReq->numBcnReqIe);
6779
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006780
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006781 for (j = 0; j < (pEseBcnReq->numBcnReqIe); j++)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006782 {
6783 for (i = 0; i < 4; i++)
6784 {
6785 /*inPtr pointing to the beginning of first space after number of ie fields*/
6786 inPtr = strpbrk( inPtr, " " );
6787 /*no ie data after the number of ie fields argument*/
6788 if (NULL == inPtr) return -EINVAL;
6789
6790 /*removing empty space*/
6791 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
6792
6793 /*no ie data after the number of ie fields argument and spaces*/
6794 if ( '\0' == *inPtr ) return -EINVAL;
6795
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08006796 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006797 if (1 != v) return -EINVAL;
6798
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306799 v = kstrtou32(buf, 10, &tempInt);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006800 if (v < 0) return -EINVAL;
6801
6802 switch (i)
6803 {
6804 case 0: /* Measurement token */
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306805 if (!tempInt)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006806 {
6807 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306808 "Invalid Measurement Token: %u", tempInt);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006809 return -EINVAL;
6810 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006811 pEseBcnReq->bcnReq[j].measurementToken = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006812 break;
6813
6814 case 1: /* Channel number */
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306815 if ((!tempInt) ||
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006816 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
6817 {
6818 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306819 "Invalid Channel Number: %u", tempInt);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006820 return -EINVAL;
6821 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006822 pEseBcnReq->bcnReq[j].channel = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006823 break;
6824
6825 case 2: /* Scan mode */
Varun Reddy Yeturu0b18d5a2013-12-04 11:42:23 -08006826 if ((tempInt < eSIR_PASSIVE_SCAN) || (tempInt > eSIR_BEACON_TABLE))
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006827 {
6828 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306829 "Invalid Scan Mode(%u) Expected{0|1|2}", tempInt);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006830 return -EINVAL;
6831 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006832 pEseBcnReq->bcnReq[j].scanMode= tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006833 break;
6834
6835 case 3: /* Measurement duration */
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306836 if (((!tempInt) && (pEseBcnReq->bcnReq[j].scanMode != eSIR_BEACON_TABLE)) ||
6837 ((pEseBcnReq->bcnReq[j].scanMode == eSIR_BEACON_TABLE)))
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006838 {
6839 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306840 "Invalid Measurement Duration: %u", tempInt);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006841 return -EINVAL;
6842 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006843 pEseBcnReq->bcnReq[j].measurementDuration = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006844 break;
6845 }
6846 }
6847 }
6848
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006849 for (j = 0; j < pEseBcnReq->numBcnReqIe; j++)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006850 {
6851 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arun Kumar Khandavallie8768212014-02-17 16:43:34 +05306852 "Index(%d) Measurement Token(%u)Channel(%u) Scan Mode(%u) Measurement Duration(%u)\n",
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006853 j,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006854 pEseBcnReq->bcnReq[j].measurementToken,
6855 pEseBcnReq->bcnReq[j].channel,
6856 pEseBcnReq->bcnReq[j].scanMode,
6857 pEseBcnReq->bcnReq[j].measurementDuration);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006858 }
6859
6860 return VOS_STATUS_SUCCESS;
6861}
6862
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006863static void hdd_GetTsmStatsCB( tAniTrafStrmMetrics tsmMetrics, const tANI_U32 staId, void *pContext )
6864{
6865 struct statsContext *pStatsContext = NULL;
6866 hdd_adapter_t *pAdapter = NULL;
6867
6868 if (NULL == pContext)
6869 {
6870 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnsonc135a9a2017-09-19 08:37:24 -07006871 "%s: Bad param, pContext [%pK]",
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006872 __func__, pContext);
6873 return;
6874 }
6875
Jeff Johnson72a40512013-12-19 10:14:15 -08006876 /* there is a race condition that exists between this callback
6877 function and the caller since the caller could time out either
6878 before or while this code is executing. we use a spinlock to
6879 serialize these actions */
6880 spin_lock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006881
6882 pStatsContext = pContext;
6883 pAdapter = pStatsContext->pAdapter;
6884 if ((NULL == pAdapter) || (STATS_CONTEXT_MAGIC != pStatsContext->magic))
6885 {
6886 /* the caller presumably timed out so there is nothing we can do */
Jeff Johnson72a40512013-12-19 10:14:15 -08006887 spin_unlock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006888 hddLog(VOS_TRACE_LEVEL_WARN,
Jeff Johnsonc135a9a2017-09-19 08:37:24 -07006889 "%s: Invalid context, pAdapter [%pK] magic [%08x]",
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006890 __func__, pAdapter, pStatsContext->magic);
6891 return;
6892 }
6893
Jeff Johnson72a40512013-12-19 10:14:15 -08006894 /* context is valid so caller is still waiting */
6895
6896 /* paranoia: invalidate the magic */
6897 pStatsContext->magic = 0;
6898
6899 /* copy over the tsm stats */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006900 pAdapter->tsmStats.UplinkPktQueueDly = tsmMetrics.UplinkPktQueueDly;
6901 vos_mem_copy(pAdapter->tsmStats.UplinkPktQueueDlyHist,
6902 tsmMetrics.UplinkPktQueueDlyHist,
6903 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
6904 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
6905 pAdapter->tsmStats.UplinkPktTxDly = tsmMetrics.UplinkPktTxDly;
6906 pAdapter->tsmStats.UplinkPktLoss = tsmMetrics.UplinkPktLoss;
6907 pAdapter->tsmStats.UplinkPktCount = tsmMetrics.UplinkPktCount;
6908 pAdapter->tsmStats.RoamingCount = tsmMetrics.RoamingCount;
6909 pAdapter->tsmStats.RoamingDly = tsmMetrics.RoamingDly;
6910
Jeff Johnson72a40512013-12-19 10:14:15 -08006911 /* notify the caller */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006912 complete(&pStatsContext->completion);
Jeff Johnson72a40512013-12-19 10:14:15 -08006913
6914 /* serialization is complete */
6915 spin_unlock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006916}
6917
6918
6919
6920static VOS_STATUS hdd_get_tsm_stats(hdd_adapter_t *pAdapter, const tANI_U8 tid,
6921 tAniTrafStrmMetrics* pTsmMetrics)
6922{
6923 hdd_station_ctx_t *pHddStaCtx = NULL;
6924 eHalStatus hstatus;
Jeff Johnson72a40512013-12-19 10:14:15 -08006925 VOS_STATUS vstatus = VOS_STATUS_SUCCESS;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006926 long lrc;
6927 struct statsContext context;
6928 hdd_context_t *pHddCtx = NULL;
6929
6930 if (NULL == pAdapter)
6931 {
6932 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: pAdapter is NULL", __func__);
6933 return VOS_STATUS_E_FAULT;
6934 }
6935
6936 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6937 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6938
6939 /* we are connected prepare our callback context */
6940 init_completion(&context.completion);
6941 context.pAdapter = pAdapter;
6942 context.magic = STATS_CONTEXT_MAGIC;
6943
6944 /* query tsm stats */
6945 hstatus = sme_GetTsmStats(pHddCtx->hHal, hdd_GetTsmStatsCB,
6946 pHddStaCtx->conn_info.staId[ 0 ],
6947 pHddStaCtx->conn_info.bssId,
6948 &context, pHddCtx->pvosContext, tid);
6949
6950 if (eHAL_STATUS_SUCCESS != hstatus)
6951 {
Jeff Johnson72a40512013-12-19 10:14:15 -08006952 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unable to retrieve statistics",
6953 __func__);
6954 vstatus = VOS_STATUS_E_FAULT;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006955 }
6956 else
6957 {
6958 /* request was sent -- wait for the response */
6959 lrc = wait_for_completion_interruptible_timeout(&context.completion,
6960 msecs_to_jiffies(WLAN_WAIT_TIME_STATS));
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006961 if (lrc <= 0)
6962 {
6963 hddLog(VOS_TRACE_LEVEL_ERROR,
6964 "%s: SME %s while retrieving statistics",
6965 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson72a40512013-12-19 10:14:15 -08006966 vstatus = VOS_STATUS_E_TIMEOUT;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006967 }
6968 }
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006969
Jeff Johnson72a40512013-12-19 10:14:15 -08006970 /* either we never sent a request, we sent a request and received a
6971 response or we sent a request and timed out. if we never sent a
6972 request or if we sent a request and got a response, we want to
6973 clear the magic out of paranoia. if we timed out there is a
6974 race condition such that the callback function could be
6975 executing at the same time we are. of primary concern is if the
6976 callback function had already verified the "magic" but had not
6977 yet set the completion variable when a timeout occurred. we
6978 serialize these activities by invalidating the magic while
6979 holding a shared spinlock which will cause us to block if the
6980 callback is currently executing */
6981 spin_lock(&hdd_context_lock);
6982 context.magic = 0;
6983 spin_unlock(&hdd_context_lock);
6984
6985 if (VOS_STATUS_SUCCESS == vstatus)
6986 {
6987 pTsmMetrics->UplinkPktQueueDly = pAdapter->tsmStats.UplinkPktQueueDly;
6988 vos_mem_copy(pTsmMetrics->UplinkPktQueueDlyHist,
6989 pAdapter->tsmStats.UplinkPktQueueDlyHist,
6990 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
6991 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
6992 pTsmMetrics->UplinkPktTxDly = pAdapter->tsmStats.UplinkPktTxDly;
6993 pTsmMetrics->UplinkPktLoss = pAdapter->tsmStats.UplinkPktLoss;
6994 pTsmMetrics->UplinkPktCount = pAdapter->tsmStats.UplinkPktCount;
6995 pTsmMetrics->RoamingCount = pAdapter->tsmStats.RoamingCount;
6996 pTsmMetrics->RoamingDly = pAdapter->tsmStats.RoamingDly;
6997 }
6998 return vstatus;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006999}
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08007000#endif /*FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07007001
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08007002#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -08007003void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
7004{
7005 eCsrBand band = -1;
7006 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
7007 switch (band)
7008 {
7009 case eCSR_BAND_ALL:
7010 *pBand = WLAN_HDD_UI_BAND_AUTO;
7011 break;
7012
7013 case eCSR_BAND_24:
7014 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
7015 break;
7016
7017 case eCSR_BAND_5G:
7018 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
7019 break;
7020
7021 default:
7022 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
7023 *pBand = -1;
7024 break;
7025 }
7026}
7027
7028/**---------------------------------------------------------------------------
7029
Srinivas Girigowda100eb322013-03-15 16:48:20 -07007030 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
7031
7032 This function parses the send action frame data passed in the format
7033 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
7034
Srinivas Girigowda56076852013-08-20 14:00:50 -07007035 \param - pValue Pointer to input data
Srinivas Girigowda100eb322013-03-15 16:48:20 -07007036 \param - pTargetApBssid Pointer to target Ap bssid
7037 \param - pChannel Pointer to the Target AP channel
7038 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
7039 \param - pBuf Pointer to data
7040 \param - pBufLen Pointer to data length
7041
7042 \return - 0 for success non-zero for failure
7043
7044 --------------------------------------------------------------------------*/
7045VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
7046 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
7047{
7048 tANI_U8 *inPtr = pValue;
7049 tANI_U8 *dataEnd;
7050 int tempInt;
7051 int j = 0;
7052 int i = 0;
7053 int v = 0;
7054 tANI_U8 tempBuf[32];
7055 tANI_U8 tempByte = 0;
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08007056 /* 12 hexa decimal digits, 5 ':' and '\0' */
7057 tANI_U8 macAddress[18];
Srinivas Girigowda100eb322013-03-15 16:48:20 -07007058
7059 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
7060 /*no argument after the command*/
7061 if (NULL == inPtr)
7062 {
7063 return -EINVAL;
7064 }
7065
7066 /*no space after the command*/
7067 else if (SPACE_ASCII_VALUE != *inPtr)
7068 {
7069 return -EINVAL;
7070 }
7071
7072 /*removing empty spaces*/
7073 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
7074
7075 /*no argument followed by spaces*/
7076 if ('\0' == *inPtr)
7077 {
7078 return -EINVAL;
7079 }
7080
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07007081 v = sscanf(inPtr, "%17s", macAddress);
7082 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Srinivas Girigowda100eb322013-03-15 16:48:20 -07007083 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07007084 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7085 "Invalid MAC address or All hex inputs are not read (%d)", v);
7086 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07007087 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07007088
7089 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
7090 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
7091 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
7092 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
7093 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
7094 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07007095
7096 /* point to the next argument */
7097 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
7098 /*no argument after the command*/
7099 if (NULL == inPtr) return -EINVAL;
7100
7101 /*removing empty spaces*/
7102 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
7103
7104 /*no argument followed by spaces*/
7105 if ('\0' == *inPtr)
7106 {
7107 return -EINVAL;
7108 }
7109
7110 /*getting the next argument ie the channel number */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08007111 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07007112 if (1 != v) return -EINVAL;
7113
Srinivas Girigowda100eb322013-03-15 16:48:20 -07007114 v = kstrtos32(tempBuf, 10, &tempInt);
Agarwal Ashish353b3a82014-04-08 14:55:11 +05307115 if ( v < 0 || tempInt <= 0 || tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX )
Kiet Lambe150c22013-11-21 16:30:32 +05307116 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07007117
7118 *pChannel = tempInt;
7119
7120 /* point to the next argument */
7121 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
7122 /*no argument after the command*/
7123 if (NULL == inPtr) return -EINVAL;
7124 /*removing empty spaces*/
7125 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
7126
7127 /*no argument followed by spaces*/
7128 if ('\0' == *inPtr)
7129 {
7130 return -EINVAL;
7131 }
7132
7133 /*getting the next argument ie the dwell time */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08007134 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07007135 if (1 != v) return -EINVAL;
7136
Srinivas Girigowda100eb322013-03-15 16:48:20 -07007137 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda5a6e0672014-01-09 14:42:57 -08007138 if ( v < 0 || tempInt < 0) return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07007139
7140 *pDwellTime = tempInt;
7141
7142 /* point to the next argument */
7143 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
7144 /*no argument after the command*/
7145 if (NULL == inPtr) return -EINVAL;
7146 /*removing empty spaces*/
7147 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
7148
7149 /*no argument followed by spaces*/
7150 if ('\0' == *inPtr)
7151 {
7152 return -EINVAL;
7153 }
7154
7155 /* find the length of data */
7156 dataEnd = inPtr;
7157 while(('\0' != *dataEnd) )
7158 {
7159 dataEnd++;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07007160 }
Kiet Lambe150c22013-11-21 16:30:32 +05307161 *pBufLen = dataEnd - inPtr ;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07007162 if ( *pBufLen <= 0) return -EINVAL;
7163
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07007164 /* Allocate the number of bytes based on the number of input characters
7165 whether it is even or odd.
7166 if the number of input characters are even, then we need N/2 byte.
7167 if the number of input characters are odd, then we need do (N+1)/2 to
7168 compensate rounding off.
7169 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
7170 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
7171 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07007172 if (NULL == *pBuf)
7173 {
7174 hddLog(VOS_TRACE_LEVEL_FATAL,
7175 "%s: vos_mem_alloc failed ", __func__);
7176 return -EINVAL;
7177 }
7178
7179 /* the buffer received from the upper layer is character buffer,
7180 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
7181 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
7182 and f0 in 3rd location */
7183 for (i = 0, j = 0; j < *pBufLen; j += 2)
7184 {
Kiet Lambe150c22013-11-21 16:30:32 +05307185 if( j+1 == *pBufLen)
7186 {
7187 tempByte = hdd_parse_hex(inPtr[j]);
7188 }
7189 else
7190 {
7191 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
7192 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07007193 (*pBuf)[i++] = tempByte;
7194 }
7195 *pBufLen = i;
7196 return VOS_STATUS_SUCCESS;
7197}
7198
Srinivas Girigowda100eb322013-03-15 16:48:20 -07007199/**---------------------------------------------------------------------------
7200
Srinivas Girigowdade697412013-02-14 16:31:48 -08007201 \brief hdd_parse_channellist() - HDD Parse channel list
7202
7203 This function parses the channel list passed in the format
7204 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07007205 if the Number of channels (N) does not match with the actual number of channels passed
7206 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
7207 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
7208 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
7209 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08007210
7211 \param - pValue Pointer to input channel list
7212 \param - ChannelList Pointer to local output array to record channel list
7213 \param - pNumChannels Pointer to number of roam scan channels
7214
7215 \return - 0 for success non-zero for failure
7216
7217 --------------------------------------------------------------------------*/
7218VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
7219{
7220 tANI_U8 *inPtr = pValue;
7221 int tempInt;
7222 int j = 0;
7223 int v = 0;
7224 char buf[32];
7225
7226 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
7227 /*no argument after the command*/
7228 if (NULL == inPtr)
7229 {
7230 return -EINVAL;
7231 }
7232
7233 /*no space after the command*/
7234 else if (SPACE_ASCII_VALUE != *inPtr)
7235 {
7236 return -EINVAL;
7237 }
7238
7239 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07007240 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08007241
7242 /*no argument followed by spaces*/
7243 if ('\0' == *inPtr)
7244 {
7245 return -EINVAL;
7246 }
7247
7248 /*getting the first argument ie the number of channels*/
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08007249 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07007250 if (1 != v) return -EINVAL;
7251
Srinivas Girigowdade697412013-02-14 16:31:48 -08007252 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07007253 if ((v < 0) ||
7254 (tempInt <= 0) ||
7255 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
7256 {
7257 return -EINVAL;
7258 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08007259
7260 *pNumChannels = tempInt;
7261
7262 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
7263 "Number of channels are: %d", *pNumChannels);
7264
7265 for (j = 0; j < (*pNumChannels); j++)
7266 {
7267 /*inPtr pointing to the beginning of first space after number of channels*/
7268 inPtr = strpbrk( inPtr, " " );
7269 /*no channel list after the number of channels argument*/
7270 if (NULL == inPtr)
7271 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07007272 if (0 != j)
7273 {
7274 *pNumChannels = j;
7275 return VOS_STATUS_SUCCESS;
7276 }
7277 else
7278 {
7279 return -EINVAL;
7280 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08007281 }
7282
7283 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07007284 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08007285
7286 /*no channel list after the number of channels argument and spaces*/
7287 if ( '\0' == *inPtr )
7288 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07007289 if (0 != j)
7290 {
7291 *pNumChannels = j;
7292 return VOS_STATUS_SUCCESS;
7293 }
7294 else
7295 {
7296 return -EINVAL;
7297 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08007298 }
7299
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08007300 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07007301 if (1 != v) return -EINVAL;
7302
Srinivas Girigowdade697412013-02-14 16:31:48 -08007303 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07007304 if ((v < 0) ||
7305 (tempInt <= 0) ||
7306 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
7307 {
7308 return -EINVAL;
7309 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08007310 pChannelList[j] = tempInt;
7311
7312 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
7313 "Channel %d added to preferred channel list",
7314 pChannelList[j] );
7315 }
7316
Srinivas Girigowdade697412013-02-14 16:31:48 -08007317 return VOS_STATUS_SUCCESS;
7318}
7319
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07007320
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05307321/**
7322 * hdd_parse_reassoc_command_v1_data() - HDD Parse reassoc command data
7323 * This function parses the reasoc command data passed in the format
7324 * REASSOC<space><bssid><space><channel>
7325 *
7326 * @pValue: Pointer to input data (its a NUL terminated string)
7327 * @pTargetApBssid: Pointer to target Ap bssid
7328 * @pChannel: Pointer to the Target AP channel
7329 *
7330 * Return: 0 for success non-zero for failure
7331 */
7332static int hdd_parse_reassoc_command_v1_data(const tANI_U8 *pValue,
7333 tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07007334{
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05307335 const tANI_U8 *inPtr = pValue;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07007336 int tempInt;
7337 int v = 0;
7338 tANI_U8 tempBuf[32];
Kiet Lamaa8e15a2014-02-11 23:30:06 -08007339 /* 12 hexa decimal digits, 5 ':' and '\0' */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08007340 tANI_U8 macAddress[18];
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07007341
7342 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
7343 /*no argument after the command*/
7344 if (NULL == inPtr)
7345 {
7346 return -EINVAL;
7347 }
7348
7349 /*no space after the command*/
7350 else if (SPACE_ASCII_VALUE != *inPtr)
7351 {
7352 return -EINVAL;
7353 }
7354
7355 /*removing empty spaces*/
7356 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
7357
7358 /*no argument followed by spaces*/
7359 if ('\0' == *inPtr)
7360 {
7361 return -EINVAL;
7362 }
7363
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07007364 v = sscanf(inPtr, "%17s", macAddress);
7365 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07007366 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07007367 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7368 "Invalid MAC address or All hex inputs are not read (%d)", v);
7369 return -EINVAL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07007370 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07007371
7372 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
7373 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
7374 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
7375 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
7376 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
7377 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07007378
7379 /* point to the next argument */
7380 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
7381 /*no argument after the command*/
7382 if (NULL == inPtr) return -EINVAL;
7383
7384 /*removing empty spaces*/
7385 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
7386
7387 /*no argument followed by spaces*/
7388 if ('\0' == *inPtr)
7389 {
7390 return -EINVAL;
7391 }
7392
7393 /*getting the next argument ie the channel number */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08007394 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07007395 if (1 != v) return -EINVAL;
7396
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07007397 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07007398 if ((v < 0) ||
Padma, Santhosh Kumar0fa809b2014-11-13 14:56:56 +05307399 (tempInt < 0) ||
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07007400 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
7401 {
7402 return -EINVAL;
7403 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07007404
7405 *pChannel = tempInt;
7406 return VOS_STATUS_SUCCESS;
7407}
7408
7409#endif
7410
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08007411#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07007412/**---------------------------------------------------------------------------
7413
7414 \brief hdd_parse_get_cckm_ie() - HDD Parse and fetch the CCKM IE
7415
7416 This function parses the SETCCKM IE command
7417 SETCCKMIE<space><ie data>
7418
7419 \param - pValue Pointer to input data
7420 \param - pCckmIe Pointer to output cckm Ie
7421 \param - pCckmIeLen Pointer to output cckm ie length
7422
7423 \return - 0 for success non-zero for failure
7424
7425 --------------------------------------------------------------------------*/
7426VOS_STATUS hdd_parse_get_cckm_ie(tANI_U8 *pValue, tANI_U8 **pCckmIe,
7427 tANI_U8 *pCckmIeLen)
7428{
7429 tANI_U8 *inPtr = pValue;
7430 tANI_U8 *dataEnd;
7431 int j = 0;
7432 int i = 0;
7433 tANI_U8 tempByte = 0;
7434
7435 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
7436 /*no argument after the command*/
7437 if (NULL == inPtr)
7438 {
7439 return -EINVAL;
7440 }
7441
7442 /*no space after the command*/
7443 else if (SPACE_ASCII_VALUE != *inPtr)
7444 {
7445 return -EINVAL;
7446 }
7447
7448 /*removing empty spaces*/
7449 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
7450
7451 /*no argument followed by spaces*/
7452 if ('\0' == *inPtr)
7453 {
7454 return -EINVAL;
7455 }
7456
7457 /* find the length of data */
7458 dataEnd = inPtr;
7459 while(('\0' != *dataEnd) )
7460 {
7461 dataEnd++;
7462 ++(*pCckmIeLen);
7463 }
7464 if ( *pCckmIeLen <= 0) return -EINVAL;
7465
7466 /* Allocate the number of bytes based on the number of input characters
7467 whether it is even or odd.
7468 if the number of input characters are even, then we need N/2 byte.
7469 if the number of input characters are odd, then we need do (N+1)/2 to
7470 compensate rounding off.
7471 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
7472 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
7473 *pCckmIe = vos_mem_malloc((*pCckmIeLen + 1)/2);
7474 if (NULL == *pCckmIe)
7475 {
7476 hddLog(VOS_TRACE_LEVEL_FATAL,
7477 "%s: vos_mem_alloc failed ", __func__);
7478 return -EINVAL;
7479 }
7480 vos_mem_zero(*pCckmIe, (*pCckmIeLen + 1)/2);
7481 /* the buffer received from the upper layer is character buffer,
7482 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
7483 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
7484 and f0 in 3rd location */
7485 for (i = 0, j = 0; j < *pCckmIeLen; j += 2)
7486 {
7487 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
7488 (*pCckmIe)[i++] = tempByte;
7489 }
7490 *pCckmIeLen = i;
7491
7492 return VOS_STATUS_SUCCESS;
7493}
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08007494#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07007495
Jeff Johnson295189b2012-06-20 16:38:30 -07007496/**---------------------------------------------------------------------------
7497
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07007498 \brief hdd_is_valid_mac_address() - Validate MAC address
7499
7500 This function validates whether the given MAC address is valid or not
7501 Expected MAC address is of the format XX:XX:XX:XX:XX:XX
7502 where X is the hexa decimal digit character and separated by ':'
7503 This algorithm works even if MAC address is not separated by ':'
7504
7505 This code checks given input string mac contains exactly 12 hexadecimal digits.
7506 and a separator colon : appears in the input string only after
7507 an even number of hex digits.
7508
7509 \param - pMacAddr pointer to the input MAC address
7510 \return - 1 for valid and 0 for invalid
7511
7512 --------------------------------------------------------------------------*/
7513
7514v_BOOL_t hdd_is_valid_mac_address(const tANI_U8 *pMacAddr)
7515{
7516 int xdigit = 0;
7517 int separator = 0;
7518 while (*pMacAddr)
7519 {
7520 if (isxdigit(*pMacAddr))
7521 {
7522 xdigit++;
7523 }
7524 else if (':' == *pMacAddr)
7525 {
7526 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
7527 break;
7528
7529 ++separator;
7530 }
7531 else
7532 {
7533 separator = -1;
7534 /* Invalid MAC found */
7535 return 0;
7536 }
7537 ++pMacAddr;
7538 }
7539 return (xdigit == 12 && (separator == 5 || separator == 0));
7540}
7541
7542/**---------------------------------------------------------------------------
7543
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307544 \brief __hdd_open() - HDD Open function
Jeff Johnson295189b2012-06-20 16:38:30 -07007545
7546 \param - dev Pointer to net_device structure
7547
7548 \return - 0 for success non-zero for failure
7549
7550 --------------------------------------------------------------------------*/
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307551int __hdd_open(struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07007552{
7553 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7554 hdd_context_t *pHddCtx;
7555 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7556 VOS_STATUS status;
7557 v_BOOL_t in_standby = TRUE;
7558
7559 if (NULL == pAdapter)
7560 {
7561 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Agarwal Ashish971c2882013-10-30 20:11:12 +05307562 "%s: pAdapter is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007563 return -ENODEV;
7564 }
7565
7566 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05307567 MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_OPEN_REQUEST,
7568 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson295189b2012-06-20 16:38:30 -07007569 if (NULL == pHddCtx)
7570 {
7571 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007572 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007573 return -ENODEV;
7574 }
7575
7576 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7577 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
7578 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07007579 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
7580 {
7581 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307582 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07007583 in_standby = FALSE;
7584 break;
7585 }
7586 else
7587 {
7588 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7589 pAdapterNode = pNext;
7590 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007591 }
7592
7593 if (TRUE == in_standby)
7594 {
7595 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
7596 {
7597 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
7598 "wlan out of power save", __func__);
7599 return -EINVAL;
7600 }
7601 }
7602
Jeff Johnson6a81ca42013-04-05 10:37:08 -07007603 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07007604 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
7605 {
7606 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007607 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007608 /* Enable TX queues only when we are connected */
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05307609 hddLog(VOS_TRACE_LEVEL_INFO, FL("Enabling queues"));
Jeff Johnson295189b2012-06-20 16:38:30 -07007610 netif_tx_start_all_queues(dev);
7611 }
7612
7613 return 0;
7614}
7615
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307616/**---------------------------------------------------------------------------
7617
7618 \brief hdd_open() - Wrapper function for __hdd_open to protect it from SSR
7619
7620 This is called in response to ifconfig up
7621
7622 \param - dev Pointer to net_device structure
7623
7624 \return - 0 for success non-zero for failure
7625
7626 --------------------------------------------------------------------------*/
7627int hdd_open(struct net_device *dev)
7628{
7629 int ret;
7630
7631 vos_ssr_protect(__func__);
7632 ret = __hdd_open(dev);
7633 vos_ssr_unprotect(__func__);
7634
7635 return ret;
7636}
7637
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +05307638int __hdd_mon_open (struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07007639{
7640 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05307641 hdd_adapter_t *sta_adapter;
7642 hdd_context_t *hdd_ctx;
Jeff Johnson295189b2012-06-20 16:38:30 -07007643
7644 if(pAdapter == NULL) {
7645 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007646 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007647 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007648 }
7649
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05307650 if (vos_get_concurrency_mode() != VOS_STA_MON)
7651 return 0;
7652
7653 hdd_ctx = WLAN_HDD_GET_CTX(pAdapter);
7654 if (wlan_hdd_validate_context(hdd_ctx))
7655 return -EINVAL;
7656
7657 sta_adapter = hdd_get_adapter(hdd_ctx, WLAN_HDD_INFRA_STATION);
7658 if (!sta_adapter) {
7659 hddLog(LOGE, FL("No valid STA interface"));
7660 return -EINVAL;
7661 }
7662
7663 if (!test_bit(DEVICE_IFACE_OPENED, &sta_adapter->event_flags)) {
7664 hddLog(LOGE, FL("STA Interface is not OPENED"));
7665 return -EINVAL;
7666 }
7667
7668 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
7669
Jeff Johnson295189b2012-06-20 16:38:30 -07007670 return 0;
7671}
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +05307672
7673int hdd_mon_open (struct net_device *dev)
7674{
7675 int ret;
7676
7677 vos_ssr_protect(__func__);
7678 ret = __hdd_mon_open(dev);
7679 vos_ssr_unprotect(__func__);
7680
7681 return ret;
7682}
7683
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05307684int __hdd_mon_stop (struct net_device *dev)
7685{
7686 hdd_adapter_t *mon_adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7687 hdd_context_t *hdd_ctx;
7688
7689 if (vos_get_concurrency_mode() != VOS_STA_MON)
7690 return 0;
7691
7692 if(!mon_adapter) {
7693 hddLog(LOGE, FL("HDD adapter is Null"));
7694 return -EINVAL;
7695 }
7696
7697 hdd_ctx = WLAN_HDD_GET_CTX(mon_adapter);
7698 if (wlan_hdd_validate_context(hdd_ctx))
7699 return -EINVAL;
7700
7701 if (!test_bit(DEVICE_IFACE_OPENED, &mon_adapter->event_flags)) {
7702 hddLog(LOGE, FL("NETDEV Interface is not OPENED"));
7703 return -ENODEV;
7704 }
7705
7706 clear_bit(DEVICE_IFACE_OPENED, &mon_adapter->event_flags);
7707 hdd_stop_adapter(hdd_ctx, mon_adapter, VOS_FALSE);
7708
7709 return 0;
7710}
7711
Katya Nigame7b69a82015-04-28 15:24:06 +05307712int hdd_mon_stop(struct net_device *dev)
7713{
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05307714 int ret;
7715
7716 vos_ssr_protect(__func__);
7717 ret = __hdd_mon_stop(dev);
7718 vos_ssr_unprotect(__func__);
7719
7720 return ret;
Katya Nigame7b69a82015-04-28 15:24:06 +05307721}
7722
Jeff Johnson295189b2012-06-20 16:38:30 -07007723/**---------------------------------------------------------------------------
7724
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307725 \brief __hdd_stop() - HDD stop function
Jeff Johnson295189b2012-06-20 16:38:30 -07007726
7727 \param - dev Pointer to net_device structure
7728
7729 \return - 0 for success non-zero for failure
7730
7731 --------------------------------------------------------------------------*/
7732
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307733int __hdd_stop (struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07007734{
Vinay Krishna Eranna90f43532014-10-27 16:45:54 +05307735 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07007736 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7737 hdd_context_t *pHddCtx;
7738 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7739 VOS_STATUS status;
7740 v_BOOL_t enter_standby = TRUE;
7741
7742 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07007743 if (NULL == pAdapter)
7744 {
7745 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Agarwal Ashish971c2882013-10-30 20:11:12 +05307746 "%s: pAdapter is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007747 return -ENODEV;
7748 }
Sachin Ahuja9b4958f2015-01-15 21:37:00 +05307749 MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_STOP_REQUEST,
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05307750 pAdapter->sessionId, pAdapter->device_mode));
Vinay Krishna Eranna90f43532014-10-27 16:45:54 +05307751
7752 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7753 ret = wlan_hdd_validate_context(pHddCtx);
7754 if (ret)
Jeff Johnson295189b2012-06-20 16:38:30 -07007755 {
Vinay Krishna Eranna90f43532014-10-27 16:45:54 +05307756 return ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07007757 }
7758
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307759 /* Nothing to be done if the interface is not opened */
7760 if (VOS_FALSE == test_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags))
7761 {
7762 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7763 "%s: NETDEV Interface is not OPENED", __func__);
7764 return -ENODEV;
7765 }
7766
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05307767 if (pHddCtx->concurrency_mode == VOS_STA_MON) {
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05307768 /*
Rajeev Kumar Sirasanagandlaa74e1222018-01-09 17:38:55 +05307769 * In STA + Monitor mode concurrency, no point in running
7770 * capture on monitor interface, when STA interface is stopped
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05307771 */
Rajeev Kumar Sirasanagandlaa74e1222018-01-09 17:38:55 +05307772 wlan_hdd_stop_mon(pHddCtx, true);
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05307773 }
7774
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307775 /* Make sure the interface is marked as closed */
Jeff Johnson6a81ca42013-04-05 10:37:08 -07007776 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07007777 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307778
7779 /* Disable TX on the interface, after this hard_start_xmit() will not
7780 * be called on that interface
7781 */
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05307782 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
Jeff Johnson295189b2012-06-20 16:38:30 -07007783 netif_tx_disable(pAdapter->dev);
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307784
7785 /* Mark the interface status as "down" for outside world */
Jeff Johnson295189b2012-06-20 16:38:30 -07007786 netif_carrier_off(pAdapter->dev);
7787
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307788 /* The interface is marked as down for outside world (aka kernel)
7789 * But the driver is pretty much alive inside. The driver needs to
7790 * tear down the existing connection on the netdev (session)
7791 * cleanup the data pipes and wait until the control plane is stabilized
7792 * for this interface. The call also needs to wait until the above
7793 * mentioned actions are completed before returning to the caller.
7794 * Notice that the hdd_stop_adapter is requested not to close the session
7795 * That is intentional to be able to scan if it is a STA/P2P interface
7796 */
7797 hdd_stop_adapter(pHddCtx, pAdapter, VOS_FALSE);
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05307798#ifdef FEATURE_WLAN_TDLS
7799 mutex_lock(&pHddCtx->tdls_lock);
7800#endif
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307801 /* DeInit the adapter. This ensures datapath cleanup as well */
c_hpothu002231a2015-02-05 14:58:51 +05307802 hdd_deinit_adapter(pHddCtx, pAdapter, TRUE);
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05307803#ifdef FEATURE_WLAN_TDLS
7804 mutex_unlock(&pHddCtx->tdls_lock);
7805#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007806 /* SoftAP ifaces should never go in power save mode
7807 making sure same here. */
7808 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07007809 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07007810 )
7811 {
7812 /* SoftAP mode, so return from here */
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307813 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
7814 "%s: In SAP MODE", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007815 EXIT();
7816 return 0;
7817 }
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307818 /* Find if any iface is up. If any iface is up then can't put device to
7819 * sleep/power save mode
7820 */
Jeff Johnson295189b2012-06-20 16:38:30 -07007821 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7822 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
7823 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07007824 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
7825 {
7826 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307827 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07007828 enter_standby = FALSE;
7829 break;
7830 }
7831 else
7832 {
7833 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7834 pAdapterNode = pNext;
7835 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007836 }
7837
7838 if (TRUE == enter_standby)
7839 {
7840 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
7841 "entering standby", __func__);
7842 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
7843 {
7844 /*log and return success*/
7845 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
7846 "wlan in power save", __func__);
7847 }
7848 }
7849
7850 EXIT();
7851 return 0;
7852}
7853
7854/**---------------------------------------------------------------------------
7855
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307856 \brief hdd_stop() - wrapper_function for __hdd_stop to protect it from SSR
Jeff Johnson295189b2012-06-20 16:38:30 -07007857
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307858 This is called in response to ifconfig down
7859
7860 \param - dev Pointer to net_device structure
7861
7862 \return - 0 for success non-zero for failure
7863-----------------------------------------------------------------------------*/
7864int hdd_stop (struct net_device *dev)
7865{
7866 int ret;
7867
7868 vos_ssr_protect(__func__);
7869 ret = __hdd_stop(dev);
7870 vos_ssr_unprotect(__func__);
7871
7872 return ret;
7873}
7874
7875/**---------------------------------------------------------------------------
7876
7877 \brief __hdd_uninit() - HDD uninit function
Jeff Johnson295189b2012-06-20 16:38:30 -07007878
7879 \param - dev Pointer to net_device structure
7880
7881 \return - void
7882
7883 --------------------------------------------------------------------------*/
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307884static void __hdd_uninit (struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07007885{
7886 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05307887 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07007888 ENTER();
7889
7890 do
7891 {
7892 if (NULL == pAdapter)
7893 {
7894 hddLog(VOS_TRACE_LEVEL_FATAL,
7895 "%s: NULL pAdapter", __func__);
7896 break;
7897 }
7898
7899 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
7900 {
7901 hddLog(VOS_TRACE_LEVEL_FATAL,
7902 "%s: Invalid magic", __func__);
7903 break;
7904 }
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05307905 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7906 if (NULL == pHddCtx)
Jeff Johnson295189b2012-06-20 16:38:30 -07007907 {
7908 hddLog(VOS_TRACE_LEVEL_FATAL,
7909 "%s: NULL pHddCtx", __func__);
7910 break;
7911 }
7912
7913 if (dev != pAdapter->dev)
7914 {
7915 hddLog(VOS_TRACE_LEVEL_FATAL,
7916 "%s: Invalid device reference", __func__);
7917 /* we haven't validated all cases so let this go for now */
7918 }
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05307919#ifdef FEATURE_WLAN_TDLS
7920 mutex_lock(&pHddCtx->tdls_lock);
7921#endif
c_hpothu002231a2015-02-05 14:58:51 +05307922 hdd_deinit_adapter(pHddCtx, pAdapter, TRUE);
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05307923#ifdef FEATURE_WLAN_TDLS
7924 mutex_unlock(&pHddCtx->tdls_lock);
7925#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007926
7927 /* after uninit our adapter structure will no longer be valid */
7928 pAdapter->dev = NULL;
7929 pAdapter->magic = 0;
Manjeet Singh47ee8472016-04-11 11:57:18 +05307930 pAdapter->pHddCtx = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007931 } while (0);
7932
7933 EXIT();
7934}
7935
7936/**---------------------------------------------------------------------------
7937
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307938 \brief hdd_uninit() - Wrapper function to protect __hdd_uninit from SSR
7939
7940 This is called during the netdev unregister to uninitialize all data
7941associated with the device
7942
7943 \param - dev Pointer to net_device structure
7944
7945 \return - void
7946
7947 --------------------------------------------------------------------------*/
7948static void hdd_uninit (struct net_device *dev)
7949{
7950 vos_ssr_protect(__func__);
7951 __hdd_uninit(dev);
7952 vos_ssr_unprotect(__func__);
7953}
7954
7955/**---------------------------------------------------------------------------
7956
Jeff Johnson295189b2012-06-20 16:38:30 -07007957 \brief hdd_release_firmware() -
7958
7959 This function calls the release firmware API to free the firmware buffer.
7960
7961 \param - pFileName Pointer to the File Name.
7962 pCtx - Pointer to the adapter .
7963
7964
7965 \return - 0 for success, non zero for failure
7966
7967 --------------------------------------------------------------------------*/
7968
7969VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
7970{
7971 VOS_STATUS status = VOS_STATUS_SUCCESS;
7972 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
7973 ENTER();
7974
7975
7976 if (!strcmp(WLAN_FW_FILE, pFileName)) {
7977
7978 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
7979
7980 if(pHddCtx->fw) {
7981 release_firmware(pHddCtx->fw);
7982 pHddCtx->fw = NULL;
7983 }
7984 else
7985 status = VOS_STATUS_E_FAILURE;
7986 }
7987 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
7988 if(pHddCtx->nv) {
7989 release_firmware(pHddCtx->nv);
7990 pHddCtx->nv = NULL;
7991 }
7992 else
7993 status = VOS_STATUS_E_FAILURE;
7994
7995 }
7996
7997 EXIT();
7998 return status;
7999}
8000
8001/**---------------------------------------------------------------------------
8002
8003 \brief hdd_request_firmware() -
8004
8005 This function reads the firmware file using the request firmware
8006 API and returns the the firmware data and the firmware file size.
8007
8008 \param - pfileName - Pointer to the file name.
8009 - pCtx - Pointer to the adapter .
8010 - ppfw_data - Pointer to the pointer of the firmware data.
8011 - pSize - Pointer to the file size.
8012
8013 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
8014
8015 --------------------------------------------------------------------------*/
8016
8017
8018VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
8019{
8020 int status;
8021 VOS_STATUS retval = VOS_STATUS_SUCCESS;
8022 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
8023 ENTER();
8024
8025 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
8026
8027 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
8028
8029 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
8030 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
8031 __func__, pfileName);
8032 retval = VOS_STATUS_E_FAILURE;
8033 }
8034
8035 else {
8036 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
8037 *pSize = pHddCtx->fw->size;
8038 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
8039 __func__, *pSize);
8040 }
8041 }
8042 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
8043
8044 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
8045
8046 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
8047 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
8048 __func__, pfileName);
8049 retval = VOS_STATUS_E_FAILURE;
8050 }
8051
8052 else {
8053 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
8054 *pSize = pHddCtx->nv->size;
8055 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
8056 __func__, *pSize);
8057 }
8058 }
8059
8060 EXIT();
8061 return retval;
8062}
8063/**---------------------------------------------------------------------------
8064 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
8065
8066 This is the function invoked by SME to inform the result of a full power
8067 request issued by HDD
8068
8069 \param - callbackcontext - Pointer to cookie
8070 status - result of request
8071
8072 \return - None
8073
8074--------------------------------------------------------------------------*/
8075void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
8076{
8077 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
8078
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07008079 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07008080 if(&pHddCtx->full_pwr_comp_var)
8081 {
8082 complete(&pHddCtx->full_pwr_comp_var);
8083 }
8084}
8085
Abhishek Singh00b71972016-01-07 10:51:04 +05308086#ifdef WLAN_FEATURE_RMC
8087static void hdd_tx_fail_ind_callback(v_U8_t *MacAddr, v_U8_t seqNo)
8088{
8089 int payload_len;
8090 struct sk_buff *skb;
8091 struct nlmsghdr *nlh;
8092 v_U8_t *data;
8093
8094 payload_len = ETH_ALEN;
8095
8096 if (0 == cesium_pid)
8097 {
8098 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: cesium process not registered",
8099 __func__);
8100 return;
8101 }
8102
8103 if ((skb = nlmsg_new(payload_len,GFP_ATOMIC)) == NULL)
8104 {
8105 hddLog(VOS_TRACE_LEVEL_ERROR,
8106 "%s: nlmsg_new() failed for msg size[%d]",
8107 __func__, NLMSG_SPACE(payload_len));
8108 return;
8109 }
8110
8111 nlh = nlmsg_put(skb, cesium_pid, seqNo, 0, payload_len, NLM_F_REQUEST);
8112
8113 if (NULL == nlh)
8114 {
8115 hddLog(VOS_TRACE_LEVEL_ERROR,
8116 "%s: nlmsg_put() failed for msg size[%d]",
8117 __func__, NLMSG_SPACE(payload_len));
8118
8119 kfree_skb(skb);
8120 return;
8121 }
8122
8123 data = nlmsg_data(nlh);
8124 memcpy(data, MacAddr, ETH_ALEN);
8125
8126 if (nlmsg_unicast(cesium_nl_srv_sock, skb, cesium_pid) < 0)
8127 {
8128 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: nlmsg_unicast() failed for msg size[%d]",
8129 __func__, NLMSG_SPACE(payload_len));
8130 }
8131
8132 return;
8133}
8134
8135/**---------------------------------------------------------------------------
8136 \brief hdd_ParseuserParams - return a pointer to the next argument
8137
8138 \return - status
8139
8140--------------------------------------------------------------------------*/
8141static int hdd_ParseUserParams(tANI_U8 *pValue, tANI_U8 **ppArg)
8142{
8143 tANI_U8 *pVal;
8144
8145 pVal = strchr(pValue, ' ');
8146
8147 if (NULL == pVal)
8148 {
8149 /* no argument remains */
8150 return -EINVAL;
8151 }
8152 else if (SPACE_ASCII_VALUE != *pVal)
8153 {
8154 /* no space after the current argument */
8155 return -EINVAL;
8156 }
8157
8158 pVal++;
8159
8160 /* remove empty spaces */
8161 while ((SPACE_ASCII_VALUE == *pVal) && ('\0' != *pVal))
8162 {
8163 pVal++;
8164 }
8165
8166 /* no argument followed by spaces */
8167 if ('\0' == *pVal)
8168 {
8169 return -EINVAL;
8170 }
8171
8172 *ppArg = pVal;
8173
8174 return 0;
8175}
8176
8177/**----------------------------------------------------------------------------
8178 \brief hdd_ParseIBSSTXFailEventParams - Parse params for SETIBSSTXFAILEVENT
8179
8180 \return - status
8181
8182------------------------------------------------------------------------------*/
8183static int hdd_ParseIBSSTXFailEventParams(tANI_U8 *pValue,
8184 tANI_U8 *tx_fail_count,
8185 tANI_U16 *pid)
8186{
8187 tANI_U8 *param = NULL;
8188 int ret;
8189
8190 ret = hdd_ParseUserParams(pValue, &param);
8191
8192 if (0 == ret && NULL != param)
8193 {
8194 if (1 != sscanf(param, "%hhu", tx_fail_count))
8195 {
8196 ret = -EINVAL;
8197 goto done;
8198 }
8199 }
8200 else
8201 {
8202 goto done;
8203 }
8204
8205 if (0 == *tx_fail_count)
8206 {
8207 *pid = 0;
8208 goto done;
8209 }
8210
8211 pValue = param;
8212 pValue++;
8213
8214 ret = hdd_ParseUserParams(pValue, &param);
8215
8216 if (0 == ret)
8217 {
8218 if (1 != sscanf(param, "%hu", pid))
8219 {
8220 ret = -EINVAL;
8221 goto done;
8222 }
8223 }
8224 else
8225 {
8226 goto done;
8227 }
8228
8229done:
8230 return ret;
8231}
8232
8233static int hdd_open_cesium_nl_sock()
8234{
8235#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
8236 struct netlink_kernel_cfg cfg = {
8237 .groups = WLAN_NLINK_MCAST_GRP_ID,
8238 .input = NULL
8239 };
8240#endif
8241 int ret = 0;
8242
8243#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
8244 cesium_nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_CESIUM,
8245#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0))
8246 THIS_MODULE,
8247#endif
8248 &cfg);
8249#else
8250 cesium_nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_CESIUM,
8251 WLAN_NLINK_MCAST_GRP_ID, NULL, NULL, THIS_MODULE);
8252#endif
8253
8254 if (cesium_nl_srv_sock == NULL)
8255 {
8256 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8257 "NLINK: cesium netlink_kernel_create failed");
8258 ret = -ECONNREFUSED;
8259 }
8260
8261 return ret;
8262}
8263
8264static void hdd_close_cesium_nl_sock()
8265{
8266 if (NULL != cesium_nl_srv_sock)
8267 {
8268 netlink_kernel_release(cesium_nl_srv_sock);
8269 cesium_nl_srv_sock = NULL;
8270 }
8271}
8272#endif /* WLAN_FEATURE_RMC */
Jeff Johnson295189b2012-06-20 16:38:30 -07008273/**---------------------------------------------------------------------------
8274
8275 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
8276
8277 This is the function invoked by SME to inform the result of BMPS
8278 request issued by HDD
8279
8280 \param - callbackcontext - Pointer to cookie
8281 status - result of request
8282
8283 \return - None
8284
8285--------------------------------------------------------------------------*/
8286void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
8287{
8288
8289 struct completion *completion_var = (struct completion*) callbackContext;
8290
Arif Hussain6d2a3322013-11-17 19:50:10 -08008291 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07008292 if(completion_var != NULL)
8293 {
8294 complete(completion_var);
8295 }
8296}
8297
8298/**---------------------------------------------------------------------------
8299
8300 \brief hdd_get_cfg_file_size() -
8301
8302 This function reads the configuration file using the request firmware
8303 API and returns the configuration file size.
8304
8305 \param - pCtx - Pointer to the adapter .
8306 - pFileName - Pointer to the file name.
8307 - pBufSize - Pointer to the buffer size.
8308
8309 \return - 0 for success, non zero for failure
8310
8311 --------------------------------------------------------------------------*/
8312
8313VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
8314{
8315 int status;
8316 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
8317
8318 ENTER();
8319
8320 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
8321
8322 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
8323 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
8324 status = VOS_STATUS_E_FAILURE;
8325 }
8326 else {
8327 *pBufSize = pHddCtx->fw->size;
8328 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
8329 release_firmware(pHddCtx->fw);
8330 pHddCtx->fw = NULL;
8331 }
8332
8333 EXIT();
8334 return VOS_STATUS_SUCCESS;
8335}
8336
8337/**---------------------------------------------------------------------------
8338
8339 \brief hdd_read_cfg_file() -
8340
8341 This function reads the configuration file using the request firmware
8342 API and returns the cfg data and the buffer size of the configuration file.
8343
8344 \param - pCtx - Pointer to the adapter .
8345 - pFileName - Pointer to the file name.
8346 - pBuffer - Pointer to the data buffer.
8347 - pBufSize - Pointer to the buffer size.
8348
8349 \return - 0 for success, non zero for failure
8350
8351 --------------------------------------------------------------------------*/
8352
8353VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
8354 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
8355{
8356 int status;
8357 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
8358
8359 ENTER();
8360
8361 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
8362
8363 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
8364 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
8365 return VOS_STATUS_E_FAILURE;
8366 }
8367 else {
8368 if(*pBufSize != pHddCtx->fw->size) {
8369 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
8370 "file size", __func__);
8371 release_firmware(pHddCtx->fw);
8372 pHddCtx->fw = NULL;
8373 return VOS_STATUS_E_FAILURE;
8374 }
8375 else {
8376 if(pBuffer) {
8377 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
8378 }
8379 release_firmware(pHddCtx->fw);
8380 pHddCtx->fw = NULL;
8381 }
8382 }
8383
8384 EXIT();
8385
8386 return VOS_STATUS_SUCCESS;
8387}
8388
8389/**---------------------------------------------------------------------------
8390
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05308391 \brief __hdd_set_mac_address() -
Jeff Johnson295189b2012-06-20 16:38:30 -07008392
8393 This function sets the user specified mac address using
8394 the command ifconfig wlanX hw ether <mac adress>.
8395
8396 \param - dev - Pointer to the net device.
8397 - addr - Pointer to the sockaddr.
8398 \return - 0 for success, non zero for failure
8399
8400 --------------------------------------------------------------------------*/
8401
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05308402static int __hdd_set_mac_address(struct net_device *dev, void *addr)
Jeff Johnson295189b2012-06-20 16:38:30 -07008403{
Mahesh A Saptasagar74088392015-02-05 17:22:09 +05308404 hdd_adapter_t *pAdapter;
8405 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07008406 struct sockaddr *psta_mac_addr = addr;
8407 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
Mahesh A Saptasagar74088392015-02-05 17:22:09 +05308408 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07008409
8410 ENTER();
Mahesh A Saptasagar74088392015-02-05 17:22:09 +05308411 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
8412 if (NULL == pAdapter)
8413 {
8414 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8415 "%s: Adapter is NULL",__func__);
8416 return -EINVAL;
8417 }
8418 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
8419 ret = wlan_hdd_validate_context(pHddCtx);
8420 if (0 != ret)
8421 {
Mahesh A Saptasagar74088392015-02-05 17:22:09 +05308422 return ret;
8423 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008424
8425 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
Jeff Johnson295189b2012-06-20 16:38:30 -07008426 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
8427
8428 EXIT();
8429 return halStatus;
8430}
8431
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05308432/**---------------------------------------------------------------------------
8433
8434 \brief hdd_set_mac_address() -
8435
8436 Wrapper function to protect __hdd_set_mac_address() function from ssr
8437
8438 \param - dev - Pointer to the net device.
8439 - addr - Pointer to the sockaddr.
8440 \return - 0 for success, non zero for failure
8441
8442 --------------------------------------------------------------------------*/
8443static int hdd_set_mac_address(struct net_device *dev, void *addr)
8444{
8445 int ret;
8446
8447 vos_ssr_protect(__func__);
8448 ret = __hdd_set_mac_address(dev, addr);
8449 vos_ssr_unprotect(__func__);
8450
8451 return ret;
8452}
8453
Jeff Johnson295189b2012-06-20 16:38:30 -07008454tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
8455{
8456 int i;
8457 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
8458 {
Abhishek Singheb183782014-02-06 13:37:21 +05308459 if( 0 == ((pHddCtx->cfg_ini->intfAddrMask) & (1 << i)) )
Jeff Johnson295189b2012-06-20 16:38:30 -07008460 break;
8461 }
8462
8463 if( VOS_MAX_CONCURRENCY_PERSONA == i)
8464 return NULL;
8465
8466 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
8467 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
8468}
8469
8470void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
8471{
8472 int i;
8473 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
8474 {
8475 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
8476 {
8477 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
8478 break;
8479 }
8480 }
8481 return;
8482}
8483
8484#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
8485 static struct net_device_ops wlan_drv_ops = {
8486 .ndo_open = hdd_open,
8487 .ndo_stop = hdd_stop,
8488 .ndo_uninit = hdd_uninit,
8489 .ndo_start_xmit = hdd_hard_start_xmit,
8490 .ndo_tx_timeout = hdd_tx_timeout,
8491 .ndo_get_stats = hdd_stats,
8492 .ndo_do_ioctl = hdd_ioctl,
8493 .ndo_set_mac_address = hdd_set_mac_address,
8494 .ndo_select_queue = hdd_select_queue,
8495#ifdef WLAN_FEATURE_PACKET_FILTERING
8496#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
8497 .ndo_set_rx_mode = hdd_set_multicast_list,
8498#else
8499 .ndo_set_multicast_list = hdd_set_multicast_list,
8500#endif //LINUX_VERSION_CODE
8501#endif
8502 };
Jeff Johnson295189b2012-06-20 16:38:30 -07008503 static struct net_device_ops wlan_mon_drv_ops = {
8504 .ndo_open = hdd_mon_open,
Katya Nigame7b69a82015-04-28 15:24:06 +05308505 .ndo_stop = hdd_mon_stop,
Jeff Johnson295189b2012-06-20 16:38:30 -07008506 .ndo_uninit = hdd_uninit,
8507 .ndo_start_xmit = hdd_mon_hard_start_xmit,
8508 .ndo_tx_timeout = hdd_tx_timeout,
8509 .ndo_get_stats = hdd_stats,
Katya Nigame7b69a82015-04-28 15:24:06 +05308510 .ndo_do_ioctl = hdd_mon_ioctl,
Jeff Johnson295189b2012-06-20 16:38:30 -07008511 .ndo_set_mac_address = hdd_set_mac_address,
8512 };
Mahesh A Saptasagar305e2632015-03-04 12:57:33 +05308513
Jeff Johnson295189b2012-06-20 16:38:30 -07008514#endif
8515
8516void hdd_set_station_ops( struct net_device *pWlanDev )
8517{
8518#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
Jeff Johnson295189b2012-06-20 16:38:30 -07008519 pWlanDev->netdev_ops = &wlan_drv_ops;
8520#else
8521 pWlanDev->open = hdd_open;
8522 pWlanDev->stop = hdd_stop;
8523 pWlanDev->uninit = hdd_uninit;
8524 pWlanDev->hard_start_xmit = NULL;
8525 pWlanDev->tx_timeout = hdd_tx_timeout;
8526 pWlanDev->get_stats = hdd_stats;
8527 pWlanDev->do_ioctl = hdd_ioctl;
Jeff Johnson295189b2012-06-20 16:38:30 -07008528 pWlanDev->set_mac_address = hdd_set_mac_address;
8529#endif
8530}
8531
Katya Nigam1fd24402015-02-16 14:52:19 +05308532void hdd_set_ibss_ops( hdd_adapter_t *pAdapter )
8533{
8534 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
8535 wlan_drv_ops.ndo_start_xmit = hdd_ibss_hard_start_xmit;
8536 #else
8537 pAdapter->dev->hard_start_xmit = hdd_ibss_hard_start_xmit;
8538 #endif
8539}
8540
Jeff Johnsoneed415b2013-01-18 16:11:20 -08008541static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07008542{
8543 struct net_device *pWlanDev = NULL;
8544 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07008545 /*
8546 * cfg80211 initialization and registration....
8547 */
Anand N Sunkadc34abbd2015-07-29 09:52:59 +05308548 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name,
8549#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0))
8550 NET_NAME_UNKNOWN,
8551#endif
8552 ether_setup, NUM_TX_QUEUES);
Jeff Johnson295189b2012-06-20 16:38:30 -07008553 if(pWlanDev != NULL)
8554 {
8555
8556 //Save the pointer to the net_device in the HDD adapter
8557 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
8558
Jeff Johnson295189b2012-06-20 16:38:30 -07008559 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
8560
8561 pAdapter->dev = pWlanDev;
8562 pAdapter->pHddCtx = pHddCtx;
8563 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
Agarwal Ashish47d18112014-08-04 19:55:07 +05308564 spin_lock_init(&pAdapter->lock_for_active_session);
Jeff Johnson295189b2012-06-20 16:38:30 -07008565
Rajeev79dbe4c2013-10-05 11:03:42 +05308566#ifdef FEATURE_WLAN_BATCH_SCAN
Rajeev79dbe4c2013-10-05 11:03:42 +05308567 pAdapter->pBatchScanRsp = NULL;
8568 pAdapter->numScanList = 0;
Rajeev Kumar20140c12013-10-21 19:39:02 -07008569 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
Kiet Lamaa8e15a2014-02-11 23:30:06 -08008570 pAdapter->prev_batch_id = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05308571 mutex_init(&pAdapter->hdd_batch_scan_lock);
8572#endif
8573
Jeff Johnson295189b2012-06-20 16:38:30 -07008574 pAdapter->isLinkUpSvcNeeded = FALSE;
8575 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
8576 //Init the net_device structure
8577 strlcpy(pWlanDev->name, name, IFNAMSIZ);
8578
8579 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
8580 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
8581 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
8582 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
8583
8584 hdd_set_station_ops( pAdapter->dev );
8585
8586 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07008587 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
8588 pAdapter->wdev.wiphy = pHddCtx->wiphy;
8589 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07008590 /* set pWlanDev's parent to underlying device */
8591 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
Kumar Anand82c009f2014-05-29 00:29:42 -07008592
8593 hdd_wmm_init( pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07008594 }
8595
8596 return pAdapter;
8597}
8598
8599VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
8600{
8601 struct net_device *pWlanDev = pAdapter->dev;
8602 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
8603 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
8604 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
8605
8606 if( rtnl_lock_held )
8607 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08008608 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07008609 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
8610 {
8611 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
8612 return VOS_STATUS_E_FAILURE;
8613 }
8614 }
8615 if (register_netdevice(pWlanDev))
8616 {
8617 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
8618 return VOS_STATUS_E_FAILURE;
8619 }
8620 }
8621 else
8622 {
8623 if(register_netdev(pWlanDev))
8624 {
8625 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
8626 return VOS_STATUS_E_FAILURE;
8627 }
8628 }
8629 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
8630
8631 return VOS_STATUS_SUCCESS;
8632}
8633
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008634static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07008635{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008636 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07008637
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008638 if (NULL == pAdapter)
8639 {
8640 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
8641 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07008642 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008643
8644 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
8645 {
8646 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
8647 return eHAL_STATUS_NOT_INITIALIZED;
8648 }
8649
8650 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
8651
Sameer Thalappilbee426e2013-10-30 10:30:30 -07008652#ifndef WLAN_OPEN_SOURCE
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008653 /* need to make sure all of our scheduled work has completed.
8654 * This callback is called from MC thread context, so it is safe to
8655 * to call below flush workqueue API from here.
Sameer Thalappilbee426e2013-10-30 10:30:30 -07008656 *
8657 * Even though this is called from MC thread context, if there is a faulty
8658 * work item in the system, that can hang this call forever. So flushing
8659 * this global work queue is not safe; and now we make sure that
8660 * individual work queues are stopped correctly. But the cancel work queue
8661 * is a GPL only API, so the proprietary version of the driver would still
8662 * rely on the global work queue flush.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008663 */
8664 flush_scheduled_work();
Sameer Thalappilbee426e2013-10-30 10:30:30 -07008665#endif
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008666
8667 /* We can be blocked while waiting for scheduled work to be
8668 * flushed, and the adapter structure can potentially be freed, in
8669 * which case the magic will have been reset. So make sure the
8670 * magic is still good, and hence the adapter structure is still
8671 * valid, before signaling completion */
8672 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
8673 {
8674 complete(&pAdapter->session_close_comp_var);
8675 }
8676
Jeff Johnson295189b2012-06-20 16:38:30 -07008677 return eHAL_STATUS_SUCCESS;
8678}
Manjeet Singh47ee8472016-04-11 11:57:18 +05308679/**
8680 * hdd_close_tx_queues() - close tx queues
8681 * @hdd_ctx: hdd global context
8682 *
8683 * Return: None
8684 */
8685static void hdd_close_tx_queues(hdd_context_t *hdd_ctx)
8686{
8687 VOS_STATUS status;
8688 hdd_adapter_t *adapter;
8689 hdd_adapter_list_node_t *adapter_node = NULL, *next_adapter = NULL;
8690 /* Not validating hdd_ctx as it's already done by the caller */
8691 ENTER();
8692 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
8693 while (NULL != adapter_node && VOS_STATUS_SUCCESS == status) {
8694 adapter = adapter_node->pAdapter;
8695 if (adapter && adapter->dev) {
8696 netif_tx_disable (adapter->dev);
8697 netif_carrier_off(adapter->dev);
8698 }
8699 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
8700 &next_adapter);
8701 adapter_node = next_adapter;
8702 }
8703 EXIT();
8704}
Jeff Johnson295189b2012-06-20 16:38:30 -07008705
8706VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
8707{
8708 struct net_device *pWlanDev = pAdapter->dev;
8709 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
8710 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
8711 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
8712 VOS_STATUS status = VOS_STATUS_E_FAILURE;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308713 long rc = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07008714
Nirav Shah7e3c8132015-06-22 23:51:42 +05308715 spin_lock_init( &pAdapter->sta_hash_lock);
8716 pAdapter->is_sta_id_hash_initialized = VOS_FALSE;
8717
Jeff Johnson295189b2012-06-20 16:38:30 -07008718 INIT_COMPLETION(pAdapter->session_open_comp_var);
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07008719 sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07008720 //Open a SME session for future operation
8721 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07008722 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07008723 if ( !HAL_STATUS_SUCCESS( halStatus ) )
8724 {
8725 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07008726 "sme_OpenSession() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07008727 halStatus, halStatus );
8728 status = VOS_STATUS_E_FAILURE;
8729 goto error_sme_open;
8730 }
8731
8732 //Block on a completion variable. Can't wait forever though.
Vinay Krishna Eranna0fe2e7c2014-04-09 21:32:08 +05308733 rc = wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07008734 &pAdapter->session_open_comp_var,
8735 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308736 if (rc <= 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07008737 {
8738 hddLog(VOS_TRACE_LEVEL_FATAL,
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308739 "Session is not opened within timeout period code %ld", rc );
Jeff Johnson295189b2012-06-20 16:38:30 -07008740 status = VOS_STATUS_E_FAILURE;
8741 goto error_sme_open;
8742 }
8743
8744 // Register wireless extensions
8745 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
8746 {
8747 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07008748 "hdd_register_wext() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07008749 halStatus, halStatus );
8750 status = VOS_STATUS_E_FAILURE;
8751 goto error_register_wext;
8752 }
Katya Nigam1fd24402015-02-16 14:52:19 +05308753
Jeff Johnson295189b2012-06-20 16:38:30 -07008754 //Safe to register the hard_start_xmit function again
Katya Nigam1fd24402015-02-16 14:52:19 +05308755 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
8756 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
8757 #else
8758 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
8759 #endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008760
8761 //Set the Connection State to Not Connected
Abhishek Singhf4669da2014-05-26 15:07:49 +05308762 hddLog(VOS_TRACE_LEVEL_INFO,
8763 "%s: Set HDD connState to eConnectionState_NotConnected",
8764 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008765 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
8766
8767 //Set the default operation channel
8768 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
8769
8770 /* Make the default Auth Type as OPEN*/
8771 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
8772
8773 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
8774 {
8775 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07008776 "hdd_init_tx_rx() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07008777 status, status );
8778 goto error_init_txrx;
8779 }
8780
8781 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
8782
8783 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
8784 {
8785 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07008786 "hdd_wmm_adapter_init() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07008787 status, status );
8788 goto error_wmm_init;
8789 }
8790
8791 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
8792
8793 return VOS_STATUS_SUCCESS;
8794
8795error_wmm_init:
8796 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
8797 hdd_deinit_tx_rx(pAdapter);
8798error_init_txrx:
8799 hdd_UnregisterWext(pWlanDev);
8800error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008801 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07008802 {
8803 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008804 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Agrawal Ashish5a3522c2016-03-02 15:08:28 +05308805 pAdapter->sessionId, FALSE, VOS_TRUE,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008806 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07008807 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308808 unsigned long rc;
8809
Jeff Johnson295189b2012-06-20 16:38:30 -07008810 //Block on a completion variable. Can't wait forever though.
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308811 rc = wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07008812 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008813 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308814 if (rc <= 0)
8815 hddLog(VOS_TRACE_LEVEL_ERROR,
8816 FL("Session is not opened within timeout period code %ld"), rc);
Jeff Johnson295189b2012-06-20 16:38:30 -07008817 }
8818}
8819error_sme_open:
8820 return status;
8821}
8822
Jeff Johnson295189b2012-06-20 16:38:30 -07008823void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
8824{
8825 hdd_cfg80211_state_t *cfgState;
8826
8827 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
8828
8829 if( NULL != cfgState->buf )
8830 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308831 long rc;
Jeff Johnson295189b2012-06-20 16:38:30 -07008832 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
8833 rc = wait_for_completion_interruptible_timeout(
8834 &pAdapter->tx_action_cnf_event,
8835 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308836 if (rc <= 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07008837 {
Deepthi Gowri91b3e9c2015-08-25 13:14:58 +05308838 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8839 "%s ERROR: HDD Wait for Action Confirmation Failed!! %ld"
8840 , __func__, rc);
8841
8842 // Inform tx status as FAILURE to upper layer and free cfgState->buf
8843 hdd_sendActionCnf( pAdapter, FALSE );
Jeff Johnson295189b2012-06-20 16:38:30 -07008844 }
8845 }
8846 return;
8847}
Jeff Johnson295189b2012-06-20 16:38:30 -07008848
c_hpothu002231a2015-02-05 14:58:51 +05308849void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
Jeff Johnson295189b2012-06-20 16:38:30 -07008850{
8851 ENTER();
8852 switch ( pAdapter->device_mode )
8853 {
Katya Nigam1fd24402015-02-16 14:52:19 +05308854 case WLAN_HDD_IBSS:
8855 {
8856 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
8857 {
8858 hdd_ibss_deinit_tx_rx( pAdapter );
8859 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
8860 }
8861 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008862 case WLAN_HDD_INFRA_STATION:
8863 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07008864 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07008865 {
8866 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
8867 {
8868 hdd_deinit_tx_rx( pAdapter );
8869 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
8870 }
8871
8872 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
8873 {
8874 hdd_wmm_adapter_close( pAdapter );
8875 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
8876 }
8877
Jeff Johnson295189b2012-06-20 16:38:30 -07008878 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07008879 break;
8880 }
8881
8882 case WLAN_HDD_SOFTAP:
8883 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07008884 {
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05308885
8886 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
8887 {
8888 hdd_wmm_adapter_close( pAdapter );
8889 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
8890 }
8891
Jeff Johnson295189b2012-06-20 16:38:30 -07008892 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07008893
c_hpothu002231a2015-02-05 14:58:51 +05308894 hdd_unregister_hostapd(pAdapter, rtnl_held);
Agrawal Ashisha0584d42016-09-29 13:03:45 +05308895 /* set con_mode to STA only when no SAP concurrency mode */
8896 if (!(hdd_get_concurrency_mode() & (VOS_SAP | VOS_P2P_GO)))
8897 hdd_set_conparam(0);
Jeff Johnson295189b2012-06-20 16:38:30 -07008898 break;
8899 }
8900
8901 case WLAN_HDD_MONITOR:
8902 {
Jeff Johnson295189b2012-06-20 16:38:30 -07008903 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
8904 {
8905 hdd_deinit_tx_rx( pAdapter );
8906 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
8907 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008908 break;
8909 }
8910
8911
8912 default:
8913 break;
8914 }
8915
8916 EXIT();
8917}
8918
8919void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
8920{
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -08008921 struct net_device *pWlanDev = NULL;
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05308922
8923 ENTER();
8924 if (NULL == pAdapter)
8925 {
8926 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8927 "%s: HDD adapter is Null", __func__);
8928 return;
8929 }
8930
8931 pWlanDev = pAdapter->dev;
Jeff Johnson295189b2012-06-20 16:38:30 -07008932
Rajeev79dbe4c2013-10-05 11:03:42 +05308933#ifdef FEATURE_WLAN_BATCH_SCAN
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05308934 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
8935 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Rajeev Kumarf999e582014-01-09 17:33:29 -08008936 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05308937 || (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)
8938 )
8939 {
Rajeev Kumarf999e582014-01-09 17:33:29 -08008940 if (pAdapter)
Rajeev79dbe4c2013-10-05 11:03:42 +05308941 {
Rajeev Kumarf999e582014-01-09 17:33:29 -08008942 if (eHDD_BATCH_SCAN_STATE_STARTED == pAdapter->batchScanState)
8943 {
8944 hdd_deinit_batch_scan(pAdapter);
8945 }
Rajeev79dbe4c2013-10-05 11:03:42 +05308946 }
Rajeev Kumarf999e582014-01-09 17:33:29 -08008947 }
Rajeev79dbe4c2013-10-05 11:03:42 +05308948#endif
8949
Jeff Johnson295189b2012-06-20 16:38:30 -07008950 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
8951 if( rtnl_held )
8952 {
8953 unregister_netdevice(pWlanDev);
8954 }
8955 else
8956 {
8957 unregister_netdev(pWlanDev);
8958 }
8959 // note that the pAdapter is no longer valid at this point
8960 // since the memory has been reclaimed
8961 }
8962
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05308963 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07008964}
8965
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008966void hdd_set_pwrparams(hdd_context_t *pHddCtx)
8967{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308968 VOS_STATUS status;
8969 hdd_adapter_t *pAdapter = NULL;
8970 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008971
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308972 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008973
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308974 /*loop through all adapters.*/
8975 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008976 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308977 pAdapter = pAdapterNode->pAdapter;
8978 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
8979 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008980
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308981 { // we skip this registration for modes other than STA and P2P client modes.
8982 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
8983 pAdapterNode = pNext;
8984 continue;
8985 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008986
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308987 //Apply Dynamic DTIM For P2P
8988 //Only if ignoreDynamicDtimInP2pMode is not set in ini
8989 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
8990 pHddCtx->cfg_ini->enableModulatedDTIM) &&
8991 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
8992 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
8993 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
8994 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
8995 (eConnectionState_Associated ==
8996 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
8997 (pHddCtx->cfg_ini->fIsBmpsEnabled))
8998 {
8999 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08009000
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05309001 powerRequest.uIgnoreDTIM = 1;
9002 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
9003
9004 if (pHddCtx->cfg_ini->enableModulatedDTIM)
9005 {
9006 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
9007 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
9008 }
9009 else
9010 {
9011 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
9012 }
9013
9014 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
9015 * specified during Enter/Exit BMPS when LCD off*/
9016 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
9017 NULL, eANI_BOOLEAN_FALSE);
9018 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
9019 NULL, eANI_BOOLEAN_FALSE);
9020
9021 /* switch to the DTIM specified in cfg.ini */
9022 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Abhishek Singh1e390cf2015-10-27 13:45:17 +05309023 "Switch to DTIM %d Listen interval %d",
9024 powerRequest.uDTIMPeriod,
9025 powerRequest.uListenInterval);
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05309026 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
9027 break;
9028
9029 }
9030
9031 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
9032 pAdapterNode = pNext;
9033 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08009034}
9035
9036void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
9037{
9038 /*Switch back to DTIM 1*/
9039 tSirSetPowerParamsReq powerRequest = { 0 };
9040
9041 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
9042 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07009043 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08009044
9045 /* Update ignoreDTIM and ListedInterval in CFG with default values */
9046 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
9047 NULL, eANI_BOOLEAN_FALSE);
9048 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
9049 NULL, eANI_BOOLEAN_FALSE);
9050
9051 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
9052 "Switch to DTIM%d",powerRequest.uListenInterval);
9053 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
9054
9055}
9056
Jeff Johnson295189b2012-06-20 16:38:30 -07009057VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
9058{
9059 VOS_STATUS status = VOS_STATUS_SUCCESS;
Sushant Kaushik4928e542014-12-29 15:25:54 +05309060 if (WLAN_HDD_IS_UNLOAD_IN_PROGRESS(pHddCtx))
9061 {
9062 hddLog( LOGE, FL("Wlan Unload in progress"));
9063 return VOS_STATUS_E_PERM;
9064 }
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05309065
9066 if (wlan_hdd_check_monitor_state(pHddCtx)) {
9067 hddLog(LOG1, FL("Monitor mode is started, cannot enable BMPS"));
9068 return VOS_STATUS_SUCCESS;
9069 }
9070
Jeff Johnson295189b2012-06-20 16:38:30 -07009071 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
9072 {
9073 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
9074 }
9075
9076 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
9077 {
9078 sme_StartAutoBmpsTimer(pHddCtx->hHal);
9079 }
9080
9081 if (pHddCtx->cfg_ini->fIsImpsEnabled)
9082 {
9083 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
9084 }
9085
9086 return status;
9087}
9088
9089VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
9090{
9091 hdd_adapter_t *pAdapter = NULL;
9092 eHalStatus halStatus;
9093 VOS_STATUS status = VOS_STATUS_E_INVAL;
9094 v_BOOL_t disableBmps = FALSE;
9095 v_BOOL_t disableImps = FALSE;
9096
9097 switch(session_type)
9098 {
9099 case WLAN_HDD_INFRA_STATION:
9100 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07009101 case WLAN_HDD_P2P_CLIENT:
9102 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07009103 //Exit BMPS -> Is Sta/P2P Client is already connected
9104 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
9105 if((NULL != pAdapter)&&
9106 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
9107 {
9108 disableBmps = TRUE;
9109 }
9110
9111 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
9112 if((NULL != pAdapter)&&
9113 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
9114 {
9115 disableBmps = TRUE;
9116 }
9117
9118 //Exit both Bmps and Imps incase of Go/SAP Mode
9119 if((WLAN_HDD_SOFTAP == session_type) ||
9120 (WLAN_HDD_P2P_GO == session_type))
9121 {
9122 disableBmps = TRUE;
9123 disableImps = TRUE;
9124 }
9125
9126 if(TRUE == disableImps)
9127 {
9128 if (pHddCtx->cfg_ini->fIsImpsEnabled)
9129 {
9130 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
9131 }
9132 }
9133
9134 if(TRUE == disableBmps)
9135 {
9136 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
9137 {
9138 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
9139
9140 if(eHAL_STATUS_SUCCESS != halStatus)
9141 {
9142 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08009143 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009144 VOS_ASSERT(0);
9145 return status;
9146 }
9147 }
9148
9149 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
9150 {
9151 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
9152
9153 if(eHAL_STATUS_SUCCESS != halStatus)
9154 {
9155 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08009156 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009157 VOS_ASSERT(0);
9158 return status;
9159 }
9160 }
9161 }
9162
9163 if((TRUE == disableBmps) ||
9164 (TRUE == disableImps))
9165 {
9166 /* Now, get the chip into Full Power now */
9167 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
9168 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
9169 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
9170
9171 if(halStatus != eHAL_STATUS_SUCCESS)
9172 {
9173 if(halStatus == eHAL_STATUS_PMC_PENDING)
9174 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309175 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07009176 //Block on a completion variable. Can't wait forever though
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309177 ret = wait_for_completion_interruptible_timeout(
9178 &pHddCtx->full_pwr_comp_var,
9179 msecs_to_jiffies(1000));
9180 if (ret <= 0)
9181 {
9182 hddLog(VOS_TRACE_LEVEL_ERROR,
9183 "%s: wait on full_pwr_comp_var failed %ld",
9184 __func__, ret);
9185 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009186 }
9187 else
9188 {
9189 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08009190 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009191 VOS_ASSERT(0);
9192 return status;
9193 }
9194 }
9195
9196 status = VOS_STATUS_SUCCESS;
9197 }
9198
9199 break;
9200 }
9201 return status;
9202}
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +05309203
9204void hdd_monPostMsgCb(tANI_U32 *magic, struct completion *cmpVar)
9205{
9206 if (magic == NULL || cmpVar == NULL) {
9207 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnsonc135a9a2017-09-19 08:37:24 -07009208 FL("invalid arguments %pK %pK"), magic, cmpVar);
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +05309209 return;
9210 }
9211 if (*magic != MON_MODE_MSG_MAGIC) {
9212 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9213 FL("maic: %x"), *magic);
9214 return;
9215 }
9216
9217 complete(cmpVar);
9218 return;
9219}
9220
Katya Nigame7b69a82015-04-28 15:24:06 +05309221void hdd_init_mon_mode (hdd_adapter_t *pAdapter)
9222 {
9223 hdd_mon_ctx_t *pMonCtx = NULL;
Katya Nigame7b69a82015-04-28 15:24:06 +05309224
Rajeev Kumar Sirasanagandla54447612018-03-06 15:49:56 +05309225 spin_lock_init(&pAdapter->sta_hash_lock);
9226 pAdapter->is_sta_id_hash_initialized = VOS_FALSE;
9227
9228 pMonCtx = WLAN_HDD_GET_MONITOR_CTX_PTR(pAdapter);
Katya Nigame7b69a82015-04-28 15:24:06 +05309229 pMonCtx->state = 0;
9230 pMonCtx->ChannelNo = 1;
9231 pMonCtx->ChannelBW = 20;
Katya Nigamd7d3a1f2015-06-11 14:04:24 +05309232 pMonCtx->crcCheckEnabled = 1;
9233 pMonCtx->typeSubtypeBitmap = 0xFFFF00000000;
9234 pMonCtx->is80211to803ConReq = 1;
Katya Nigame7b69a82015-04-28 15:24:06 +05309235 pMonCtx->numOfMacFilters = 0;
9236 }
9237
Jeff Johnson295189b2012-06-20 16:38:30 -07009238
9239hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08009240 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07009241 tANI_U8 rtnl_held )
9242{
9243 hdd_adapter_t *pAdapter = NULL;
9244 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
9245 VOS_STATUS status = VOS_STATUS_E_FAILURE;
9246 VOS_STATUS exitbmpsStatus;
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05309247 v_CONTEXT_t pVosContext = NULL;
9248
9249 /* No need to check for NULL, reaching this step
9250 * means vos context is initialized
9251 */
9252 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07009253
Arif Hussain6d2a3322013-11-17 19:50:10 -08009254 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d",__func__,iface_name,session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07009255
Nirav Shah436658f2014-02-28 17:05:45 +05309256 if(macAddr == NULL)
9257 {
9258 /* Not received valid macAddr */
9259 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9260 "%s:Unable to add virtual intf: Not able to get"
9261 "valid mac address",__func__);
9262 return NULL;
9263 }
9264
Jeff Johnson295189b2012-06-20 16:38:30 -07009265 //Disable BMPS incase of Concurrency
9266 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
9267
9268 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
9269 {
9270 //Fail to Exit BMPS
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309271 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Exit BMPS", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009272 VOS_ASSERT(0);
9273 return NULL;
9274 }
9275
9276 switch(session_type)
9277 {
9278 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07009279 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07009280 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07009281 {
9282 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
9283
9284 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309285 {
9286 hddLog(VOS_TRACE_LEVEL_FATAL,
9287 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07009288 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309289 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009290
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05309291#ifdef FEATURE_WLAN_TDLS
9292 /* A Mutex Lock is introduced while changing/initializing the mode to
9293 * protect the concurrent access for the Adapters by TDLS module.
9294 */
Rajesh Chauhana34c6e62014-03-25 16:37:58 +05309295 mutex_lock(&pHddCtx->tdls_lock);
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05309296#endif
9297
Jeff Johnsone7245742012-09-05 17:12:55 -07009298 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
9299 NL80211_IFTYPE_P2P_CLIENT:
9300 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07009301
Jeff Johnson295189b2012-06-20 16:38:30 -07009302 pAdapter->device_mode = session_type;
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05309303#ifdef FEATURE_WLAN_TDLS
9304 mutex_unlock(&pHddCtx->tdls_lock);
9305#endif
Sunil Dutt66485cb2013-12-19 19:05:03 +05309306
Mahesh A Saptasagar67ab9222015-10-21 15:38:41 +05309307 hdd_initialize_adapter_common(pAdapter);
Sunil Dutt66485cb2013-12-19 19:05:03 +05309308 status = hdd_init_station_mode( pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07009309 if( VOS_STATUS_SUCCESS != status )
9310 goto err_free_netdev;
9311
9312 status = hdd_register_interface( pAdapter, rtnl_held );
9313 if( VOS_STATUS_SUCCESS != status )
9314 {
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05309315#ifdef FEATURE_WLAN_TDLS
9316 mutex_lock(&pHddCtx->tdls_lock);
9317#endif
c_hpothu002231a2015-02-05 14:58:51 +05309318 hdd_deinit_adapter(pHddCtx, pAdapter, rtnl_held);
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05309319#ifdef FEATURE_WLAN_TDLS
9320 mutex_unlock(&pHddCtx->tdls_lock);
9321#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009322 goto err_free_netdev;
9323 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05309324
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05309325 // Workqueue which gets scheduled in IPv4 notification callback.
Anand N Sunkaddc63c792015-06-03 14:33:24 +05309326 vos_init_work(&pAdapter->ipv4NotifierWorkQueue, hdd_ipv4_notifier_work_queue);
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05309327
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05309328#ifdef WLAN_NS_OFFLOAD
9329 // Workqueue which gets scheduled in IPv6 notification callback.
Anand N Sunkaddc63c792015-06-03 14:33:24 +05309330 vos_init_work(&pAdapter->ipv6NotifierWorkQueue, hdd_ipv6_notifier_work_queue);
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05309331#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009332 //Stop the Interface TX queue.
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05309333 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
Jeff Johnson295189b2012-06-20 16:38:30 -07009334 netif_tx_disable(pAdapter->dev);
9335 //netif_tx_disable(pWlanDev);
9336 netif_carrier_off(pAdapter->dev);
9337
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +05309338 if (WLAN_HDD_P2P_CLIENT == session_type ||
9339 WLAN_HDD_P2P_DEVICE == session_type)
9340 {
9341 /* Initialize the work queue to defer the
9342 * back to back RoC request */
Anand N Sunkaddc63c792015-06-03 14:33:24 +05309343 vos_init_delayed_work(&pAdapter->roc_work,
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +05309344 hdd_p2p_roc_work_queue);
9345 }
9346
Jeff Johnson295189b2012-06-20 16:38:30 -07009347 break;
9348 }
9349
Jeff Johnson295189b2012-06-20 16:38:30 -07009350 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07009351 case WLAN_HDD_SOFTAP:
9352 {
9353 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
9354 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309355 {
9356 hddLog(VOS_TRACE_LEVEL_FATAL,
9357 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07009358 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309359 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009360
Jeff Johnson295189b2012-06-20 16:38:30 -07009361 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
9362 NL80211_IFTYPE_AP:
9363 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07009364 pAdapter->device_mode = session_type;
9365
Mahesh A Saptasagar67ab9222015-10-21 15:38:41 +05309366 hdd_initialize_adapter_common(pAdapter);
Hanumanth Reddy Pothula15bc0fa2017-02-03 17:24:17 +05309367 status = hdd_init_ap_mode(pAdapter, false);
Jeff Johnson295189b2012-06-20 16:38:30 -07009368 if( VOS_STATUS_SUCCESS != status )
9369 goto err_free_netdev;
9370
Nirav Shah7e3c8132015-06-22 23:51:42 +05309371 status = hdd_sta_id_hash_attach(pAdapter);
9372 if (VOS_STATUS_SUCCESS != status)
9373 {
9374 hddLog(VOS_TRACE_LEVEL_FATAL,
9375 FL("failed to attach hash for session %d"), session_type);
9376 hdd_deinit_adapter(pHddCtx, pAdapter, rtnl_held);
9377 goto err_free_netdev;
9378 }
9379
Jeff Johnson295189b2012-06-20 16:38:30 -07009380 status = hdd_register_hostapd( pAdapter, rtnl_held );
9381 if( VOS_STATUS_SUCCESS != status )
9382 {
c_hpothu002231a2015-02-05 14:58:51 +05309383 hdd_deinit_adapter(pHddCtx, pAdapter, rtnl_held);
Jeff Johnson295189b2012-06-20 16:38:30 -07009384 goto err_free_netdev;
9385 }
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05309386 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
Jeff Johnson295189b2012-06-20 16:38:30 -07009387 netif_tx_disable(pAdapter->dev);
9388 netif_carrier_off(pAdapter->dev);
9389
9390 hdd_set_conparam( 1 );
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +05309391
Hanumanth Reddy Pothulab4537b82018-03-02 12:20:38 +05309392 // Workqueue which gets scheduled in IPv4 notification callback.
9393 vos_init_work(&pAdapter->ipv4NotifierWorkQueue,
9394 hdd_ipv4_notifier_work_queue);
9395
9396#ifdef WLAN_NS_OFFLOAD
9397 // Workqueue which gets scheduled in IPv6 notification callback.
9398 vos_init_work(&pAdapter->ipv6NotifierWorkQueue,
9399 hdd_ipv6_notifier_work_queue);
9400#endif
9401
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +05309402 if (WLAN_HDD_P2P_GO == session_type)
9403 {
9404 /* Initialize the work queue to
9405 * defer the back to back RoC request */
9406 INIT_DELAYED_WORK(&pAdapter->roc_work,
9407 hdd_p2p_roc_work_queue);
9408 }
Bhargav Shahd0715912015-10-01 18:17:37 +05309409
Jeff Johnson295189b2012-06-20 16:38:30 -07009410 break;
9411 }
9412 case WLAN_HDD_MONITOR:
9413 {
Jeff Johnson295189b2012-06-20 16:38:30 -07009414 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
9415 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309416 {
9417 hddLog(VOS_TRACE_LEVEL_FATAL,
9418 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07009419 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309420 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009421
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05309422 pAdapter->device_mode = session_type;
9423 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
9424
Katya Nigame7b69a82015-04-28 15:24:06 +05309425 // Register wireless extensions
9426 if( VOS_STATUS_SUCCESS != (status = hdd_register_wext(pAdapter->dev)))
9427 {
9428 hddLog(VOS_TRACE_LEVEL_FATAL,
9429 "hdd_register_wext() failed with status code %08d [x%08x]",
9430 status, status );
9431 status = VOS_STATUS_E_FAILURE;
9432 }
9433
Jeff Johnson295189b2012-06-20 16:38:30 -07009434#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
9435 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
9436#else
9437 pAdapter->dev->open = hdd_mon_open;
9438 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
Katya Nigame7b69a82015-04-28 15:24:06 +05309439 pAdapter->dev->stop = hdd_mon_stop;
9440 pAdapter->dev->do_ioctl = hdd_mon_ioctl;
Jeff Johnson295189b2012-06-20 16:38:30 -07009441#endif
Katya Nigame7b69a82015-04-28 15:24:06 +05309442 hdd_init_mon_mode( pAdapter );
Mahesh A Saptasagar67ab9222015-10-21 15:38:41 +05309443 hdd_initialize_adapter_common(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07009444 hdd_init_tx_rx( pAdapter );
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05309445
9446 if (VOS_MONITOR_MODE != hdd_get_conparam())
9447 WLANTL_SetMonRxCbk( pVosContext, hdd_rx_packet_monitor_cbk );
9448
Jeff Johnson295189b2012-06-20 16:38:30 -07009449 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05309450 status = hdd_register_interface( pAdapter, rtnl_held );
Katya Nigame7b69a82015-04-28 15:24:06 +05309451 //Stop the Interface TX queue.
9452 netif_tx_disable(pAdapter->dev);
9453 netif_carrier_off(pAdapter->dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07009454 }
9455 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07009456 case WLAN_HDD_FTM:
9457 {
9458 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
9459
9460 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309461 {
9462 hddLog(VOS_TRACE_LEVEL_FATAL,
9463 FL("failed to allocate adapter for session %d"), session_type);
9464 return NULL;
9465 }
9466
Jeff Johnson295189b2012-06-20 16:38:30 -07009467 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
9468 * message while loading driver in FTM mode. */
9469 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
9470 pAdapter->device_mode = session_type;
9471 status = hdd_register_interface( pAdapter, rtnl_held );
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05309472
Mahesh A Saptasagar67ab9222015-10-21 15:38:41 +05309473 hdd_initialize_adapter_common(pAdapter);
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05309474 hdd_init_tx_rx( pAdapter );
9475
9476 //Stop the Interface TX queue.
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05309477 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05309478 netif_tx_disable(pAdapter->dev);
9479 netif_carrier_off(pAdapter->dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07009480 }
9481 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07009482 default:
9483 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309484 hddLog(VOS_TRACE_LEVEL_FATAL,"%s Invalid session type %d",
9485 __func__, session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07009486 VOS_ASSERT(0);
9487 return NULL;
9488 }
9489 }
9490
Jeff Johnson295189b2012-06-20 16:38:30 -07009491 if( VOS_STATUS_SUCCESS == status )
9492 {
Mahesh A Saptasagar67ab9222015-10-21 15:38:41 +05309493 //Add it to the hdd's session list.
Jeff Johnson295189b2012-06-20 16:38:30 -07009494 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
9495 if( NULL == pHddAdapterNode )
9496 {
9497 status = VOS_STATUS_E_NOMEM;
9498 }
9499 else
9500 {
9501 pHddAdapterNode->pAdapter = pAdapter;
9502 status = hdd_add_adapter_back ( pHddCtx,
9503 pHddAdapterNode );
9504 }
9505 }
9506
9507 if( VOS_STATUS_SUCCESS != status )
9508 {
9509 if( NULL != pAdapter )
9510 {
9511 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
9512 pAdapter = NULL;
9513 }
9514 if( NULL != pHddAdapterNode )
9515 {
9516 vos_mem_free( pHddAdapterNode );
9517 }
9518
9519 goto resume_bmps;
9520 }
9521
9522 if(VOS_STATUS_SUCCESS == status)
9523 {
9524 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07009525 //Initialize the WoWL service
9526 if(!hdd_init_wowl(pAdapter))
9527 {
9528 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
9529 goto err_free_netdev;
9530 }
Manjeet Singh3ed79242017-01-11 19:04:32 +05309531 //Initialize the TSF capture data
9532 wlan_hdd_tsf_init(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07009533 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009534 return pAdapter;
9535
9536err_free_netdev:
9537 free_netdev(pAdapter->dev);
9538 wlan_hdd_release_intf_addr( pHddCtx,
9539 pAdapter->macAddressCurrent.bytes );
9540
9541resume_bmps:
9542 //If bmps disabled enable it
9543 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
9544 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05309545 if (pHddCtx->hdd_wlan_suspended)
9546 {
9547 hdd_set_pwrparams(pHddCtx);
9548 }
9549 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07009550 }
9551 return NULL;
9552}
9553
9554VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
9555 tANI_U8 rtnl_held )
9556{
9557 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
9558 VOS_STATUS status;
9559
9560 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
9561 if( VOS_STATUS_SUCCESS != status )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309562 {
9563 hddLog(VOS_TRACE_LEVEL_WARN,"%s: adapter list empty %d",
9564 __func__, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07009565 return status;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309566 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009567
9568 while ( pCurrent->pAdapter != pAdapter )
9569 {
9570 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
9571 if( VOS_STATUS_SUCCESS != status )
9572 break;
9573
9574 pCurrent = pNext;
9575 }
9576 pAdapterNode = pCurrent;
9577 if( VOS_STATUS_SUCCESS == status )
9578 {
9579 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
9580 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05309581
9582#ifdef FEATURE_WLAN_TDLS
9583
9584 /* A Mutex Lock is introduced while changing/initializing the mode to
9585 * protect the concurrent access for the Adapters by TDLS module.
9586 */
Rajesh Chauhana34c6e62014-03-25 16:37:58 +05309587 mutex_lock(&pHddCtx->tdls_lock);
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05309588#endif
9589
Jeff Johnson295189b2012-06-20 16:38:30 -07009590 hdd_remove_adapter( pHddCtx, pAdapterNode );
9591 vos_mem_free( pAdapterNode );
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08009592 pAdapterNode = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07009593
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05309594#ifdef FEATURE_WLAN_TDLS
9595 mutex_unlock(&pHddCtx->tdls_lock);
9596#endif
9597
Jeff Johnson295189b2012-06-20 16:38:30 -07009598
9599 /* If there is a single session of STA/P2P client, re-enable BMPS */
Agarwal Ashish51325b52014-06-16 16:50:49 +05309600 if ((!vos_concurrent_open_sessions_running()) &&
9601 ((pHddCtx->no_of_open_sessions[VOS_STA_MODE] >= 1) ||
9602 (pHddCtx->no_of_open_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
Jeff Johnson295189b2012-06-20 16:38:30 -07009603 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05309604 if (pHddCtx->hdd_wlan_suspended)
9605 {
9606 hdd_set_pwrparams(pHddCtx);
9607 }
9608 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07009609 }
9610
9611 return VOS_STATUS_SUCCESS;
9612 }
9613
9614 return VOS_STATUS_E_FAILURE;
9615}
9616
9617VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
9618{
9619 hdd_adapter_list_node_t *pHddAdapterNode;
9620 VOS_STATUS status;
9621
9622 ENTER();
9623
9624 do
9625 {
9626 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
9627 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
9628 {
9629 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
9630 vos_mem_free( pHddAdapterNode );
9631 }
9632 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
9633
9634 EXIT();
9635
9636 return VOS_STATUS_SUCCESS;
9637}
9638
9639void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
9640{
9641 v_U8_t addIE[1] = {0};
9642
9643 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
9644 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
9645 eANI_BOOLEAN_FALSE) )
9646 {
9647 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08009648 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07009649 }
9650
9651 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
9652 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
9653 eANI_BOOLEAN_FALSE) )
9654 {
9655 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08009656 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07009657 }
9658
9659 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
9660 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
9661 eANI_BOOLEAN_FALSE) )
9662 {
9663 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08009664 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07009665 }
9666}
9667
Anurag Chouhan83026002016-12-13 22:46:21 +05309668VOS_STATUS hdd_cleanup_ap_events(hdd_adapter_t *adapter)
9669{
9670#ifdef DHCP_SERVER_OFFLOAD
9671 vos_event_destroy(&adapter->dhcp_status.vos_event);
9672#endif
Anurag Chouhan0b29de02016-12-16 13:18:40 +05309673#ifdef MDNS_OFFLOAD
9674 vos_event_destroy(&adapter->mdns_status.vos_event);
9675#endif
Anurag Chouhan83026002016-12-13 22:46:21 +05309676 return VOS_STATUS_SUCCESS;
9677}
9678
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05309679int wlan_hdd_stop_mon(hdd_context_t *hdd_ctx, bool wait)
9680{
9681 hdd_mon_ctx_t *mon_ctx;
9682 long ret;
9683 v_U32_t magic;
9684 struct completion cmp_var;
9685 void (*func_ptr)(tANI_U32 *magic, struct completion *cmpVar) = NULL;
9686 hdd_adapter_t *adapter;
9687
9688 adapter = hdd_get_adapter(hdd_ctx, WLAN_HDD_MONITOR);
9689 if (!adapter) {
9690 hddLog(LOGE, FL("Invalid STA + MON mode"));
9691 return -EINVAL;
9692 }
9693
9694 mon_ctx = WLAN_HDD_GET_MONITOR_CTX_PTR(adapter);
9695 if (!mon_ctx)
9696 return 0;
9697
9698 if (mon_ctx->state != MON_MODE_START)
9699 return 0;
9700
9701 mon_ctx->state = MON_MODE_STOP;
9702 if (wait) {
9703 func_ptr = hdd_monPostMsgCb;
9704 magic = MON_MODE_MSG_MAGIC;
9705 init_completion(&cmp_var);
9706 }
9707
9708 if (VOS_STATUS_SUCCESS != wlan_hdd_mon_postMsg(&magic, &cmp_var,
9709 mon_ctx,
9710 hdd_monPostMsgCb)) {
9711 hddLog(LOGE, FL("failed to stop MON MODE"));
9712 mon_ctx->state = MON_MODE_START;
9713 magic = 0;
9714 return -EINVAL;
9715 }
9716
9717 if (!wait)
9718 goto bmps_roaming;
9719
9720 ret = wait_for_completion_timeout(&cmp_var, MON_MODE_MSG_TIMEOUT);
9721 magic = 0;
9722 if (ret <= 0 ) {
9723 hddLog(LOGE,
9724 FL("timeout on stop monitor mode completion %ld"), ret);
9725 return -EINVAL;
9726 }
9727
9728bmps_roaming:
9729 hddLog(LOG1, FL("Enable BMPS"));
9730 hdd_enable_bmps_imps(hdd_ctx);
9731 hdd_restore_roaming(hdd_ctx);
9732
9733 return 0;
9734}
9735
9736bool wlan_hdd_check_monitor_state(hdd_context_t *hdd_ctx)
9737{
9738 hdd_adapter_t *mon_adapter;
9739 hdd_mon_ctx_t *mon_ctx;
9740
9741 if (hdd_ctx->concurrency_mode != VOS_STA_MON)
9742 return false;
9743
9744 mon_adapter = hdd_get_adapter(hdd_ctx, WLAN_HDD_MONITOR);
9745 if (!mon_adapter) {
9746 hddLog(LOGE, FL("Invalid concurrency mode"));
9747 return false;
9748 }
9749
9750 mon_ctx = WLAN_HDD_GET_MONITOR_CTX_PTR(mon_adapter);
9751 if (mon_ctx->state == MON_MODE_START)
9752 return true;
9753
9754 return false;
9755}
9756
9757int wlan_hdd_check_and_stop_mon(hdd_adapter_t *sta_adapter, bool wait)
9758{
9759 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(sta_adapter);
9760
9761 if ((sta_adapter->device_mode != WLAN_HDD_INFRA_STATION) ||
9762 !wlan_hdd_check_monitor_state(hdd_ctx))
9763 return 0;
9764
9765 if (wlan_hdd_stop_mon(hdd_ctx, wait))
9766 return -EINVAL;
9767
9768 return 0;
9769}
9770
9771void hdd_disable_roaming(hdd_context_t *hdd_ctx)
9772{
9773 if (!hdd_ctx)
9774 return;
9775
9776 if (!hdd_ctx->cfg_ini->isFastRoamIniFeatureEnabled) {
9777 hdd_ctx->roaming_ini_original = CFG_LFR_FEATURE_ENABLED_MIN;
9778 return;
9779 }
9780
9781 hddLog(LOG1, FL("Disable driver and firmware roaming"));
9782
9783 hdd_ctx->roaming_ini_original =
9784 hdd_ctx->cfg_ini->isFastRoamIniFeatureEnabled;
9785
9786 hdd_ctx->cfg_ini->isFastRoamIniFeatureEnabled =
9787 CFG_LFR_FEATURE_ENABLED_MIN;
9788
9789 sme_UpdateIsFastRoamIniFeatureEnabled(hdd_ctx->hHal,
9790 CFG_LFR_FEATURE_ENABLED_MIN);
9791}
9792
9793void hdd_restore_roaming(hdd_context_t *hdd_ctx)
9794{
9795 if (!hdd_ctx->roaming_ini_original)
9796 return;
9797
9798 hddLog(LOG1, FL("Enable driver and firmware roaming"));
9799
9800 hdd_ctx->cfg_ini->isFastRoamIniFeatureEnabled =
9801 CFG_LFR_FEATURE_ENABLED_MAX;
9802
9803 hdd_ctx->roaming_ini_original = CFG_LFR_FEATURE_ENABLED_MIN;
9804
9805 sme_UpdateIsFastRoamIniFeatureEnabled(hdd_ctx->hHal,
9806 CFG_LFR_FEATURE_ENABLED_MAX);
9807}
Anurag Chouhan83026002016-12-13 22:46:21 +05309808
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05309809VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
9810 const v_BOOL_t bCloseSession )
Jeff Johnson295189b2012-06-20 16:38:30 -07009811{
9812 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
9813 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
Kaushik, Sushant4975a572014-10-21 16:07:48 +05309814 hdd_scaninfo_t *pScanInfo = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07009815 union iwreq_data wrqu;
Kaushik, Sushant7005e372014-04-08 11:36:54 +05309816 v_U8_t retry = 0;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309817 long ret;
Nirav Shah7e3c8132015-06-22 23:51:42 +05309818 VOS_STATUS status;
Jeff Johnson295189b2012-06-20 16:38:30 -07009819
Anand N Sunkad26d71b92014-12-24 18:08:22 +05309820 if (pHddCtx->isLogpInProgress) {
9821 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
9822 "%s:LOGP in Progress. Ignore!!!",__func__);
9823 return VOS_STATUS_E_FAILURE;
9824 }
9825
Jeff Johnson295189b2012-06-20 16:38:30 -07009826 ENTER();
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +05309827
Kaushik, Sushant4975a572014-10-21 16:07:48 +05309828 pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07009829 switch(pAdapter->device_mode)
9830 {
Nirav Shah0cf4d892015-11-05 16:27:27 +05309831 case WLAN_HDD_IBSS:
9832 if ( VOS_TRUE == bCloseSession )
9833 {
9834 status = hdd_sta_id_hash_detach(pAdapter);
9835 if (status != VOS_STATUS_SUCCESS)
9836 hddLog(VOS_TRACE_LEVEL_ERROR,
9837 FL("sta id hash detach failed"));
9838 }
9839
Jeff Johnson295189b2012-06-20 16:38:30 -07009840 case WLAN_HDD_INFRA_STATION:
9841 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07009842 case WLAN_HDD_P2P_DEVICE:
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05309843 {
9844 hdd_station_ctx_t *pstation = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Mahesh A Saptasagare4d05d42015-07-02 16:17:20 +05309845#ifdef FEATURE_WLAN_TDLS
9846 mutex_lock(&pHddCtx->tdls_lock);
9847 wlan_hdd_tdls_exit(pAdapter, TRUE);
9848 mutex_unlock(&pHddCtx->tdls_lock);
9849#endif
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05309850 if( hdd_connIsConnected(pstation) ||
9851 (pstation->conn_info.connState == eConnectionState_Connecting) )
Jeff Johnson295189b2012-06-20 16:38:30 -07009852 {
Abhishek Singhe21a5212017-06-09 09:42:58 +05309853 /*
9854 * Indicate sme of disconnect so that in progress connection
9855 * or preauth can be aborted.
9856 */
9857 sme_abortConnection(WLAN_HDD_GET_HAL_CTX(pAdapter),
9858 pAdapter->sessionId);
Abhishek Singh99f17b82017-02-06 16:57:56 +05309859 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07009860 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
9861 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
9862 pAdapter->sessionId,
9863 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
9864 else
9865 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
9866 pAdapter->sessionId,
9867 eCSR_DISCONNECT_REASON_UNSPECIFIED);
Abhishek Singh7b52ed52016-02-11 17:45:54 +05309868 /* Success implies disconnect command got queued up successfully
9869 * Or cmd not queued as scan for SSID is in progress
9870 */
9871 if((eHAL_STATUS_SUCCESS == halStatus) ||
9872 (eHAL_STATUS_CMD_NOT_QUEUED == halStatus))
Jeff Johnson295189b2012-06-20 16:38:30 -07009873 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309874 ret = wait_for_completion_interruptible_timeout(
9875 &pAdapter->disconnect_comp_var,
9876 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Abhishek Singh7b52ed52016-02-11 17:45:54 +05309877 if (ret <= 0 &&
9878 (eHAL_STATUS_CMD_NOT_QUEUED != halStatus))
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309879 {
9880 hddLog(VOS_TRACE_LEVEL_ERROR,
9881 "%s: wait on disconnect_comp_var failed %ld",
9882 __func__, ret);
9883 }
9884 }
9885 else
9886 {
9887 hddLog(LOGE, "%s: failed to post disconnect event to SME",
9888 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009889 }
9890 memset(&wrqu, '\0', sizeof(wrqu));
9891 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
9892 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
9893 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
9894 }
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05309895 else if(pstation->conn_info.connState ==
9896 eConnectionState_Disconnecting)
9897 {
9898 ret = wait_for_completion_interruptible_timeout(
9899 &pAdapter->disconnect_comp_var,
9900 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
9901 if (ret <= 0)
9902 {
9903 hddLog(VOS_TRACE_LEVEL_ERROR,
9904 FL("wait on disconnect_comp_var failed %ld"), ret);
9905 }
9906 }
Sachin Ahuja27dd2402016-08-01 20:30:31 +05309907 if(pScanInfo != NULL && pHddCtx->scan_info.mScanPending)
Jeff Johnson295189b2012-06-20 16:38:30 -07009908 {
Mahesh A Saptasagar0b61dcc2016-02-15 14:23:38 +05309909 wlan_hdd_scan_abort(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07009910 }
Abhishek Singh3ac179b2015-09-21 10:01:34 +05309911 if ((pAdapter->device_mode != WLAN_HDD_INFRA_STATION) &&
9912 (pAdapter->device_mode != WLAN_HDD_IBSS))
Kaushik, Sushant7005e372014-04-08 11:36:54 +05309913 {
9914 while (pAdapter->is_roc_inprogress)
9915 {
9916 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9917 "%s: ROC in progress for session %d!!!",
9918 __func__, pAdapter->sessionId);
9919 // waiting for ROC to expire
9920 msleep(500);
9921 /* In GO present case , if retry exceeds 3,
9922 it means something went wrong. */
9923 if ( retry++ > MAX_WAIT_FOR_ROC_COMPLETION )
9924 {
9925 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9926 "%s: ROC completion is not received.!!!", __func__);
Deepthi Gowri70498252015-01-20 15:56:45 +05309927 if (eHAL_STATUS_SUCCESS !=
9928 sme_CancelRemainOnChannel( WLAN_HDD_GET_HAL_CTX( pAdapter),
9929 pAdapter->sessionId ))
9930 {
9931 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9932 FL("Failed to Cancel Remain on Channel"));
9933 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +05309934 wait_for_completion_interruptible_timeout(
9935 &pAdapter->cancel_rem_on_chan_var,
9936 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
9937 break;
9938 }
9939 }
Anand N Sunkaddc63c792015-06-03 14:33:24 +05309940 vos_flush_delayed_work(&pAdapter->roc_work);
Kaushik, Sushant7005e372014-04-08 11:36:54 +05309941 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05309942#ifdef WLAN_NS_OFFLOAD
Anand N Sunkaddc63c792015-06-03 14:33:24 +05309943 vos_flush_work(&pAdapter->ipv6NotifierWorkQueue);
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05309944#endif
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +05309945
Anand N Sunkaddc63c792015-06-03 14:33:24 +05309946 vos_flush_work(&pAdapter->ipv4NotifierWorkQueue);
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +05309947
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05309948 /* It is possible that the caller of this function does not
9949 * wish to close the session
9950 */
9951 if (VOS_TRUE == bCloseSession &&
9952 test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07009953 {
9954 INIT_COMPLETION(pAdapter->session_close_comp_var);
9955 if (eHAL_STATUS_SUCCESS ==
Agrawal Ashish5a3522c2016-03-02 15:08:28 +05309956 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId, FALSE,
9957 VOS_FALSE, hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07009958 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309959 unsigned long ret;
9960
Jeff Johnson295189b2012-06-20 16:38:30 -07009961 //Block on a completion variable. Can't wait forever though.
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309962 ret = wait_for_completion_timeout(
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05309963 &pAdapter->session_close_comp_var,
9964 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309965 if ( 0 >= ret)
9966 {
9967 hddLog(LOGE, "%s: failure waiting for session_close_comp_var %ld",
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05309968 __func__, ret);
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309969 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009970 }
9971 }
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05309972 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009973 break;
9974
9975 case WLAN_HDD_SOFTAP:
9976 case WLAN_HDD_P2P_GO:
Nirav Shah0cf4d892015-11-05 16:27:27 +05309977 if ( VOS_TRUE == bCloseSession )
9978 {
9979 status = hdd_sta_id_hash_detach(pAdapter);
9980 if (status != VOS_STATUS_SUCCESS)
9981 hddLog(VOS_TRACE_LEVEL_ERROR,
9982 FL("sta id hash detach failed"));
9983 }
9984
Jeff Johnson295189b2012-06-20 16:38:30 -07009985 //Any softap specific cleanup here...
Anurag Chouhan83026002016-12-13 22:46:21 +05309986 hdd_cleanup_ap_events(pAdapter);
Kaushik, Sushant7005e372014-04-08 11:36:54 +05309987 if (pAdapter->device_mode == WLAN_HDD_P2P_GO) {
9988 while (pAdapter->is_roc_inprogress) {
9989 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9990 "%s: ROC in progress for session %d!!!",
9991 __func__, pAdapter->sessionId);
9992 msleep(500);
9993 if ( retry++ > MAX_WAIT_FOR_ROC_COMPLETION ) {
9994 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9995 "%s: ROC completion is not received.!!!", __func__);
9996 WLANSAP_CancelRemainOnChannel(
9997 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
9998 wait_for_completion_interruptible_timeout(
9999 &pAdapter->cancel_rem_on_chan_var,
10000 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
10001 break;
10002 }
10003 }
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +053010004
Anand N Sunkaddc63c792015-06-03 14:33:24 +053010005 vos_flush_delayed_work(&pAdapter->roc_work);
Kaushik, Sushant7005e372014-04-08 11:36:54 +053010006 }
Agrawal Ashish17ef5082016-10-17 18:33:21 +053010007#ifdef SAP_AUTH_OFFLOAD
10008 if (pHddCtx->cfg_ini->enable_sap_auth_offload)
10009 hdd_set_sap_auth_offload(pAdapter, FALSE);
10010#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070010011 mutex_lock(&pHddCtx->sap_lock);
10012 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
10013 {
10014 VOS_STATUS status;
10015 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10016
10017 //Stop Bss.
10018 status = WLANSAP_StopBss(pHddCtx->pvosContext);
10019 if (VOS_IS_STATUS_SUCCESS(status))
10020 {
10021 hdd_hostapd_state_t *pHostapdState =
10022 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
10023
10024 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
10025
10026 if (!VOS_IS_STATUS_SUCCESS(status))
10027 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +053010028 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss %d",
10029 __func__, status);
Jeff Johnson295189b2012-06-20 16:38:30 -070010030 }
10031 }
10032 else
10033 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070010034 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -070010035 }
10036 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
Agarwal Ashish51325b52014-06-16 16:50:49 +053010037 wlan_hdd_decr_active_session(pHddCtx, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -070010038
10039 if (eHAL_STATUS_FAILURE ==
10040 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
10041 0, NULL, eANI_BOOLEAN_FALSE))
10042 {
10043 hddLog(LOGE,
10044 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070010045 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -070010046 }
10047
10048 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
10049 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
10050 eANI_BOOLEAN_FALSE) )
10051 {
10052 hddLog(LOGE,
10053 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
10054 }
10055
10056 // Reset WNI_CFG_PROBE_RSP Flags
10057 wlan_hdd_reset_prob_rspies(pAdapter);
10058 kfree(pAdapter->sessionCtx.ap.beacon);
10059 pAdapter->sessionCtx.ap.beacon = NULL;
10060 }
10061 mutex_unlock(&pHddCtx->sap_lock);
Hanumanth Reddy Pothulab4537b82018-03-02 12:20:38 +053010062
10063#ifdef WLAN_NS_OFFLOAD
10064 vos_flush_work(&pAdapter->ipv6NotifierWorkQueue);
10065#endif
10066 vos_flush_work(&pAdapter->ipv4NotifierWorkQueue);
10067
Jeff Johnson295189b2012-06-20 16:38:30 -070010068 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -070010069
Jeff Johnson295189b2012-06-20 16:38:30 -070010070 case WLAN_HDD_MONITOR:
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +053010071 if (VOS_MONITOR_MODE != hdd_get_conparam())
10072 wlan_hdd_stop_mon(pHddCtx, true);
10073 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -070010074
Jeff Johnson295189b2012-06-20 16:38:30 -070010075 default:
10076 break;
10077 }
10078
10079 EXIT();
10080 return VOS_STATUS_SUCCESS;
10081}
10082
Kapil Gupta137ef892016-12-13 19:38:00 +053010083/**
10084 * wlan_hdd_restart_sap() - to restart SAP in driver internally
10085 * @ap_adapter: - Pointer to SAP hdd_adapter_t structure
10086 *
10087 * wlan_hdd_restart_sap first delete SAP and do cleanup.
10088 * After that WLANSAP_StartBss start re-start process of SAP.
10089 *
10090 * Return: None
10091 */
10092static void wlan_hdd_restart_sap(hdd_adapter_t *ap_adapter)
10093{
10094 hdd_ap_ctx_t *pHddApCtx;
10095 hdd_hostapd_state_t *pHostapdState;
10096 VOS_STATUS vos_status;
10097 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(ap_adapter);
Rajeev Kumar Sirasanagandla5b21a9c2018-01-08 17:05:11 +053010098#ifdef USE_CFG80211_DEL_STA_V2
Kapil Gupta137ef892016-12-13 19:38:00 +053010099 struct station_del_parameters delStaParams;
10100#endif
10101 tsap_Config_t *pConfig;
10102
10103 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
10104 pConfig = &pHddApCtx->sapConfig;
10105
10106 mutex_lock(&pHddCtx->sap_lock);
10107 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags)) {
Rajeev Kumar Sirasanagandla5b21a9c2018-01-08 17:05:11 +053010108#ifdef USE_CFG80211_DEL_STA_V2
Kapil Gupta137ef892016-12-13 19:38:00 +053010109 delStaParams.mac = NULL;
10110 delStaParams.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
10111 delStaParams.reason_code = eCsrForcedDeauthSta;
10112 wlan_hdd_cfg80211_del_station(ap_adapter->wdev.wiphy, ap_adapter->dev,
10113 &delStaParams);
10114#else
10115 wlan_hdd_cfg80211_del_station(ap_adapter->wdev.wiphy, ap_adapter->dev,
10116 NULL);
10117#endif
10118 hdd_cleanup_actionframe(pHddCtx, ap_adapter);
10119
10120 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
10121 vos_event_reset(&pHostapdState->vosEvent);
10122
10123 if (VOS_STATUS_SUCCESS == WLANSAP_StopBss(pHddCtx->pvosContext)) {
10124 vos_status = vos_wait_single_event(&pHostapdState->vosEvent,
10125 10000);
10126 if (!VOS_IS_STATUS_SUCCESS(vos_status)) {
10127 hddLog(LOGE, FL("SAP Stop Failed"));
10128 goto end;
10129 }
10130 }
10131 clear_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
10132 wlan_hdd_decr_active_session(pHddCtx, ap_adapter->device_mode);
10133 hddLog(LOG1, FL("SAP Stop Success"));
10134
10135 if (0 != wlan_hdd_cfg80211_update_apies(ap_adapter)) {
10136 hddLog(LOGE, FL("SAP Not able to set AP IEs"));
10137 goto end;
10138 }
10139
10140 if (WLANSAP_StartBss(pHddCtx->pvosContext, hdd_hostapd_SAPEventCB,
10141 pConfig, (v_PVOID_t)ap_adapter->dev) != VOS_STATUS_SUCCESS) {
10142 hddLog(LOGE, FL("SAP Start Bss fail"));
10143 goto end;
10144 }
10145
10146 hddLog(LOG1, FL("Waiting for SAP to start"));
10147 vos_status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
10148 if (!VOS_IS_STATUS_SUCCESS(vos_status)) {
10149 hddLog(LOGE, FL("SAP Start failed"));
10150 goto end;
10151 }
10152 hddLog(LOG1, FL("SAP Start Success"));
10153 set_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
10154 wlan_hdd_incr_active_session(pHddCtx, ap_adapter->device_mode);
10155 pHostapdState->bCommit = TRUE;
Anurag Chouhanb2951ae2017-03-12 13:41:35 +053010156 if (!VOS_IS_STATUS_SUCCESS(hdd_dhcp_mdns_offload(ap_adapter))) {
10157 hddLog(VOS_TRACE_LEVEL_ERROR, FL("DHCP/MDNS offload Failed!!"));
10158 vos_event_reset(&pHostapdState->vosEvent);
10159 if (VOS_STATUS_SUCCESS == WLANSAP_StopBss(pHddCtx->pvosContext)) {
10160 vos_status = vos_wait_single_event(&pHostapdState->vosEvent,
10161 10000);
10162 if (!VOS_IS_STATUS_SUCCESS(vos_status)) {
10163 hddLog(LOGE, FL("SAP Stop Failed"));
10164 goto end;
10165 }
10166 }
10167 }
Kapil Gupta137ef892016-12-13 19:38:00 +053010168 }
10169end:
10170 mutex_unlock(&pHddCtx->sap_lock);
10171 return;
10172}
10173
10174/**
10175 * __hdd_sap_restart_handle() - to handle restarting of SAP
10176 * @work: name of the work
10177 *
10178 * Purpose of this function is to trigger sap start. this function
10179 * will be called from workqueue.
10180 *
10181 * Return: void.
10182 */
10183static void __hdd_sap_restart_handle(struct work_struct *work)
10184{
10185 hdd_adapter_t *sap_adapter;
10186 hdd_context_t *hdd_ctx = container_of(work,
10187 hdd_context_t,
10188 sap_start_work);
10189 if (0 != wlan_hdd_validate_context(hdd_ctx)) {
10190 vos_ssr_unprotect(__func__);
10191 return;
10192 }
10193 sap_adapter = hdd_get_adapter(hdd_ctx,
10194 WLAN_HDD_SOFTAP);
10195 if (sap_adapter == NULL) {
10196 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
10197 FL("sap_adapter is NULL"));
10198 vos_ssr_unprotect(__func__);
10199 return;
10200 }
10201
10202 if (hdd_ctx->is_ch_avoid_in_progress) {
10203 sap_adapter->sessionCtx.ap.sapConfig.channel = AUTO_CHANNEL_SELECT;
10204 wlan_hdd_restart_sap(sap_adapter);
10205 hdd_change_ch_avoidance_status(hdd_ctx, false);
10206 }
Agrawal Ashish574b3e62017-02-09 18:58:34 +053010207 if (hdd_ctx->cfg_ini->enable_sap_auth_offload)
10208 wlan_hdd_restart_sap(sap_adapter);
Kapil Gupta137ef892016-12-13 19:38:00 +053010209}
10210
10211/**
10212 * hdd_sap_restart_handle() - to handle restarting of SAP
10213 * @work: name of the work
10214 *
10215 * Purpose of this function is to trigger sap start. this function
10216 * will be called from workqueue.
10217 *
10218 * Return: void.
10219 */
10220static void hdd_sap_restart_handle(struct work_struct *work)
10221{
10222 vos_ssr_protect(__func__);
10223 __hdd_sap_restart_handle(work);
10224 vos_ssr_unprotect(__func__);
10225}
10226
10227
Abhishek Singh78c691f2017-11-30 13:48:44 +053010228/**
10229 * __hdd_force_scc_with_ecsa_handle() - to handle force scc using ecsa
10230 * @work: name of the work
10231 *
10232 * Purpose of this function is to force SCC using ECSA. This function
10233 * will be called from workqueue.
10234 *
10235 * Return: void.
10236 */
10237static void
10238__hdd_force_scc_with_ecsa_handle(struct work_struct *work)
10239{
10240 hdd_adapter_t *sap_adapter;
10241 hdd_station_ctx_t *sta_ctx;
10242 hdd_adapter_t *sta_adapter;
Ganesh Kondabattini3655a6d2018-01-08 20:25:39 +053010243 ptSapContext sap_ctx = NULL;
10244 v_CONTEXT_t vos_ctx;
10245 tANI_U8 target_channel;
10246 tsap_Config_t *sap_config;
10247 bool sta_sap_scc_on_dfs_chan;
10248 eNVChannelEnabledType chan_state;
Abhishek Singh78c691f2017-11-30 13:48:44 +053010249 hdd_context_t *hdd_ctx = container_of(to_delayed_work(work),
10250 hdd_context_t,
10251 ecsa_chan_change_work);
10252
10253 if (wlan_hdd_validate_context(hdd_ctx))
10254 return;
10255
10256 sap_adapter = hdd_get_adapter(hdd_ctx,
10257 WLAN_HDD_SOFTAP);
10258 if (!sap_adapter) {
10259 hddLog(LOGE, FL("sap_adapter is NULL"));
10260 return;
10261 }
10262
Ganesh Kondabattini3655a6d2018-01-08 20:25:39 +053010263 vos_ctx = hdd_ctx->pvosContext;
10264 if (!vos_ctx) {
10265 hddLog(LOGE, FL("vos_ctx is NULL"));
10266 return;
10267 }
10268
10269 sap_ctx = VOS_GET_SAP_CB(vos_ctx);
10270 if (!sap_ctx) {
10271 hddLog(LOGE, FL("sap_ctx is NULL"));
10272 return;
10273 }
10274
10275 sap_config = &sap_adapter->sessionCtx.ap.sapConfig;
10276
10277 sta_sap_scc_on_dfs_chan = hdd_is_sta_sap_scc_allowed_on_dfs_chan(hdd_ctx);
10278
Abhishek Singh78c691f2017-11-30 13:48:44 +053010279 sta_adapter = hdd_get_adapter(hdd_ctx,
10280 WLAN_HDD_INFRA_STATION);
10281 if (!sta_adapter) {
10282 hddLog(LOGE, FL("sta_adapter is NULL"));
10283 return;
10284 }
Abhishek Singh78c691f2017-11-30 13:48:44 +053010285
Abhishek Singh10e17cf2018-03-12 14:34:22 +053010286 if (wlansap_chk_n_set_chan_change_in_progress(sap_ctx))
Abhishek Singh78c691f2017-11-30 13:48:44 +053010287 return;
Abhishek Singh10e17cf2018-03-12 14:34:22 +053010288 INIT_COMPLETION(sap_ctx->ecsa_info.chan_switch_comp);
10289
10290 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(sta_adapter);
10291 if (sta_ctx->conn_info.connState != eConnectionState_Associated) {
10292 if (sta_ctx->conn_info.connState == eConnectionState_NotConnected) {
10293 chan_state = vos_nv_getChannelEnabledState(sap_ctx->channel);
10294 hddLog(LOG1, FL("sta not in connected state %d, sta_sap_scc_on_dfs_chan %d, chan_state %d"),
10295 sta_ctx->conn_info.connState, sta_sap_scc_on_dfs_chan,
10296 chan_state);
10297 if (sta_sap_scc_on_dfs_chan &&
10298 (chan_state == NV_CHANNEL_DFS)) {
10299 hddLog(LOGE, FL("Switch SAP to user configured channel"));
10300 target_channel = sap_config->user_config_channel;
10301 goto switch_channel;
10302 }
10303 }
10304 goto abort;
Abhishek Singh78c691f2017-11-30 13:48:44 +053010305 }
10306
Ganesh Kondabattini3655a6d2018-01-08 20:25:39 +053010307 target_channel = sta_ctx->conn_info.operationChannel;
10308switch_channel:
10309 hddLog(LOGE, FL("Switch SAP to %d channel"),
10310 target_channel);
Abhishek Singh10e17cf2018-03-12 14:34:22 +053010311 if (!wlansap_set_channel_change(vos_ctx, target_channel, true))
10312 return;
10313
10314abort:
10315 wlansap_reset_chan_change_in_progress(sap_ctx);
10316 complete(&sap_ctx->ecsa_info.chan_switch_comp);
Abhishek Singh78c691f2017-11-30 13:48:44 +053010317}
10318
10319/**
10320 * hdd_force_scc_with_ecsa_handle() - to handle force scc using ecsa
10321 * @work: name of the work
10322 *
10323 * Purpose of this function is to force SCC using ECSA. This function
10324 * will be called from workqueue.
10325 *
10326 * Return: void.
10327 */
10328static void
10329hdd_force_scc_with_ecsa_handle(struct work_struct *work)
10330{
10331 vos_ssr_protect(__func__);
10332 __hdd_force_scc_with_ecsa_handle(work);
10333 vos_ssr_unprotect(__func__);
10334}
10335
Abhishek Singh10e17cf2018-03-12 14:34:22 +053010336int hdd_wait_for_ecsa_complete(hdd_context_t *hdd_ctx)
10337{
10338 int ret;
10339 ptSapContext sap_ctx = NULL;
10340 v_CONTEXT_t vos_ctx;
10341
10342 vos_ctx = hdd_ctx->pvosContext;
10343 if (!vos_ctx) {
10344 hddLog(LOGE, FL("vos_ctx is NULL"));
10345 return 0;
10346 }
10347
10348 sap_ctx = VOS_GET_SAP_CB(vos_ctx);
10349 if (!sap_ctx) {
10350 hddLog(LOG1, FL("sap_ctx is NULL"));
10351 return 0;
10352 }
10353 if(!sap_ctx->isSapSessionOpen) {
10354 hddLog(LOG1, FL("sap session not opened, SAP in state %d"),
10355 sap_ctx->sapsMachine);
10356 return 0;
10357 }
10358
10359 if (!wlansap_get_change_in_progress(sap_ctx)) {
10360 hddLog(LOG1, FL("channel switch not in progress"));
10361 return 0;
10362 }
10363 ret = wait_for_completion_timeout(&sap_ctx->ecsa_info.chan_switch_comp,
10364 msecs_to_jiffies(HDD_SAP_CHAN_CNG_WAIT_TIME));
10365 if (!ret)
10366 {
10367 hddLog(LOGE, FL("Timeout waiting for SAP channel switch"));
10368 return ret;
10369 }
10370
10371 return 0;
10372}
10373
10374
Ganesh Kondabattini3655a6d2018-01-08 20:25:39 +053010375/**
10376 * hdd_is_sta_sap_scc_allowed_on_dfs_chan() - check if sta+sap scc allowed on
10377 * dfs chan
10378 * @hdd_ctx: pointer to hdd context
10379 *
10380 * This function used to check if sta+sap scc allowed on DFS channel.
10381 *
10382 * Return: None
10383 */
10384bool hdd_is_sta_sap_scc_allowed_on_dfs_chan(hdd_context_t *hdd_ctx)
10385{
10386 if (hdd_ctx->cfg_ini->force_scc_with_ecsa &&
10387 hdd_ctx->cfg_ini->sta_sap_scc_on_dfs_chan)
10388 return true;
10389 else
10390 return false;
10391}
10392
Jeff Johnson295189b2012-06-20 16:38:30 -070010393VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
10394{
10395 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
10396 VOS_STATUS status;
10397 hdd_adapter_t *pAdapter;
10398
10399 ENTER();
10400
10401 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10402
10403 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
10404 {
10405 pAdapter = pAdapterNode->pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -070010406
Agarwal Ashish3a38bd12014-06-12 15:16:52 +053010407 hdd_stop_adapter( pHddCtx, pAdapter, VOS_TRUE );
Jeff Johnson295189b2012-06-20 16:38:30 -070010408
10409 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10410 pAdapterNode = pNext;
10411 }
10412
10413 EXIT();
10414
10415 return VOS_STATUS_SUCCESS;
10416}
10417
Rajeev Kumarf999e582014-01-09 17:33:29 -080010418
10419#ifdef FEATURE_WLAN_BATCH_SCAN
10420/**---------------------------------------------------------------------------
10421
10422 \brief hdd_deinit_batch_scan () - This function cleans up batch scan data
10423 structures
10424
10425 \param - pAdapter Pointer to HDD adapter
10426
10427 \return - None
10428
10429 --------------------------------------------------------------------------*/
10430void hdd_deinit_batch_scan(hdd_adapter_t *pAdapter)
10431{
10432 tHddBatchScanRsp *pNode;
10433 tHddBatchScanRsp *pPrev;
10434
Siddharth Bhalb3e9b792014-02-24 15:14:16 +053010435 if (NULL == pAdapter)
Rajeev Kumarf999e582014-01-09 17:33:29 -080010436 {
Siddharth Bhalb3e9b792014-02-24 15:14:16 +053010437 hddLog(VOS_TRACE_LEVEL_ERROR,
10438 "%s: Adapter context is Null", __func__);
10439 return;
10440 }
10441
10442 pNode = pAdapter->pBatchScanRsp;
10443 while (pNode)
10444 {
10445 pPrev = pNode;
10446 pNode = pNode->pNext;
10447 vos_mem_free((v_VOID_t * )pPrev);
Rajeev Kumarf999e582014-01-09 17:33:29 -080010448 }
10449
10450 pAdapter->pBatchScanRsp = NULL;
10451 pAdapter->numScanList = 0;
10452 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
10453 pAdapter->prev_batch_id = 0;
10454
10455 return;
10456}
10457#endif
10458
10459
Jeff Johnson295189b2012-06-20 16:38:30 -070010460VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
10461{
10462 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
10463 VOS_STATUS status;
10464 hdd_adapter_t *pAdapter;
10465
10466 ENTER();
10467
10468 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10469
10470 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
10471 {
10472 pAdapter = pAdapterNode->pAdapter;
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +053010473 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
Jeff Johnson295189b2012-06-20 16:38:30 -070010474 netif_tx_disable(pAdapter->dev);
Hanumanth Reddy Pothulad864f312017-01-18 16:16:08 +053010475
10476 if (pHddCtx->cfg_ini->sap_internal_restart &&
10477 pAdapter->device_mode == WLAN_HDD_SOFTAP) {
10478 hddLog(LOG1, FL("driver supports sap restart"));
10479 vos_flush_work(&pHddCtx->sap_start_work);
10480 hdd_sap_indicate_disconnect_for_sta(pAdapter);
10481 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Hanumanth Reddy Pothula15bc0fa2017-02-03 17:24:17 +053010482 hdd_softap_deinit_tx_rx(pAdapter, true);
10483 hdd_sap_destroy_timers(pAdapter);
Hanumanth Reddy Pothulad864f312017-01-18 16:16:08 +053010484 } else {
10485 netif_carrier_off(pAdapter->dev);
10486 }
Jeff Johnson295189b2012-06-20 16:38:30 -070010487
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -070010488 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
Hanumanth Reddy Pothulada449f12018-03-13 18:19:19 +053010489
10490 if (pAdapter->device_mode == WLAN_HDD_MONITOR)
10491 pAdapter->sessionCtx.monitor.state = MON_MODE_STOP;
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -070010492
Jeff Johnson295189b2012-06-20 16:38:30 -070010493 hdd_deinit_tx_rx(pAdapter);
Agarwal Ashish6267caa2014-08-06 19:16:21 +053010494
Katya Nigam1fd24402015-02-16 14:52:19 +053010495 if(pAdapter->device_mode == WLAN_HDD_IBSS )
10496 hdd_ibss_deinit_tx_rx(pAdapter);
10497
Nirav Shah7e3c8132015-06-22 23:51:42 +053010498 status = hdd_sta_id_hash_detach(pAdapter);
10499 if (status != VOS_STATUS_SUCCESS)
10500 hddLog(VOS_TRACE_LEVEL_ERROR,
10501 FL("sta id hash detach failed for session id %d"),
10502 pAdapter->sessionId);
10503
Agarwal Ashish6267caa2014-08-06 19:16:21 +053010504 wlan_hdd_decr_active_session(pHddCtx, pAdapter->device_mode);
10505
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +053010506 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
10507 {
10508 hdd_wmm_adapter_close( pAdapter );
10509 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
10510 }
Jeff Johnson295189b2012-06-20 16:38:30 -070010511
Siddharth Bhal2db319d2014-12-03 12:37:18 +053010512 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
10513 {
10514 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
10515 }
10516
Rajeev Kumarf999e582014-01-09 17:33:29 -080010517#ifdef FEATURE_WLAN_BATCH_SCAN
10518 if (eHDD_BATCH_SCAN_STATE_STARTED == pAdapter->batchScanState)
10519 {
10520 hdd_deinit_batch_scan(pAdapter);
10521 }
10522#endif
10523
Mahesh A Saptasagarf5b8eff2015-01-31 01:07:07 +053010524#ifdef FEATURE_WLAN_TDLS
10525 mutex_lock(&pHddCtx->tdls_lock);
Pradeep Reddy POTTETI2d4d5c42015-03-03 14:34:19 +053010526 wlan_hdd_tdls_exit(pAdapter, TRUE);
Mahesh A Saptasagarf5b8eff2015-01-31 01:07:07 +053010527 mutex_unlock(&pHddCtx->tdls_lock);
10528#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070010529 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10530 pAdapterNode = pNext;
10531 }
10532
10533 EXIT();
10534
10535 return VOS_STATUS_SUCCESS;
10536}
10537
Abhishek Singhbbe0b2a2016-12-05 11:57:36 +053010538/**
Abhishek Singh5a597e62016-12-05 15:16:30 +053010539 * hdd_get_bss_entry() - Get the bss entry matching the chan, bssid and ssid
10540 * @wiphy: wiphy
10541 * @channel: channel of the BSS to find
10542 * @bssid: bssid of the BSS to find
10543 * @ssid: ssid of the BSS to find
10544 * @ssid_len: ssid len of of the BSS to find
10545 *
10546 * The API is a wrapper to get bss from kernel matching the chan,
10547 * bssid and ssid
10548 *
10549 * Return: Void
10550 */
10551#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) \
10552 && !defined(WITH_BACKPORTS) && !defined(IEEE80211_PRIVACY)
10553
10554struct cfg80211_bss* hdd_get_bss_entry(struct wiphy *wiphy,
10555 struct ieee80211_channel *channel,
10556 const u8 *bssid,
10557 const u8 *ssid, size_t ssid_len)
10558{
10559 return cfg80211_get_bss(wiphy, channel, bssid,
10560 ssid, ssid_len,
10561 WLAN_CAPABILITY_ESS,
10562 WLAN_CAPABILITY_ESS);
10563}
10564#else
10565struct cfg80211_bss* hdd_get_bss_entry(struct wiphy *wiphy,
10566 struct ieee80211_channel *channel,
10567 const u8 *bssid,
10568 const u8 *ssid, size_t ssid_len)
10569{
10570 return cfg80211_get_bss(wiphy, channel, bssid,
10571 ssid, ssid_len,
10572 IEEE80211_BSS_TYPE_ESS,
10573 IEEE80211_PRIVACY_ANY);
10574}
10575#endif
10576
Rajeev Kumar Sirasanagandla5b21a9c2018-01-08 17:05:11 +053010577#if defined(CFG80211_CONNECT_BSS) || \
10578 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
10579
10580#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) || \
10581 defined (CFG80211_CONNECT_TIMEOUT_REASON_CODE)
10582/**
10583 * hdd_connect_bss() - helper function to send connection status to supplicant
10584 * @dev: network device
10585 * @bssid: bssid to which we want to associate
10586 * @bss: information about connected bss
10587 * @req_ie: Request Information Element
10588 * @req_ie_len: len of the req IE
10589 * @resp_ie: Response IE
10590 * @resp_ie_len: len of ht response IE
10591 * @status: status
10592 * @gfp: Kernel Flag
10593 *
10594 * This is a helper function to send connection status to supplicant
10595 * and gets invoked from wrapper API
10596 *
10597 * Return: Void
10598 */
10599static void hdd_connect_bss(struct net_device *dev,
10600 const u8 *bssid,
10601 struct cfg80211_bss *bss,
10602 const u8 *req_ie,
10603 size_t req_ie_len,
10604 const u8 *resp_ie,
10605 size_t resp_ie_len,
10606 u16 status,
10607 gfp_t gfp)
10608{
10609 cfg80211_connect_bss(dev, bssid, bss, req_ie, req_ie_len,
10610 resp_ie, resp_ie_len, status, gfp, NL80211_TIMEOUT_UNSPECIFIED);
10611}
10612#else
10613/**
10614 * hdd_connect_bss() - helper function to send connection status to supplicant
10615 * @dev: network device
10616 * @bssid: bssid to which we want to associate
10617 * @bss: information about connected bss
10618 * @req_ie: Request Information Element
10619 * @req_ie_len: len of the req IE
10620 * @resp_ie: Response IE
10621 * @resp_ie_len: len of ht response IE
10622 * @status: status
10623 * @gfp: Kernel Flag
10624 *
10625 * This is a helper function to send connection status to supplicant
10626 * and gets invoked from wrapper API
10627 *
10628 * Return: Void
10629 */
10630static void hdd_connect_bss(struct net_device *dev,
10631 const u8 *bssid,
10632 struct cfg80211_bss *bss,
10633 const u8 *req_ie,
10634 size_t req_ie_len,
10635 const u8 *resp_ie,
10636 size_t resp_ie_len,
10637 u16 status,
10638 gfp_t gfp)
10639{
10640 cfg80211_connect_bss(dev, bssid, bss, req_ie, req_ie_len,
10641 resp_ie, resp_ie_len, status, gfp);
10642}
10643#endif
10644
Abhishek Singh5a597e62016-12-05 15:16:30 +053010645/**
Abhishek Singhbbe0b2a2016-12-05 11:57:36 +053010646 * hdd_connect_result() - API to send connection status to supplicant
10647 * @dev: network device
10648 * @bssid: bssid to which we want to associate
10649 * @roam_info: information about connected bss
10650 * @req_ie: Request Information Element
10651 * @req_ie_len: len of the req IE
10652 * @resp_ie: Response IE
10653 * @resp_ie_len: len of ht response IE
10654 * @status: status
10655 * @gfp: Kernel Flag
10656 *
10657 * The API is a wrapper to send connection status to supplicant
10658 *
10659 * Return: Void
10660 */
Abhishek Singhbbe0b2a2016-12-05 11:57:36 +053010661void hdd_connect_result(struct net_device *dev,
10662 const u8 *bssid,
10663 tCsrRoamInfo *roam_info,
10664 const u8 *req_ie,
10665 size_t req_ie_len,
10666 const u8 *resp_ie,
10667 size_t resp_ie_len,
10668 u16 status,
10669 gfp_t gfp)
10670{
10671 hdd_adapter_t *padapter = (hdd_adapter_t *) netdev_priv(dev);
10672 struct cfg80211_bss *bss = NULL;
10673
10674 if (WLAN_STATUS_SUCCESS == status) {
10675 struct ieee80211_channel *chan;
10676 int freq;
10677 int chan_no = roam_info->pBssDesc->channelId;;
10678
10679 if (chan_no <= 14)
10680 freq = ieee80211_channel_to_frequency(chan_no,
Rajeev Kumar Sirasanagandla5b21a9c2018-01-08 17:05:11 +053010681 HDD_NL80211_BAND_2GHZ);
Abhishek Singhbbe0b2a2016-12-05 11:57:36 +053010682 else
10683 freq = ieee80211_channel_to_frequency(chan_no,
Rajeev Kumar Sirasanagandla5b21a9c2018-01-08 17:05:11 +053010684 HDD_NL80211_BAND_5GHZ);
Abhishek Singhbbe0b2a2016-12-05 11:57:36 +053010685
10686 chan = ieee80211_get_channel(padapter->wdev.wiphy, freq);
Abhishek Singh5a597e62016-12-05 15:16:30 +053010687 bss = hdd_get_bss_entry(padapter->wdev.wiphy,
10688 chan, bssid,
10689 roam_info->u.pConnectedProfile->SSID.ssId,
10690 roam_info->u.pConnectedProfile->SSID.length);
Abhishek Singhbbe0b2a2016-12-05 11:57:36 +053010691 }
10692
Rajeev Kumar Sirasanagandla5b21a9c2018-01-08 17:05:11 +053010693 hdd_connect_bss(dev, bssid, bss, req_ie, req_ie_len, resp_ie, resp_ie_len,
10694 status, gfp);
Abhishek Singhbbe0b2a2016-12-05 11:57:36 +053010695}
10696#else
Rajeev Kumar Sirasanagandla5b21a9c2018-01-08 17:05:11 +053010697/**
10698 * hdd_connect_result() - API to send connection status to supplicant
10699 * @dev: network device
10700 * @bssid: bssid to which we want to associate
10701 * @roam_info: information about connected bss
10702 * @req_ie: Request Information Element
10703 * @req_ie_len: len of the req IE
10704 * @resp_ie: Response IE
10705 * @resp_ie_len: len of ht response IE
10706 * @status: status
10707 * @gfp: Kernel Flag
10708 *
10709 * The API is a wrapper to send connection status to supplicant
10710 *
10711 * Return: Void
10712 */
Abhishek Singhbbe0b2a2016-12-05 11:57:36 +053010713void hdd_connect_result(struct net_device *dev,
10714 const u8 *bssid,
10715 tCsrRoamInfo *roam_info,
10716 const u8 *req_ie,
10717 size_t req_ie_len,
10718 const u8 * resp_ie,
10719 size_t resp_ie_len,
10720 u16 status,
10721 gfp_t gfp)
10722{
10723 cfg80211_connect_result(dev, bssid, req_ie, req_ie_len,
10724 resp_ie, resp_ie_len, status, gfp);
10725}
10726#endif
10727
Jeff Johnson295189b2012-06-20 16:38:30 -070010728VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
10729{
10730 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
10731 VOS_STATUS status;
10732 hdd_adapter_t *pAdapter;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +053010733 eConnectionState connState;
Hanumanth Reddy Pothulada449f12018-03-13 18:19:19 +053010734 v_CONTEXT_t pVosContext;
Jeff Johnson295189b2012-06-20 16:38:30 -070010735
10736 ENTER();
10737
10738 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10739
10740 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
10741 {
10742 pAdapter = pAdapterNode->pAdapter;
10743
Kumar Anand82c009f2014-05-29 00:29:42 -070010744 hdd_wmm_init( pAdapter );
10745
Jeff Johnson295189b2012-06-20 16:38:30 -070010746 switch(pAdapter->device_mode)
10747 {
10748 case WLAN_HDD_INFRA_STATION:
10749 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -070010750 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +053010751
10752 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
10753
Jeff Johnson295189b2012-06-20 16:38:30 -070010754 hdd_init_station_mode(pAdapter);
10755 /* Open the gates for HDD to receive Wext commands */
10756 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -070010757 pHddCtx->scan_info.mScanPending = FALSE;
10758 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -070010759
10760 //Trigger the initial scan
Mukul Sharmae74e42c2015-08-06 23:55:49 +053010761 if (!pHddCtx->isLogpInProgress)
10762 hdd_wlan_initial_scan(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -070010763
10764 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +053010765 if (eConnectionState_Associated == connState ||
10766 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -070010767 {
10768 union iwreq_data wrqu;
10769 memset(&wrqu, '\0', sizeof(wrqu));
10770 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
10771 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
10772 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -070010773 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -070010774
Jeff Johnson295189b2012-06-20 16:38:30 -070010775 /* indicate disconnected event to nl80211 */
Mahesh A Saptasagar9ff4bcc2016-06-01 17:17:50 +053010776 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, false,
Mahesh A Saptasagarb5a15142016-05-25 11:27:43 +053010777 WLAN_REASON_UNSPECIFIED);
Jeff Johnson295189b2012-06-20 16:38:30 -070010778 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +053010779 else if (eConnectionState_Connecting == connState)
10780 {
10781 /*
10782 * Indicate connect failure to supplicant if we were in the
10783 * process of connecting
10784 */
Abhishek Singhbbe0b2a2016-12-05 11:57:36 +053010785 hdd_connect_result(pAdapter->dev, NULL, NULL,
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +053010786 NULL, 0, NULL, 0,
10787 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
10788 GFP_KERNEL);
10789 }
Jeff Johnson295189b2012-06-20 16:38:30 -070010790 break;
10791
10792 case WLAN_HDD_SOFTAP:
Hanumanth Reddy Pothulad864f312017-01-18 16:16:08 +053010793 if (pHddCtx->cfg_ini->sap_internal_restart) {
Hanumanth Reddy Pothula15bc0fa2017-02-03 17:24:17 +053010794 hdd_init_ap_mode(pAdapter, true);
Hanumanth Reddy Pothulad864f312017-01-18 16:16:08 +053010795 status = hdd_sta_id_hash_attach(pAdapter);
10796 if (VOS_STATUS_SUCCESS != status)
10797 {
10798 hddLog(VOS_TRACE_LEVEL_FATAL,
10799 FL("failed to attach hash for"));
10800 }
10801 }
Jeff Johnson295189b2012-06-20 16:38:30 -070010802 break;
10803
10804 case WLAN_HDD_P2P_GO:
Sameer Thalappiledf0d792013-08-09 14:31:03 -070010805 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send stop ap to supplicant",
Jeff Johnson295189b2012-06-20 16:38:30 -070010806 __func__);
Sameer Thalappiledf0d792013-08-09 14:31:03 -070010807 cfg80211_ap_stopped(pAdapter->dev, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -070010808 break;
10809
10810 case WLAN_HDD_MONITOR:
Hanumanth Reddy Pothulada449f12018-03-13 18:19:19 +053010811 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
10812
10813 hddLog(VOS_TRACE_LEVEL_INFO, FL("[SSR] monitor mode"));
10814 if (!pVosContext) {
10815 hddLog(VOS_TRACE_LEVEL_ERROR, FL("vos context is NULL"));
10816 break;
10817 }
10818
10819 hdd_init_tx_rx(pAdapter);
10820 WLANTL_SetMonRxCbk( pVosContext, hdd_rx_packet_monitor_cbk);
Jeff Johnson295189b2012-06-20 16:38:30 -070010821 break;
Hanumanth Reddy Pothulada449f12018-03-13 18:19:19 +053010822
Jeff Johnson295189b2012-06-20 16:38:30 -070010823 default:
10824 break;
10825 }
10826
10827 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10828 pAdapterNode = pNext;
10829 }
10830
10831 EXIT();
10832
10833 return VOS_STATUS_SUCCESS;
10834}
10835
10836VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
10837{
10838 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
10839 hdd_adapter_t *pAdapter;
10840 VOS_STATUS status;
10841 v_U32_t roamId;
c_hpothu6ff1c3c2013-10-01 19:01:57 +053010842 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -070010843
10844 ENTER();
10845
10846 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10847
10848 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
10849 {
10850 pAdapter = pAdapterNode->pAdapter;
10851
10852 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
10853 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
10854 {
10855 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10856 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10857
Abhishek Singhf4669da2014-05-26 15:07:49 +053010858 hddLog(VOS_TRACE_LEVEL_INFO,
10859 "%s: Set HDD connState to eConnectionState_NotConnected",
10860 __func__);
Ganesh Kondabattini04338412015-09-14 15:39:09 +053010861 spin_lock_bh(&pAdapter->lock_for_active_session);
10862 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState)
10863 {
10864 wlan_hdd_decr_active_session(pHddCtx, pAdapter->device_mode);
10865 }
Jeff Johnson295189b2012-06-20 16:38:30 -070010866 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
Ganesh Kondabattini04338412015-09-14 15:39:09 +053010867 spin_unlock_bh(&pAdapter->lock_for_active_session);
Jeff Johnson295189b2012-06-20 16:38:30 -070010868 init_completion(&pAdapter->disconnect_comp_var);
10869 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
10870 eCSR_DISCONNECT_REASON_UNSPECIFIED);
10871
c_hpothu6ff1c3c2013-10-01 19:01:57 +053010872 ret = wait_for_completion_interruptible_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -070010873 &pAdapter->disconnect_comp_var,
10874 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +053010875 if (0 >= ret)
10876 hddLog(LOGE, "%s: failure waiting for disconnect_comp_var %ld",
10877 __func__, ret);
Jeff Johnson295189b2012-06-20 16:38:30 -070010878
10879 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
10880 pHddCtx->isAmpAllowed = VOS_FALSE;
10881 sme_RoamConnect(pHddCtx->hHal,
10882 pAdapter->sessionId, &(pWextState->roamProfile),
10883 &roamId);
10884 }
10885
10886 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10887 pAdapterNode = pNext;
10888 }
10889
10890 EXIT();
10891
10892 return VOS_STATUS_SUCCESS;
10893}
10894
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -070010895void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
10896{
10897 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
10898 VOS_STATUS status;
10899 hdd_adapter_t *pAdapter;
10900 hdd_station_ctx_t *pHddStaCtx;
10901 hdd_ap_ctx_t *pHddApCtx;
10902 hdd_hostapd_state_t * pHostapdState;
10903 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
10904 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
10905 const char *p2pMode = "DEV";
10906 const char *ccMode = "Standalone";
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -070010907
10908 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10909 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
10910 {
10911 pAdapter = pAdapterNode->pAdapter;
10912 switch (pAdapter->device_mode) {
10913 case WLAN_HDD_INFRA_STATION:
10914 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10915 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
10916 staChannel = pHddStaCtx->conn_info.operationChannel;
10917 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
10918 }
10919 break;
10920 case WLAN_HDD_P2P_CLIENT:
10921 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10922 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
10923 p2pChannel = pHddStaCtx->conn_info.operationChannel;
10924 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
10925 p2pMode = "CLI";
10926 }
10927 break;
10928 case WLAN_HDD_P2P_GO:
10929 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
10930 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
10931 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
10932 p2pChannel = pHddApCtx->operatingChannel;
10933 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
10934 }
10935 p2pMode = "GO";
10936 break;
10937 case WLAN_HDD_SOFTAP:
10938 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
10939 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
10940 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
10941 apChannel = pHddApCtx->operatingChannel;
10942 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
10943 }
10944 break;
10945 default:
10946 break;
10947 }
10948 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10949 pAdapterNode = pNext;
10950 }
10951 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
10952 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
10953 }
Yeshwanth Sriram Guntuka0004c0b2017-12-06 14:43:49 +053010954 hddLog(VOS_TRACE_LEVEL_ERROR, "wlan(%d) " MAC_ADDRESS_STR " %s",
10955 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -070010956 if (p2pChannel > 0) {
Sushant Kaushikdc3184b2015-10-09 12:00:21 +053010957 hddLog(VOS_TRACE_LEVEL_ERROR, "p2p-%s(%d) " MAC_ADDRESS_STR,
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -070010958 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
10959 }
10960 if (apChannel > 0) {
Sushant Kaushikdc3184b2015-10-09 12:00:21 +053010961 hddLog(VOS_TRACE_LEVEL_ERROR, "AP(%d) " MAC_ADDRESS_STR,
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -070010962 apChannel, MAC_ADDR_ARRAY(apBssid));
10963 }
10964
10965 if (p2pChannel > 0 && apChannel > 0) {
10966 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
10967 }
10968}
10969
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -070010970bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -070010971{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -070010972 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -070010973}
10974
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -070010975/* Once SSR is disabled then it cannot be set. */
10976void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -070010977{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -070010978 if (HDD_SSR_DISABLED == isSsrRequired)
10979 return;
10980
Jeff Johnson295189b2012-06-20 16:38:30 -070010981 isSsrRequired = value;
10982}
10983
Hema Aparna Medicharla6b4d4f32015-06-23 04:09:12 +053010984void hdd_set_pre_close( hdd_context_t *pHddCtx)
10985{
10986 sme_PreClose(pHddCtx->hHal);
10987}
10988
Jeff Johnson295189b2012-06-20 16:38:30 -070010989VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
10990 hdd_adapter_list_node_t** ppAdapterNode)
10991{
10992 VOS_STATUS status;
Mukul Sharmaae1266d2015-06-26 15:29:53 +053010993 spin_lock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010994 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
10995 (hdd_list_node_t**) ppAdapterNode );
Mukul Sharmaae1266d2015-06-26 15:29:53 +053010996 spin_unlock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010997 return status;
10998}
10999
11000VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
11001 hdd_adapter_list_node_t* pAdapterNode,
11002 hdd_adapter_list_node_t** pNextAdapterNode)
11003{
11004 VOS_STATUS status;
Mukul Sharmaae1266d2015-06-26 15:29:53 +053011005 spin_lock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070011006 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
11007 (hdd_list_node_t*) pAdapterNode,
11008 (hdd_list_node_t**)pNextAdapterNode );
11009
Mukul Sharmaae1266d2015-06-26 15:29:53 +053011010 spin_unlock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070011011 return status;
11012}
11013
11014VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
11015 hdd_adapter_list_node_t* pAdapterNode)
11016{
11017 VOS_STATUS status;
Mukul Sharmaae1266d2015-06-26 15:29:53 +053011018 spin_lock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070011019 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
11020 &pAdapterNode->node );
Mukul Sharmaae1266d2015-06-26 15:29:53 +053011021 spin_unlock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070011022 return status;
11023}
11024
11025VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
11026 hdd_adapter_list_node_t** ppAdapterNode)
11027{
11028 VOS_STATUS status;
Mukul Sharmaae1266d2015-06-26 15:29:53 +053011029 spin_lock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070011030 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
11031 (hdd_list_node_t**) ppAdapterNode );
Mukul Sharmaae1266d2015-06-26 15:29:53 +053011032 spin_unlock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070011033 return status;
11034}
11035
11036VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
11037 hdd_adapter_list_node_t* pAdapterNode)
11038{
11039 VOS_STATUS status;
Mukul Sharmaae1266d2015-06-26 15:29:53 +053011040 spin_lock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070011041 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
11042 (hdd_list_node_t*) pAdapterNode );
Mukul Sharmaae1266d2015-06-26 15:29:53 +053011043 spin_unlock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070011044 return status;
11045}
11046
11047VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
11048 hdd_adapter_list_node_t* pAdapterNode)
11049{
11050 VOS_STATUS status;
Mukul Sharmaae1266d2015-06-26 15:29:53 +053011051 spin_lock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070011052 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
11053 (hdd_list_node_t*) pAdapterNode );
Mukul Sharmaae1266d2015-06-26 15:29:53 +053011054 spin_unlock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070011055 return status;
11056}
11057
11058hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
11059 tSirMacAddr macAddr )
11060{
11061 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
11062 hdd_adapter_t *pAdapter;
11063 VOS_STATUS status;
11064
11065 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
11066
11067 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
11068 {
11069 pAdapter = pAdapterNode->pAdapter;
11070
11071 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
11072 macAddr, sizeof(tSirMacAddr) ) )
11073 {
11074 return pAdapter;
11075 }
11076 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
11077 pAdapterNode = pNext;
11078 }
11079
11080 return NULL;
11081
11082}
11083
11084hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
11085{
11086 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
11087 hdd_adapter_t *pAdapter;
11088 VOS_STATUS status;
11089
11090 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
11091
11092 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
11093 {
11094 pAdapter = pAdapterNode->pAdapter;
11095
11096 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
11097 IFNAMSIZ ) )
11098 {
11099 return pAdapter;
11100 }
11101 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
11102 pAdapterNode = pNext;
11103 }
11104
11105 return NULL;
11106
11107}
11108
Ganesh Kondabattinicbfdc392015-09-11 19:12:59 +053011109hdd_adapter_t *hdd_get_adapter_by_sme_session_id( hdd_context_t *pHddCtx,
11110 tANI_U32 sme_session_id )
11111{
11112 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
11113 hdd_adapter_t *pAdapter;
11114 VOS_STATUS vos_status;
11115
11116
11117 vos_status = hdd_get_front_adapter( pHddCtx, &pAdapterNode);
11118
11119 while ((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == vos_status))
11120 {
11121 pAdapter = pAdapterNode->pAdapter;
11122
11123 if (pAdapter->sessionId == sme_session_id)
11124 return pAdapter;
11125
11126 vos_status = hdd_get_next_adapter(pHddCtx, pAdapterNode, &pNext);
11127 pAdapterNode = pNext;
11128 }
11129
11130 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
11131 "%s: sme_session_id %d does not exist with host",
11132 __func__, sme_session_id);
11133
11134 return NULL;
11135}
11136
Jeff Johnson295189b2012-06-20 16:38:30 -070011137hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
11138{
11139 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
11140 hdd_adapter_t *pAdapter;
11141 VOS_STATUS status;
11142
11143 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
11144
11145 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
11146 {
11147 pAdapter = pAdapterNode->pAdapter;
11148
11149 if( pAdapter && (mode == pAdapter->device_mode) )
11150 {
11151 return pAdapter;
11152 }
11153 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
11154 pAdapterNode = pNext;
11155 }
11156
11157 return NULL;
11158
11159}
11160
11161//Remove this function later
11162hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
11163{
11164 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
11165 hdd_adapter_t *pAdapter;
11166 VOS_STATUS status;
11167
11168 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
11169
11170 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
11171 {
11172 pAdapter = pAdapterNode->pAdapter;
11173
11174 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
11175 {
11176 return pAdapter;
11177 }
11178
11179 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
11180 pAdapterNode = pNext;
11181 }
11182
11183 return NULL;
11184
11185}
11186
Jeff Johnson295189b2012-06-20 16:38:30 -070011187/**---------------------------------------------------------------------------
11188
Mahesh A Saptasgar64534612014-09-23 13:13:33 +053011189 \brief hdd_get_operating_channel() -
Jeff Johnson295189b2012-06-20 16:38:30 -070011190
11191 This API returns the operating channel of the requested device mode
11192
11193 \param - pHddCtx - Pointer to the HDD context.
11194 - mode - Device mode for which operating channel is required
11195 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
11196 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
11197 \return - channel number. "0" id the requested device is not found OR it is not connected.
11198 --------------------------------------------------------------------------*/
11199v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
11200{
11201 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
11202 VOS_STATUS status;
11203 hdd_adapter_t *pAdapter;
11204 v_U8_t operatingChannel = 0;
11205
11206 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
11207
11208 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
11209 {
11210 pAdapter = pAdapterNode->pAdapter;
11211
11212 if( mode == pAdapter->device_mode )
11213 {
11214 switch(pAdapter->device_mode)
11215 {
11216 case WLAN_HDD_INFRA_STATION:
11217 case WLAN_HDD_P2P_CLIENT:
11218 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
11219 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
11220 break;
11221 case WLAN_HDD_SOFTAP:
11222 case WLAN_HDD_P2P_GO:
11223 /*softap connection info */
11224 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
11225 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
11226 break;
11227 default:
11228 break;
11229 }
11230
11231 break; //Found the device of interest. break the loop
11232 }
11233
11234 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
11235 pAdapterNode = pNext;
11236 }
11237 return operatingChannel;
11238}
11239
11240#ifdef WLAN_FEATURE_PACKET_FILTERING
11241/**---------------------------------------------------------------------------
11242
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +053011243 \brief __hdd_set_multicast_list() -
Jeff Johnson295189b2012-06-20 16:38:30 -070011244
11245 This used to set the multicast address list.
11246
11247 \param - dev - Pointer to the WLAN device.
11248 - skb - Pointer to OS packet (sk_buff).
Mahesh A Saptasagar74088392015-02-05 17:22:09 +053011249 \return - success/fail
Jeff Johnson295189b2012-06-20 16:38:30 -070011250
11251 --------------------------------------------------------------------------*/
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +053011252static void __hdd_set_multicast_list(struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -070011253{
Mahesh A Saptasagar74088392015-02-05 17:22:09 +053011254 hdd_adapter_t *pAdapter;
11255 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -070011256 int mc_count;
Mahesh A Saptasagar74088392015-02-05 17:22:09 +053011257 int i = 0, ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -070011258 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +053011259
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +053011260 ENTER();
11261
Mahesh A Saptasagar74088392015-02-05 17:22:09 +053011262 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Gopichand Nakkala0f276812013-02-24 14:45:51 +053011263 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -070011264 {
11265 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +053011266 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -070011267 return;
11268 }
Mahesh A Saptasagar74088392015-02-05 17:22:09 +053011269 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11270 ret = wlan_hdd_validate_context(pHddCtx);
11271 if (0 != ret)
11272 {
Mahesh A Saptasagar74088392015-02-05 17:22:09 +053011273 return;
11274 }
Jeff Johnson295189b2012-06-20 16:38:30 -070011275 if (dev->flags & IFF_ALLMULTI)
11276 {
11277 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070011278 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +053011279 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -070011280 }
Mahesh A Saptasagar74088392015-02-05 17:22:09 +053011281 else
Jeff Johnson295189b2012-06-20 16:38:30 -070011282 {
11283 mc_count = netdev_mc_count(dev);
11284 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070011285 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -070011286 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
11287 {
11288 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070011289 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +053011290 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -070011291 return;
11292 }
11293
Gopichand Nakkala0f276812013-02-24 14:45:51 +053011294 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -070011295
11296 netdev_for_each_mc_addr(ha, dev) {
11297 if (i == mc_count)
11298 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +053011299 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
11300 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
Arif Hussain6d2a3322013-11-17 19:50:10 -080011301 hddLog(VOS_TRACE_LEVEL_INFO, "%s: mlist[%d] = "MAC_ADDRESS_STR,
Mahesh A Saptasagar74088392015-02-05 17:22:09 +053011302 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +053011303 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -070011304 i++;
11305 }
11306 }
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +053011307
Ganesh Kondabattinifb37e652015-10-09 15:46:47 +053011308 if (pHddCtx->hdd_wlan_suspended)
11309 {
11310 /*
11311 * Configure the Mcast address list to FW
11312 * If wlan is already in suspend mode
11313 */
11314 wlan_hdd_set_mc_addr_list(pAdapter, TRUE);
11315 }
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +053011316 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -070011317 return;
11318}
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +053011319
11320static void hdd_set_multicast_list(struct net_device *dev)
11321{
11322 vos_ssr_protect(__func__);
11323 __hdd_set_multicast_list(dev);
11324 vos_ssr_unprotect(__func__);
11325}
Jeff Johnson295189b2012-06-20 16:38:30 -070011326#endif
11327
11328/**---------------------------------------------------------------------------
11329
11330 \brief hdd_select_queue() -
11331
11332 This function is registered with the Linux OS for network
11333 core to decide which queue to use first.
11334
11335 \param - dev - Pointer to the WLAN device.
11336 - skb - Pointer to OS packet (sk_buff).
11337 \return - ac, Queue Index/access category corresponding to UP in IP header
11338
11339 --------------------------------------------------------------------------*/
11340v_U16_t hdd_select_queue(struct net_device *dev,
Anand N Sunkade9adb1b2015-07-29 09:56:45 +053011341 struct sk_buff *skb
11342#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0))
11343 , void *accel_priv
11344#endif
11345#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0))
11346 , select_queue_fallback_t fallback
11347#endif
11348)
Jeff Johnson295189b2012-06-20 16:38:30 -070011349{
11350 return hdd_wmm_select_queue(dev, skb);
11351}
11352
11353
11354/**---------------------------------------------------------------------------
11355
11356 \brief hdd_wlan_initial_scan() -
11357
11358 This function triggers the initial scan
11359
11360 \param - pAdapter - Pointer to the HDD adapter.
11361
11362 --------------------------------------------------------------------------*/
11363void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
11364{
11365 tCsrScanRequest scanReq;
11366 tCsrChannelInfo channelInfo;
11367 eHalStatus halStatus;
Jeff Johnson02797792013-10-26 19:17:13 -070011368 tANI_U32 scanId;
Jeff Johnson295189b2012-06-20 16:38:30 -070011369 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11370
11371 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
11372 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
11373 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
11374
11375 if(sme_Is11dSupported(pHddCtx->hHal))
11376 {
11377 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
11378 if ( HAL_STATUS_SUCCESS( halStatus ) )
11379 {
11380 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
11381 if( !scanReq.ChannelInfo.ChannelList )
11382 {
11383 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
11384 vos_mem_free(channelInfo.ChannelList);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -080011385 channelInfo.ChannelList = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -070011386 return;
11387 }
11388 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
11389 channelInfo.numOfChannels);
11390 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
11391 vos_mem_free(channelInfo.ChannelList);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -080011392 channelInfo.ChannelList = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -070011393 }
11394
11395 scanReq.scanType = eSIR_PASSIVE_SCAN;
11396 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
11397 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
11398 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
11399 }
11400 else
11401 {
11402 scanReq.scanType = eSIR_ACTIVE_SCAN;
11403 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
11404 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
11405 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
11406 }
11407
11408 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
11409 if ( !HAL_STATUS_SUCCESS( halStatus ) )
11410 {
11411 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
11412 __func__, halStatus );
11413 }
11414
11415 if(sme_Is11dSupported(pHddCtx->hHal))
11416 vos_mem_free(scanReq.ChannelInfo.ChannelList);
11417}
11418
Jeff Johnson295189b2012-06-20 16:38:30 -070011419/**---------------------------------------------------------------------------
11420
11421 \brief hdd_full_power_callback() - HDD full power callback function
11422
11423 This is the function invoked by SME to inform the result of a full power
11424 request issued by HDD
11425
11426 \param - callbackcontext - Pointer to cookie
11427 \param - status - result of request
11428
11429 \return - None
11430
11431 --------------------------------------------------------------------------*/
11432static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
11433{
Jeff Johnson72a40512013-12-19 10:14:15 -080011434 struct statsContext *pContext = callbackContext;
Jeff Johnson295189b2012-06-20 16:38:30 -070011435
11436 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnsonc135a9a2017-09-19 08:37:24 -070011437 "%s: context = %pK, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -070011438
11439 if (NULL == callbackContext)
11440 {
11441 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnsonc135a9a2017-09-19 08:37:24 -070011442 "%s: Bad param, context [%pK]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070011443 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -070011444 return;
11445 }
11446
Jeff Johnson72a40512013-12-19 10:14:15 -080011447 /* there is a race condition that exists between this callback
11448 function and the caller since the caller could time out either
11449 before or while this code is executing. we use a spinlock to
11450 serialize these actions */
11451 spin_lock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070011452
11453 if (POWER_CONTEXT_MAGIC != pContext->magic)
11454 {
11455 /* the caller presumably timed out so there is nothing we can do */
Jeff Johnson72a40512013-12-19 10:14:15 -080011456 spin_unlock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070011457 hddLog(VOS_TRACE_LEVEL_WARN,
11458 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070011459 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -070011460 return;
11461 }
11462
Jeff Johnson72a40512013-12-19 10:14:15 -080011463 /* context is valid so caller is still waiting */
11464
11465 /* paranoia: invalidate the magic */
11466 pContext->magic = 0;
11467
11468 /* notify the caller */
Jeff Johnson295189b2012-06-20 16:38:30 -070011469 complete(&pContext->completion);
Jeff Johnson72a40512013-12-19 10:14:15 -080011470
11471 /* serialization is complete */
11472 spin_unlock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070011473}
11474
Katya Nigamf0511f62015-05-05 16:40:57 +053011475void wlan_hdd_mon_set_typesubtype( hdd_mon_ctx_t *pMonCtx,int type)
11476{
11477 pMonCtx->typeSubtypeBitmap = 0;
11478 if( type%10 ) /* Management Packets */
11479 pMonCtx->typeSubtypeBitmap |= 0xFFFF;
11480 type/=10;
11481 if( type%10 ) /* Control Packets */
11482 pMonCtx->typeSubtypeBitmap |= 0xFFFF0000;
11483 type/=10;
11484 if( type%10 ) /* Data Packets */
11485 pMonCtx->typeSubtypeBitmap |= 0xFFFF00000000;
11486}
11487
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053011488VOS_STATUS wlan_hdd_mon_postMsg(tANI_U32 *magic, struct completion *cmpVar,
11489 hdd_mon_ctx_t *pMonCtx , void* callback)
Katya Nigamf0511f62015-05-05 16:40:57 +053011490{
11491 vos_msg_t monMsg;
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053011492 tSirMonModeReq *pMonModeReq;
Katya Nigamf0511f62015-05-05 16:40:57 +053011493
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053011494 if (MON_MODE_START == pMonCtx->state)
11495 monMsg.type = WDA_MON_START_REQ;
11496 else if (MON_MODE_STOP == pMonCtx->state)
11497 monMsg.type = WDA_MON_STOP_REQ;
11498 else {
11499 hddLog(VOS_TRACE_LEVEL_ERROR,
11500 FL("invalid monitor state %d"), pMonCtx->state);
Katya Nigamf0511f62015-05-05 16:40:57 +053011501 return VOS_STATUS_E_FAILURE;
11502 }
11503
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053011504 pMonModeReq = vos_mem_malloc(sizeof(tSirMonModeReq));
11505 if (pMonModeReq == NULL) {
11506 hddLog(VOS_TRACE_LEVEL_ERROR,
11507 FL("fail to allocate memory for monitor mode req"));
11508 return VOS_STATUS_E_FAILURE;
11509 }
Katya Nigamf0511f62015-05-05 16:40:57 +053011510
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053011511 pMonModeReq->magic = magic;
11512 pMonModeReq->cmpVar = cmpVar;
11513 pMonModeReq->data = pMonCtx;
11514 pMonModeReq->callback = callback;
Katya Nigamf0511f62015-05-05 16:40:57 +053011515
Katya Nigamf0511f62015-05-05 16:40:57 +053011516 monMsg.reserved = 0;
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053011517 monMsg.bodyptr = pMonModeReq;
Katya Nigamf0511f62015-05-05 16:40:57 +053011518 monMsg.bodyval = 0;
11519
11520 if (VOS_STATUS_SUCCESS != vos_mq_post_message(
11521 VOS_MODULE_ID_WDA,(vos_msg_t *)&monMsg)) {
11522 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: : Failed to post Msg to HAL",__func__);
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053011523 vos_mem_free(pMonModeReq);
Katya Nigamf0511f62015-05-05 16:40:57 +053011524 }
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053011525 return VOS_STATUS_SUCCESS;
Katya Nigamf0511f62015-05-05 16:40:57 +053011526}
11527
Katya Nigame7b69a82015-04-28 15:24:06 +053011528void wlan_hdd_mon_close(hdd_context_t *pHddCtx)
11529{
11530 VOS_STATUS vosStatus;
11531 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053011532 long ret;
11533 hdd_mon_ctx_t *pMonCtx = NULL;
11534 v_U32_t magic;
11535 struct completion cmpVar;
Hanumantha Reddy Pothulac99bc062015-09-08 14:59:26 +053011536
Katya Nigame7b69a82015-04-28 15:24:06 +053011537 hdd_adapter_t *pAdapter = hdd_get_adapter(pHddCtx,WLAN_HDD_MONITOR);
11538 if(pAdapter == NULL || pVosContext == NULL)
11539 {
11540 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:pAdapter is NULL",__func__);
11541 return ;
11542 }
Katya Nigamf0511f62015-05-05 16:40:57 +053011543
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053011544 pMonCtx = WLAN_HDD_GET_MONITOR_CTX_PTR(pAdapter);
11545 if (pMonCtx!= NULL && pMonCtx->state == MON_MODE_START) {
11546 pMonCtx->state = MON_MODE_STOP;
11547 magic = MON_MODE_MSG_MAGIC;
11548 init_completion(&cmpVar);
11549 if (VOS_STATUS_SUCCESS !=
11550 wlan_hdd_mon_postMsg(&magic, &cmpVar,
11551 pMonCtx, hdd_monPostMsgCb)) {
11552 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
11553 FL("failed to post MON MODE REQ"));
11554 pMonCtx->state = MON_MODE_START;
11555 magic = 0;
11556 return;
11557 }
11558 ret = wait_for_completion_timeout(&cmpVar, MON_MODE_MSG_TIMEOUT);
11559 magic = 0;
11560 if (ret <= 0 ) {
11561 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
11562 FL("timeout on monitor mode completion %ld"), ret);
11563 }
11564 }
11565
Katya Nigame7b69a82015-04-28 15:24:06 +053011566 hdd_UnregisterWext(pAdapter->dev);
11567
11568 vos_mon_stop( pVosContext );
11569
11570 vosStatus = vos_sched_close( pVosContext );
11571 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
11572 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
11573 "%s: Failed to close VOSS Scheduler",__func__);
11574 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
11575 }
11576
11577 vosStatus = vos_nv_close();
11578 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
11579 {
11580 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
11581 "%s: Failed to close NV", __func__);
11582 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
11583 }
11584
11585 vos_close(pVosContext);
11586
11587 #ifdef WLAN_KD_READY_NOTIFIER
11588 nl_srv_exit(pHddCtx->ptt_pid);
11589 #else
11590 nl_srv_exit();
11591 #endif
11592
Katya Nigame7b69a82015-04-28 15:24:06 +053011593 hdd_close_all_adapters( pHddCtx );
Katya Nigame7b69a82015-04-28 15:24:06 +053011594}
Agrawal Ashish33ec71e2015-11-26 20:20:58 +053011595/**
11596 * hdd_wlan_free_wiphy_channels - free Channel pointer for wiphy
11597 * @ wiphy: the wiphy to validate against
11598 *
11599 * Return: void
11600 */
11601void hdd_wlan_free_wiphy_channels(struct wiphy *wiphy)
11602{
11603 int i =0;
Rajeev Kumar Sirasanagandla5b21a9c2018-01-08 17:05:11 +053011604 for (i = 0; i < HDD_NUM_NL80211_BANDS; i++)
Agrawal Ashish33ec71e2015-11-26 20:20:58 +053011605 {
11606 if (NULL != wiphy->bands[i] &&
11607 (NULL != wiphy->bands[i]->channels))
11608 {
11609 vos_mem_free(wiphy->bands[i]->channels);
11610 wiphy->bands[i]->channels = NULL;
11611 }
11612 }
11613}
Jeff Johnson295189b2012-06-20 16:38:30 -070011614/**---------------------------------------------------------------------------
11615
11616 \brief hdd_wlan_exit() - HDD WLAN exit function
11617
11618 This is the driver exit point (invoked during rmmod)
11619
11620 \param - pHddCtx - Pointer to the HDD Context
11621
11622 \return - None
11623
11624 --------------------------------------------------------------------------*/
11625void hdd_wlan_exit(hdd_context_t *pHddCtx)
11626{
11627 eHalStatus halStatus;
11628 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
11629 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +053011630 struct wiphy *wiphy = pHddCtx->wiphy;
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -080011631 hdd_adapter_t* pAdapter = NULL;
Jeff Johnson72a40512013-12-19 10:14:15 -080011632 struct statsContext powerContext;
Jeff Johnson295189b2012-06-20 16:38:30 -070011633 long lrc;
c_hpothu5ab05e92014-06-13 17:34:05 +053011634 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -070011635
11636 ENTER();
11637
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053011638
Katya Nigame7b69a82015-04-28 15:24:06 +053011639 if (VOS_MONITOR_MODE == hdd_get_conparam())
11640 {
11641 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: MONITOR MODE",__func__);
11642 wlan_hdd_mon_close(pHddCtx);
Hanumantha Reddy Pothulac99bc062015-09-08 14:59:26 +053011643 goto free_hdd_ctx;
Katya Nigame7b69a82015-04-28 15:24:06 +053011644 }
11645 else if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -080011646 {
11647 // Unloading, restart logic is no more required.
11648 wlan_hdd_restart_deinit(pHddCtx);
Jeff Johnsone7245742012-09-05 17:12:55 -070011649
Agarwal Ashishb20e0ff2014-12-17 22:50:19 +053011650#ifdef FEATURE_WLAN_TDLS
11651 /* At the time of driver unloading; if tdls connection is present;
11652 * hdd_rx_packet_cbk calls wlan_hdd_tdls_find_peer.
11653 * wlan_hdd_tdls_find_peer always checks for valid context;
11654 * as load/unload in progress there can be a race condition.
11655 * hdd_rx_packet_cbk calls wlan_hdd_tdls_find_peer only
11656 * when tdls state is enabled.
11657 * As soon as driver set load/unload flag; tdls flag also needs
11658 * to be disabled so that hdd_rx_packet_cbk won't call
11659 * wlan_hdd_tdls_find_peer.
11660 */
Masti, Narayanraddi20494af2015-12-17 20:56:42 +053011661 wlan_hdd_tdls_set_mode(pHddCtx, eTDLS_SUPPORT_DISABLED, FALSE,
11662 HDD_SET_TDLS_MODE_SOURCE_USER);
Agarwal Ashishb20e0ff2014-12-17 22:50:19 +053011663#endif
11664
c_hpothu5ab05e92014-06-13 17:34:05 +053011665 vosStatus = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
11666 while (NULL != pAdapterNode && VOS_STATUS_E_EMPTY != vosStatus)
Jeff Johnson295189b2012-06-20 16:38:30 -070011667 {
c_hpothu5ab05e92014-06-13 17:34:05 +053011668 pAdapter = pAdapterNode->pAdapter;
11669 if (NULL != pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -070011670 {
Mahesh A Saptasagar305e2632015-03-04 12:57:33 +053011671 /* Disable TX on the interface, after this hard_start_xmit() will
11672 * not be called on that interface
11673 */
11674 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
11675 netif_tx_disable(pAdapter->dev);
11676
11677 /* Mark the interface status as "down" for outside world */
11678 netif_carrier_off(pAdapter->dev);
11679
Agarwal Ashish9ffa5b92014-11-18 21:07:02 +053011680 /* DeInit the adapter. This ensures that all data packets
11681 * are freed.
11682 */
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +053011683#ifdef FEATURE_WLAN_TDLS
11684 mutex_lock(&pHddCtx->tdls_lock);
11685#endif
c_hpothu002231a2015-02-05 14:58:51 +053011686 hdd_deinit_adapter(pHddCtx, pAdapter, FALSE);
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +053011687#ifdef FEATURE_WLAN_TDLS
11688 mutex_unlock(&pHddCtx->tdls_lock);
11689#endif
Masti, Narayanraddi26378462016-01-05 18:20:28 +053011690 vos_flush_delayed_work(&pHddCtx->scan_ctxt.scan_work);
11691
11692 wlan_hdd_init_deinit_defer_scan_context(&pHddCtx->scan_ctxt);
Agarwal Ashish9ffa5b92014-11-18 21:07:02 +053011693
c_hpothu5ab05e92014-06-13 17:34:05 +053011694 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode ||
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +053011695 WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ||
11696 WLAN_HDD_MONITOR == pAdapter->device_mode)
c_hpothu5ab05e92014-06-13 17:34:05 +053011697 {
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +053011698 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode ||
11699 WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)
11700 wlan_hdd_cfg80211_deregister_frames(pAdapter);
11701
c_hpothu5ab05e92014-06-13 17:34:05 +053011702 hdd_UnregisterWext(pAdapter->dev);
11703 }
Kaushik, Sushant4975a572014-10-21 16:07:48 +053011704
Jeff Johnson295189b2012-06-20 16:38:30 -070011705 }
c_hpothu5ab05e92014-06-13 17:34:05 +053011706 vosStatus = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
11707 pAdapterNode = pNext;
Jeff Johnson295189b2012-06-20 16:38:30 -070011708 }
mukul sharmabab477d2015-06-11 17:14:55 +053011709
Kaushik, Sushant4975a572014-10-21 16:07:48 +053011710 // Cancel any outstanding scan requests. We are about to close all
11711 // of our adapters, but an adapter structure is what SME passes back
11712 // to our callback function. Hence if there are any outstanding scan
11713 // requests then there is a race condition between when the adapter
11714 // is closed and when the callback is invoked.We try to resolve that
11715 // race condition here by canceling any outstanding scans before we
11716 // close the adapters.
11717 // Note that the scans may be cancelled in an asynchronous manner,
11718 // so ideally there needs to be some kind of synchronization. Rather
11719 // than introduce a new synchronization here, we will utilize the
11720 // fact that we are about to Request Full Power, and since that is
11721 // synchronized, the expectation is that by the time Request Full
11722 // Power has completed all scans will be cancelled.
11723 if (pHddCtx->scan_info.mScanPending)
11724 {
Hema Aparna Medicharlaf05f6cd2015-01-21 14:44:19 +053011725 if(NULL != pAdapter)
11726 {
11727 hddLog(VOS_TRACE_LEVEL_INFO,
11728 FL("abort scan mode: %d sessionId: %d"),
11729 pAdapter->device_mode,
11730 pAdapter->sessionId);
11731 }
11732 hdd_abort_mac_scan(pHddCtx,
11733 pHddCtx->scan_info.sessionId,
11734 eCSR_SCAN_ABORT_DEFAULT);
Kaushik, Sushant4975a572014-10-21 16:07:48 +053011735 }
Jeff Johnson295189b2012-06-20 16:38:30 -070011736 }
c_hpothu5ab05e92014-06-13 17:34:05 +053011737 else
Jeff Johnson88ba7742013-02-27 14:36:02 -080011738 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +053011739 hddLog(VOS_TRACE_LEVEL_INFO,"%s: FTM MODE",__func__);
Hanumantha Reddy Pothula45af96b2015-02-12 16:07:58 +053011740 if (pHddCtx->ftm.ftm_state == WLAN_FTM_STARTING)
11741 {
11742 INIT_COMPLETION(pHddCtx->ftm.startCmpVar);
11743 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
11744 "%s: in middle of FTM START", __func__);
11745 lrc = wait_for_completion_timeout(&pHddCtx->ftm.startCmpVar,
11746 msecs_to_jiffies(20000));
11747 if(!lrc)
11748 {
11749 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
11750 "%s: timedout on ftmStartCmpVar fatal error", __func__);
11751 }
11752 }
Jeff Johnson88ba7742013-02-27 14:36:02 -080011753 wlan_hdd_ftm_close(pHddCtx);
11754 goto free_hdd_ctx;
11755 }
c_hpothu6ff1c3c2013-10-01 19:01:57 +053011756
Jeff Johnson295189b2012-06-20 16:38:30 -070011757 /* DeRegister with platform driver as client for Suspend/Resume */
11758 vosStatus = hddDeregisterPmOps(pHddCtx);
11759 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
11760 {
11761 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
11762 VOS_ASSERT(0);
11763 }
11764
11765 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
11766 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
11767 {
11768 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
11769 }
Jeff Johnson295189b2012-06-20 16:38:30 -070011770
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -070011771 //Stop the traffic monitor timer
Mahesh A Saptasagard461e432016-07-20 15:01:40 +053011772 if ((pHddCtx->cfg_ini->dynSplitscan) && (VOS_TIMER_STATE_RUNNING ==
11773 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr)))
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -070011774 {
11775 vos_timer_stop(&pHddCtx->tx_rx_trafficTmr);
11776 }
11777
11778 // Destroy the traffic monitor timer
Mahesh A Saptasagard461e432016-07-20 15:01:40 +053011779 if ((pHddCtx->cfg_ini->dynSplitscan) &&
11780 (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
11781 &pHddCtx->tx_rx_trafficTmr))))
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -070011782 {
11783 hddLog(VOS_TRACE_LEVEL_ERROR,
11784 "%s: Cannot deallocate Traffic monitor timer", __func__);
11785 }
11786
Bhargav Shahd0715912015-10-01 18:17:37 +053011787 if (VOS_TIMER_STATE_RUNNING ==
11788 vos_timer_getCurrentState(&pHddCtx->delack_timer)) {
11789 vos_timer_stop(&pHddCtx->delack_timer);
11790 }
11791
11792 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
11793 &pHddCtx->delack_timer))) {
11794 hddLog(VOS_TRACE_LEVEL_ERROR,
11795 "%s: Cannot deallocate Bus bandwidth timer", __func__);
11796 }
11797
Masti, Narayanraddi44b0db02015-12-22 11:54:35 +053011798 if (VOS_TIMER_STATE_RUNNING ==
11799 vos_timer_getCurrentState(&pHddCtx->tdls_source_timer)) {
11800 vos_timer_stop(&pHddCtx->tdls_source_timer);
11801 }
11802
Abhishek Singh8a3e4dc2017-01-02 10:39:18 +053011803 vos_set_snoc_high_freq_voting(false);
11804
Masti, Narayanraddi44b0db02015-12-22 11:54:35 +053011805 vos_timer_destroy(&pHddCtx->tdls_source_timer);
11806
Jeff Johnson295189b2012-06-20 16:38:30 -070011807 //Disable IMPS/BMPS as we do not want the device to enter any power
11808 //save mode during shutdown
11809 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
11810 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
11811 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
11812
11813 //Ensure that device is in full power as we will touch H/W during vos_Stop
11814 init_completion(&powerContext.completion);
11815 powerContext.magic = POWER_CONTEXT_MAGIC;
11816
11817 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
11818 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
11819
11820 if (eHAL_STATUS_SUCCESS != halStatus)
11821 {
11822 if (eHAL_STATUS_PMC_PENDING == halStatus)
11823 {
11824 /* request was sent -- wait for the response */
11825 lrc = wait_for_completion_interruptible_timeout(
11826 &powerContext.completion,
11827 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
Jeff Johnson295189b2012-06-20 16:38:30 -070011828 if (lrc <= 0)
11829 {
11830 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070011831 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -070011832 }
11833 }
11834 else
11835 {
11836 hddLog(VOS_TRACE_LEVEL_ERROR,
11837 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070011838 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -070011839 /* continue -- need to clean up as much as possible */
11840 }
11841 }
Hanumantha Reddy Pothula81b42b22015-05-12 13:52:00 +053011842 if ((eHAL_STATUS_SUCCESS == halStatus) ||
11843 (eHAL_STATUS_PMC_PENDING == halStatus && lrc > 0))
11844 {
11845 /* This will issue a dump command which will clean up
11846 BTQM queues and unblock MC thread */
11847 vos_fwDumpReq(274, 0, 0, 0, 0, 1);
11848 }
Jeff Johnson295189b2012-06-20 16:38:30 -070011849
Jeff Johnson72a40512013-12-19 10:14:15 -080011850 /* either we never sent a request, we sent a request and received a
11851 response or we sent a request and timed out. if we never sent a
11852 request or if we sent a request and got a response, we want to
11853 clear the magic out of paranoia. if we timed out there is a
11854 race condition such that the callback function could be
11855 executing at the same time we are. of primary concern is if the
11856 callback function had already verified the "magic" but had not
11857 yet set the completion variable when a timeout occurred. we
11858 serialize these activities by invalidating the magic while
11859 holding a shared spinlock which will cause us to block if the
11860 callback is currently executing */
11861 spin_lock(&hdd_context_lock);
11862 powerContext.magic = 0;
11863 spin_unlock(&hdd_context_lock);
11864
Hema Aparna Medicharlaa6cf65e2015-06-01 16:23:28 +053011865 /* If Device is shutdown, no point for SME to wait for responses
11866 from device. Pre Close SME */
11867 if(wcnss_device_is_shutdown())
11868 {
11869 sme_PreClose(pHddCtx->hHal);
11870 }
Yue Ma0d4891e2013-08-06 17:01:45 -070011871 hdd_debugfs_exit(pHddCtx);
11872
Ratheesh S P35ed8b12015-04-27 14:01:07 +053011873#ifdef WLAN_NS_OFFLOAD
Ratheesh S P36dbc932015-08-07 14:28:57 +053011874 hddLog(LOG1, FL("Unregister IPv6 notifier"));
Ratheesh S P35ed8b12015-04-27 14:01:07 +053011875 unregister_inet6addr_notifier(&pHddCtx->ipv6_notifier);
11876#endif
Ratheesh S P36dbc932015-08-07 14:28:57 +053011877 hddLog(LOG1, FL("Unregister IPv4 notifier"));
Ratheesh S P35ed8b12015-04-27 14:01:07 +053011878 unregister_inetaddr_notifier(&pHddCtx->ipv4_notifier);
11879
Jeff Johnson295189b2012-06-20 16:38:30 -070011880 // Unregister the Net Device Notifier
11881 unregister_netdevice_notifier(&hdd_netdev_notifier);
11882
Jeff Johnson295189b2012-06-20 16:38:30 -070011883 hdd_stop_all_adapters( pHddCtx );
11884
Jeff Johnson295189b2012-06-20 16:38:30 -070011885#ifdef WLAN_BTAMP_FEATURE
11886 vosStatus = WLANBAP_Stop(pVosContext);
11887 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
11888 {
11889 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
11890 "%s: Failed to stop BAP",__func__);
11891 }
11892#endif //WLAN_BTAMP_FEATURE
11893
11894 //Stop all the modules
11895 vosStatus = vos_stop( pVosContext );
11896 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
11897 {
11898 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
11899 "%s: Failed to stop VOSS",__func__);
11900 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
Hanumantha Reddy Pothulabd9601a2016-02-12 13:22:27 +053011901 if (isSsrPanicOnFailure())
11902 VOS_BUG(0);
Jeff Johnson295189b2012-06-20 16:38:30 -070011903 }
11904
Jeff Johnson295189b2012-06-20 16:38:30 -070011905 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -070011906 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -070011907
11908 //Close the scheduler before calling vos_close to make sure no thread is
11909 // scheduled after the each module close is called i.e after all the data
11910 // structures are freed.
11911 vosStatus = vos_sched_close( pVosContext );
11912 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
11913 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
11914 "%s: Failed to close VOSS Scheduler",__func__);
11915 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
11916 }
Jeff Johnsone7245742012-09-05 17:12:55 -070011917#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
11918 /* Destroy the wake lock */
Sushant Kaushik83392fa2015-05-05 17:44:40 +053011919 vos_wake_lock_destroy(&pHddCtx->rx_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -070011920#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -080011921 /* Destroy the wake lock */
Sushant Kaushik83392fa2015-05-05 17:44:40 +053011922 vos_wake_lock_destroy(&pHddCtx->sap_wake_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070011923
Mihir Shete7a24b5f2013-12-21 12:18:31 +053011924#ifdef CONFIG_ENABLE_LINUX_REG
11925 vosStatus = vos_nv_close();
11926 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
11927 {
11928 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
11929 "%s: Failed to close NV", __func__);
11930 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
11931 }
11932#endif
11933
Jeff Johnson295189b2012-06-20 16:38:30 -070011934 //Close VOSS
11935 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
11936 vos_close(pVosContext);
11937
Jeff Johnson295189b2012-06-20 16:38:30 -070011938 //Close Watchdog
11939 if(pHddCtx->cfg_ini->fIsLogpEnabled)
11940 vos_watchdog_close(pVosContext);
11941
Gopichand Nakkalaa0358482013-06-12 17:05:47 +053011942 //Clean up HDD Nlink Service
11943 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Gopichand Nakkalaa0358482013-06-12 17:05:47 +053011944
Manjeet Singh47ee8472016-04-11 11:57:18 +053011945 hdd_close_tx_queues(pHddCtx);
c_manjeecfd1efb2015-09-25 19:32:34 +053011946 wlan_free_fwr_mem_dump_buffer();
11947 memdump_deinit();
11948
Vinay Krishna Erannad938c422014-03-10 17:14:21 +053011949#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +053011950 if (pHddCtx->cfg_ini->wlanLoggingEnable)
Vinay Krishna Erannad938c422014-03-10 17:14:21 +053011951 {
11952 wlan_logging_sock_deactivate_svc();
11953 }
11954#endif
11955
Vinay Krishna Erannaef30b522014-08-26 17:48:16 +053011956#ifdef WLAN_KD_READY_NOTIFIER
11957 nl_srv_exit(pHddCtx->ptt_pid);
11958#else
11959 nl_srv_exit();
11960#endif /* WLAN_KD_READY_NOTIFIER */
11961
Abhishek Singh00b71972016-01-07 10:51:04 +053011962#ifdef WLAN_FEATURE_RMC
11963 hdd_close_cesium_nl_sock();
11964#endif /* WLAN_FEATURE_RMC */
Vinay Krishna Erannaef30b522014-08-26 17:48:16 +053011965
Jeff Johnson295189b2012-06-20 16:38:30 -070011966 hdd_close_all_adapters( pHddCtx );
11967
Padma, Santhosh Kumar9cd38332015-11-17 12:18:10 +053011968 vos_flush_delayed_work(&pHddCtx->spoof_mac_addr_work);
Abhishek Singh78c691f2017-11-30 13:48:44 +053011969 vos_flush_delayed_work(&pHddCtx->ecsa_chan_change_work);
Kapil Gupta137ef892016-12-13 19:38:00 +053011970 vos_flush_work(&pHddCtx->sap_start_work);
Padma, Santhosh Kumar9cd38332015-11-17 12:18:10 +053011971
Hanumantha Reddy Pothula97f9bc92015-08-10 17:21:20 +053011972free_hdd_ctx:
Jeff Johnson295189b2012-06-20 16:38:30 -070011973 /* free the power on lock from platform driver */
11974 if (free_riva_power_on_lock("wlan"))
11975 {
11976 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
11977 __func__);
11978 }
11979
c_hpothu78c7b602014-05-17 17:35:49 +053011980 //Free up dynamically allocated members inside HDD Adapter
11981 if (pHddCtx->cfg_ini)
11982 {
11983 kfree(pHddCtx->cfg_ini);
11984 pHddCtx->cfg_ini= NULL;
11985 }
11986
Hanumanth Reddy Pothula1efcd162018-03-14 14:32:27 +053011987 hdd_request_manager_deinit();
11988
Hanumantha Reddy Pothula6fe221c2016-01-28 15:01:09 +053011989 /* FTM/MONITOR mode, WIPHY did not registered
Leo Changf04ddad2013-09-18 13:46:38 -070011990 If un-register here, system crash will happen */
Hanumantha Reddy Pothula6fe221c2016-01-28 15:01:09 +053011991 if (!(VOS_FTM_MODE == hdd_get_conparam() ||
11992 VOS_MONITOR_MODE == hdd_get_conparam()))
Leo Changf04ddad2013-09-18 13:46:38 -070011993 {
11994 wiphy_unregister(wiphy) ;
Agrawal Ashish33ec71e2015-11-26 20:20:58 +053011995 hdd_wlan_free_wiphy_channels(wiphy);
Leo Changf04ddad2013-09-18 13:46:38 -070011996 }
Jeff Johnson295189b2012-06-20 16:38:30 -070011997 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -070011998 if (hdd_is_ssr_required())
11999 {
12000 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -070012001 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -070012002 msleep(5000);
12003 }
12004 hdd_set_ssr_required (VOS_FALSE);
12005}
12006
12007
12008/**---------------------------------------------------------------------------
12009
12010 \brief hdd_update_config_from_nv() - Function to update the contents of
12011 the running configuration with parameters taken from NV storage
12012
12013 \param - pHddCtx - Pointer to the HDD global context
12014
12015 \return - VOS_STATUS_SUCCESS if successful
12016
12017 --------------------------------------------------------------------------*/
12018static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
12019{
Jeff Johnson295189b2012-06-20 16:38:30 -070012020 v_BOOL_t itemIsValid = VOS_FALSE;
12021 VOS_STATUS status;
12022 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
12023 v_U8_t macLoop;
12024
12025 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
12026 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
12027 if(status != VOS_STATUS_SUCCESS)
12028 {
Arif Hussain6d2a3322013-11-17 19:50:10 -080012029 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed");
Jeff Johnson295189b2012-06-20 16:38:30 -070012030 return VOS_STATUS_E_FAILURE;
12031 }
12032
12033 if (itemIsValid == VOS_TRUE)
12034 {
Arif Hussain6d2a3322013-11-17 19:50:10 -080012035 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV");
Jeff Johnson295189b2012-06-20 16:38:30 -070012036 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
12037 VOS_MAX_CONCURRENCY_PERSONA);
12038 if(status != VOS_STATUS_SUCCESS)
12039 {
12040 /* Get MAC from NV fail, not update CFG info
12041 * INI MAC value will be used for MAC setting */
Arif Hussain6d2a3322013-11-17 19:50:10 -080012042 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed");
Jeff Johnson295189b2012-06-20 16:38:30 -070012043 return VOS_STATUS_E_FAILURE;
12044 }
12045
12046 /* If first MAC is not valid, treat all others are not valid
12047 * Then all MACs will be got from ini file */
12048 if(vos_is_macaddr_zero(&macFromNV[0]))
12049 {
12050 /* MAC address in NV file is not configured yet */
12051 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
12052 return VOS_STATUS_E_INVAL;
12053 }
12054
12055 /* Get MAC address from NV, update CFG info */
12056 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
12057 {
12058 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
12059 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +053012060 hddLog(VOS_TRACE_LEVEL_ERROR,"not valid MAC from NV for %d", macLoop);
Jeff Johnson295189b2012-06-20 16:38:30 -070012061 /* This MAC is not valid, skip it
12062 * This MAC will be got from ini file */
12063 }
12064 else
12065 {
12066 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
12067 (v_U8_t *)&macFromNV[macLoop].bytes[0],
12068 VOS_MAC_ADDR_SIZE);
12069 }
12070 }
12071 }
12072 else
12073 {
12074 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
12075 return VOS_STATUS_E_FAILURE;
12076 }
Jeff Johnson295189b2012-06-20 16:38:30 -070012077
Jeff Johnson295189b2012-06-20 16:38:30 -070012078
12079 return VOS_STATUS_SUCCESS;
12080}
12081
12082/**---------------------------------------------------------------------------
12083
12084 \brief hdd_post_voss_start_config() - HDD post voss start config helper
12085
12086 \param - pAdapter - Pointer to the HDD
12087
12088 \return - None
12089
12090 --------------------------------------------------------------------------*/
12091VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
12092{
12093 eHalStatus halStatus;
12094 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +053012095 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -070012096
Jeff Johnson295189b2012-06-20 16:38:30 -070012097
12098 // Send ready indication to the HDD. This will kick off the MAC
12099 // into a 'running' state and should kick off an initial scan.
12100 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
12101 if ( !HAL_STATUS_SUCCESS( halStatus ) )
12102 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +053012103 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -070012104 "code %08d [x%08x]",__func__, halStatus, halStatus );
12105 return VOS_STATUS_E_FAILURE;
12106 }
12107
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +053012108 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -070012109 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
12110 // And RIVA will crash
12111 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
12112 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +053012113 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
12114 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
12115
12116
Jeff Johnson295189b2012-06-20 16:38:30 -070012117 return VOS_STATUS_SUCCESS;
12118}
12119
Jeff Johnson295189b2012-06-20 16:38:30 -070012120/* wake lock APIs for HDD */
Sushant Kaushik83392fa2015-05-05 17:44:40 +053012121void hdd_prevent_suspend(uint32_t reason)
Jeff Johnson295189b2012-06-20 16:38:30 -070012122{
Sushant Kaushik83392fa2015-05-05 17:44:40 +053012123
12124 vos_wake_lock_acquire(&wlan_wake_lock, reason);
12125
Jeff Johnson295189b2012-06-20 16:38:30 -070012126}
12127
Sushant Kaushik83392fa2015-05-05 17:44:40 +053012128void hdd_allow_suspend(uint32_t reason)
Jeff Johnson295189b2012-06-20 16:38:30 -070012129{
Sushant Kaushik83392fa2015-05-05 17:44:40 +053012130
12131 vos_wake_lock_release(&wlan_wake_lock, reason);
12132
Jeff Johnson295189b2012-06-20 16:38:30 -070012133}
12134
Sushant Kaushik83392fa2015-05-05 17:44:40 +053012135void hdd_prevent_suspend_timeout(v_U32_t timeout, uint32_t reason)
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -070012136{
Sushant Kaushik83392fa2015-05-05 17:44:40 +053012137
12138 vos_wake_lock_timeout_release(&wlan_wake_lock, timeout,
12139 reason);
12140
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -070012141}
12142
Jeff Johnson295189b2012-06-20 16:38:30 -070012143/**---------------------------------------------------------------------------
12144
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070012145 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
12146 information between Host and Riva
12147
12148 This function gets reported version of FW
12149 It also finds the version of Riva headers used to compile the host
12150 It compares the above two and prints a warning if they are different
12151 It gets the SW and HW version string
12152 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
12153 indicating the features they support through a bitmap
12154
12155 \param - pHddCtx - Pointer to HDD context
12156
12157 \return - void
12158
12159 --------------------------------------------------------------------------*/
12160
12161void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
12162{
12163
12164 tSirVersionType versionCompiled;
12165 tSirVersionType versionReported;
12166 tSirVersionString versionString;
12167 tANI_U8 fwFeatCapsMsgSupported = 0;
12168 VOS_STATUS vstatus;
12169
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -080012170 memset(&versionCompiled, 0, sizeof(versionCompiled));
12171 memset(&versionReported, 0, sizeof(versionReported));
12172
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070012173 /* retrieve and display WCNSS version information */
12174 do {
12175
12176 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
12177 &versionCompiled);
12178 if (!VOS_IS_STATUS_SUCCESS(vstatus))
12179 {
12180 hddLog(VOS_TRACE_LEVEL_FATAL,
12181 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070012182 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070012183 break;
12184 }
12185
12186 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
12187 &versionReported);
12188 if (!VOS_IS_STATUS_SUCCESS(vstatus))
12189 {
12190 hddLog(VOS_TRACE_LEVEL_FATAL,
12191 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070012192 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070012193 break;
12194 }
12195
12196 if ((versionCompiled.major != versionReported.major) ||
12197 (versionCompiled.minor != versionReported.minor) ||
12198 (versionCompiled.version != versionReported.version) ||
12199 (versionCompiled.revision != versionReported.revision))
12200 {
12201 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
12202 "Host expected %u.%u.%u.%u\n",
12203 WLAN_MODULE_NAME,
12204 (int)versionReported.major,
12205 (int)versionReported.minor,
12206 (int)versionReported.version,
12207 (int)versionReported.revision,
12208 (int)versionCompiled.major,
12209 (int)versionCompiled.minor,
12210 (int)versionCompiled.version,
12211 (int)versionCompiled.revision);
12212 }
12213 else
12214 {
12215 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
12216 WLAN_MODULE_NAME,
12217 (int)versionReported.major,
12218 (int)versionReported.minor,
12219 (int)versionReported.version,
12220 (int)versionReported.revision);
12221 }
12222
12223 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
12224 versionString,
12225 sizeof(versionString));
12226 if (!VOS_IS_STATUS_SUCCESS(vstatus))
12227 {
12228 hddLog(VOS_TRACE_LEVEL_FATAL,
12229 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070012230 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070012231 break;
12232 }
12233
12234 pr_info("%s: WCNSS software version %s\n",
12235 WLAN_MODULE_NAME, versionString);
Sushant Kaushik084f6592015-09-10 13:11:56 +053012236 vos_mem_copy(pHddCtx->fw_Version, versionString, sizeof(versionString));
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070012237
12238 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
12239 versionString,
12240 sizeof(versionString));
12241 if (!VOS_IS_STATUS_SUCCESS(vstatus))
12242 {
12243 hddLog(VOS_TRACE_LEVEL_FATAL,
12244 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070012245 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070012246 break;
12247 }
12248
12249 pr_info("%s: WCNSS hardware version %s\n",
12250 WLAN_MODULE_NAME, versionString);
12251
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -070012252 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
12253 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070012254 send the message only if it the riva is 1.1
12255 minor numbers for different riva branches:
12256 0 -> (1.0)Mainline Build
12257 1 -> (1.1)Mainline Build
12258 2->(1.04) Stability Build
12259 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -070012260 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070012261 ((versionReported.minor>=1) && (versionReported.version>=1)))
12262 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
12263 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -070012264
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070012265 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -080012266 {
12267#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
12268 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
12269 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
12270#endif
Ravi Joshid2ca7c42013-07-23 08:37:49 -070012271 /* Indicate if IBSS heartbeat monitoring needs to be offloaded */
12272 if (!pHddCtx->cfg_ini->enableIbssHeartBeatOffload)
12273 {
12274 sme_disableFeatureCapablity(IBSS_HEARTBEAT_OFFLOAD);
12275 }
12276
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070012277 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -080012278 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070012279
12280 } while (0);
12281
12282}
Neelansh Mittaledafed22014-09-04 18:54:39 +053012283void wlan_hdd_send_svc_nlink_msg(int type, void *data, int len)
12284{
12285 struct sk_buff *skb;
12286 struct nlmsghdr *nlh;
12287 tAniMsgHdr *ani_hdr;
Hanumantha Reddy Pothulacf2c7ea2015-04-27 14:50:47 +053012288 int flags = GFP_KERNEL;
Bhargav shah23c94942015-10-13 12:48:35 +053012289 void *nl_data = NULL;
Neelansh Mittaledafed22014-09-04 18:54:39 +053012290
Hanumantha Reddy Pothulacf2c7ea2015-04-27 14:50:47 +053012291 if (in_interrupt() || irqs_disabled() || in_atomic())
12292 flags = GFP_ATOMIC;
12293
12294 skb = alloc_skb(NLMSG_SPACE(WLAN_NL_MAX_PAYLOAD), flags);
Neelansh Mittaledafed22014-09-04 18:54:39 +053012295
12296 if(skb == NULL) {
12297 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
12298 "%s: alloc_skb failed", __func__);
12299 return;
12300 }
12301
12302 nlh = (struct nlmsghdr *)skb->data;
12303 nlh->nlmsg_pid = 0; /* from kernel */
12304 nlh->nlmsg_flags = 0;
12305 nlh->nlmsg_seq = 0;
12306 nlh->nlmsg_type = WLAN_NL_MSG_SVC;
12307
12308 ani_hdr = NLMSG_DATA(nlh);
12309 ani_hdr->type = type;
12310
12311 switch(type) {
12312 case WLAN_SVC_SAP_RESTART_IND:
12313 ani_hdr->length = 0;
12314 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr)));
12315 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr)));
12316 break;
Bhargav Shahd0715912015-10-01 18:17:37 +053012317 case WLAN_SVC_WLAN_TP_IND:
12318 ani_hdr->length = len;
12319 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr)
12320 + len));
12321 nl_data = (char *)ani_hdr + sizeof(tAniMsgHdr);
12322 memcpy(nl_data, data, len);
12323 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + len));
12324 break;
Bhargav shah23c94942015-10-13 12:48:35 +053012325 case WLAN_MSG_RPS_ENABLE_IND:
12326 ani_hdr->length = len;
12327 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + len));
12328 nl_data = (char *)ani_hdr + sizeof(tAniMsgHdr);
12329 memcpy(nl_data, data, len);
12330 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + len));
12331 break;
Neelansh Mittaledafed22014-09-04 18:54:39 +053012332 default:
12333 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
12334 "Attempt to send unknown nlink message %d", type);
12335 kfree_skb(skb);
12336 return;
12337 }
12338
12339 nl_srv_bcast(skb);
12340
12341 return;
12342}
12343
Bhargav Shahd0715912015-10-01 18:17:37 +053012344/**
12345 * hdd_request_tcp_delack() - Find the Delack value based on RX packet
12346 * @pHddCtx: Valid Global HDD context pointer
12347 * @rx_packets: Number of RX packet in perticular time
12348 *
12349 * Based on the RX packet this function calculate next value of tcp delack.
12350 * This function compare rx packet value to high and low threshold limit.
12351 *
12352 * Return: void
12353 */
12354void hdd_request_tcp_delack(hdd_context_t *pHddCtx, uint64_t rx_packets)
12355{
12356 /* average of rx_packets and prev_rx is taken so that
12357 bus width doesnot fluctuate much */
12358 uint64_t temp_rx = (rx_packets + pHddCtx->prev_rx)/2;
12359 TP_IND_TYPE next_rx_level = pHddCtx->cur_rx_level;
Neelansh Mittaledafed22014-09-04 18:54:39 +053012360
Bhargav Shahd0715912015-10-01 18:17:37 +053012361 pHddCtx->prev_rx = rx_packets;
12362 if (temp_rx > pHddCtx->cfg_ini->tcpDelAckThresholdHigh)
12363 next_rx_level = TP_IND_HIGH;
12364 else if (temp_rx <= pHddCtx->cfg_ini->tcpDelAckThresholdLow)
12365 next_rx_level = TP_IND_LOW;
12366
12367 hdd_set_delack_value(pHddCtx, next_rx_level);
12368}
12369
12370#define HDD_BW_GET_DIFF(x, y) ((x) >= (y) ? (x) - (y) : (ULONG_MAX - (y) + (x)))
12371
12372/**
12373 * hdd_tcp_delack_compute_function() - get link status
12374 * @priv: Valid Global HDD context pointer
12375 *
12376 * This function find number of RX packet during timer life span.
12377 * It request tcp delack with number of RX packet and re-configure delack timer
12378 * for tcpDelAckComputeInterval timer interval.
12379 *
12380 * Return: void
12381 */
12382void hdd_tcp_delack_compute_function(void *priv)
12383{
12384 hdd_context_t *pHddCtx = (hdd_context_t *)priv;
12385 hdd_adapter_t *pAdapter = NULL;
12386 v_U32_t rx_packets = 0;
12387 hdd_adapter_list_node_t *pAdapterNode = NULL;
12388 VOS_STATUS status = 0;
12389
12390 for (status = hdd_get_front_adapter(pHddCtx, &pAdapterNode);
12391 NULL != pAdapterNode && VOS_STATUS_SUCCESS == status;
12392 status = hdd_get_next_adapter(pHddCtx, pAdapterNode, &pAdapterNode)) {
12393 if ((pAdapter = pAdapterNode->pAdapter) == NULL)
12394 continue;
12395
12396 rx_packets += HDD_BW_GET_DIFF(pAdapter->stats.rx_packets,
12397 pAdapter->prev_rx_packets);
12398 pAdapter->prev_rx_packets = pAdapter->stats.rx_packets;
12399 }
12400
12401 hdd_request_tcp_delack(pHddCtx, rx_packets);
12402
12403 vos_timer_start(&pHddCtx->delack_timer,
12404 pHddCtx->cfg_ini->tcpDelAckComputeInterval);
12405}
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070012406
12407/**---------------------------------------------------------------------------
12408
Gopichand Nakkalafce506f2013-07-03 23:55:16 +053012409 \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
12410
12411 \param - pHddCtx - Pointer to the hdd context
12412
12413 \return - true if hardware supports 5GHz
12414
12415 --------------------------------------------------------------------------*/
Vinay Krishna Erannafacf5e22014-02-24 13:16:25 +053012416boolean hdd_is_5g_supported(hdd_context_t * pHddCtx)
Gopichand Nakkalafce506f2013-07-03 23:55:16 +053012417{
12418 /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
12419 * then hardware support 5Ghz.
12420 */
12421 if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode())
12422 {
Ratheesh S P36dbc932015-08-07 14:28:57 +053012423 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware supports 5Ghz", __func__);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +053012424 return true;
12425 }
12426 else
12427 {
Ratheesh S P36dbc932015-08-07 14:28:57 +053012428 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware doesn't supports 5Ghz",
Gopichand Nakkalafce506f2013-07-03 23:55:16 +053012429 __func__);
12430 return false;
12431 }
12432}
12433
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053012434/**---------------------------------------------------------------------------
12435
12436 \brief hdd_generate_iface_mac_addr_auto() - HDD Mac Interface Auto
12437 generate function
12438
12439 This is generate the random mac address for WLAN interface
12440
12441 \param - pHddCtx - Pointer to HDD context
12442 idx - Start interface index to get auto
12443 generated mac addr.
12444 mac_addr - Mac address
12445
12446 \return - 0 for success, < 0 for failure
12447
12448 --------------------------------------------------------------------------*/
12449
12450static int hdd_generate_iface_mac_addr_auto(hdd_context_t *pHddCtx,
12451 int idx, v_MACADDR_t mac_addr)
12452{
12453 int i;
12454 unsigned int serialno;
12455 serialno = wcnss_get_serial_number();
12456
12457 if (0 != serialno)
12458 {
12459 /* MAC address has 3 bytes of OUI so we have a maximum of 3
12460 bytes of the serial number that can be used to generate
12461 the other 3 bytes of the MAC address. Mask off all but
12462 the lower 3 bytes (this will also make sure we don't
12463 overflow in the next step) */
12464 serialno &= 0x00FFFFFF;
12465
12466 /* we need a unique address for each session */
12467 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
12468
12469 /* autogen other Mac addresses */
12470 for (i = idx; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
12471 {
12472 /* start with the entire default address */
12473 pHddCtx->cfg_ini->intfMacAddr[i] = mac_addr;
12474 /* then replace the lower 3 bytes */
12475 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
12476 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
12477 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
12478
Nachiket Kukadede2e24f2017-09-25 16:24:27 +053012479 if (0 == memcmp(&pHddCtx->cfg_ini->intfMacAddr[i].bytes[0],
12480 &mac_addr.bytes[0], VOS_MAC_ADDR_SIZE))
12481 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] +=
12482 VOS_MAX_CONCURRENCY_PERSONA;
12483
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053012484 serialno++;
12485 hddLog(VOS_TRACE_LEVEL_ERROR,
12486 "%s: Derived Mac Addr: "
12487 MAC_ADDRESS_STR, __func__,
12488 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[i].bytes));
12489 }
12490
12491 }
12492 else
12493 {
12494 hddLog(LOGE, FL("Failed to Get Serial NO"));
12495 return -1;
12496 }
12497 return 0;
12498}
Gopichand Nakkalafce506f2013-07-03 23:55:16 +053012499
Katya Nigame7b69a82015-04-28 15:24:06 +053012500int wlan_hdd_mon_open(hdd_context_t *pHddCtx)
12501{
12502 VOS_STATUS status;
12503 v_CONTEXT_t pVosContext= NULL;
12504 hdd_adapter_t *pAdapter= NULL;
12505
12506 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
12507
12508 if (NULL == pVosContext)
12509 {
12510 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
12511 "%s: Trying to open VOSS without a PreOpen", __func__);
12512 VOS_ASSERT(0);
12513 return VOS_STATUS_E_FAILURE;
12514 }
12515
12516 status = vos_nv_open();
12517 if (!VOS_IS_STATUS_SUCCESS(status))
12518 {
12519 /* NV module cannot be initialized */
12520 hddLog( VOS_TRACE_LEVEL_FATAL,
12521 "%s: vos_nv_open failed", __func__);
12522 return VOS_STATUS_E_FAILURE;
12523 }
12524
12525 status = vos_init_wiphy_from_nv_bin();
12526 if (!VOS_IS_STATUS_SUCCESS(status))
12527 {
12528 /* NV module cannot be initialized */
12529 hddLog( VOS_TRACE_LEVEL_FATAL,
12530 "%s: vos_init_wiphy failed", __func__);
12531 goto err_vos_nv_close;
12532 }
12533
12534 status = vos_open( &pVosContext, pHddCtx->parent_dev);
12535 if ( !VOS_IS_STATUS_SUCCESS( status ))
12536 {
12537 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
12538 goto err_vos_nv_close;
12539 }
12540
12541 status = vos_mon_start( pVosContext );
12542 if ( !VOS_IS_STATUS_SUCCESS( status ) )
12543 {
12544 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
12545 goto err_vosclose;
12546 }
12547
12548 WLANTL_SetMonRxCbk( pVosContext, hdd_rx_packet_monitor_cbk );
12549 WDA_featureCapsExchange(pVosContext);
12550 wcnss_wlan_set_drvdata(pHddCtx->parent_dev, pHddCtx);
12551
12552 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_MONITOR, "wlan%d",
12553 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
12554 if( pAdapter == NULL )
12555 {
12556 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
12557 goto err_close_adapter;
12558 }
12559
12560 //Initialize the nlink service
12561 if(nl_srv_init() != 0)
12562 {
12563 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
12564 goto err_close_adapter;
12565 }
12566 return VOS_STATUS_SUCCESS;
12567
12568err_close_adapter:
12569 hdd_close_all_adapters( pHddCtx );
12570 vos_mon_stop( pVosContext );
12571err_vosclose:
12572 status = vos_sched_close( pVosContext );
12573 if (!VOS_IS_STATUS_SUCCESS(status)) {
12574 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
12575 "%s: Failed to close VOSS Scheduler", __func__);
12576 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
12577 }
12578 vos_close(pVosContext );
12579
12580err_vos_nv_close:
12581 vos_nv_close();
12582
12583return status;
12584}
Gopichand Nakkalafce506f2013-07-03 23:55:16 +053012585/**---------------------------------------------------------------------------
12586
Mihir Shetefc7ff5b2014-01-27 11:30:05 +053012587 \brief hdd_11d_scan_done - callback to be executed when 11d scan is
12588 completed to flush out the scan results
12589
12590 11d scan is done during driver load and is a passive scan on all
12591 channels supported by the device, 11d scans may find some APs on
12592 frequencies which are forbidden to be used in the regulatory domain
12593 the device is operating in. If these APs are notified to the supplicant
12594 it may try to connect to these APs, thus flush out all the scan results
12595 which are present in SME after 11d scan is done.
12596
12597 \return - eHalStatus
12598
12599 --------------------------------------------------------------------------*/
12600static eHalStatus hdd_11d_scan_done(tHalHandle halHandle, void *pContext,
12601 tANI_U32 scanId, eCsrScanStatus status)
12602{
12603 ENTER();
12604
12605 sme_ScanFlushResult(halHandle, 0);
12606
12607 EXIT();
12608
12609 return eHAL_STATUS_SUCCESS;
12610}
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012611/**---------------------------------------------------------------------------
12612
12613 \brief hdd_init_frame_logging_done - callback to be executed when mgmt frame
12614 logging is completed successfully.
12615
12616 \return - None
12617
12618 --------------------------------------------------------------------------*/
c_manjeecfd1efb2015-09-25 19:32:34 +053012619void hdd_init_frame_logging_done(void *fwlogInitCbContext, tAniLoggingInitRsp *pRsp)
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012620{
Siddharth Bhald1be97f2015-05-27 22:39:59 +053012621 hdd_context_t* pHddCtx = (hdd_context_t*)fwlogInitCbContext;
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012622
12623 if (NULL == pHddCtx)
12624 {
12625 hddLog(VOS_TRACE_LEVEL_ERROR,
12626 "%s: HDD context is NULL",__func__);
12627 return;
12628 }
12629
c_manjeecfd1efb2015-09-25 19:32:34 +053012630 if ((pRsp->status == VOS_STATUS_SUCCESS) &&
Mahesh A Saptasagarfabb1a02015-06-29 12:17:04 +053012631 (TRUE == pHddCtx->cfg_ini->enableMgmtLogging))
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012632 {
12633 hddLog(VOS_TRACE_LEVEL_INFO, FL("Mgmt Frame Logging init successful"));
12634 pHddCtx->mgmt_frame_logging = TRUE;
12635 }
12636 else
12637 {
12638 hddLog(VOS_TRACE_LEVEL_INFO, FL("Mgmt Frame Logging init not success"));
12639 pHddCtx->mgmt_frame_logging = FALSE;
c_manjeecfd1efb2015-09-25 19:32:34 +053012640 return;
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012641 }
12642
c_manjeecfd1efb2015-09-25 19:32:34 +053012643 /*Check feature supported by FW*/
12644 if(TRUE == sme_IsFeatureSupportedByFW(MEMORY_DUMP_SUPPORTED))
12645 {
12646 //Store fwr mem dump size given by firmware.
12647 wlan_store_fwr_mem_dump_size(pRsp->fw_mem_dump_max_size);
12648 }
12649 else
12650 {
12651 wlan_store_fwr_mem_dump_size(0);
12652 }
12653
12654
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012655}
12656/**---------------------------------------------------------------------------
12657
12658 \brief hdd_init_frame_logging - function to initialize frame logging.
12659 Currently only Mgmt Frames are logged in both TX
12660 and Rx direction and are sent to userspace
12661 application using logger thread when queried.
12662
12663 \return - None
12664
12665 --------------------------------------------------------------------------*/
Siddharth Bhald1be97f2015-05-27 22:39:59 +053012666void hdd_init_frame_logging(hdd_context_t* pHddCtx)
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012667{
12668 eHalStatus halStatus = eHAL_STATUS_FAILURE;
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053012669 tSirFWLoggingInitParam wlanFWLoggingInitParam = {0};
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012670
Siddharth Bhald1be97f2015-05-27 22:39:59 +053012671 if (TRUE != sme_IsFeatureSupportedByFW(MGMT_FRAME_LOGGING) &&
12672 TRUE != sme_IsFeatureSupportedByFW(LOGGING_ENHANCEMENT))
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012673 {
12674 hddLog(VOS_TRACE_LEVEL_INFO, FL("MGMT_FRAME_LOGGING not supp by FW"));
12675 return;
12676 }
12677
c_manjeecfd1efb2015-09-25 19:32:34 +053012678 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Configuring %s %s %s %s Logging",__func__,
Siddharth Bhald1be97f2015-05-27 22:39:59 +053012679 pHddCtx->cfg_ini->enableFWLogging?"FW Log,":"",
12680 pHddCtx->cfg_ini->enableContFWLogging ? "Cont FW log,":"",
c_manjeecfd1efb2015-09-25 19:32:34 +053012681 pHddCtx->cfg_ini->enableMgmtLogging ? "Mgmt Pkt Log":"",
12682 pHddCtx->cfg_ini->enableFwrMemDump ? "Fw Mem dump":"");
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012683
Siddharth Bhald1be97f2015-05-27 22:39:59 +053012684 if (pHddCtx->cfg_ini->enableFWLogging ||
12685 pHddCtx->cfg_ini->enableContFWLogging)
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012686 {
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053012687 wlanFWLoggingInitParam.enableFlag |= WLAN_QXDM_LOG_EN;
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012688 }
12689
Sushant Kaushik46804902015-07-08 14:46:03 +053012690 if (pHddCtx->cfg_ini->enableMgmtLogging)
12691 {
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053012692 wlanFWLoggingInitParam.enableFlag |= WLAN_FRAME_LOG_EN;
Sushant Kaushik46804902015-07-08 14:46:03 +053012693 }
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012694 if (pHddCtx->cfg_ini->enableBMUHWtracing)
12695 {
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053012696 wlanFWLoggingInitParam.enableFlag |= WLAN_BMUHW_TRACE_LOG_EN;
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012697 }
c_manjeecfd1efb2015-09-25 19:32:34 +053012698 if(pHddCtx->cfg_ini->enableFwrMemDump &&
12699 (TRUE == sme_IsFeatureSupportedByFW(MEMORY_DUMP_SUPPORTED)))
12700 {
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053012701 wlanFWLoggingInitParam.enableFlag |= WLAN_FW_MEM_DUMP_EN;
c_manjeecfd1efb2015-09-25 19:32:34 +053012702 }
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053012703 if( wlanFWLoggingInitParam.enableFlag == 0 )
c_manjeecfd1efb2015-09-25 19:32:34 +053012704 {
12705 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Logging not enabled", __func__);
12706 return;
12707 }
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053012708 wlanFWLoggingInitParam.frameType = WLAN_FRAME_LOGGING_FRAMETYPE_MGMT;
12709 wlanFWLoggingInitParam.frameSize = WLAN_MGMT_LOGGING_FRAMESIZE_128BYTES;
12710 wlanFWLoggingInitParam.bufferMode = WLAN_FRAME_LOGGING_BUFFERMODE_CIRCULAR;
12711 wlanFWLoggingInitParam.continuousFrameLogging =
Siddharth Bhald1be97f2015-05-27 22:39:59 +053012712 pHddCtx->cfg_ini->enableContFWLogging;
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012713
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053012714 wlanFWLoggingInitParam.enableFlag &= ~WLAN_DPU_TXP_LOG_EN;
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012715
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053012716 wlanFWLoggingInitParam.minLogBufferSize =
Siddharth Bhald1be97f2015-05-27 22:39:59 +053012717 pHddCtx->cfg_ini->minLoggingBufferSize;
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053012718 wlanFWLoggingInitParam.maxLogBufferSize =
Siddharth Bhald1be97f2015-05-27 22:39:59 +053012719 pHddCtx->cfg_ini->maxLoggingBufferSize;
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053012720 wlanFWLoggingInitParam.fwlogInitCallback = hdd_init_frame_logging_done;
12721 wlanFWLoggingInitParam.fwlogInitCbContext= pHddCtx;
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012722
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053012723 halStatus = sme_InitMgmtFrameLogging(pHddCtx->hHal, &wlanFWLoggingInitParam);
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012724
12725 if (eHAL_STATUS_SUCCESS != halStatus)
12726 {
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053012727 hddLog(LOGE, FL("sme_InitMgmtFrameLogging failed, returned %d"),
12728 halStatus);
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012729 }
12730
12731 return;
12732}
Mihir Shetefc7ff5b2014-01-27 11:30:05 +053012733
Bhargav shah23c94942015-10-13 12:48:35 +053012734static void hdd_dp_util_send_rps_ind(hdd_context_t *hdd_ctxt)
12735{
12736 hdd_adapter_t *adapter;
12737 hdd_adapter_list_node_t *adapter_node, *next;
12738 VOS_STATUS status = VOS_STATUS_SUCCESS;
12739 struct wlan_rps_data rps_data;
12740 int count;
12741
12742 if(!hdd_ctxt->cfg_ini->rps_mask)
12743 {
12744 return;
12745 }
12746
12747 for (count=0; count < WLAN_SVC_IFACE_NUM_QUEUES; count++)
12748 {
12749 rps_data.cpu_map[count] = hdd_ctxt->cfg_ini->rps_mask;
12750 }
12751
12752 rps_data.num_queues = WLAN_SVC_IFACE_NUM_QUEUES;
12753
12754 hddLog(LOG1, FL("0x%x 0x%x 0x%x 0x%x 0x%x 0x%x"),
12755 rps_data.cpu_map[0], rps_data.cpu_map[1],rps_data.cpu_map[2],
12756 rps_data.cpu_map[3], rps_data.cpu_map[4], rps_data.cpu_map[5]);
12757
12758 status = hdd_get_front_adapter (hdd_ctxt, &adapter_node);
12759
12760 while (NULL != adapter_node && VOS_STATUS_SUCCESS == status)
12761 {
12762 adapter = adapter_node->pAdapter;
12763 if (NULL != adapter) {
12764 strlcpy(rps_data.ifname, adapter->dev->name,
12765 sizeof(rps_data.ifname));
12766 wlan_hdd_send_svc_nlink_msg(WLAN_MSG_RPS_ENABLE_IND,
12767 (void *)&rps_data,sizeof(rps_data));
12768 }
12769 status = hdd_get_next_adapter (hdd_ctxt, adapter_node, &next);
12770 adapter_node = next;
12771 }
12772}
12773
Masti, Narayanraddi26378462016-01-05 18:20:28 +053012774void wlan_hdd_schedule_defer_scan(struct work_struct *work)
12775{
12776 scan_context_t *scan_ctx =
12777 container_of(work, scan_context_t, scan_work.work);
12778
12779 if (NULL == scan_ctx)
12780 {
12781 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
12782 FL("scan_ctx is NULL"));
12783 return;
12784 }
12785
12786 if (unlikely(TDLS_CTX_MAGIC != scan_ctx->magic))
12787 return;
12788
12789 scan_ctx->attempt++;
12790
12791 wlan_hdd_cfg80211_scan(scan_ctx->wiphy,
12792#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
12793 scan_ctx->dev,
12794#endif
12795 scan_ctx->scan_request);
12796}
12797
12798int wlan_hdd_copy_defer_scan_context(hdd_context_t *pHddCtx,
12799 struct wiphy *wiphy,
12800#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
12801 struct net_device *dev,
12802#endif
12803 struct cfg80211_scan_request *request)
12804{
12805 scan_context_t *scan_ctx;
12806
12807 ENTER();
12808 if (0 != (wlan_hdd_validate_context(pHddCtx)))
12809 {
12810 return -1;
12811 }
12812
12813 scan_ctx = &pHddCtx->scan_ctxt;
12814
12815 scan_ctx->wiphy = wiphy;
12816#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
12817 scan_ctx->dev = dev;
12818#endif
12819
12820 scan_ctx->scan_request = request;
12821
12822 EXIT();
12823 return 0;
12824}
12825
12826void wlan_hdd_defer_scan_init_work(hdd_context_t *pHddCtx,
12827 struct wiphy *wiphy,
12828#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
12829 struct net_device *dev,
12830#endif
12831 struct cfg80211_scan_request *request,
12832 unsigned long delay)
12833{
12834 if (TDLS_CTX_MAGIC != pHddCtx->scan_ctxt.magic)
12835 {
12836#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
12837 wlan_hdd_copy_defer_scan_context(pHddCtx, wiphy, dev, request);
12838#else
12839 wlan_hdd_copy_defer_scan_context(pHddCtx, wiphy, request);
12840#endif
12841 pHddCtx->scan_ctxt.attempt = 0;
12842 pHddCtx->scan_ctxt.magic = TDLS_CTX_MAGIC;
12843 }
12844 schedule_delayed_work(&pHddCtx->scan_ctxt.scan_work, delay);
12845}
12846
12847void wlan_hdd_init_deinit_defer_scan_context(scan_context_t *scan_ctx)
12848{
12849 scan_ctx->magic = 0;
12850 scan_ctx->attempt = 0;
12851 scan_ctx->reject = 0;
12852 scan_ctx->scan_request = NULL;
12853
12854 return;
12855}
12856
Mihir Shetefc7ff5b2014-01-27 11:30:05 +053012857/**---------------------------------------------------------------------------
12858
Jeff Johnson295189b2012-06-20 16:38:30 -070012859 \brief hdd_wlan_startup() - HDD init function
12860
12861 This is the driver startup code executed once a WLAN device has been detected
12862
12863 \param - dev - Pointer to the underlying device
12864
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -080012865 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -070012866
12867 --------------------------------------------------------------------------*/
12868
12869int hdd_wlan_startup(struct device *dev )
12870{
12871 VOS_STATUS status;
12872 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -070012873 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -070012874 hdd_context_t *pHddCtx = NULL;
12875 v_CONTEXT_t pVosContext= NULL;
12876#ifdef WLAN_BTAMP_FEATURE
12877 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
12878 WLANBAP_ConfigType btAmpConfig;
12879 hdd_config_t *pConfig;
12880#endif
12881 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -070012882 struct wiphy *wiphy;
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053012883 v_MACADDR_t mac_addr;
Jeff Johnson295189b2012-06-20 16:38:30 -070012884
12885 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -070012886 /*
12887 * cfg80211: wiphy allocation
12888 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +053012889 wiphy = wlan_hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t)) ;
Jeff Johnson295189b2012-06-20 16:38:30 -070012890
12891 if(wiphy == NULL)
12892 {
12893 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -080012894 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -070012895 }
Jeff Johnson295189b2012-06-20 16:38:30 -070012896 pHddCtx = wiphy_priv(wiphy);
12897
Jeff Johnson295189b2012-06-20 16:38:30 -070012898 //Initialize the adapter context to zeros.
12899 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
12900
Jeff Johnson295189b2012-06-20 16:38:30 -070012901 pHddCtx->wiphy = wiphy;
Sushant Kaushik83392fa2015-05-05 17:44:40 +053012902 hdd_prevent_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_INIT);
Mihir Shete18156292014-03-11 15:38:30 +053012903 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_LOAD_IN_PROGRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -070012904
12905 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
12906
Siddharth Bhalcd92b782015-06-29 12:25:40 +053012907 /* register for riva power on lock to platform driver
12908 * Locking power early to ensure FW doesn't reset by kernel while
12909 * host driver is busy initializing itself */
12910 if (req_riva_power_on_lock("wlan"))
12911 {
12912 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
12913 __func__);
12914 goto err_free_hdd_context;
12915 }
12916
Jeff Johnson295189b2012-06-20 16:38:30 -070012917 /*Get vos context here bcoz vos_open requires it*/
12918 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
12919
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -080012920 if(pVosContext == NULL)
12921 {
12922 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
12923 goto err_free_hdd_context;
12924 }
12925
Jeff Johnson295189b2012-06-20 16:38:30 -070012926 //Save the Global VOSS context in adapter context for future.
12927 pHddCtx->pvosContext = pVosContext;
12928
12929 //Save the adapter context in global context for future.
12930 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
12931
Jeff Johnson295189b2012-06-20 16:38:30 -070012932 pHddCtx->parent_dev = dev;
Sreelakshmi Konamkif0646d52016-12-09 12:35:31 +053012933 pHddCtx->last_scan_reject_session_id = 0xFF;
12934 pHddCtx->last_scan_reject_reason = 0;
Sreelakshmi Konamki20ebed92016-10-27 12:13:30 +053012935 pHddCtx->last_scan_reject_timestamp = 0;
Abhishek Singhe4b12562017-06-20 16:53:39 +053012936 pHddCtx->scan_reject_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -070012937
12938 init_completion(&pHddCtx->full_pwr_comp_var);
12939 init_completion(&pHddCtx->standby_comp_var);
12940 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -070012941 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -080012942 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Kiet Lam46b8e4e2013-11-06 21:49:53 +053012943 init_completion(&pHddCtx->wiphy_channel_update_event);
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +053012944 init_completion(&pHddCtx->ssr_comp_var);
Mahesh A Saptasagar67ab9222015-10-21 15:38:41 +053012945 init_completion(&pHddCtx->mc_sus_event_var);
12946 init_completion(&pHddCtx->tx_sus_event_var);
12947 init_completion(&pHddCtx->rx_sus_event_var);
12948
Amar Singhala49cbc52013-10-08 18:37:44 -070012949
mukul sharma4bd8d2e2015-08-13 20:33:25 +053012950 hdd_init_ll_stats_ctx(pHddCtx);
Anurag Chouhan6ee81542017-02-09 18:09:27 +053012951 hdd_init_nud_stats_ctx(pHddCtx);
mukul sharma4bd8d2e2015-08-13 20:33:25 +053012952
Amar Singhala49cbc52013-10-08 18:37:44 -070012953#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhalfddc28c2013-09-05 13:03:40 -070012954 init_completion(&pHddCtx->linux_reg_req);
Amar Singhala49cbc52013-10-08 18:37:44 -070012955#else
12956 init_completion(&pHddCtx->driver_crda_req);
12957#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070012958
Padma, Santhosh Kumara1aa4a32015-06-19 19:00:46 +053012959#ifdef WLAN_FEATURE_EXTSCAN
12960 init_completion(&pHddCtx->ext_scan_context.response_event);
12961#endif /* WLAN_FEATURE_EXTSCAN */
12962
Kamath Vinayak4000c9a2013-08-23 14:24:27 +053012963 spin_lock_init(&pHddCtx->schedScan_lock);
Kapil Gupta137ef892016-12-13 19:38:00 +053012964 vos_spin_lock_init(&pHddCtx->sap_update_info_lock);
Kamath Vinayak4000c9a2013-08-23 14:24:27 +053012965
Jeff Johnson295189b2012-06-20 16:38:30 -070012966 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
12967
Padma, Santhosh Kumar9cd38332015-11-17 12:18:10 +053012968 vos_init_delayed_work(&pHddCtx->spoof_mac_addr_work,
12969 hdd_processSpoofMacAddrRequest);
Kapil Gupta137ef892016-12-13 19:38:00 +053012970 vos_init_work(&pHddCtx->sap_start_work, hdd_sap_restart_handle);
Abhishek Singh78c691f2017-11-30 13:48:44 +053012971 vos_init_delayed_work(&pHddCtx->ecsa_chan_change_work,
12972 hdd_force_scc_with_ecsa_handle);
Padma, Santhosh Kumar9cd38332015-11-17 12:18:10 +053012973
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +053012974#ifdef FEATURE_WLAN_TDLS
12975 /* tdls_lock is initialized before an hdd_open_adapter ( which is
12976 * invoked by other instances also) to protect the concurrent
12977 * access for the Adapters by TDLS module.
12978 */
12979 mutex_init(&pHddCtx->tdls_lock);
12980#endif
Siddharth Bhal76972212014-10-15 16:22:51 +053012981 mutex_init(&pHddCtx->spoofMacAddr.macSpoofingLock);
Mukul Sharma1fd6efd2015-02-14 00:29:14 +053012982 mutex_init(&pHddCtx->wmmLock);
12983
Srinivas Girigowda8bf64cb2015-09-30 19:50:09 +053012984 hdd_init_offloaded_packets_ctx(pHddCtx);
Agarwal Ashish1f422872014-07-22 00:11:55 +053012985 /* By default Strict Regulatory For FCC should be false */
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +053012986
Agarwal Ashish1f422872014-07-22 00:11:55 +053012987 pHddCtx->nEnableStrictRegulatoryForFCC = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -070012988 // Load all config first as TL config is needed during vos_open
12989 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
12990 if(pHddCtx->cfg_ini == NULL)
12991 {
12992 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
12993 goto err_free_hdd_context;
12994 }
12995
Hanumanth Reddy Pothula1efcd162018-03-14 14:32:27 +053012996 hdd_request_manager_init();
12997
Jeff Johnson295189b2012-06-20 16:38:30 -070012998 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
12999
13000 // Read and parse the qcom_cfg.ini file
13001 status = hdd_parse_config_ini( pHddCtx );
13002 if ( VOS_STATUS_SUCCESS != status )
13003 {
13004 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
13005 __func__, WLAN_INI_FILE);
13006 goto err_config;
13007 }
Arif Hussaind5218912013-12-05 01:10:55 -080013008#ifdef MEMORY_DEBUG
13009 if (pHddCtx->cfg_ini->IsMemoryDebugSupportEnabled)
13010 vos_mem_init();
13011
13012 hddLog(VOS_TRACE_LEVEL_INFO, "%s: gEnableMemoryDebug=%d",
13013 __func__, pHddCtx->cfg_ini->IsMemoryDebugSupportEnabled);
13014#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070013015
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +053013016 /* INI has been read, initialise the configuredMcastBcastFilter with
13017 * INI value as this will serve as the default value
13018 */
13019 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
13020 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
13021 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +053013022
13023 if (false == hdd_is_5g_supported(pHddCtx))
13024 {
13025 //5Ghz is not supported.
13026 if (1 != pHddCtx->cfg_ini->nBandCapability)
13027 {
13028 hddLog(VOS_TRACE_LEVEL_INFO,
13029 "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__);
13030 pHddCtx->cfg_ini->nBandCapability = 1;
13031 }
13032 }
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +053013033
13034 /* If SNR Monitoring is enabled, FW has to parse all beacons
13035 * for calcaluting and storing the average SNR, so set Nth beacon
13036 * filter to 1 to enable FW to parse all the beaocons
13037 */
13038 if (1 == pHddCtx->cfg_ini->fEnableSNRMonitoring)
13039 {
13040 /* The log level is deliberately set to WARN as overriding
13041 * nthBeaconFilter to 1 will increase power cosumption and this
13042 * might just prove helpful to detect the power issue.
13043 */
13044 hddLog(VOS_TRACE_LEVEL_WARN,
13045 "%s: Setting pHddCtx->cfg_ini->nthBeaconFilter = 1", __func__);
13046 pHddCtx->cfg_ini->nthBeaconFilter = 1;
13047 }
Jeff Johnson295189b2012-06-20 16:38:30 -070013048 /*
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +053013049 * cfg80211: Initialization ...
Jeff Johnson295189b2012-06-20 16:38:30 -070013050 */
Manjeet Singh61016fa2016-12-02 11:10:19 +053013051 if (0 < wlan_hdd_cfg80211_init(dev, wiphy, pHddCtx->cfg_ini))
Jeff Johnson295189b2012-06-20 16:38:30 -070013052 {
Manjeet Singh61016fa2016-12-02 11:10:19 +053013053 hddLog(VOS_TRACE_LEVEL_FATAL,
13054 "%s: wlan_hdd_cfg80211_init return failure", __func__);
13055 goto err_config;
Jeff Johnson295189b2012-06-20 16:38:30 -070013056 }
Jeff Johnson295189b2012-06-20 16:38:30 -070013057
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -080013058 // Update VOS trace levels based upon the cfg.ini
13059 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
13060 pHddCtx->cfg_ini->vosTraceEnableBAP);
13061 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
13062 pHddCtx->cfg_ini->vosTraceEnableTL);
13063 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
13064 pHddCtx->cfg_ini->vosTraceEnableWDI);
13065 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
13066 pHddCtx->cfg_ini->vosTraceEnableHDD);
13067 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
13068 pHddCtx->cfg_ini->vosTraceEnableSME);
13069 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
13070 pHddCtx->cfg_ini->vosTraceEnablePE);
Katya Nigam70d68332013-09-16 16:49:45 +053013071 hdd_vos_trace_enable(VOS_MODULE_ID_PMC,
13072 pHddCtx->cfg_ini->vosTraceEnablePMC);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -080013073 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
13074 pHddCtx->cfg_ini->vosTraceEnableWDA);
13075 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
13076 pHddCtx->cfg_ini->vosTraceEnableSYS);
13077 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
13078 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -080013079 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
13080 pHddCtx->cfg_ini->vosTraceEnableSAP);
13081 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
13082 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -080013083
Jeff Johnson295189b2012-06-20 16:38:30 -070013084 // Update WDI trace levels based upon the cfg.ini
13085 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
13086 pHddCtx->cfg_ini->wdiTraceEnableDAL);
13087 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
13088 pHddCtx->cfg_ini->wdiTraceEnableCTL);
13089 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
13090 pHddCtx->cfg_ini->wdiTraceEnableDAT);
13091 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
13092 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -070013093
Jeff Johnson88ba7742013-02-27 14:36:02 -080013094 if (VOS_FTM_MODE == hdd_get_conparam())
13095 {
Jeff Johnson295189b2012-06-20 16:38:30 -070013096 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
13097 {
13098 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
13099 goto err_free_hdd_context;
13100 }
13101 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
Sachin Ahuja38ef5e02015-03-13 17:31:16 +053013102 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_NO_LOAD_UNLOAD_IN_PROGRESS;
c_hpothu2de0ef62014-04-15 16:16:15 +053013103 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -070013104 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -080013105 }
Jeff Johnson295189b2012-06-20 16:38:30 -070013106
Katya Nigame7b69a82015-04-28 15:24:06 +053013107 if( VOS_MONITOR_MODE == hdd_get_conparam())
13108 {
13109 if ( VOS_STATUS_SUCCESS != wlan_hdd_mon_open(pHddCtx))
13110 {
13111 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_mon_open Failed",__func__);
13112 goto err_free_hdd_context;
13113 }
13114 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Driver loaded in Monitor Mode",__func__);
13115 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_NO_LOAD_UNLOAD_IN_PROGRESS;
13116 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
13117 return VOS_STATUS_SUCCESS;
13118 }
13119
Jeff Johnson88ba7742013-02-27 14:36:02 -080013120 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -070013121 if(pHddCtx->cfg_ini->fIsLogpEnabled)
13122 {
13123 status = vos_watchdog_open(pVosContext,
13124 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
13125
13126 if(!VOS_IS_STATUS_SUCCESS( status ))
13127 {
13128 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Ashish Kumar Dhanotiya532bdef2017-05-09 17:31:59 +053013129 goto err_config;
Jeff Johnson295189b2012-06-20 16:38:30 -070013130 }
13131 }
13132
13133 pHddCtx->isLogpInProgress = FALSE;
13134 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
13135
Amar Singhala49cbc52013-10-08 18:37:44 -070013136#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -070013137 /* initialize the NV module. This is required so that
13138 we can initialize the channel information in wiphy
13139 from the NV.bin data. The channel information in
13140 wiphy needs to be initialized before wiphy registration */
13141
13142 status = vos_nv_open();
13143 if (!VOS_IS_STATUS_SUCCESS(status))
13144 {
13145 /* NV module cannot be initialized */
13146 hddLog( VOS_TRACE_LEVEL_FATAL,
13147 "%s: vos_nv_open failed", __func__);
Vinay Krishna Eranna2025d892014-09-18 16:51:42 +053013148 goto err_wdclose;
Amar Singhal0a402232013-10-11 20:57:16 -070013149 }
13150
13151 status = vos_init_wiphy_from_nv_bin();
13152 if (!VOS_IS_STATUS_SUCCESS(status))
13153 {
13154 /* NV module cannot be initialized */
13155 hddLog( VOS_TRACE_LEVEL_FATAL,
13156 "%s: vos_init_wiphy failed", __func__);
13157 goto err_vos_nv_close;
13158 }
13159
Amar Singhala49cbc52013-10-08 18:37:44 -070013160#endif
Mahesh A Saptasagarc3ed0122016-01-19 16:45:11 +053013161 //Initialize the nlink service
13162 if(nl_srv_init() != 0)
13163 {
13164 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
13165 goto err_vos_nv_close;
13166 }
13167
13168#ifdef WLAN_KD_READY_NOTIFIER
13169 pHddCtx->kd_nl_init = 1;
13170#endif /* WLAN_KD_READY_NOTIFIER */
13171
Girish Gowlibf0e1ab2015-01-19 16:05:16 +053013172 vos_set_roam_delay_stats_enabled(pHddCtx->cfg_ini->gEnableRoamDelayStats);
Arun Kumar Khandavalliebb19482014-03-25 13:56:53 +053013173 status = vos_open( &pVosContext, pHddCtx->parent_dev);
Jeff Johnson295189b2012-06-20 16:38:30 -070013174 if ( !VOS_IS_STATUS_SUCCESS( status ))
13175 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -080013176 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
Mahesh A Saptasagarc3ed0122016-01-19 16:45:11 +053013177 goto err_nl_srv;
Jeff Johnson295189b2012-06-20 16:38:30 -070013178 }
13179
Jeff Johnson295189b2012-06-20 16:38:30 -070013180 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
13181
13182 if ( NULL == pHddCtx->hHal )
13183 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -080013184 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -070013185 goto err_vosclose;
13186 }
13187
Jeff Johnsonbc676b42013-02-14 16:04:08 -080013188 status = vos_preStart( pHddCtx->pvosContext );
13189 if ( !VOS_IS_STATUS_SUCCESS( status ) )
13190 {
13191 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053013192 goto err_vosclose;
Jeff Johnsonbc676b42013-02-14 16:04:08 -080013193 }
Jeff Johnsone7245742012-09-05 17:12:55 -070013194
Arif Hussaineaf68602013-12-30 23:10:44 -080013195 if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan)
13196 {
13197 pHddCtx->cfg_ini->enableDFSChnlScan = enable_dfs_chan_scan;
13198 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_dfs_chan_scan set to %d",
13199 __func__, enable_dfs_chan_scan);
13200 }
13201 if (0 == enable_11d || 1 == enable_11d)
13202 {
13203 pHddCtx->cfg_ini->Is11dSupportEnabled = enable_11d;
13204 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_11d set to %d",
13205 __func__, enable_11d);
13206 }
13207
Jeff Johnsonbc676b42013-02-14 16:04:08 -080013208 /* Note that the vos_preStart() sequence triggers the cfg download.
13209 The cfg download must occur before we update the SME config
13210 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -070013211 status = hdd_set_sme_config( pHddCtx );
13212
13213 if ( VOS_STATUS_SUCCESS != status )
13214 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -080013215 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053013216 goto err_vosclose;
Jeff Johnsonbc676b42013-02-14 16:04:08 -080013217 }
Jeff Johnson295189b2012-06-20 16:38:30 -070013218
Jeff Johnson295189b2012-06-20 16:38:30 -070013219 /* In the integrated architecture we update the configuration from
13220 the INI file and from NV before vOSS has been started so that
13221 the final contents are available to send down to the cCPU */
13222
13223 // Apply the cfg.ini to cfg.dat
13224 if (FALSE == hdd_update_config_dat(pHddCtx))
13225 {
13226 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053013227 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -070013228 }
13229
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053013230 // Get mac addr from platform driver
13231 ret = wcnss_get_wlan_mac_address((char*)&mac_addr.bytes);
13232
13233 if ((0 == ret) && (!vos_is_macaddr_zero(&mac_addr)))
Jeff Johnson295189b2012-06-20 16:38:30 -070013234 {
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053013235 /* Store the mac addr for first interface */
13236 pHddCtx->cfg_ini->intfMacAddr[0] = mac_addr;
13237
13238 hddLog(VOS_TRACE_LEVEL_ERROR,
13239 "%s: WLAN Mac Addr: "
13240 MAC_ADDRESS_STR, __func__,
13241 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
13242
13243 /* Here, passing Arg2 as 1 because we do not want to change the
13244 last 3 bytes (means non OUI bytes) of first interface mac
13245 addr.
13246 */
13247 if (0 != hdd_generate_iface_mac_addr_auto(pHddCtx, 1, mac_addr))
13248 {
13249 hddLog(VOS_TRACE_LEVEL_ERROR,
13250 "%s: Failed to generate wlan interface mac addr "
13251 "using MAC from ini file ", __func__);
13252 }
13253 }
13254 else if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
13255 {
13256 // Apply the NV to cfg.dat
13257 /* Prima Update MAC address only at here */
Jeff Johnson295189b2012-06-20 16:38:30 -070013258#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
13259 /* There was not a valid set of MAC Addresses in NV. See if the
13260 default addresses were modified by the cfg.ini settings. If so,
13261 we'll use them, but if not, we'll autogenerate a set of MAC
13262 addresses based upon the device serial number */
13263
13264 static const v_MACADDR_t default_address =
13265 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
Jeff Johnson295189b2012-06-20 16:38:30 -070013266
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053013267 if (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
13268 sizeof(default_address)))
Jeff Johnson295189b2012-06-20 16:38:30 -070013269 {
13270 /* cfg.ini has the default address, invoke autogen logic */
13271
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053013272 /* Here, passing Arg2 as 0 because we want to change the
13273 last 3 bytes (means non OUI bytes) of all the interfaces
13274 mac addr.
13275 */
13276 if (0 != hdd_generate_iface_mac_addr_auto(pHddCtx, 0,
13277 default_address))
Jeff Johnson295189b2012-06-20 16:38:30 -070013278 {
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053013279 hddLog(VOS_TRACE_LEVEL_ERROR,
13280 "%s: Failed to generate wlan interface mac addr "
13281 "using MAC from ini file " MAC_ADDRESS_STR, __func__,
13282 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
Jeff Johnson295189b2012-06-20 16:38:30 -070013283 }
Jeff Johnson295189b2012-06-20 16:38:30 -070013284 }
13285 else
13286#endif //WLAN_AUTOGEN_MACADDR_FEATURE
13287 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -080013288 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -070013289 "%s: Invalid MAC address in NV, using MAC from ini file "
13290 MAC_ADDRESS_STR, __func__,
13291 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
13292 }
13293 }
13294 {
13295 eHalStatus halStatus;
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053013296
13297 /* Set the MAC Address Currently this is used by HAL to
13298 * add self sta. Remove this once self sta is added as
13299 * part of session open.
13300 */
Jeff Johnson295189b2012-06-20 16:38:30 -070013301 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
13302 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
13303 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053013304
Jeff Johnson295189b2012-06-20 16:38:30 -070013305 if (!HAL_STATUS_SUCCESS( halStatus ))
13306 {
13307 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
13308 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053013309 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -070013310 }
13311 }
Jeff Johnson295189b2012-06-20 16:38:30 -070013312
13313 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
13314 Note: Firmware image will be read and downloaded inside vos_start API */
13315 status = vos_start( pHddCtx->pvosContext );
13316 if ( !VOS_IS_STATUS_SUCCESS( status ) )
13317 {
13318 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
Hanumantha Reddy Pothulabd9601a2016-02-12 13:22:27 +053013319 if (isSsrPanicOnFailure())
13320 VOS_BUG(0);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053013321 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -070013322 }
13323
Leo Chang6cec3e22014-01-21 15:33:49 -080013324#ifdef FEATURE_WLAN_CH_AVOID
13325 /* Plug in avoid channel notification callback
13326 * This should happen before ADD_SELF_STA
13327 * FW will send first IND with ADD_SELF_STA REQ from host */
Pradeep Reddy POTTETI5c2e16d2014-06-27 16:47:38 +053013328
13329 /* check the Channel Avoidance is enabled */
13330 if (TRUE == pHddCtx->cfg_ini->fenableCHAvoidance)
13331 {
13332 sme_AddChAvoidCallback(pHddCtx->hHal,
13333 hdd_hostapd_ch_avoid_cb);
13334 }
Leo Chang6cec3e22014-01-21 15:33:49 -080013335#endif /* FEATURE_WLAN_CH_AVOID */
13336
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070013337 /* Exchange capability info between Host and FW and also get versioning info from FW */
13338 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -070013339
Agarwal Ashishad9281b2014-06-10 14:57:30 +053013340#ifdef CONFIG_ENABLE_LINUX_REG
13341 status = wlan_hdd_init_channels(pHddCtx);
13342 if ( !VOS_IS_STATUS_SUCCESS( status ) )
13343 {
13344 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: wlan_hdd_init_channels failed",
13345 __func__);
13346 goto err_vosstop;
13347 }
13348#endif
13349
Jeff Johnson295189b2012-06-20 16:38:30 -070013350 status = hdd_post_voss_start_config( pHddCtx );
13351 if ( !VOS_IS_STATUS_SUCCESS( status ) )
13352 {
13353 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
13354 __func__);
13355 goto err_vosstop;
13356 }
Amar Singhala49cbc52013-10-08 18:37:44 -070013357
13358#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +053013359 wlan_hdd_cfg80211_update_reg_info( wiphy );
13360
13361 /* registration of wiphy dev with cfg80211 */
13362 if (0 > wlan_hdd_cfg80211_register(wiphy))
13363 {
13364 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
13365 goto err_vosstop;
13366 }
Amar Singhala49cbc52013-10-08 18:37:44 -070013367#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070013368
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053013369#ifdef CONFIG_ENABLE_LINUX_REG
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053013370 /* registration of wiphy dev with cfg80211 */
13371 if (0 > wlan_hdd_cfg80211_register(wiphy))
13372 {
13373 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
13374 goto err_vosstop;
13375 }
13376
Agarwal Ashish6db9d532014-09-30 18:19:10 +053013377 status = wlan_hdd_init_channels_for_cc(pHddCtx, INIT);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053013378 if ( !VOS_IS_STATUS_SUCCESS( status ) )
13379 {
13380 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: wlan_hdd_init_channels_for_cc failed",
13381 __func__);
13382 goto err_unregister_wiphy;
13383 }
13384#endif
13385
c_hpothu4a298be2014-12-22 21:12:51 +053013386 wcnss_wlan_set_drvdata(pHddCtx->parent_dev, pHddCtx);
13387
Jeff Johnson295189b2012-06-20 16:38:30 -070013388 if (VOS_STA_SAP_MODE == hdd_get_conparam())
13389 {
13390 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
13391 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
13392 }
13393 else
13394 {
Jeff Johnson295189b2012-06-20 16:38:30 -070013395 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
13396 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
13397 if (pAdapter != NULL)
13398 {
Katya Nigama7d81d72014-11-12 12:44:34 +053013399 if (pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated && !(pHddCtx->cfg_ini->intfMacAddr[0].bytes[0] & 0x02))
Jeff Johnson295189b2012-06-20 16:38:30 -070013400 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +053013401 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
13402 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
13403 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -070013404
Gopichand Nakkala49f96f62013-02-06 14:38:17 +053013405 /* Generate the P2P Device Address. This consists of the device's
13406 * primary MAC address with the locally administered bit set.
13407 */
13408 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -070013409 }
13410 else
13411 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +053013412 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
13413 if (p2p_dev_addr != NULL)
13414 {
13415 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
13416 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
13417 }
13418 else
13419 {
13420 hddLog(VOS_TRACE_LEVEL_FATAL,
13421 "%s: Failed to allocate mac_address for p2p_device",
13422 __func__);
13423 goto err_close_adapter;
13424 }
Jeff Johnson295189b2012-06-20 16:38:30 -070013425 }
Jeff Johnsone7245742012-09-05 17:12:55 -070013426
13427 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
13428 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
13429 if ( NULL == pP2pAdapter )
13430 {
13431 hddLog(VOS_TRACE_LEVEL_FATAL,
13432 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070013433 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -070013434 goto err_close_adapter;
13435 }
Jeff Johnsone7245742012-09-05 17:12:55 -070013436 }
Jeff Johnson295189b2012-06-20 16:38:30 -070013437 }
Jeff Johnson295189b2012-06-20 16:38:30 -070013438
13439 if( pAdapter == NULL )
13440 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -080013441 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
13442 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -070013443 }
Jeff Johnsone7245742012-09-05 17:12:55 -070013444
Arif Hussain66559122013-11-21 10:11:40 -080013445 if (country_code)
13446 {
13447 eHalStatus ret;
Arif Hussaincb607082013-12-20 11:57:42 -080013448 INIT_COMPLETION(pAdapter->change_country_code);
Arif Hussain66559122013-11-21 10:11:40 -080013449 hdd_checkandupdate_dfssetting(pAdapter, country_code);
13450#ifndef CONFIG_ENABLE_LINUX_REG
13451 hdd_checkandupdate_phymode(pAdapter, country_code);
13452#endif
Arif Hussaineaf68602013-12-30 23:10:44 -080013453 ret = sme_ChangeCountryCode(pHddCtx->hHal,
13454 (void *)(tSmeChangeCountryCallback)
13455 wlan_hdd_change_country_code_callback,
Arif Hussain66559122013-11-21 10:11:40 -080013456 country_code,
13457 pAdapter, pHddCtx->pvosContext,
Abhishek Singha306a442013-11-07 18:39:01 +053013458 eSIR_TRUE, eSIR_TRUE);
Arif Hussain66559122013-11-21 10:11:40 -080013459 if (eHAL_STATUS_SUCCESS == ret)
13460 {
Arif Hussaincb607082013-12-20 11:57:42 -080013461 ret = wait_for_completion_interruptible_timeout(
13462 &pAdapter->change_country_code,
13463 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
13464
13465 if (0 >= ret)
13466 {
13467 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
13468 "%s: SME while setting country code timed out", __func__);
13469 }
Arif Hussain66559122013-11-21 10:11:40 -080013470 }
13471 else
13472 {
Arif Hussaincb607082013-12-20 11:57:42 -080013473 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
13474 "%s: SME Change Country code from module param fail ret=%d",
13475 __func__, ret);
Arif Hussain66559122013-11-21 10:11:40 -080013476 }
13477 }
13478
Jeff Johnson295189b2012-06-20 16:38:30 -070013479#ifdef WLAN_BTAMP_FEATURE
13480 vStatus = WLANBAP_Open(pVosContext);
13481 if(!VOS_IS_STATUS_SUCCESS(vStatus))
13482 {
13483 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
13484 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -070013485 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -070013486 }
13487
13488 vStatus = BSL_Init(pVosContext);
13489 if(!VOS_IS_STATUS_SUCCESS(vStatus))
13490 {
13491 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
13492 "%s: Failed to Init BSL",__func__);
13493 goto err_bap_close;
13494 }
13495 vStatus = WLANBAP_Start(pVosContext);
13496 if (!VOS_IS_STATUS_SUCCESS(vStatus))
13497 {
13498 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
13499 "%s: Failed to start TL",__func__);
13500 goto err_bap_close;
13501 }
13502
13503 pConfig = pHddCtx->cfg_ini;
13504 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
13505 status = WLANBAP_SetConfig(&btAmpConfig);
13506
13507#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -070013508
Mihir Shete9c238772014-10-15 14:35:16 +053013509 /*
13510 * UapsdMask is 0xf if U-APSD is enbaled for all AC's...
13511 * The value of CFG_QOS_WMM_UAPSD_MASK_DEFAULT is 0xaa(Magic Value)
13512 * which is greater than 0xf. So the below check is safe to make
13513 * sure that there is no entry for UapsdMask in the ini
13514 */
13515 if (CFG_QOS_WMM_UAPSD_MASK_DEFAULT == pHddCtx->cfg_ini->UapsdMask)
13516 {
13517 if(IS_DYNAMIC_WMM_PS_ENABLED)
13518 {
13519 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: Enable UAPSD for VI & VO",
13520 __func__);
13521 pHddCtx->cfg_ini->UapsdMask =
13522 CFG_QOS_WMM_UAPSD_MASK_DYMANIC_WMM_PS_DEFAULT;
13523 }
13524 else
13525 {
13526 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: Do not enable UAPSD",
13527 __func__);
13528 pHddCtx->cfg_ini->UapsdMask =
13529 CFG_QOS_WMM_UAPSD_MASK_LEGACY_WMM_PS_DEFAULT;
13530 }
13531 }
13532
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -070013533#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
13534 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
13535 {
13536 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
13537 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
13538 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
13539 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
13540 }
13541#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070013542
Agarwal Ashish4b87f922014-06-18 03:03:21 +053013543 wlan_hdd_tdls_init(pHddCtx);
13544
Masti, Narayanraddi26378462016-01-05 18:20:28 +053013545 wlan_hdd_init_deinit_defer_scan_context(&pHddCtx->scan_ctxt);
13546
13547 vos_init_delayed_work(&pHddCtx->scan_ctxt.scan_work,
13548 wlan_hdd_schedule_defer_scan);
13549
Mihir Shetefc7ff5b2014-01-27 11:30:05 +053013550 sme_Register11dScanDoneCallback(pHddCtx->hHal, hdd_11d_scan_done);
13551
Jeff Johnson295189b2012-06-20 16:38:30 -070013552 /* Register with platform driver as client for Suspend/Resume */
13553 status = hddRegisterPmOps(pHddCtx);
13554 if ( !VOS_IS_STATUS_SUCCESS( status ) )
13555 {
13556 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
13557#ifdef WLAN_BTAMP_FEATURE
13558 goto err_bap_stop;
13559#else
Jeff Johnsone7245742012-09-05 17:12:55 -070013560 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -070013561#endif //WLAN_BTAMP_FEATURE
13562 }
13563
Yue Ma0d4891e2013-08-06 17:01:45 -070013564 /* Open debugfs interface */
13565 if (VOS_STATUS_SUCCESS != hdd_debugfs_init(pAdapter))
13566 {
13567 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
13568 "%s: hdd_debugfs_init failed!", __func__);
Yue Ma0d4891e2013-08-06 17:01:45 -070013569 }
13570
Jeff Johnson295189b2012-06-20 16:38:30 -070013571 /* Register TM level change handler function to the platform */
13572 status = hddDevTmRegisterNotifyCallback(pHddCtx);
13573 if ( !VOS_IS_STATUS_SUCCESS( status ) )
13574 {
13575 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
13576 goto err_unregister_pmops;
13577 }
Jeff Johnson295189b2012-06-20 16:38:30 -070013578
Jeff Johnson295189b2012-06-20 16:38:30 -070013579 // register net device notifier for device change notification
13580 ret = register_netdevice_notifier(&hdd_netdev_notifier);
13581
13582 if(ret < 0)
13583 {
13584 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
Siddharth Bhalcd92b782015-06-29 12:25:40 +053013585 goto err_unregister_pmops;
Jeff Johnson295189b2012-06-20 16:38:30 -070013586 }
13587
Jeff Johnson295189b2012-06-20 16:38:30 -070013588 //Initialize the BTC service
13589 if(btc_activate_service(pHddCtx) != 0)
13590 {
13591 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
Mahesh A Saptasagarc3ed0122016-01-19 16:45:11 +053013592 goto err_reg_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -070013593 }
13594
Padma, Santhosh Kumar2762e9d2015-10-20 15:02:57 +053013595#ifdef FEATURE_OEM_DATA_SUPPORT
13596 //Initialize the OEM service
13597 if (oem_activate_service(pHddCtx) != 0)
13598 {
13599 hddLog(VOS_TRACE_LEVEL_FATAL,
13600 "%s: oem_activate_service failed", __func__);
Hanumanth Reddy Pothula13789c42017-09-12 15:18:13 +053013601 goto err_btc_activate_service;
Padma, Santhosh Kumar2762e9d2015-10-20 15:02:57 +053013602 }
13603#endif
13604
Jeff Johnson295189b2012-06-20 16:38:30 -070013605#ifdef PTT_SOCK_SVC_ENABLE
13606 //Initialize the PTT service
13607 if(ptt_sock_activate_svc(pHddCtx) != 0)
13608 {
13609 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
Hanumanth Reddy Pothula13789c42017-09-12 15:18:13 +053013610 goto err_oem_activate_service;
Jeff Johnson295189b2012-06-20 16:38:30 -070013611 }
13612#endif
13613
Abhishek Singh00b71972016-01-07 10:51:04 +053013614#ifdef WLAN_FEATURE_RMC
13615 if (hdd_open_cesium_nl_sock() < 0)
13616 {
13617 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_open_cesium_nl_sock failed", __func__);
Hanumanth Reddy Pothula13789c42017-09-12 15:18:13 +053013618 goto err_ptt_sock_activate_svc;
Abhishek Singh00b71972016-01-07 10:51:04 +053013619 }
13620#endif
13621
Vinay Krishna Erannad938c422014-03-10 17:14:21 +053013622#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
13623 if(pHddCtx->cfg_ini && pHddCtx->cfg_ini->wlanLoggingEnable)
13624 {
Deepthi Gowri78083a32014-11-04 12:55:51 +053013625 if(wlan_logging_sock_activate_svc(
13626 pHddCtx->cfg_ini->wlanLoggingFEToConsole,
Sushant Kaushik33200572015-08-05 16:46:20 +053013627 pHddCtx->cfg_ini->wlanLoggingNumBuf,
13628 pHddCtx->cfg_ini->wlanPerPktStatsLogEnable,
13629 pHddCtx->cfg_ini->wlanPerPktStatsNumBuf))
Deepthi Gowri78083a32014-11-04 12:55:51 +053013630 {
13631 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wlan_logging_sock_activate_svc"
13632 " failed", __func__);
Hanumanth Reddy Pothula13789c42017-09-12 15:18:13 +053013633 goto err_open_cesium_nl_sock;
Deepthi Gowri78083a32014-11-04 12:55:51 +053013634 }
13635 //TODO: To Remove enableDhcpDebug and use gEnableDebugLog for
13636 //EAPOL and DHCP
Sachin Ahuja8c65f382014-12-12 15:34:21 +053013637 if (!pHddCtx->cfg_ini->gEnableDebugLog)
13638 pHddCtx->cfg_ini->gEnableDebugLog =
Sushant Kaushik6e4e2bc2015-10-05 17:23:07 +053013639 VOS_PKT_PROTO_TYPE_EAPOL | VOS_PKT_PROTO_TYPE_DHCP |
13640 VOS_PKT_PROTO_TYPE_ARP;
Vinay Krishna Erannad938c422014-03-10 17:14:21 +053013641 }
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053013642
Siddharth Bhald1be97f2015-05-27 22:39:59 +053013643 if (pHddCtx->cfg_ini->wlanLoggingEnable &&
13644 (pHddCtx->cfg_ini->enableFWLogging ||
Siddharth Bhaldb963232015-06-25 19:34:35 +053013645 pHddCtx->cfg_ini->enableMgmtLogging ||
c_manjeecfd1efb2015-09-25 19:32:34 +053013646 pHddCtx->cfg_ini->enableContFWLogging ||
13647 pHddCtx->cfg_ini->enableFwrMemDump )
13648 )
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053013649 {
Siddharth Bhald1be97f2015-05-27 22:39:59 +053013650 hdd_init_frame_logging(pHddCtx);
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053013651 }
13652 else
13653 {
Siddharth Bhald1be97f2015-05-27 22:39:59 +053013654 hddLog(VOS_TRACE_LEVEL_INFO, FL("Logging disabled in ini"));
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053013655 }
13656
Vinay Krishna Erannad938c422014-03-10 17:14:21 +053013657#endif
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053013658
Agrawal Ashish17ef5082016-10-17 18:33:21 +053013659#ifdef SAP_AUTH_OFFLOAD
13660 if (!sme_IsFeatureSupportedByFW(SAP_OFFLOADS))
13661 {
13662 hddLog(VOS_TRACE_LEVEL_INFO, FL(" SAP AUTH OFFLOAD not supp by FW"));
13663 pHddCtx->cfg_ini->enable_sap_auth_offload = 0;
13664 }
13665#endif
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053013666
Sushant Kaushik215778f2015-05-21 14:05:36 +053013667 if (vos_is_multicast_logging())
13668 wlan_logging_set_log_level();
13669
Jeff Johnson295189b2012-06-20 16:38:30 -070013670 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -070013671 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -070013672 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -070013673 /* Action frame registered in one adapter which will
13674 * applicable to all interfaces
13675 */
Agarwal Ashish8fa0e9a2014-05-23 00:40:12 +053013676 wlan_hdd_cfg80211_register_frames(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -070013677 }
Jeff Johnson295189b2012-06-20 16:38:30 -070013678
13679 mutex_init(&pHddCtx->sap_lock);
Mahesh A Saptasagar60627942014-10-13 13:55:14 +053013680 mutex_init(&pHddCtx->roc_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070013681
Jeff Johnsone7245742012-09-05 17:12:55 -070013682#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
13683 /* Initialize the wake lcok */
Sushant Kaushik83392fa2015-05-05 17:44:40 +053013684 vos_wake_lock_init(&pHddCtx->rx_wake_lock,
Jeff Johnsone7245742012-09-05 17:12:55 -070013685 "qcom_rx_wakelock");
Sushant Kaushik83392fa2015-05-05 17:44:40 +053013686
Jeff Johnsone7245742012-09-05 17:12:55 -070013687#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -080013688 /* Initialize the wake lcok */
Sushant Kaushik83392fa2015-05-05 17:44:40 +053013689 vos_wake_lock_init(&pHddCtx->sap_wake_lock,
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -080013690 "qcom_sap_wakelock");
Sushant Kaushik83392fa2015-05-05 17:44:40 +053013691
Jeff Johnsone7245742012-09-05 17:12:55 -070013692
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -070013693 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
13694 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -070013695
Katya Nigam5c306ea2014-06-19 15:39:54 +053013696 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_NO_LOAD_UNLOAD_IN_PROGRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -070013697 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
Sushant Kaushik83392fa2015-05-05 17:44:40 +053013698 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_INIT);
Katya Nigam5c306ea2014-06-19 15:39:54 +053013699
13700#ifdef FEATURE_WLAN_SCAN_PNO
13701 /*SME must send channel update configuration to RIVA*/
13702 sme_UpdateChannelConfig(pHddCtx->hHal);
13703#endif
Abhishek Singhf644b272014-08-21 02:59:39 +053013704 /* Send the update default channel list to the FW*/
13705 sme_UpdateChannelList(pHddCtx->hHal);
Mukul Sharma45063942015-04-01 20:07:59 +053013706
13707 /* Fwr capabilities received, Set the Dot11 mode */
Abhishek Singh41ebce12016-02-03 10:43:21 +053013708 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter),
13709 hdd_cfg_xlate_to_csr_phy_mode(pHddCtx->cfg_ini->dot11Mode));
Mukul Sharma45063942015-04-01 20:07:59 +053013710 sme_SetDefDot11Mode(pHddCtx->hHal);
13711
Abhishek Singha306a442013-11-07 18:39:01 +053013712#ifndef CONFIG_ENABLE_LINUX_REG
13713 /*updating wiphy so that regulatory user hints can be processed*/
13714 if (wiphy)
13715 {
13716 regulatory_hint(wiphy, "00");
13717 }
13718#endif
Jeff Johnsone7245742012-09-05 17:12:55 -070013719 // Initialize the restart logic
13720 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +053013721
Hanumanth Reddy Pothula146bca42016-11-08 12:01:07 +053013722 if (pHddCtx->cfg_ini->fIsLogpEnabled) {
13723 vos_wdthread_init_timer_work(vos_process_wd_timer);
13724 /* Initialize the timer to detect thread stuck issues */
13725 vos_thread_stuck_timer_init(
13726 &((VosContextType*)pVosContext)->vosWatchdog);
13727 }
13728
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -070013729 //Register the traffic monitor timer now
13730 if ( pHddCtx->cfg_ini->dynSplitscan)
13731 {
13732 vos_timer_init(&pHddCtx->tx_rx_trafficTmr,
13733 VOS_TIMER_TYPE_SW,
13734 hdd_tx_rx_pkt_cnt_stat_timer_handler,
13735 (void *)pHddCtx);
13736 }
Srinivas Dasari030bad32015-02-18 23:23:54 +053013737 wlan_hdd_cfg80211_nan_init(pHddCtx);
13738
Bhargav Shahd0715912015-10-01 18:17:37 +053013739 mutex_init(&pHddCtx->cur_rx_level_lock);
13740 vos_timer_init(&pHddCtx->delack_timer, VOS_TIMER_TYPE_SW,
13741 hdd_tcp_delack_compute_function,(void *)pHddCtx);
Masti, Narayanraddi44b0db02015-12-22 11:54:35 +053013742 vos_timer_init(&pHddCtx->tdls_source_timer, VOS_TIMER_TYPE_SW,
13743 wlan_hdd_change_tdls_mode, (void *)pHddCtx);
Bhargav Shahd0715912015-10-01 18:17:37 +053013744
Dino Mycle6fb96c12014-06-10 11:52:40 +053013745#ifdef WLAN_FEATURE_EXTSCAN
13746 sme_EXTScanRegisterCallback(pHddCtx->hHal,
13747 wlan_hdd_cfg80211_extscan_callback,
13748 pHddCtx);
13749#endif /* WLAN_FEATURE_EXTSCAN */
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053013750
Padma, Santhosh Kumar2ccac212015-10-20 17:27:27 +053013751#ifdef FEATURE_OEM_DATA_SUPPORT
13752 sme_OemDataRegisterCallback(pHddCtx->hHal,
13753 wlan_hdd_cfg80211_oemdata_callback,
13754 pHddCtx);
13755#endif /* FEATURE_OEM_DATA_SUPPORT */
13756
Gupta, Kapil7c34b322015-09-30 13:12:35 +053013757 sme_set_rssi_threshold_breached_cb(pHddCtx->hHal, hdd_rssi_threshold_breached_cb);
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053013758#ifdef WLAN_NS_OFFLOAD
13759 // Register IPv6 notifier to notify if any change in IP
13760 // So that we can reconfigure the offload parameters
13761 pHddCtx->ipv6_notifier.notifier_call = wlan_hdd_ipv6_changed;
13762 ret = register_inet6addr_notifier(&pHddCtx->ipv6_notifier);
13763 if (ret)
13764 {
Ratheesh S P36dbc932015-08-07 14:28:57 +053013765 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Failed to register IPv6 notifier"));
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053013766 }
13767 else
13768 {
Ratheesh S P36dbc932015-08-07 14:28:57 +053013769 hddLog(VOS_TRACE_LEVEL_INFO, FL("Registered IPv6 notifier"));
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053013770 }
13771#endif
13772
Sravan Kumar Kairamb0edc612016-10-26 13:55:24 +053013773 vos_mem_set((uint8_t *)&pHddCtx->bad_sta, HDD_MAX_STA_COUNT, 0);
13774
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053013775 // Register IPv4 notifier to notify if any change in IP
13776 // So that we can reconfigure the offload parameters
13777 pHddCtx->ipv4_notifier.notifier_call = wlan_hdd_ipv4_changed;
13778 ret = register_inetaddr_notifier(&pHddCtx->ipv4_notifier);
13779 if (ret)
13780 {
Ratheesh S P36dbc932015-08-07 14:28:57 +053013781 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Failed to register IPv4 notifier"));
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053013782 }
13783 else
13784 {
Ratheesh S P36dbc932015-08-07 14:28:57 +053013785 hddLog(VOS_TRACE_LEVEL_INFO, FL("Registered IPv4 notifier"));
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053013786 }
c_manjeecfd1efb2015-09-25 19:32:34 +053013787 /*Fw mem dump procfs initialization*/
13788 memdump_init();
Bhargav shah23c94942015-10-13 12:48:35 +053013789 hdd_dp_util_send_rps_ind(pHddCtx);
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053013790
Nishank Aggarwalc11826c2016-12-15 18:54:10 +053013791 pHddCtx->is_ap_mode_wow_supported =
13792 sme_IsFeatureSupportedByFW(SAP_MODE_WOW);
Sravan Kumar Kairam091e5b62017-01-23 14:14:20 +053013793
Hanumanth Reddy Pothulae92bcc12017-05-19 13:56:35 +053013794 pHddCtx->is_fatal_event_log_sup =
13795 sme_IsFeatureSupportedByFW(FATAL_EVENT_LOGGING);
13796 hddLog(VOS_TRACE_LEVEL_INFO, FL("FATAL_EVENT_LOGGING: %d"),
13797 pHddCtx->is_fatal_event_log_sup);
13798
Sravan Kumar Kairam091e5b62017-01-23 14:14:20 +053013799 hdd_assoc_registerFwdEapolCB(pVosContext);
13800
Ashish Kumar Dhanotiya32d092b2018-02-20 21:43:57 +053013801 mutex_init(&pHddCtx->cache_channel_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070013802 goto success;
13803
Hanumanth Reddy Pothula13789c42017-09-12 15:18:13 +053013804err_open_cesium_nl_sock:
13805#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
13806 hdd_close_cesium_nl_sock();
13807#endif
13808
13809err_ptt_sock_activate_svc:
13810#ifdef PTT_SOCK_SVC_ENABLE
13811 ptt_sock_deactivate_svc(pHddCtx);
13812#endif
13813
13814err_oem_activate_service:
13815#ifdef FEATURE_OEM_DATA_SUPPORT
13816 oem_deactivate_service();
13817#endif
13818
13819err_btc_activate_service:
13820 btc_deactivate_service();
13821
Jeff Johnson295189b2012-06-20 16:38:30 -070013822err_reg_netdev:
13823 unregister_netdevice_notifier(&hdd_netdev_notifier);
13824
Jeff Johnson295189b2012-06-20 16:38:30 -070013825err_unregister_pmops:
13826 hddDevTmUnregisterNotifyCallback(pHddCtx);
13827 hddDeregisterPmOps(pHddCtx);
13828
Yue Ma0d4891e2013-08-06 17:01:45 -070013829 hdd_debugfs_exit(pHddCtx);
13830
Jeff Johnson295189b2012-06-20 16:38:30 -070013831#ifdef WLAN_BTAMP_FEATURE
13832err_bap_stop:
13833 WLANBAP_Stop(pVosContext);
13834#endif
13835
13836#ifdef WLAN_BTAMP_FEATURE
13837err_bap_close:
13838 WLANBAP_Close(pVosContext);
13839#endif
13840
Jeff Johnson295189b2012-06-20 16:38:30 -070013841err_close_adapter:
13842 hdd_close_all_adapters( pHddCtx );
Mahesh A Saptasagar9ecefe42014-07-15 18:43:49 +053013843#ifdef CONFIG_ENABLE_LINUX_REG
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053013844err_unregister_wiphy:
Mahesh A Saptasagar9ecefe42014-07-15 18:43:49 +053013845#endif
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +053013846 wiphy_unregister(wiphy) ;
Agrawal Ashish33ec71e2015-11-26 20:20:58 +053013847 hdd_wlan_free_wiphy_channels(wiphy);
13848
Jeff Johnson295189b2012-06-20 16:38:30 -070013849err_vosstop:
13850 vos_stop(pVosContext);
13851
Amar Singhala49cbc52013-10-08 18:37:44 -070013852err_vosclose:
Jeff Johnson295189b2012-06-20 16:38:30 -070013853 status = vos_sched_close( pVosContext );
13854 if (!VOS_IS_STATUS_SUCCESS(status)) {
13855 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
13856 "%s: Failed to close VOSS Scheduler", __func__);
13857 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
13858 }
Amar Singhala49cbc52013-10-08 18:37:44 -070013859 vos_close(pVosContext );
13860
Mahesh A Saptasagarc3ed0122016-01-19 16:45:11 +053013861err_nl_srv:
13862#ifdef WLAN_KD_READY_NOTIFIER
13863 nl_srv_exit(pHddCtx->ptt_pid);
13864#else
13865 nl_srv_exit();
13866#endif /* WLAN_KD_READY_NOTIFIER */
Amar Singhal0a402232013-10-11 20:57:16 -070013867err_vos_nv_close:
13868
c_hpothue6a36282014-03-19 12:27:38 +053013869#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -070013870 vos_nv_close();
13871
c_hpothu70f8d812014-03-22 22:59:23 +053013872#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070013873
13874err_wdclose:
13875 if(pHddCtx->cfg_ini->fIsLogpEnabled)
13876 vos_watchdog_close(pVosContext);
13877
Jeff Johnson295189b2012-06-20 16:38:30 -070013878err_config:
Hanumanth Reddy Pothula1efcd162018-03-14 14:32:27 +053013879 hdd_request_manager_deinit();
Jeff Johnson295189b2012-06-20 16:38:30 -070013880 kfree(pHddCtx->cfg_ini);
13881 pHddCtx->cfg_ini= NULL;
13882
13883err_free_hdd_context:
Sushant Kaushik83392fa2015-05-05 17:44:40 +053013884 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_INIT);
Siddharth Bhalcd92b782015-06-29 12:25:40 +053013885 free_riva_power_on_lock("wlan");
Jeff Johnson295189b2012-06-20 16:38:30 -070013886 wiphy_free(wiphy) ;
13887 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -070013888 VOS_BUG(1);
13889
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -080013890 if (hdd_is_ssr_required())
13891 {
13892 /* WDI timeout had happened during load, so SSR is needed here */
13893 subsystem_restart("wcnss");
13894 msleep(5000);
13895 }
13896 hdd_set_ssr_required (VOS_FALSE);
13897
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -080013898 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -070013899
13900success:
13901 EXIT();
13902 return 0;
13903}
13904
13905/**---------------------------------------------------------------------------
13906
Jeff Johnson32d95a32012-09-10 13:15:23 -070013907 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -070013908
Jeff Johnson32d95a32012-09-10 13:15:23 -070013909 This is the driver entry point - called in different timeline depending
13910 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -070013911
13912 \param - None
13913
13914 \return - 0 for success, non zero for failure
13915
13916 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -070013917static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -070013918{
13919 VOS_STATUS status;
13920 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -070013921 struct device *dev = NULL;
13922 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -070013923#ifdef HAVE_WCNSS_CAL_DOWNLOAD
13924 int max_retries = 0;
13925#endif
Siddharth Bhalc7e79b62014-10-10 22:37:38 +053013926#ifdef HAVE_CBC_DONE
13927 int max_cbc_retries = 0;
13928#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070013929
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +053013930#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
13931 wlan_logging_sock_init_svc();
13932#endif
13933
Jeff Johnson295189b2012-06-20 16:38:30 -070013934 ENTER();
13935
Sushant Kaushik83392fa2015-05-05 17:44:40 +053013936 vos_wake_lock_init(&wlan_wake_lock, "wlan");
Jeff Johnson295189b2012-06-20 16:38:30 -070013937
13938 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
13939 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
13940
Jeff Johnson295189b2012-06-20 16:38:30 -070013941#ifdef ANI_BUS_TYPE_PCI
13942
13943 dev = wcnss_wlan_get_device();
13944
13945#endif // ANI_BUS_TYPE_PCI
13946
13947#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -070013948
13949#ifdef HAVE_WCNSS_CAL_DOWNLOAD
13950 /* wait until WCNSS driver downloads NV */
Ravi Kumar Bokka7a139e62016-11-17 21:32:55 +053013951 while (!wcnss_device_ready() && 10 >= ++max_retries) {
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -070013952 msleep(1000);
13953 }
Siddharth Bhalc7e79b62014-10-10 22:37:38 +053013954
Ravi Kumar Bokka7a139e62016-11-17 21:32:55 +053013955 if (max_retries >= 10) {
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -070013956 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
Sushant Kaushik83392fa2015-05-05 17:44:40 +053013957 vos_wake_lock_destroy(&wlan_wake_lock);
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +053013958#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
13959 wlan_logging_sock_deinit_svc();
13960#endif
13961
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -070013962 return -ENODEV;
13963 }
13964#endif
13965
Siddharth Bhalc7e79b62014-10-10 22:37:38 +053013966#ifdef HAVE_CBC_DONE
13967 while (!wcnss_cbc_complete() && 10 >= ++max_cbc_retries) {
13968 msleep(1000);
13969 }
13970 if (max_cbc_retries >= 10) {
13971 hddLog(VOS_TRACE_LEVEL_FATAL, "%s:CBC not completed", __func__);
13972 }
13973#endif
13974
Jeff Johnson295189b2012-06-20 16:38:30 -070013975 dev = wcnss_wlan_get_device();
13976#endif // ANI_BUS_TYPE_PLATFORM
13977
13978
13979 do {
13980 if (NULL == dev) {
13981 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
13982 ret_status = -1;
13983 break;
13984 }
13985
Jeff Johnson295189b2012-06-20 16:38:30 -070013986#ifdef TIMER_MANAGER
13987 vos_timer_manager_init();
13988#endif
13989
13990 /* Preopen VOSS so that it is ready to start at least SAL */
13991 status = vos_preOpen(&pVosContext);
13992
13993 if (!VOS_IS_STATUS_SUCCESS(status))
13994 {
13995 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
13996 ret_status = -1;
13997 break;
13998 }
13999
Sushant Kaushik02beb352015-06-04 15:15:01 +053014000 hddTraceInit();
Padma, Santhosh Kumar9093b202015-07-21 15:37:38 +053014001 hdd_register_debug_callback();
14002
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070014003#ifndef MODULE
14004 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
14005 */
14006 hdd_set_conparam((v_UINT_t)con_mode);
14007#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070014008
14009 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -080014010 if (hdd_wlan_startup(dev))
14011 {
Jeff Johnson295189b2012-06-20 16:38:30 -070014012 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -080014013 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -070014014 vos_preClose( &pVosContext );
14015 ret_status = -1;
14016 break;
14017 }
14018
Jeff Johnson295189b2012-06-20 16:38:30 -070014019 } while (0);
14020
14021 if (0 != ret_status)
14022 {
Jeff Johnson295189b2012-06-20 16:38:30 -070014023#ifdef TIMER_MANAGER
14024 vos_timer_exit();
14025#endif
14026#ifdef MEMORY_DEBUG
14027 vos_mem_exit();
14028#endif
Sushant Kaushik83392fa2015-05-05 17:44:40 +053014029 vos_wake_lock_destroy(&wlan_wake_lock);
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +053014030#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
14031 wlan_logging_sock_deinit_svc();
14032#endif
14033
Jeff Johnson295189b2012-06-20 16:38:30 -070014034 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
14035 }
14036 else
14037 {
14038 //Send WLAN UP indication to Nlink Service
14039 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
14040
14041 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Jeff Johnson295189b2012-06-20 16:38:30 -070014042 }
14043
14044 EXIT();
14045
14046 return ret_status;
14047}
14048
Jeff Johnson32d95a32012-09-10 13:15:23 -070014049/**---------------------------------------------------------------------------
14050
14051 \brief hdd_module_init() - Init Function
14052
14053 This is the driver entry point (invoked when module is loaded using insmod)
14054
14055 \param - None
14056
14057 \return - 0 for success, non zero for failure
14058
14059 --------------------------------------------------------------------------*/
14060#ifdef MODULE
14061static int __init hdd_module_init ( void)
14062{
14063 return hdd_driver_init();
14064}
Jeff Johnson32d95a32012-09-10 13:15:23 -070014065#else /* #ifdef MODULE */
14066static int __init hdd_module_init ( void)
14067{
14068 /* Driver initialization is delayed to fwpath_changed_handler */
14069 return 0;
14070}
Jeff Johnson32d95a32012-09-10 13:15:23 -070014071#endif /* #ifdef MODULE */
14072
Jeff Johnson295189b2012-06-20 16:38:30 -070014073
14074/**---------------------------------------------------------------------------
14075
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070014076 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -070014077
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070014078 This is the driver exit point (invoked when module is unloaded using rmmod
14079 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -070014080
14081 \param - None
14082
14083 \return - None
14084
14085 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070014086static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -070014087{
14088 hdd_context_t *pHddCtx = NULL;
14089 v_CONTEXT_t pVosContext = NULL;
Agarwal Ashish5e414792014-06-08 15:25:23 +053014090 v_REGDOMAIN_t regId;
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +053014091 unsigned long rc = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -070014092
14093 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
14094
14095 //Get the global vos context
14096 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
14097
14098 if(!pVosContext)
14099 {
14100 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
14101 goto done;
14102 }
14103
14104 //Get the HDD context.
14105 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
14106
14107 if(!pHddCtx)
14108 {
14109 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
14110 }
Katya Nigame7b69a82015-04-28 15:24:06 +053014111 else if (VOS_MONITOR_MODE == hdd_get_conparam())
14112 {
14113 hddLog(VOS_TRACE_LEVEL_INFO,"%s: MONITOR MODE",__func__);
14114 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_UNLOAD_IN_PROGRESS;
14115 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
14116 hdd_wlan_exit(pHddCtx);
14117 vos_preClose( &pVosContext );
14118 goto done;
14119 }
Jeff Johnson295189b2012-06-20 16:38:30 -070014120 else
14121 {
Siddharth Bhal2e5871b2015-03-24 16:20:51 +053014122 /* We wait for active entry threads to exit from driver
14123 * by waiting until rtnl_lock is available.
14124 */
14125 rtnl_lock();
14126 rtnl_unlock();
14127
Siddharth Bhal3c29dca2015-02-19 00:41:40 +053014128 INIT_COMPLETION(pHddCtx->ssr_comp_var);
14129 if ((pHddCtx->isLogpInProgress) && (FALSE ==
14130 vos_is_wlan_in_badState(VOS_MODULE_ID_HDD, NULL)))
14131 {
Siddharth Bhala204f572015-01-17 02:03:36 +053014132 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Siddharth Bhal3c29dca2015-02-19 00:41:40 +053014133 "%s:SSR in Progress; block rmmod !!!", __func__);
Siddharth Bhala204f572015-01-17 02:03:36 +053014134 rc = wait_for_completion_timeout(&pHddCtx->ssr_comp_var,
14135 msecs_to_jiffies(30000));
14136 if(!rc)
14137 {
14138 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
14139 "%s:SSR timedout, fatal error", __func__);
14140 VOS_BUG(0);
14141 }
14142 }
14143
Siddharth Bhal3c29dca2015-02-19 00:41:40 +053014144 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_UNLOAD_IN_PROGRESS;
14145 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
Jeff Johnson295189b2012-06-20 16:38:30 -070014146
c_hpothu8adb97b2014-12-08 19:38:20 +053014147 /* Driver Need to send country code 00 in below condition
14148 * 1) If gCountryCodePriority is set to 1; and last country
14149 * code set is through 11d. This needs to be done in case
14150 * when NV country code is 00.
14151 * This Needs to be done as when kernel store last country
14152 * code and if stored country code is not through 11d,
14153 * in sme_HandleChangeCountryCodeByUser we will disable 11d
14154 * in next load/unload as soon as we get any country through
14155 * 11d. In sme_HandleChangeCountryCodeByUser
14156 * pMsg->countryCode will be last countryCode and
14157 * pMac->scan.countryCode11d will be country through 11d so
14158 * due to mismatch driver will disable 11d.
14159 *
14160 */
Agarwal Ashish8db39882014-07-30 21:56:07 +053014161
c_hpothu8adb97b2014-12-08 19:38:20 +053014162 if ((eANI_BOOLEAN_TRUE == sme_Is11dCountrycode(pHddCtx->hHal) &&
Agarwal Ashish8dcd2862014-07-25 11:58:52 +053014163 pHddCtx->cfg_ini->fSupplicantCountryCodeHasPriority &&
Abhishek Singh2a705962014-10-30 14:47:28 +053014164 sme_Is11dSupported(pHddCtx->hHal)))
c_hpothu8adb97b2014-12-08 19:38:20 +053014165 {
14166 hddLog(VOS_TRACE_LEVEL_INFO,
Agarwal Ashish8dcd2862014-07-25 11:58:52 +053014167 FL("CountryCode 00 is being set while unloading driver"));
c_hpothu8adb97b2014-12-08 19:38:20 +053014168 vos_nv_getRegDomainFromCountryCode(&regId , "00", COUNTRY_USER);
14169 }
Agarwal Ashish5e414792014-06-08 15:25:23 +053014170
c_hpothu8adb97b2014-12-08 19:38:20 +053014171 //Do all the cleanup before deregistering the driver
14172 hdd_wlan_exit(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -070014173 }
14174
Jeff Johnson295189b2012-06-20 16:38:30 -070014175 vos_preClose( &pVosContext );
14176
14177#ifdef TIMER_MANAGER
14178 vos_timer_exit();
14179#endif
14180#ifdef MEMORY_DEBUG
14181 vos_mem_exit();
14182#endif
14183
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +053014184#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
14185 wlan_logging_sock_deinit_svc();
14186#endif
14187
Jeff Johnson295189b2012-06-20 16:38:30 -070014188done:
Sushant Kaushik83392fa2015-05-05 17:44:40 +053014189 vos_wake_lock_destroy(&wlan_wake_lock);
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +053014190
Jeff Johnson295189b2012-06-20 16:38:30 -070014191 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
14192}
14193
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070014194/**---------------------------------------------------------------------------
14195
14196 \brief hdd_module_exit() - Exit function
14197
14198 This is the driver exit point (invoked when module is unloaded using rmmod)
14199
14200 \param - None
14201
14202 \return - None
14203
14204 --------------------------------------------------------------------------*/
14205static void __exit hdd_module_exit(void)
14206{
14207 hdd_driver_exit();
14208}
14209
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070014210#ifdef MODULE
14211static int fwpath_changed_handler(const char *kmessage,
14212 struct kernel_param *kp)
14213{
Jeff Johnson76052702013-04-16 13:55:05 -070014214 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070014215}
14216
14217static int con_mode_handler(const char *kmessage,
14218 struct kernel_param *kp)
14219{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -070014220 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070014221}
14222#else /* #ifdef MODULE */
14223/**---------------------------------------------------------------------------
14224
Jeff Johnson76052702013-04-16 13:55:05 -070014225 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070014226
Jeff Johnson76052702013-04-16 13:55:05 -070014227 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070014228 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -070014229 - invoked when module parameter fwpath is modified from userspace to signal
14230 initializing the WLAN driver or when con_mode is modified from userspace
14231 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070014232
14233 \return - 0 for success, non zero for failure
14234
14235 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -070014236static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070014237{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -070014238 int ret_status;
14239
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070014240 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -070014241 ret_status = hdd_driver_init();
14242 wlan_hdd_inited = ret_status ? 0 : 1;
14243 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070014244 }
14245
14246 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -070014247
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070014248 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -070014249
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -070014250 ret_status = hdd_driver_init();
14251 wlan_hdd_inited = ret_status ? 0 : 1;
14252 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070014253}
14254
Jeff Johnson295189b2012-06-20 16:38:30 -070014255/**---------------------------------------------------------------------------
14256
Jeff Johnson76052702013-04-16 13:55:05 -070014257 \brief fwpath_changed_handler() - Handler Function
14258
14259 Handle changes to the fwpath parameter
14260
14261 \return - 0 for success, non zero for failure
14262
14263 --------------------------------------------------------------------------*/
14264static int fwpath_changed_handler(const char *kmessage,
14265 struct kernel_param *kp)
14266{
14267 int ret;
14268
14269 ret = param_set_copystring(kmessage, kp);
14270 if (0 == ret)
14271 ret = kickstart_driver();
14272 return ret;
14273}
14274
14275/**---------------------------------------------------------------------------
14276
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070014277 \brief con_mode_handler() -
14278
14279 Handler function for module param con_mode when it is changed by userspace
14280 Dynamically linked - do nothing
14281 Statically linked - exit and init driver, as in rmmod and insmod
14282
Jeff Johnson76052702013-04-16 13:55:05 -070014283 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070014284
Jeff Johnson76052702013-04-16 13:55:05 -070014285 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070014286
14287 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -070014288static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070014289{
Jeff Johnson76052702013-04-16 13:55:05 -070014290 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070014291
Jeff Johnson76052702013-04-16 13:55:05 -070014292 ret = param_set_int(kmessage, kp);
14293 if (0 == ret)
14294 ret = kickstart_driver();
14295 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070014296}
14297#endif /* #ifdef MODULE */
14298
14299/**---------------------------------------------------------------------------
14300
Jeff Johnson295189b2012-06-20 16:38:30 -070014301 \brief hdd_get_conparam() -
14302
14303 This is the driver exit point (invoked when module is unloaded using rmmod)
14304
14305 \param - None
14306
14307 \return - tVOS_CON_MODE
14308
14309 --------------------------------------------------------------------------*/
14310tVOS_CON_MODE hdd_get_conparam ( void )
14311{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070014312#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -070014313 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070014314#else
14315 return (tVOS_CON_MODE)curr_con_mode;
14316#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070014317}
14318void hdd_set_conparam ( v_UINT_t newParam )
14319{
14320 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070014321#ifndef MODULE
14322 curr_con_mode = con_mode;
14323#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070014324}
14325/**---------------------------------------------------------------------------
14326
14327 \brief hdd_softap_sta_deauth() - function
14328
14329 This to take counter measure to handle deauth req from HDD
14330
14331 \param - pAdapter - Pointer to the HDD
14332
14333 \param - enable - boolean value
14334
14335 \return - None
14336
14337 --------------------------------------------------------------------------*/
14338
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +053014339VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter,
14340 struct tagCsrDelStaParams *pDelStaParams)
Jeff Johnson295189b2012-06-20 16:38:30 -070014341{
Jeff Johnson295189b2012-06-20 16:38:30 -070014342 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -080014343 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Hanumanth Reddy Pothula57323632017-12-06 17:55:09 +053014344 struct hdd_cache_sta_info *cache_sta_info;
14345 ptSapContext pSapCtx = VOS_GET_SAP_CB(pVosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -070014346
14347 ENTER();
14348
Jeff Johnsonc135a9a2017-09-19 08:37:24 -070014349 hddLog(LOG1, "hdd_softap_sta_deauth:(%pK, false)",
Rajesh Chauhan18488fc2013-08-22 10:15:03 -070014350 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -070014351
Hanumanth Reddy Pothula57323632017-12-06 17:55:09 +053014352 if (!pSapCtx) {
14353 hddLog(LOGE, "sap context is NULL");
14354 return vosStatus;
14355 }
14356
14357 cache_sta_info = hdd_get_cache_stainfo(pSapCtx->cache_sta_info,
14358 pDelStaParams->peerMacAddr);
14359 if (cache_sta_info) {
14360 cache_sta_info->reason_code = pDelStaParams->reason_code;
14361 cache_sta_info->rx_rate =
14362 wlan_tl_get_sta_rx_rate(pVosContext, cache_sta_info->ucSTAId);
14363 WLANTL_GetSAPStaRSSi(pVosContext, cache_sta_info->ucSTAId,
14364 &cache_sta_info->rssi);
14365 }
14366
Jeff Johnson295189b2012-06-20 16:38:30 -070014367 //Ignore request to deauth bcmc station
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +053014368 if (pDelStaParams->peerMacAddr[0] & 0x1)
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -080014369 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -070014370
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +053014371 vosStatus = WLANSAP_DeauthSta(pVosContext, pDelStaParams);
Jeff Johnson295189b2012-06-20 16:38:30 -070014372
14373 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -080014374 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -070014375}
14376
14377/**---------------------------------------------------------------------------
14378
Rashmi Ramanna1f0948d2014-08-28 15:33:48 +053014379 \brief hdd_del_all_sta() - function
14380
14381 This function removes all the stations associated on stopping AP/P2P GO.
14382
14383 \param - pAdapter - Pointer to the HDD
14384
14385 \return - None
14386
14387 --------------------------------------------------------------------------*/
14388
14389int hdd_del_all_sta(hdd_adapter_t *pAdapter)
14390{
14391 v_U16_t i;
14392 VOS_STATUS vos_status;
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +053014393 v_CONTEXT_t pVosContext = ( WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
14394 ptSapContext pSapCtx = NULL;
14395 pSapCtx = VOS_GET_SAP_CB(pVosContext);
14396 if(pSapCtx == NULL){
14397 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
14398 FL("psapCtx is NULL"));
14399 return 1;
14400 }
Rashmi Ramanna1f0948d2014-08-28 15:33:48 +053014401 ENTER();
14402
14403 hddLog(VOS_TRACE_LEVEL_INFO,
14404 "%s: Delete all STAs associated.",__func__);
14405 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
14406 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
14407 )
14408 {
14409 for(i = 0; i < WLAN_MAX_STA_COUNT; i++)
14410 {
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +053014411 if ((pSapCtx->aStaInfo[i].isUsed) &&
14412 (!pSapCtx->aStaInfo[i].isDeauthInProgress))
Rashmi Ramanna1f0948d2014-08-28 15:33:48 +053014413 {
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +053014414 struct tagCsrDelStaParams delStaParams;
14415
14416 WLANSAP_PopulateDelStaParams(
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +053014417 pSapCtx->aStaInfo[i].macAddrSTA.bytes,
Sushant Kaushik4cd28f62014-12-26 14:23:50 +053014418 eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
14419 SIR_MAC_MGMT_DEAUTH >> 4,
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +053014420 &delStaParams);
14421 vos_status = hdd_softap_sta_deauth(pAdapter, &delStaParams);
Rashmi Ramanna1f0948d2014-08-28 15:33:48 +053014422 if (VOS_IS_STATUS_SUCCESS(vos_status))
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +053014423 pSapCtx->aStaInfo[i].isDeauthInProgress = TRUE;
Rashmi Ramanna1f0948d2014-08-28 15:33:48 +053014424 }
14425 }
14426 }
14427
14428 EXIT();
14429 return 0;
14430}
14431
14432/**---------------------------------------------------------------------------
14433
Jeff Johnson295189b2012-06-20 16:38:30 -070014434 \brief hdd_softap_sta_disassoc() - function
14435
14436 This to take counter measure to handle deauth req from HDD
14437
14438 \param - pAdapter - Pointer to the HDD
14439
14440 \param - enable - boolean value
14441
14442 \return - None
14443
14444 --------------------------------------------------------------------------*/
14445
14446void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
14447{
Hanumanth Reddy Pothula57323632017-12-06 17:55:09 +053014448 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
14449 struct hdd_cache_sta_info *cache_sta_info;
14450 ptSapContext pSapCtx = VOS_GET_SAP_CB(pVosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -070014451
14452 ENTER();
14453
Jeff Johnsonc135a9a2017-09-19 08:37:24 -070014454 hddLog( LOGE, "hdd_softap_sta_disassoc:(%pK, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -070014455
Hanumanth Reddy Pothula57323632017-12-06 17:55:09 +053014456 if (!pSapCtx) {
14457 hddLog(LOGE, "sap context is NULL");
14458 return ;
14459 }
14460
Jeff Johnson295189b2012-06-20 16:38:30 -070014461 //Ignore request to disassoc bcmc station
14462 if( pDestMacAddress[0] & 0x1 )
14463 return;
14464
Hanumanth Reddy Pothula57323632017-12-06 17:55:09 +053014465 cache_sta_info = hdd_get_cache_stainfo(pSapCtx->cache_sta_info,
14466 pDestMacAddress);
14467 if (cache_sta_info) {
14468 cache_sta_info->reason_code = eSIR_MAC_DEAUTH_LEAVING_BSS_REASON;
14469 cache_sta_info->rx_rate =
14470 wlan_tl_get_sta_rx_rate(pVosContext, cache_sta_info->ucSTAId);
14471 WLANTL_GetSAPStaRSSi(pVosContext, cache_sta_info->ucSTAId,
14472 &cache_sta_info->rssi);
14473 }
14474
Jeff Johnson295189b2012-06-20 16:38:30 -070014475 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
14476}
14477
14478void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
14479{
14480 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
14481
14482 ENTER();
14483
Jeff Johnsonc135a9a2017-09-19 08:37:24 -070014484 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%pK, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -070014485
14486 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
14487}
14488
Jeff Johnson295189b2012-06-20 16:38:30 -070014489/**---------------------------------------------------------------------------
14490 *
14491 * \brief hdd_get__concurrency_mode() -
14492 *
14493 *
14494 * \param - None
14495 *
14496 * \return - CONCURRENCY MODE
14497 *
14498 * --------------------------------------------------------------------------*/
14499tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
14500{
14501 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
14502 hdd_context_t *pHddCtx;
14503
14504 if (NULL != pVosContext)
14505 {
14506 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
14507 if (NULL != pHddCtx)
14508 {
14509 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
14510 }
14511 }
14512
14513 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070014514 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -070014515 return VOS_STA;
14516}
Sushant Kaushikabb7ee62014-07-18 16:20:12 +053014517v_BOOL_t
14518wlan_hdd_is_GO_power_collapse_allowed (hdd_context_t* pHddCtx)
14519{
14520 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -070014521
Sushant Kaushikabb7ee62014-07-18 16:20:12 +053014522 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_GO);
14523 if (pAdapter == NULL)
14524 {
14525 hddLog(VOS_TRACE_LEVEL_INFO,
14526 FL("GO doesn't exist"));
14527 return TRUE;
14528 }
14529 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
14530 {
14531 hddLog(VOS_TRACE_LEVEL_INFO,
14532 FL("GO started"));
14533 return TRUE;
14534 }
14535 else
14536 /* wait till GO changes its interface to p2p device */
14537 hddLog(VOS_TRACE_LEVEL_INFO,
14538 FL("Del_bss called, avoid apps suspend"));
14539 return FALSE;
14540
14541}
Jeff Johnson295189b2012-06-20 16:38:30 -070014542/* Decide whether to allow/not the apps power collapse.
14543 * Allow apps power collapse if we are in connected state.
14544 * if not, allow only if we are in IMPS */
14545v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
14546{
14547 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -080014548 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -080014549 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -070014550 hdd_config_t *pConfig = pHddCtx->cfg_ini;
14551 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
14552 hdd_adapter_t *pAdapter = NULL;
14553 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -080014554 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -070014555
Jeff Johnson295189b2012-06-20 16:38:30 -070014556 if (VOS_STA_SAP_MODE == hdd_get_conparam())
14557 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -070014558
Yathish9f22e662012-12-10 14:21:35 -080014559 concurrent_state = hdd_get_concurrency_mode();
14560
Sushant Kaushikabb7ee62014-07-18 16:20:12 +053014561 if ((concurrent_state == (VOS_STA | VOS_P2P_GO)) &&
14562 !(wlan_hdd_is_GO_power_collapse_allowed(pHddCtx)))
14563 return FALSE;
Yathish9f22e662012-12-10 14:21:35 -080014564#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
Sushant Kaushikabb7ee62014-07-18 16:20:12 +053014565
Yathish9f22e662012-12-10 14:21:35 -080014566 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
Sushant Kaushikabb7ee62014-07-18 16:20:12 +053014567 (concurrent_state == (VOS_STA | VOS_P2P_GO)))&&
Yathish9f22e662012-12-10 14:21:35 -080014568 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
14569 return TRUE;
14570#endif
14571
Jeff Johnson295189b2012-06-20 16:38:30 -070014572 /*loop through all adapters. TBD fix for Concurrency */
14573 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
14574 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
14575 {
14576 pAdapter = pAdapterNode->pAdapter;
14577 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
14578 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
14579 {
Srikant Kuppafef66a72013-01-30 17:32:44 -080014580 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
c_hpothu4e8faac2014-05-16 17:38:44 +053014581 && (pmcState != IMPS && pmcState != BMPS && pmcState != UAPSD
c_hpothu1c6957d2015-01-06 18:19:47 +053014582 && pmcState != STOPPED && pmcState != STANDBY &&
14583 pmcState != WOWL)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -080014584 (eANI_BOOLEAN_TRUE == scanRspPending) ||
14585 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -070014586 {
Mukul Sharma4be88422015-03-09 20:29:07 +053014587 if(pmcState == FULL_POWER &&
14588 sme_IsCoexScoIndicationSet(pHddCtx->hHal))
14589 {
14590 /*
14591 * When SCO indication comes from Coex module , host will
14592 * enter in to full power mode, but this should not prevent
14593 * apps processor power collapse.
14594 */
14595 hddLog(LOG1,
14596 FL("Allow apps power collapse"
14597 "even when sco indication is set"));
14598 return TRUE;
14599 }
Srikant Kuppafef66a72013-01-30 17:32:44 -080014600 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Deepthi Gowri03a979f2016-11-03 15:20:19 +053014601 "pmcState = %d scanRspPending = %d "
14602 "inMiddleOfRoaming = %d connected = %d",
14603 __func__, pmcState, scanRspPending,
14604 inMiddleOfRoaming, hdd_connIsConnected(
14605 WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )));
14606 wlan_hdd_get_tdls_stats(pAdapter);
14607 return FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -070014608 }
14609 }
14610 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
14611 pAdapterNode = pNext;
14612 }
14613 return TRUE;
14614}
14615
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -080014616/* Decides whether to send suspend notification to Riva
14617 * if any adapter is in BMPS; then it is required */
14618v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
14619{
14620 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
14621 hdd_config_t *pConfig = pHddCtx->cfg_ini;
14622
14623 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
14624 {
14625 return TRUE;
14626 }
14627 return FALSE;
14628}
14629
Jeff Johnson295189b2012-06-20 16:38:30 -070014630void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
14631{
14632 switch(mode)
14633 {
Chilam Ngc4244af2013-04-01 15:37:32 -070014634 case VOS_STA_MODE:
14635 case VOS_P2P_CLIENT_MODE:
14636 case VOS_P2P_GO_MODE:
14637 case VOS_STA_SAP_MODE:
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +053014638 case VOS_MONITOR_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -070014639 pHddCtx->concurrency_mode |= (1 << mode);
Agarwal Ashish51325b52014-06-16 16:50:49 +053014640 pHddCtx->no_of_open_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -070014641 break;
14642 default:
14643 break;
Jeff Johnson295189b2012-06-20 16:38:30 -070014644 }
Agarwal Ashish51325b52014-06-16 16:50:49 +053014645 hddLog(VOS_TRACE_LEVEL_INFO, FL("concurrency_mode = 0x%x "
14646 "Number of open sessions for mode %d = %d"),
14647 pHddCtx->concurrency_mode, mode,
14648 pHddCtx->no_of_open_sessions[mode]);
Jeff Johnson295189b2012-06-20 16:38:30 -070014649}
14650
14651
14652void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
14653{
14654 switch(mode)
14655 {
Chilam Ngc4244af2013-04-01 15:37:32 -070014656 case VOS_STA_MODE:
14657 case VOS_P2P_CLIENT_MODE:
14658 case VOS_P2P_GO_MODE:
14659 case VOS_STA_SAP_MODE:
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +053014660 case VOS_MONITOR_MODE:
Agarwal Ashish51325b52014-06-16 16:50:49 +053014661 pHddCtx->no_of_open_sessions[mode]--;
14662 if (!(pHddCtx->no_of_open_sessions[mode]))
14663 pHddCtx->concurrency_mode &= (~(1 << mode));
Jeff Johnson295189b2012-06-20 16:38:30 -070014664 break;
14665 default:
14666 break;
14667 }
Agarwal Ashish51325b52014-06-16 16:50:49 +053014668 hddLog(VOS_TRACE_LEVEL_INFO, FL("concurrency_mode = 0x%x "
14669 "Number of open sessions for mode %d = %d"),
14670 pHddCtx->concurrency_mode, mode, pHddCtx->no_of_open_sessions[mode]);
14671
14672}
14673/**---------------------------------------------------------------------------
14674 *
14675 * \brief wlan_hdd_incr_active_session()
14676 *
14677 * This function increments the number of active sessions
14678 * maintained per device mode
14679 * Incase of STA/P2P CLI/IBSS upon connection indication it is incremented
14680 * Incase of SAP/P2P GO upon bss start it is incremented
14681 *
14682 * \param pHddCtx - HDD Context
14683 * \param mode - device mode
14684 *
14685 * \return - None
14686 *
14687 * --------------------------------------------------------------------------*/
14688void wlan_hdd_incr_active_session(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
14689{
14690 switch (mode) {
14691 case VOS_STA_MODE:
14692 case VOS_P2P_CLIENT_MODE:
14693 case VOS_P2P_GO_MODE:
14694 case VOS_STA_SAP_MODE:
14695 pHddCtx->no_of_active_sessions[mode]++;
14696 break;
14697 default:
14698 hddLog(VOS_TRACE_LEVEL_INFO, FL("Not Expected Mode %d"), mode);
14699 break;
14700 }
14701 hddLog(VOS_TRACE_LEVEL_INFO, FL("No.# of active sessions for mode %d = %d"),
14702 mode,
14703 pHddCtx->no_of_active_sessions[mode]);
14704}
14705
14706/**---------------------------------------------------------------------------
14707 *
14708 * \brief wlan_hdd_decr_active_session()
14709 *
14710 * This function decrements the number of active sessions
14711 * maintained per device mode
14712 * Incase of STA/P2P CLI/IBSS upon disconnection it is decremented
14713 * Incase of SAP/P2P GO upon bss stop it is decremented
14714 *
14715 * \param pHddCtx - HDD Context
14716 * \param mode - device mode
14717 *
14718 * \return - None
14719 *
14720 * --------------------------------------------------------------------------*/
14721void wlan_hdd_decr_active_session(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
14722{
Bhargav Shahd0715912015-10-01 18:17:37 +053014723
Agarwal Ashish51325b52014-06-16 16:50:49 +053014724 switch (mode) {
14725 case VOS_STA_MODE:
14726 case VOS_P2P_CLIENT_MODE:
14727 case VOS_P2P_GO_MODE:
14728 case VOS_STA_SAP_MODE:
Agarwal Ashish5325f522014-08-06 00:58:44 +053014729 if (pHddCtx->no_of_active_sessions[mode] > 0)
14730 pHddCtx->no_of_active_sessions[mode]--;
14731 else
14732 hddLog(VOS_TRACE_LEVEL_INFO, FL(" No.# of Active sessions"
14733 "is already Zero"));
Agarwal Ashish51325b52014-06-16 16:50:49 +053014734 break;
14735 default:
14736 hddLog(VOS_TRACE_LEVEL_INFO, FL("Not Expected Mode %d"), mode);
14737 break;
14738 }
14739 hddLog(VOS_TRACE_LEVEL_INFO, FL("No.# of active sessions for mode %d = %d"),
14740 mode,
14741 pHddCtx->no_of_active_sessions[mode]);
Jeff Johnson295189b2012-06-20 16:38:30 -070014742}
14743
Jeff Johnsone7245742012-09-05 17:12:55 -070014744/**---------------------------------------------------------------------------
14745 *
14746 * \brief wlan_hdd_restart_init
14747 *
14748 * This function initalizes restart timer/flag. An internal function.
14749 *
14750 * \param - pHddCtx
14751 *
14752 * \return - None
14753 *
14754 * --------------------------------------------------------------------------*/
14755
14756static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
14757{
14758 /* Initialize */
14759 pHddCtx->hdd_restart_retries = 0;
14760 atomic_set(&pHddCtx->isRestartInProgress, 0);
14761 vos_timer_init(&pHddCtx->hdd_restart_timer,
14762 VOS_TIMER_TYPE_SW,
14763 wlan_hdd_restart_timer_cb,
14764 pHddCtx);
14765}
14766/**---------------------------------------------------------------------------
14767 *
14768 * \brief wlan_hdd_restart_deinit
14769 *
14770 * This function cleans up the resources used. An internal function.
14771 *
14772 * \param - pHddCtx
14773 *
14774 * \return - None
14775 *
14776 * --------------------------------------------------------------------------*/
14777
14778static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
14779{
14780
14781 VOS_STATUS vos_status;
14782 /* Block any further calls */
14783 atomic_set(&pHddCtx->isRestartInProgress, 1);
14784 /* Cleanup */
14785 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
14786 if (!VOS_IS_STATUS_SUCCESS(vos_status))
c_hpothu6ff1c3c2013-10-01 19:01:57 +053014787 hddLog(LOGE, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -070014788 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
14789 if (!VOS_IS_STATUS_SUCCESS(vos_status))
c_hpothu6ff1c3c2013-10-01 19:01:57 +053014790 hddLog(LOGE, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -070014791
14792}
14793
14794/**---------------------------------------------------------------------------
14795 *
14796 * \brief wlan_hdd_framework_restart
14797 *
14798 * This function uses a cfg80211 API to start a framework initiated WLAN
14799 * driver module unload/load.
14800 *
14801 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
14802 *
14803 *
14804 * \param - pHddCtx
14805 *
14806 * \return - VOS_STATUS_SUCCESS: Success
14807 * VOS_STATUS_E_EMPTY: Adapter is Empty
14808 * VOS_STATUS_E_NOMEM: No memory
14809
14810 * --------------------------------------------------------------------------*/
14811
14812static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
14813{
14814 VOS_STATUS status = VOS_STATUS_SUCCESS;
14815 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -070014816 int len = (sizeof (struct ieee80211_mgmt));
14817 struct ieee80211_mgmt *mgmt = NULL;
14818
14819 /* Prepare the DEAUTH managment frame with reason code */
14820 mgmt = kzalloc(len, GFP_KERNEL);
14821 if(mgmt == NULL)
14822 {
14823 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
14824 "%s: memory allocation failed (%d bytes)", __func__, len);
14825 return VOS_STATUS_E_NOMEM;
14826 }
14827 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -070014828
14829 /* Iterate over all adapters/devices */
14830 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Hanumantha Reddy Pothulada0fe362015-02-27 18:37:03 +053014831 if ((NULL == pAdapterNode) || (VOS_STATUS_SUCCESS != status))
14832 {
14833 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnsonc135a9a2017-09-19 08:37:24 -070014834 FL("fail to get adapter: %pK %d"), pAdapterNode, status);
Hanumantha Reddy Pothulada0fe362015-02-27 18:37:03 +053014835 goto end;
14836 }
14837
Jeff Johnsone7245742012-09-05 17:12:55 -070014838 do
14839 {
Hanumantha Reddy Pothulada0fe362015-02-27 18:37:03 +053014840 if(pAdapterNode->pAdapter &&
14841 WLAN_HDD_ADAPTER_MAGIC == pAdapterNode->pAdapter->magic)
Jeff Johnsone7245742012-09-05 17:12:55 -070014842 {
14843 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
14844 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
14845 pAdapterNode->pAdapter->dev->name,
14846 pAdapterNode->pAdapter->device_mode,
14847 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -070014848 /*
14849 * CFG80211 event to restart the driver
14850 *
14851 * 'cfg80211_send_unprot_deauth' sends a
14852 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
14853 * of SME(Linux Kernel) state machine.
14854 *
14855 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
14856 * the driver.
14857 *
14858 */
Abhishek Singh00b71972016-01-07 10:51:04 +053014859
Anand N Sunkade9adb1b2015-07-29 09:56:45 +053014860#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
14861 cfg80211_rx_unprot_mlme_mgmt(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len);
14862#else
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -070014863 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Anand N Sunkade9adb1b2015-07-29 09:56:45 +053014864#endif
Jeff Johnsone7245742012-09-05 17:12:55 -070014865 }
14866 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
14867 pAdapterNode = pNext;
14868 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
14869
Hanumantha Reddy Pothulada0fe362015-02-27 18:37:03 +053014870 end:
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -070014871 /* Free the allocated management frame */
14872 kfree(mgmt);
14873
Jeff Johnsone7245742012-09-05 17:12:55 -070014874 /* Retry until we unload or reach max count */
14875 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
14876 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
14877
14878 return status;
14879
14880}
14881/**---------------------------------------------------------------------------
14882 *
14883 * \brief wlan_hdd_restart_timer_cb
14884 *
14885 * Restart timer callback. An internal function.
14886 *
14887 * \param - User data:
14888 *
14889 * \return - None
14890 *
14891 * --------------------------------------------------------------------------*/
14892
14893void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
14894{
14895 hdd_context_t *pHddCtx = usrDataForCallback;
14896 wlan_hdd_framework_restart(pHddCtx);
14897 return;
14898
14899}
14900
14901
14902/**---------------------------------------------------------------------------
14903 *
14904 * \brief wlan_hdd_restart_driver
14905 *
14906 * This function sends an event to supplicant to restart the WLAN driver.
14907 *
14908 * This function is called from vos_wlanRestart.
14909 *
14910 * \param - pHddCtx
14911 *
14912 * \return - VOS_STATUS_SUCCESS: Success
14913 * VOS_STATUS_E_EMPTY: Adapter is Empty
14914 * VOS_STATUS_E_ALREADY: Request already in progress
14915
14916 * --------------------------------------------------------------------------*/
14917VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
14918{
14919 VOS_STATUS status = VOS_STATUS_SUCCESS;
14920
14921 /* A tight check to make sure reentrancy */
14922 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
14923 {
Mihir Shetefd528652014-06-23 19:07:50 +053014924 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnsone7245742012-09-05 17:12:55 -070014925 "%s: WLAN restart is already in progress", __func__);
14926
14927 return VOS_STATUS_E_ALREADY;
14928 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -070014929 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -080014930#ifdef HAVE_WCNSS_RESET_INTR
Siddharth Bhal864e7e82015-04-07 20:07:24 +053014931 wcnss_reset_fiq(TRUE);
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -070014932#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -070014933
Jeff Johnsone7245742012-09-05 17:12:55 -070014934 return status;
14935}
14936
Bhargav Shahd0715912015-10-01 18:17:37 +053014937/**
14938 * hdd_get_total_sessions() - provide total number of active sessions
14939 * @pHddCtx: Valid Global HDD context pointer
14940 *
14941 * This function iterates through pAdaptors and find the number of all active
14942 * sessions. This active sessions includes connected sta, p2p client and number
14943 * of client connected to sap/p2p go.
14944 *
14945 * Return: Total number of active sessions.
14946 */
14947v_U8_t hdd_get_total_sessions(hdd_context_t *pHddCtx)
14948{
14949 v_U8_t active_session = 0;
14950 hdd_station_ctx_t *pHddStaCtx;
14951 hdd_adapter_list_node_t *pAdapterNode, *pNext;
14952 hdd_adapter_t *pAdapter;
14953 VOS_STATUS status;
14954
14955 status = hdd_get_front_adapter(pHddCtx, &pAdapterNode);
14956 while (NULL != pAdapterNode && VOS_STATUS_SUCCESS == status) {
14957 pAdapter = pAdapterNode->pAdapter;
14958 switch (pAdapter->device_mode) {
14959 case VOS_STA_MODE:
14960 case VOS_P2P_CLIENT_MODE:
14961 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14962 if(eConnectionState_Associated == pHddStaCtx->conn_info.connState)
14963 active_session += 1;
14964 break;
14965 case VOS_STA_SAP_MODE:
14966 case VOS_P2P_GO_MODE:
14967 active_session += hdd_softap_get_connected_sta(pAdapter);
14968 break;
14969 default:
14970 break;
14971 }
14972
14973 status = hdd_get_next_adapter(pHddCtx, pAdapterNode, &pNext);
14974 pAdapterNode = pNext;
14975 }
14976
14977 return active_session;
14978}
14979
14980/**
14981 * hdd_set_delack_value() - Set delack value
14982 * @pHddCtx: Valid Global HDD context pointer
14983 * @next_rx_level: Value to set for delack
14984 *
14985 * This function compare present value and next value of delack. If the both
14986 * are diffrent then it sets next value .
14987 *
14988 * Return: void.
14989 */
14990void hdd_set_delack_value(hdd_context_t *pHddCtx, v_U32_t next_rx_level)
14991{
14992 if (pHddCtx->cur_rx_level != next_rx_level) {
14993 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_DEBUG,
14994 "%s: TCP DELACK trigger level %d",
14995 __func__, next_rx_level);
14996 mutex_lock(&pHddCtx->cur_rx_level_lock);
14997 pHddCtx->cur_rx_level = next_rx_level;
14998 mutex_unlock(&pHddCtx->cur_rx_level_lock);
14999 wlan_hdd_send_svc_nlink_msg(WLAN_SVC_WLAN_TP_IND, &next_rx_level,
15000 sizeof(next_rx_level));
15001 }
15002}
15003
15004/**
15005 * hdd_set_default_stop_delack_timer() - Start delack timer
15006 * @pHddCtx: Valid Global HDD context pointer
15007 *
15008 * This function stop delack timer and set delack value to default..
15009 *
15010 * Return: void.
15011 */
15012
15013void hdd_set_default_stop_delack_timer(hdd_context_t *pHddCtx)
15014{
15015 if (VOS_TIMER_STATE_RUNNING !=
15016 vos_timer_getCurrentState(&pHddCtx->delack_timer)) {
15017 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_DEBUG,
15018 "%s: Can not stop timer", __func__);
15019 return;
15020 }
15021
15022 vos_timer_stop(&pHddCtx->delack_timer);
15023 hdd_set_delack_value(pHddCtx, TP_IND_LOW);
15024}
15025
15026/**
15027 * hdd_start_delack_timer() - Start delack timer
15028 * @pHddCtx: Valid Global HDD context pointer
15029 *
15030 * This function starts the delack timer for tcpDelAckComputeInterval time
15031 * interval.The default timer value is 2 second.
15032 *
15033 * Return: void.
15034 */
15035void hdd_start_delack_timer(hdd_context_t *pHddCtx)
15036{
15037 if (VOS_TIMER_STATE_RUNNING ==
15038 vos_timer_getCurrentState(&pHddCtx->delack_timer)) {
15039 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_DEBUG,
15040 "%s: Timer is already running", __func__);
15041 return;
15042 }
15043
15044 vos_timer_start(&pHddCtx->delack_timer,
15045 pHddCtx->cfg_ini->tcpDelAckComputeInterval);
15046}
15047
15048/**
15049 * hdd_update_prev_rx_packet_count() - Update previous rx packet count
15050 * @pHddCtx: Valid Global HDD context pointer
15051 *
15052 * This function updates the prev_rx_packets count from the corresponding
15053 * pAdapter states. This prev_rx_packets will diffed with the packet count
15054 * at the end of delack timer. That can give number of RX packet is spacific
15055 * time.
15056 *
15057 * Return: void.
15058 */
15059void hdd_update_prev_rx_packet_count(hdd_context_t *pHddCtx)
15060{
15061 hdd_adapter_list_node_t *pAdapterNode, *pNext;
15062 hdd_adapter_t *pAdapter;
15063 VOS_STATUS status;
15064
15065 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
15066 while (NULL != pAdapterNode && VOS_STATUS_SUCCESS == status) {
15067 pAdapter = pAdapterNode->pAdapter;
15068 pAdapter->prev_rx_packets = pAdapter->stats.rx_packets;
15069 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
15070 pAdapterNode = pNext;
15071 }
15072}
15073
15074/**
15075 * hdd_manage_delack_timer() - start\stop delack timer
15076 * @pHddCtx: Valid Global HDD context pointer
15077 *
15078 * This function check the number of concerent session present, it starts the
15079 * delack timer if only one session is present.
15080 * In the case of BT_COEX and TDLS mode it blindly stop delack functionality.
15081 *
15082 * Return: void.
15083 */
15084void hdd_manage_delack_timer(hdd_context_t *pHddCtx)
15085{
15086 uint8_t sessions;
15087
15088 if (!pHddCtx->cfg_ini->enable_delack) {
15089 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_DEBUG,
15090 "%s: TCP DELACK is not enabled", __func__);
15091 return;
15092 }
15093
15094 /* Blindly stop timer of BTCOEX and TDLS Session is up */
15095 if (pHddCtx->mode != 0) {
15096 hdd_set_default_stop_delack_timer(pHddCtx);
15097 return;
15098 }
15099
15100 sessions = hdd_get_total_sessions(pHddCtx);
15101 if (sessions == 1) {
15102 hdd_update_prev_rx_packet_count(pHddCtx);
15103 hdd_start_delack_timer(pHddCtx);
15104 } else {
15105 hdd_set_default_stop_delack_timer(pHddCtx);
15106 }
15107}
15108
Mihir Shetee1093ba2014-01-21 20:13:32 +053015109/**---------------------------------------------------------------------------
15110 *
15111 * \brief wlan_hdd_init_channels
15112 *
15113 * This function is used to initialize the channel list in CSR
15114 *
15115 * This function is called from hdd_wlan_startup
15116 *
15117 * \param - pHddCtx: HDD context
15118 *
15119 * \return - VOS_STATUS_SUCCESS: Success
15120 * VOS_STATUS_E_FAULT: Failure reported by SME
15121
15122 * --------------------------------------------------------------------------*/
15123static VOS_STATUS wlan_hdd_init_channels(hdd_context_t *pHddCtx)
15124{
15125 eHalStatus status;
15126
15127 status = sme_InitChannels(pHddCtx->hHal);
15128 if (HAL_STATUS_SUCCESS(status))
15129 {
15130 return VOS_STATUS_SUCCESS;
15131 }
15132 else
15133 {
15134 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Channel initialization failed(%d)",
15135 __func__, status);
15136 return VOS_STATUS_E_FAULT;
15137 }
15138}
15139
Mihir Shete04206452014-11-20 17:50:58 +053015140#ifdef CONFIG_ENABLE_LINUX_REG
Agarwal Ashish6db9d532014-09-30 18:19:10 +053015141VOS_STATUS wlan_hdd_init_channels_for_cc(hdd_context_t *pHddCtx, driver_load_type init )
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053015142{
15143 eHalStatus status;
15144
Agarwal Ashish6db9d532014-09-30 18:19:10 +053015145 status = sme_InitChannelsForCC(pHddCtx->hHal, init);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053015146 if (HAL_STATUS_SUCCESS(status))
15147 {
15148 return VOS_STATUS_SUCCESS;
15149 }
15150 else
15151 {
15152 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Issue reg hint failed(%d)",
15153 __func__, status);
15154 return VOS_STATUS_E_FAULT;
15155 }
15156}
Mihir Shete04206452014-11-20 17:50:58 +053015157#endif
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -070015158/*
15159 * API to find if there is any STA or P2P-Client is connected
15160 */
15161VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
15162{
15163 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
15164}
Jeff Johnsone7245742012-09-05 17:12:55 -070015165
Mihir Shetee2ae82a2015-03-16 14:08:49 +053015166
15167/*
15168 * API to find if the firmware will send logs using DXE channel
15169 */
15170v_U8_t hdd_is_fw_logging_enabled(void)
15171{
15172 hdd_context_t *pHddCtx;
15173
15174 pHddCtx = vos_get_context(VOS_MODULE_ID_HDD,
15175 vos_get_global_context(VOS_MODULE_ID_HDD, NULL));
15176
Sachin Ahuja084313e2015-05-21 17:57:10 +053015177 return (pHddCtx && pHddCtx->cfg_ini->enableMgmtLogging);
Mihir Shetee2ae82a2015-03-16 14:08:49 +053015178}
15179
Agarwal Ashish57e84372014-12-05 18:26:53 +053015180/*
Mihir Shetebe94ebb2015-05-26 12:07:14 +053015181 * API to find if the firmware will send trace logs using DXE channel
15182 */
15183v_U8_t hdd_is_fw_ev_logging_enabled(void)
15184{
15185 hdd_context_t *pHddCtx;
15186
15187 pHddCtx = vos_get_context(VOS_MODULE_ID_HDD,
15188 vos_get_global_context(VOS_MODULE_ID_HDD, NULL));
15189
15190 return (pHddCtx && pHddCtx->cfg_ini->enableFWLogging);
15191}
15192/*
Agarwal Ashish57e84372014-12-05 18:26:53 +053015193 * API to find if there is any session connected
15194 */
15195VOS_STATUS hdd_is_any_session_connected(hdd_context_t *pHddCtx)
15196{
15197 return sme_is_any_session_connected(pHddCtx->hHal);
15198}
15199
15200
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053015201int wlan_hdd_scan_abort(hdd_adapter_t *pAdapter)
15202{
15203 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15204 hdd_scaninfo_t *pScanInfo = NULL;
Girish Gowli4bf7a632014-06-12 13:42:11 +053015205 long status = 0;
c_hpothua3d45d52015-01-05 14:11:17 +053015206 tSirAbortScanStatus abortScanStatus;
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053015207
15208 pScanInfo = &pHddCtx->scan_info;
Ratnam Rachuric7681132015-06-30 10:35:13 +053015209 INIT_COMPLETION(pScanInfo->abortscan_event_var);
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053015210 if (pScanInfo->mScanPending)
15211 {
c_hpothua3d45d52015-01-05 14:11:17 +053015212 abortScanStatus = hdd_abort_mac_scan(pHddCtx, pScanInfo->sessionId,
15213 eCSR_SCAN_ABORT_DEFAULT);
15214 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
15215 FL("abortScanStatus: %d"), abortScanStatus);
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053015216
c_hpothua3d45d52015-01-05 14:11:17 +053015217 /* If there is active scan command lets wait for the completion else
15218 * there is no need to wait as scan command might be in the SME pending
15219 * command list.
15220 */
15221 if (abortScanStatus == eSIR_ABORT_ACTIVE_SCAN_LIST_NOT_EMPTY)
15222 {
Mukul Sharmab392b642017-08-17 17:45:29 +053015223 status = wait_for_completion_timeout(
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053015224 &pScanInfo->abortscan_event_var,
15225 msecs_to_jiffies(5000));
c_hpothua3d45d52015-01-05 14:11:17 +053015226 if (0 >= status)
15227 {
15228 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Girish Gowli4bf7a632014-06-12 13:42:11 +053015229 "%s: Timeout or Interrupt occurred while waiting for abort"
15230 "scan, status- %ld", __func__, status);
c_hpothua3d45d52015-01-05 14:11:17 +053015231 return -ETIMEDOUT;
15232 }
15233 }
15234 else if (abortScanStatus == eSIR_ABORT_SCAN_FAILURE)
15235 {
15236 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
15237 FL("hdd_abort_mac_scan failed"));
15238 return -VOS_STATUS_E_FAILURE;
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053015239 }
15240 }
Girish Gowli4bf7a632014-06-12 13:42:11 +053015241 return 0;
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053015242}
15243
Abhishek Singh7d624e12015-11-30 14:29:27 +053015244/**
15245 * hdd_indicate_mgmt_frame() - Wrapper to indicate management frame to
15246 * user space
15247 * @frame_ind: Management frame data to be informed.
15248 *
15249 * This function is used to indicate management frame to
15250 * user space
15251 *
15252 * Return: None
15253 *
15254 */
15255void hdd_indicate_mgmt_frame(tSirSmeMgmtFrameInd *frame_ind)
15256{
15257 hdd_context_t *hdd_ctx = NULL;
15258 hdd_adapter_t *adapter = NULL;
15259 v_CONTEXT_t vos_context = NULL;
15260
15261 /* Get the global VOSS context.*/
15262 vos_context = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
15263 if (!vos_context) {
15264 hddLog(LOGE, FL("Global VOS context is Null"));
15265 return;
15266 }
15267 /* Get the HDD context.*/
15268 hdd_ctx =
15269 (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, vos_context );
15270
15271 if (0 != wlan_hdd_validate_context(hdd_ctx))
15272 {
15273 return;
15274 }
15275 adapter = hdd_get_adapter_by_sme_session_id(hdd_ctx,
15276 frame_ind->sessionId);
15277
15278 if ((NULL != adapter) &&
15279 (WLAN_HDD_ADAPTER_MAGIC == adapter->magic))
15280 __hdd_indicate_mgmt_frame(adapter,
15281 frame_ind->frameLen,
15282 frame_ind->frameBuf,
15283 frame_ind->frameType,
15284 frame_ind->rxChan,
15285 frame_ind->rxRssi);
15286 return;
15287
15288}
15289
c_hpothu225aa7c2014-10-22 17:45:13 +053015290VOS_STATUS wlan_hdd_cancel_remain_on_channel(hdd_context_t *pHddCtx)
15291{
15292 hdd_adapter_t *pAdapter;
15293 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
15294 VOS_STATUS vosStatus;
15295
15296 vosStatus = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
15297 while (NULL != pAdapterNode && VOS_STATUS_E_EMPTY != vosStatus)
15298 {
15299 pAdapter = pAdapterNode->pAdapter;
15300 if (NULL != pAdapter)
15301 {
15302 if (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode ||
15303 WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ||
15304 WLAN_HDD_P2P_GO == pAdapter->device_mode)
15305 {
15306 hddLog(LOG1, FL("abort ROC deviceMode: %d"),
15307 pAdapter->device_mode);
15308 if (VOS_STATUS_SUCCESS !=
15309 wlan_hdd_cancel_existing_remain_on_channel(pAdapter))
15310 {
15311 hddLog(LOGE, FL("failed to abort ROC"));
15312 return VOS_STATUS_E_FAILURE;
15313 }
15314 }
15315 }
15316 vosStatus = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
15317 pAdapterNode = pNext;
15318 }
15319 return VOS_STATUS_SUCCESS;
15320}
Mahesh A Saptasagard477b092015-02-06 15:12:16 +053015321
Mihir Shete0be28772015-02-17 18:42:14 +053015322hdd_remain_on_chan_ctx_t *hdd_get_remain_on_channel_ctx(hdd_context_t *pHddCtx)
15323{
15324 hdd_adapter_t *pAdapter;
15325 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
15326 hdd_cfg80211_state_t *cfgState;
15327 hdd_remain_on_chan_ctx_t *pRemainChanCtx = NULL;
15328 VOS_STATUS vosStatus;
15329
15330 vosStatus = hdd_get_front_adapter (pHddCtx, &pAdapterNode);
15331 while (NULL != pAdapterNode && VOS_STATUS_E_EMPTY != vosStatus)
15332 {
15333 pAdapter = pAdapterNode->pAdapter;
15334 if (NULL != pAdapter)
15335 {
15336 cfgState = WLAN_HDD_GET_CFG_STATE_PTR(pAdapter);
15337 pRemainChanCtx = cfgState->remain_on_chan_ctx;
15338 if (pRemainChanCtx)
15339 break;
15340 }
15341 vosStatus = hdd_get_next_adapter (pHddCtx, pAdapterNode, &pNext);
15342 pAdapterNode = pNext;
15343 }
15344 return pRemainChanCtx;
15345}
15346
Padma, Santhosh Kumar778d8382015-03-04 17:41:22 +053015347/**
15348 * wlan_hdd_handle_dfs_chan_scan () - handles disable/enable DFS channels
15349 *
15350 * @pHddCtx: HDD context within host driver
15351 * @dfsScanMode: dfsScanMode passed from ioctl
15352 *
15353 */
15354
15355VOS_STATUS wlan_hdd_handle_dfs_chan_scan(hdd_context_t *pHddCtx,
15356 tANI_U8 dfsScanMode)
15357{
15358 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
15359 hdd_adapter_t *pAdapter;
15360 VOS_STATUS vosStatus;
15361 hdd_station_ctx_t *pHddStaCtx;
15362 eHalStatus status = eHAL_STATUS_SUCCESS;
15363
15364 if(!pHddCtx)
15365 {
15366 hddLog(LOGE, FL("HDD context is Null"));
15367 return eHAL_STATUS_FAILURE;
15368 }
15369
15370 if (pHddCtx->scan_info.mScanPending)
15371 {
15372 hddLog(LOG1, FL("Aborting scan for sessionId: %d"),
15373 pHddCtx->scan_info.sessionId);
15374 hdd_abort_mac_scan(pHddCtx,
15375 pHddCtx->scan_info.sessionId,
15376 eCSR_SCAN_ABORT_DEFAULT);
15377 }
15378
15379 if (!dfsScanMode)
15380 {
15381 vosStatus = hdd_get_front_adapter( pHddCtx, &pAdapterNode);
15382 while ((NULL != pAdapterNode) &&
15383 (VOS_STATUS_SUCCESS == vosStatus))
15384 {
15385 pAdapter = pAdapterNode->pAdapter;
15386
15387 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
15388 {
15389 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
15390
15391 if(!pHddStaCtx)
15392 {
15393 hddLog(LOGE, FL("HDD STA context is Null"));
15394 return eHAL_STATUS_FAILURE;
15395 }
15396
15397 /* if STA is already connected on DFS channel,
15398 disconnect immediately*/
15399 if (hdd_connIsConnected(pHddStaCtx) &&
15400 (NV_CHANNEL_DFS ==
15401 vos_nv_getChannelEnabledState(
15402 pHddStaCtx->conn_info.operationChannel)))
15403 {
15404 status = sme_RoamDisconnect(pHddCtx->hHal,
15405 pAdapter->sessionId,
15406 eCSR_DISCONNECT_REASON_UNSPECIFIED);
15407 hddLog(LOG1, FL("Client connected on DFS channel %d,"
15408 "sme_RoamDisconnect returned with status: %d"
15409 "for sessionid: %d"), pHddStaCtx->conn_info.
15410 operationChannel, status, pAdapter->sessionId);
15411 }
15412 }
15413
15414 vosStatus = hdd_get_next_adapter(pHddCtx, pAdapterNode,
15415 &pNext);
15416 pAdapterNode = pNext;
15417 }
15418 }
15419
15420 sme_UpdateDFSScanMode(pHddCtx->hHal, dfsScanMode);
15421 sme_UpdateDFSRoamMode(pHddCtx->hHal,
15422 (dfsScanMode != DFS_CHNL_SCAN_DISABLED));
15423
15424 status = sme_HandleDFSChanScan(pHddCtx->hHal);
15425 if (!HAL_STATUS_SUCCESS(status))
15426 {
15427 hddLog(LOGE,
15428 FL("Failed in sme_HandleDFSChanScan (err=%d)"), status);
15429 return status;
15430 }
15431
15432 return status;
15433}
15434
Nirav Shah7e3c8132015-06-22 23:51:42 +053015435static int hdd_log2_ceil(unsigned value)
15436{
15437 /* need to switch to unsigned math so that negative values
15438 * will right-shift towards 0 instead of -1
15439 */
15440 unsigned tmp = value;
15441 int log2 = -1;
15442
15443 if (value == 0)
15444 return 0;
15445
15446 while (tmp) {
15447 log2++;
15448 tmp >>= 1;
15449 }
15450 if (1U << log2 != value)
15451 log2++;
15452
15453 return log2;
15454}
15455
15456/**
15457 * hdd_sta_id_hash_attach() - initialize sta id to macaddr hash
15458 * @pAdapter: adapter handle
15459 *
15460 * Return: vos status
15461 */
15462VOS_STATUS hdd_sta_id_hash_attach(hdd_adapter_t *pAdapter)
15463{
15464 int hash_elem, log2, i;
15465
15466 spin_lock_bh( &pAdapter->sta_hash_lock);
15467 if (pAdapter->is_sta_id_hash_initialized == VOS_TRUE) {
15468 spin_unlock_bh( &pAdapter->sta_hash_lock);
15469 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
15470 "%s: hash already attached for session id %d",
15471 __func__, pAdapter->sessionId);
15472 return VOS_STATUS_SUCCESS;
15473 }
15474 spin_unlock_bh( &pAdapter->sta_hash_lock);
15475
15476 hash_elem = WLAN_MAX_STA_COUNT;
15477 hash_elem *= HDD_STA_ID_HASH_MULTIPLIER;
15478 log2 = hdd_log2_ceil(hash_elem);
15479 hash_elem = 1 << log2;
15480
15481 pAdapter->sta_id_hash.mask = hash_elem - 1;
15482 pAdapter->sta_id_hash.idx_bits = log2;
15483 pAdapter->sta_id_hash.bins =
15484 vos_mem_malloc(hash_elem *sizeof(hdd_list_t));
15485 if (!pAdapter->sta_id_hash.bins) {
15486 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
15487 "%s: malloc failed for session %d",
15488 __func__, pAdapter->sessionId);
15489 return VOS_STATUS_E_NOMEM;
15490 }
15491
15492 for (i = 0; i < hash_elem; i++)
15493 hdd_list_init(&pAdapter->sta_id_hash.bins[i], WLAN_MAX_STA_COUNT);
15494
15495 spin_lock_bh( &pAdapter->sta_hash_lock);
15496 pAdapter->is_sta_id_hash_initialized = VOS_TRUE;
15497 spin_unlock_bh( &pAdapter->sta_hash_lock);
15498 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
15499 "%s: Station ID Hash attached for session id %d",
15500 __func__, pAdapter->sessionId);
15501
15502 return VOS_STATUS_SUCCESS;
15503}
15504
15505/**
15506 * hdd_sta_id_hash_detach() - deinit sta_id to macaddr hash
15507 * @pAdapter: adapter handle
15508 *
15509 * Return: vos status
15510 */
15511VOS_STATUS hdd_sta_id_hash_detach(hdd_adapter_t *pAdapter)
15512{
15513 int hash_elem, i;
15514 v_SIZE_t size;
15515
15516 spin_lock_bh( &pAdapter->sta_hash_lock);
15517 if (pAdapter->is_sta_id_hash_initialized != VOS_TRUE) {
15518 spin_unlock_bh( &pAdapter->sta_hash_lock);
15519 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
15520 "%s: hash not initialized for session id %d",
15521 __func__, pAdapter->sessionId);
15522 return VOS_STATUS_SUCCESS;
15523 }
15524
15525 pAdapter->is_sta_id_hash_initialized = VOS_FALSE;
15526 spin_unlock_bh( &pAdapter->sta_hash_lock);
15527
15528 hash_elem = 1 << pAdapter->sta_id_hash.idx_bits;
15529
15530 /* free all station info*/
15531 for (i = 0; i < hash_elem; i++) {
15532 hdd_list_size(&pAdapter->sta_id_hash.bins[i], &size);
15533 if (size != 0) {
15534 VOS_STATUS status;
15535 hdd_staid_hash_node_t *sta_info_node = NULL;
15536 hdd_staid_hash_node_t *next_node = NULL;
15537 status = hdd_list_peek_front ( &pAdapter->sta_id_hash.bins[i],
15538 (hdd_list_node_t**) &sta_info_node );
15539
15540 while ( NULL != sta_info_node && VOS_STATUS_SUCCESS == status )
15541 {
15542 status = hdd_list_remove_node( &pAdapter->sta_id_hash.bins[i],
15543 &sta_info_node->node);
15544 vos_mem_free(sta_info_node);
15545
15546 status = hdd_list_peek_next (&pAdapter->sta_id_hash.bins[i],
15547 (hdd_list_node_t*)sta_info_node,
15548 (hdd_list_node_t**)&next_node);
15549 sta_info_node = next_node;
15550 }
15551 }
15552 }
15553
15554 vos_mem_free(pAdapter->sta_id_hash.bins);
15555 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
15556 "%s: Station ID Hash detached for session id %d",
15557 __func__, pAdapter->sessionId);
15558 return VOS_STATUS_SUCCESS;
15559}
15560
15561/**
15562 * hdd_sta_id_hash_calculate_index() - derive index from macaddr
15563 * @pAdapter: adapter handle
15564 * @mac_addr_in: input mac address
15565 *
15566 * Return: index derived from mac address
15567 */
15568int hdd_sta_id_hash_calculate_index(hdd_adapter_t *pAdapter,
15569 v_MACADDR_t *mac_addr_in)
15570{
15571 uint16 index;
15572 struct hdd_align_mac_addr_t * mac_addr =
15573 (struct hdd_align_mac_addr_t *)mac_addr_in;
15574
15575 index = mac_addr->bytes_ab ^
15576 mac_addr->bytes_cd ^ mac_addr->bytes_ef;
15577 index ^= index >> pAdapter->sta_id_hash.idx_bits;
15578 index &= pAdapter->sta_id_hash.mask;
15579 return index;
15580}
15581
15582/**
15583 * hdd_sta_id_hash_add_entry() - add entry in hash
15584 * @pAdapter: adapter handle
15585 * @sta_id: station id
15586 * @mac_addr: mac address
15587 *
15588 * Return: vos status
15589 */
15590VOS_STATUS hdd_sta_id_hash_add_entry(hdd_adapter_t *pAdapter,
15591 v_U8_t sta_id, v_MACADDR_t *mac_addr)
15592{
15593 uint16 index;
15594 hdd_staid_hash_node_t *sta_info_node = NULL;
15595
Nirav Shah7e3c8132015-06-22 23:51:42 +053015596 index = hdd_sta_id_hash_calculate_index(pAdapter, mac_addr);
15597 sta_info_node = vos_mem_malloc(sizeof(hdd_staid_hash_node_t));
15598 if (!sta_info_node) {
Nirav Shah7e3c8132015-06-22 23:51:42 +053015599 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
15600 "%s: malloc failed", __func__);
15601 return VOS_STATUS_E_NOMEM;
15602 }
15603
15604 sta_info_node->sta_id = sta_id;
15605 vos_mem_copy(&sta_info_node->mac_addr, mac_addr, sizeof(v_MACADDR_t));
15606
Nirav Shah303ed5c2015-08-24 10:29:25 +053015607 spin_lock_bh( &pAdapter->sta_hash_lock);
15608 if (pAdapter->is_sta_id_hash_initialized != VOS_TRUE) {
15609 spin_unlock_bh( &pAdapter->sta_hash_lock);
15610 vos_mem_free(sta_info_node);
15611 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
15612 "%s: hash is not initialized for session id %d",
15613 __func__, pAdapter->sessionId);
15614 return VOS_STATUS_E_FAILURE;
15615 }
15616
Nirav Shah7e3c8132015-06-22 23:51:42 +053015617 hdd_list_insert_back ( &pAdapter->sta_id_hash.bins[index],
15618 (hdd_list_node_t*) sta_info_node );
15619 spin_unlock_bh( &pAdapter->sta_hash_lock);
15620 return VOS_STATUS_SUCCESS;
15621}
15622
15623/**
15624 * hdd_sta_id_hash_remove_entry() - remove entry from hash
15625 * @pAdapter: adapter handle
15626 * @sta_id: station id
15627 * @mac_addr: mac address
15628 *
15629 * Return: vos status
15630 */
15631VOS_STATUS hdd_sta_id_hash_remove_entry(hdd_adapter_t *pAdapter,
15632 v_U8_t sta_id, v_MACADDR_t *mac_addr)
15633{
15634 uint16 index;
15635 VOS_STATUS status;
15636 hdd_staid_hash_node_t *sta_info_node = NULL;
15637 hdd_staid_hash_node_t *next_node = NULL;
15638
15639 spin_lock_bh( &pAdapter->sta_hash_lock);
15640 if (pAdapter->is_sta_id_hash_initialized != VOS_TRUE) {
15641 spin_unlock_bh( &pAdapter->sta_hash_lock);
15642 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
15643 "%s: hash is not initialized for session id %d",
15644 __func__, pAdapter->sessionId);
15645 return VOS_STATUS_E_FAILURE;
15646 }
15647
15648 index = hdd_sta_id_hash_calculate_index(pAdapter, mac_addr);
15649 status = hdd_list_peek_front ( &pAdapter->sta_id_hash.bins[index],
15650 (hdd_list_node_t**) &sta_info_node );
15651
15652 while ( NULL != sta_info_node && VOS_STATUS_SUCCESS == status )
15653 {
15654 if (sta_info_node->sta_id == sta_id) {
15655 status = hdd_list_remove_node( &pAdapter->sta_id_hash.bins[index],
15656 &sta_info_node->node);
15657 vos_mem_free(sta_info_node);
15658 break;
15659 }
15660 status = hdd_list_peek_next (&pAdapter->sta_id_hash.bins[index],
15661 (hdd_list_node_t*)sta_info_node, (hdd_list_node_t**)&next_node);
15662 sta_info_node = next_node;
15663 }
15664 spin_unlock_bh( &pAdapter->sta_hash_lock);
15665 return status;
15666}
15667
15668/**
15669 * hdd_sta_id_find_from_mac_addr() - find sta id from mac address
15670 * @pAdapter: adapter handle
15671 * @mac_addr_in: mac address
15672 *
15673 * Return: station id
15674 */
15675int hdd_sta_id_find_from_mac_addr(hdd_adapter_t *pAdapter,
15676 v_MACADDR_t *mac_addr_in)
15677{
15678 uint8 is_found = 0;
15679 uint8 sta_id = HDD_WLAN_INVALID_STA_ID;
15680 uint16 index;
15681 VOS_STATUS status;
15682 hdd_staid_hash_node_t *sta_info_node = NULL;
15683 hdd_staid_hash_node_t *next_node = NULL;
15684
15685 spin_lock_bh( &pAdapter->sta_hash_lock);
15686 if (pAdapter->is_sta_id_hash_initialized != VOS_TRUE) {
15687 spin_unlock_bh( &pAdapter->sta_hash_lock);
Bhargav Shahce3b32c2015-08-10 12:29:24 +053015688 hddLog(VOS_TRACE_LEVEL_INFO,
Nirav Shah7e3c8132015-06-22 23:51:42 +053015689 FL("hash is not initialized for session id %d"),
15690 pAdapter->sessionId);
15691 return HDD_WLAN_INVALID_STA_ID;
15692 }
15693
15694 index = hdd_sta_id_hash_calculate_index(pAdapter, mac_addr_in);
15695 status = hdd_list_peek_front ( &pAdapter->sta_id_hash.bins[index],
15696 (hdd_list_node_t**) &sta_info_node );
15697
15698 while ( NULL != sta_info_node && VOS_STATUS_SUCCESS == status )
15699 {
15700 if (vos_mem_compare(&sta_info_node->mac_addr,
15701 mac_addr_in, sizeof(v_MACADDR_t))) {
15702 is_found = 1;
15703 sta_id = sta_info_node->sta_id;
15704 break;
15705 }
15706 status = hdd_list_peek_next (&pAdapter->sta_id_hash.bins[index],
15707 (hdd_list_node_t*)sta_info_node,
15708 (hdd_list_node_t**)&next_node);
15709 sta_info_node = next_node;
15710 }
15711 spin_unlock_bh( &pAdapter->sta_hash_lock);
15712 return sta_id;
15713}
15714
c_manjeecfd1efb2015-09-25 19:32:34 +053015715/*FW memory dump feature*/
15716/**
15717 * This structure hold information about the /proc file
15718 *
15719 */
15720static struct proc_dir_entry *proc_file, *proc_dir;
15721
15722/**
15723 * memdump_read() - perform read operation in memory dump proc file
15724 *
15725 * @file - handle for the proc file.
15726 * @buf - pointer to user space buffer.
15727 * @count - number of bytes to be read.
15728 * @pos - offset in the from buffer.
15729 *
15730 * This function performs read operation for the memory dump proc file.
15731 *
15732 * Return: number of bytes read on success, error code otherwise.
15733 */
15734static ssize_t memdump_read(struct file *file, char __user *buf,
15735 size_t count, loff_t *pos)
15736{
15737 int status;
15738 hdd_context_t *hdd_ctx = (hdd_context_t *)PDE_DATA(file_inode(file));
15739 size_t ret_count;
c_manjeef1495642015-10-13 18:35:01 +053015740 loff_t bytes_left;
c_manjeecfd1efb2015-09-25 19:32:34 +053015741 ENTER();
15742
15743 hddLog(LOG1, FL("Read req for size:%zu pos:%llu"), count, *pos);
15744 status = wlan_hdd_validate_context(hdd_ctx);
15745 if (0 != status) {
15746 return -EINVAL;
15747 }
15748
15749 if (!wlan_fwr_mem_dump_test_and_set_read_allowed_bit()) {
15750 hddLog(LOGE, FL("Current mem dump request timed out/failed"));
15751 return -EINVAL;
15752 }
15753
15754 /* run fs_read_handler in an atomic context*/
15755 vos_ssr_protect(__func__);
c_manjeef1495642015-10-13 18:35:01 +053015756 ret_count = wlan_fwr_mem_dump_fsread_handler( buf, count, pos, &bytes_left);
15757 if(bytes_left == 0)
c_manjeecfd1efb2015-09-25 19:32:34 +053015758 {
15759 /*Free the fwr mem dump buffer */
15760 wlan_free_fwr_mem_dump_buffer();
15761 wlan_set_fwr_mem_dump_state(FW_MEM_DUMP_IDLE);
c_manjeef1495642015-10-13 18:35:01 +053015762 ret_count=0;
c_manjeecfd1efb2015-09-25 19:32:34 +053015763 }
15764 /*if SSR/unload code is waiting for memdump_read to finish,signal it*/
15765 vos_ssr_unprotect(__func__);
15766 EXIT();
15767 return ret_count;
15768}
15769
15770/**
15771 * struct memdump_fops - file operations for memory dump feature
15772 * @read - read function for memory dump operation.
15773 *
15774 * This structure initialize the file operation handle for memory
15775 * dump feature
15776 */
15777static const struct file_operations memdump_fops = {
15778 read: memdump_read
15779};
15780
15781/*
15782* wlan_hdd_fw_mem_dump_cb : callback for Fw mem dump request
15783* To be passed by HDD to WDA and called upon receiving of response
15784* from firmware
15785* @fwMemDumpReqContext : memory dump request context
15786* @dump_rsp : dump response from HAL
15787* Returns none
15788*/
15789void wlan_hdd_fw_mem_dump_cb(void *fwMemDumpReqContext,
15790 tAniFwrDumpRsp *dump_rsp)
15791{
c_manjeef1495642015-10-13 18:35:01 +053015792 struct hdd_fw_mem_dump_req_ctx *pHddFwMemDumpCtx = (struct hdd_fw_mem_dump_req_ctx *)fwMemDumpReqContext;
c_manjeecfd1efb2015-09-25 19:32:34 +053015793
c_manjeef1495642015-10-13 18:35:01 +053015794 ENTER();
15795 spin_lock(&hdd_context_lock);
15796 if(!pHddFwMemDumpCtx || (FW_MEM_DUMP_MAGIC != pHddFwMemDumpCtx->magic)) {
15797 spin_unlock(&hdd_context_lock);
15798 return;
15799 }
15800 /* report the status to requesting function and free mem.*/
c_manjeecfd1efb2015-09-25 19:32:34 +053015801 if (dump_rsp->dump_status != eHAL_STATUS_SUCCESS) {
c_manjeef1495642015-10-13 18:35:01 +053015802 hddLog(LOGE, FL("fw dump request declined by fwr"));
15803 //set the request completion variable
15804 complete(&(pHddFwMemDumpCtx->req_completion));
c_manjeecfd1efb2015-09-25 19:32:34 +053015805 //Free the allocated fwr dump
15806 wlan_free_fwr_mem_dump_buffer();
15807 wlan_set_fwr_mem_dump_state(FW_MEM_DUMP_IDLE);
c_manjeecfd1efb2015-09-25 19:32:34 +053015808 }
c_manjeef1495642015-10-13 18:35:01 +053015809 else {
15810 hddLog(LOG1, FL("fw dump request accepted by fwr"));
15811 /* register the HDD callback which will be called by SVC */
15812 wlan_set_svc_fw_mem_dump_req_cb((void*)wlan_hdd_fw_mem_dump_req_cb,(void*)pHddFwMemDumpCtx);
15813 }
15814 spin_unlock(&hdd_context_lock);
c_manjeecfd1efb2015-09-25 19:32:34 +053015815 EXIT();
15816
15817}
15818
15819/**
15820 * memdump_procfs_remove() - Remove file/dir under procfs for memory dump
15821 *
15822 * This function removes file/dir under proc file system that was
15823 * processing firmware memory dump
15824 *
15825 * Return: None
15826 */
15827static void memdump_procfs_remove(void)
15828{
15829 remove_proc_entry(PROCFS_MEMDUMP_NAME, proc_dir);
15830 hddLog(LOG1 , FL("/proc/%s/%s removed\n"),
15831 PROCFS_MEMDUMP_DIR, PROCFS_MEMDUMP_NAME);
15832 remove_proc_entry(PROCFS_MEMDUMP_DIR, NULL);
15833 hddLog(LOG1 , FL("/proc/%s removed\n"), PROCFS_MEMDUMP_DIR);
15834}
15835
15836/**
15837 * memdump_procfs_init() - Initialize procfs for memory dump
15838 *
15839 * @vos_ctx - Global vos context.
15840 *
15841 * This function create file under proc file system to be used later for
15842 * processing firmware memory dump
15843 *
15844 * Return: 0 on success, error code otherwise.
15845 */
15846static int memdump_procfs_init(void *vos_ctx)
15847{
15848 hdd_context_t *hdd_ctx;
15849
15850 hdd_ctx = vos_get_context(VOS_MODULE_ID_HDD, vos_ctx);
15851 if (!hdd_ctx) {
15852 hddLog(LOGE , FL("Invalid HDD context"));
15853 return -EINVAL;
15854 }
15855
15856 proc_dir = proc_mkdir(PROCFS_MEMDUMP_DIR, NULL);
15857 if (proc_dir == NULL) {
15858 remove_proc_entry(PROCFS_MEMDUMP_DIR, NULL);
15859 hddLog(LOGE , FL("Error: Could not initialize /proc/%s"),
15860 PROCFS_MEMDUMP_DIR);
15861 return -ENOMEM;
15862 }
15863
15864 proc_file = proc_create_data(PROCFS_MEMDUMP_NAME,
15865 S_IRUSR | S_IWUSR, proc_dir,
15866 &memdump_fops, hdd_ctx);
15867 if (proc_file == NULL) {
15868 remove_proc_entry(PROCFS_MEMDUMP_NAME, proc_dir);
15869 hddLog(LOGE , FL("Error: Could not initialize /proc/%s"),
15870 PROCFS_MEMDUMP_NAME);
15871 return -ENOMEM;
15872 }
15873
15874 hddLog(LOG1 , FL("/proc/%s/%s created"),
15875 PROCFS_MEMDUMP_DIR, PROCFS_MEMDUMP_NAME);
15876
15877 return 0;
15878}
15879
15880/**
15881 * memdump_init() - Initialization function for memory dump feature
15882 *
15883 * This function creates proc file for memdump feature and registers
15884 * HDD callback function with SME.
15885 *
15886 * Return - 0 on success, error otherwise
15887 */
15888int memdump_init(void)
15889{
15890 hdd_context_t *hdd_ctx;
15891 void *vos_ctx;
15892 int status = 0;
15893
15894 vos_ctx = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
15895 if (!vos_ctx) {
15896 hddLog(LOGE, FL("Invalid VOS context"));
15897 return -EINVAL;
15898 }
15899
15900 hdd_ctx = vos_get_context(VOS_MODULE_ID_HDD, vos_ctx);
15901 if (!hdd_ctx) {
15902 hddLog(LOGE , FL("Invalid HDD context"));
15903 return -EINVAL;
15904 }
15905
15906 status = memdump_procfs_init(vos_ctx);
15907 if (status) {
15908 hddLog(LOGE , FL("Failed to create proc file"));
15909 return status;
15910 }
15911
15912 return 0;
15913}
15914
15915/**
15916 * memdump_deinit() - De initialize memdump feature
15917 *
15918 * This function removes proc file created for memdump feature.
15919 *
15920 * Return: None
15921 */
15922int memdump_deinit(void)
15923{
15924 hdd_context_t *hdd_ctx;
15925 void *vos_ctx;
15926
15927 vos_ctx = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
15928 if (!vos_ctx) {
15929 hddLog(LOGE, FL("Invalid VOS context"));
15930 return -EINVAL;
15931 }
15932
15933 hdd_ctx = vos_get_context(VOS_MODULE_ID_HDD, vos_ctx);
15934 if(!hdd_ctx) {
15935 hddLog(LOGE , FL("Invalid HDD context"));
15936 return -EINVAL;
15937 }
15938
15939 memdump_procfs_remove();
15940 return 0;
15941}
15942
15943/**
15944 * wlan_hdd_fw_mem_dump_req(pHddCtx) - common API(cfg80211/ioctl) for requesting fw mem dump to SME
15945 * Return: HAL status
15946 */
15947
15948int wlan_hdd_fw_mem_dump_req(hdd_context_t * pHddCtx)
15949{
15950 tAniFwrDumpReq fw_mem_dump_req={0};
c_manjeef1495642015-10-13 18:35:01 +053015951 struct hdd_fw_mem_dump_req_ctx fw_mem_dump_ctx;
c_manjeecfd1efb2015-09-25 19:32:34 +053015952 eHalStatus status = eHAL_STATUS_FAILURE;
Abhishek Singh4eca9822015-12-09 18:07:34 +053015953 int ret=0, result;
c_manjeecfd1efb2015-09-25 19:32:34 +053015954 ENTER();
c_manjeef1495642015-10-13 18:35:01 +053015955
c_manjeecfd1efb2015-09-25 19:32:34 +053015956 /*Check whether a dump request is already going on
15957 *Caution this function will free previously held memory if new dump request is allowed*/
15958 if (!wlan_fwr_mem_dump_test_and_set_write_allowed_bit()) {
15959 hddLog(LOGE, FL("Fw memdump already in progress"));
15960 return -EBUSY;
15961 }
15962 //Allocate memory for fw mem dump buffer
15963 ret = wlan_fwr_mem_dump_buffer_allocation();
15964 if(ret == -EFAULT)
15965 {
15966 hddLog(LOGE, FL("Fwr mem dump not supported by FW"));
15967 return ret;
15968 }
15969 if (0 != ret) {
15970 hddLog(LOGE, FL("Fwr mem Allocation failed"));
15971 return -ENOMEM;
15972 }
c_manjeef1495642015-10-13 18:35:01 +053015973 init_completion(&fw_mem_dump_ctx.req_completion);
15974 fw_mem_dump_ctx.magic = FW_MEM_DUMP_MAGIC;
15975 fw_mem_dump_ctx.status = false;
15976
c_manjeecfd1efb2015-09-25 19:32:34 +053015977 fw_mem_dump_req.fwMemDumpReqCallback = wlan_hdd_fw_mem_dump_cb;
c_manjeef1495642015-10-13 18:35:01 +053015978 fw_mem_dump_req.fwMemDumpReqContext = &fw_mem_dump_ctx;
c_manjeecfd1efb2015-09-25 19:32:34 +053015979 status = sme_FwMemDumpReq(pHddCtx->hHal, &fw_mem_dump_req);
15980 if(eHAL_STATUS_SUCCESS != status)
15981 {
15982 hddLog(VOS_TRACE_LEVEL_ERROR,
15983 "%s: fw_mem_dump_req failed ", __func__);
15984 wlan_free_fwr_mem_dump_buffer();
c_manjeef1495642015-10-13 18:35:01 +053015985 ret = -EFAULT;
15986 goto cleanup;
c_manjeecfd1efb2015-09-25 19:32:34 +053015987 }
c_manjeef1495642015-10-13 18:35:01 +053015988 /*wait for fw mem dump completion to send event to userspace*/
Abhishek Singh4eca9822015-12-09 18:07:34 +053015989 result =
15990 wait_for_completion_timeout(&fw_mem_dump_ctx.req_completion,
15991 msecs_to_jiffies(FW_MEM_DUMP_TIMEOUT_MS));
15992 if (0 >= result )
c_manjeef1495642015-10-13 18:35:01 +053015993 {
15994 hddLog(VOS_TRACE_LEVEL_ERROR,
Abhishek Singh4eca9822015-12-09 18:07:34 +053015995 "%s: fw_mem_dump_req timeout %d ", __func__,result);
15996 ret = -ETIMEDOUT;
c_manjeef1495642015-10-13 18:35:01 +053015997 }
15998cleanup:
15999 spin_lock(&hdd_context_lock);
16000 fw_mem_dump_ctx.magic = 0;
Abhishek Singh4eca9822015-12-09 18:07:34 +053016001 if(!ret && !fw_mem_dump_ctx.status)
16002 ret = -EFAULT;
c_manjeef1495642015-10-13 18:35:01 +053016003 spin_unlock(&hdd_context_lock);
c_manjeecfd1efb2015-09-25 19:32:34 +053016004
c_manjeef1495642015-10-13 18:35:01 +053016005 EXIT();
Abhishek Singh4eca9822015-12-09 18:07:34 +053016006 return ret;
c_manjeef1495642015-10-13 18:35:01 +053016007}
16008
16009/**
16010 * HDD callback which will be called by SVC to indicate mem dump completion.
16011 */
16012void wlan_hdd_fw_mem_dump_req_cb(struct hdd_fw_mem_dump_req_ctx* pHddFwMemDumpCtx)
16013{
16014 if (!pHddFwMemDumpCtx) {
16015 hddLog(VOS_TRACE_LEVEL_ERROR,
16016 "%s: HDD context not valid ", __func__);
16017 return;
16018 }
16019 spin_lock(&hdd_context_lock);
16020 /* check the req magic and set status */
16021 if (pHddFwMemDumpCtx->magic == FW_MEM_DUMP_MAGIC)
16022 {
16023 pHddFwMemDumpCtx->status = true;
16024 //signal the completion
16025 complete(&(pHddFwMemDumpCtx->req_completion));
16026 }
16027 else
16028 {
16029 hddLog(VOS_TRACE_LEVEL_ERROR,
16030 "%s: fw mem dump request possible timeout ", __func__);
16031 }
16032 spin_unlock(&hdd_context_lock);
c_manjeecfd1efb2015-09-25 19:32:34 +053016033}
16034
Mahesh A Saptasagar67ab9222015-10-21 15:38:41 +053016035void hdd_initialize_adapter_common(hdd_adapter_t *pAdapter)
16036{
16037 if (NULL == pAdapter)
16038 {
16039 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: pAdapter is NULL ", __func__);
16040 return;
16041 }
16042 init_completion(&pAdapter->session_open_comp_var);
16043 init_completion(&pAdapter->session_close_comp_var);
16044 init_completion(&pAdapter->disconnect_comp_var);
16045 init_completion(&pAdapter->linkup_event_var);
16046 init_completion(&pAdapter->cancel_rem_on_chan_var);
16047 init_completion(&pAdapter->rem_on_chan_ready_event);
16048 init_completion(&pAdapter->pno_comp_var);
16049#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
16050 init_completion(&pAdapter->offchannel_tx_event);
16051#endif
16052 init_completion(&pAdapter->tx_action_cnf_event);
16053#ifdef FEATURE_WLAN_TDLS
16054 init_completion(&pAdapter->tdls_add_station_comp);
16055 init_completion(&pAdapter->tdls_del_station_comp);
16056 init_completion(&pAdapter->tdls_mgmt_comp);
16057 init_completion(&pAdapter->tdls_link_establish_req_comp);
16058#endif
16059
16060#ifdef WLAN_FEATURE_RMC
16061 init_completion(&pAdapter->ibss_peer_info_comp);
16062#endif /* WLAN_FEATURE_RMC */
16063 init_completion(&pAdapter->ula_complete);
16064 init_completion(&pAdapter->change_country_code);
16065
16066#ifdef FEATURE_WLAN_BATCH_SCAN
16067 init_completion(&pAdapter->hdd_set_batch_scan_req_var);
16068 init_completion(&pAdapter->hdd_get_batch_scan_req_var);
16069#endif
Kapil Gupta2b44acb2016-12-30 16:49:51 +053016070 init_completion(&pAdapter->wlan_suspend_comp_var);
Mahesh A Saptasagar67ab9222015-10-21 15:38:41 +053016071
16072 return;
16073}
c_manjeecfd1efb2015-09-25 19:32:34 +053016074
Anurag Chouhan0b29de02016-12-16 13:18:40 +053016075#ifdef MDNS_OFFLOAD
16076
16077/**
16078 * hdd_mdns_enable_offload_done() - mdns enable offload response api
16079 * @padapter: holds adapter
16080 * @status: response status
16081 *
16082 * Return - None
16083 */
16084void hdd_mdns_enable_offload_done(void *padapter, VOS_STATUS status)
16085{
16086 hdd_adapter_t* adapter = (hdd_adapter_t*) padapter;
16087
16088 ENTER();
16089
16090 if (NULL == adapter)
16091 {
16092 hddLog(VOS_TRACE_LEVEL_ERROR,
16093 "%s: adapter is NULL",__func__);
16094 return;
16095 }
16096
16097 adapter->mdns_status.mdns_enable_status = status;
16098 vos_event_set(&adapter->mdns_status.vos_event);
16099 return;
16100}
16101
16102/**
16103 * hdd_mdns_fqdn_offload_done() - mdns fqdn offload response api
16104 * @padapter: holds adapter
16105 * @status: responce status
16106 *
16107 * Return - None
16108 */
16109void hdd_mdns_fqdn_offload_done(void *padapter, VOS_STATUS status)
16110{
16111 hdd_adapter_t* adapter = (hdd_adapter_t*) padapter;
16112
16113 ENTER();
16114
16115 if (NULL == adapter)
16116 {
16117 hddLog(VOS_TRACE_LEVEL_ERROR,
16118 "%s: adapter is NULL",__func__);
16119 return;
16120 }
16121
16122 adapter->mdns_status.mdns_fqdn_status = status;
16123 return;
16124}
16125
16126/**
16127 * hdd_mdns_resp_offload_done() - mdns resp offload response api
16128 * @padapter: holds adapter
16129 * @status: responce status
16130 *
16131 * Return - None
16132 */
16133void hdd_mdns_resp_offload_done(void *padapter, VOS_STATUS status)
16134{
16135 hdd_adapter_t* adapter = (hdd_adapter_t*) padapter;
16136
16137 ENTER();
16138
16139 if (NULL == adapter)
16140 {
16141 hddLog(VOS_TRACE_LEVEL_ERROR,
16142 "%s: adapter is NULL",__func__);
16143 return;
16144 }
16145
16146 adapter->mdns_status.mdns_resp_status = status;
16147 return;
16148}
16149
16150/**
16151 * wlan_hdd_mdns_process_response_dname() - Process mDNS domain name
16152 * @response: Pointer to a struct hdd_mdns_resp_info
16153 * @resp_info: Pointer to a struct tSirMDNSResponseInfo
16154 *
16155 * This function will pack the whole domain name without compression. It will
16156 * add the leading len for each field and add zero length octet to terminate
16157 * the domain name.
16158 *
16159 * Return: Return boolean. TRUE for success, FALSE for fail.
16160 */
16161static bool
16162wlan_hdd_mdns_process_response_dname(struct hdd_mdns_resp_info *response,
16163 sir_mdns_resp_info resp_info)
16164{
16165 uint8_t num;
16166 uint16_t idx;
16167 uint8_t len = 0;
16168
16169 if ((response == NULL) || (response->data == NULL) ||
16170 (response->offset == NULL)) {
16171 hddLog(LOGE, FL("Either data or offset in response is NULL!"));
16172 return FALSE;
16173 }
16174
16175 if ((resp_info == NULL) ||
16176 (resp_info->resp_len >= MAX_MDNS_RESP_LEN)) {
16177 hddLog(LOGE, FL("resp_len exceeds %d!"), MAX_MDNS_RESP_LEN);
16178 return FALSE;
16179 }
16180
16181 for (num = 0; num < response->num_entries; num++) {
16182 response->offset[num] =
16183 resp_info->resp_len + MDNS_HEADER_LEN;
16184 idx = num * MAX_LEN_DOMAINNAME_FIELD;
16185 len = strlen((char *)&response->data[idx]);
16186 if ((resp_info->resp_len + len + 1) >= MAX_MDNS_RESP_LEN) {
16187 hddLog(LOGE, FL("resp_len exceeds %d!"),
16188 MAX_MDNS_RESP_LEN);
16189 return FALSE;
16190 }
16191 resp_info->resp_data[resp_info->resp_len] = len;
16192 resp_info->resp_len++;
16193 vos_mem_copy(&resp_info->resp_data[resp_info->resp_len],
16194 &response->data[idx], len);
16195 resp_info->resp_len += len;
16196 }
16197
16198 /* The domain name terminates with the zero length octet */
16199 if (num == response->num_entries) {
16200 if (resp_info->resp_len >= MAX_MDNS_RESP_LEN) {
16201 hddLog(LOGE, FL("resp_len exceeds %d!"),
16202 MAX_MDNS_RESP_LEN);
16203 return FALSE;
16204 }
16205 resp_info->resp_data[resp_info->resp_len] = 0;
16206 resp_info->resp_len++;
16207 }
16208
16209 return TRUE;
16210}
16211
16212/**
16213 * wlan_hdd_mdns_format_response_u16() - Form uint16_t response data
16214 * @value: The uint16_t value is formed to the struct tSirMDNSResponseInfo
16215 * @resp_info: Pointer to a struct tSirMDNSResponseInfo
16216 *
16217 * Return: None
16218 */
16219static void wlan_hdd_mdns_format_response_u16(uint16_t value,
16220 sir_mdns_resp_info resp_info)
16221{
16222 uint8_t val_u8;
16223
16224 if ((resp_info == NULL) || (resp_info->resp_data == NULL))
16225 return;
16226 val_u8 = (value & 0xff00) >> 8;
16227 resp_info->resp_data[resp_info->resp_len++] = val_u8;
16228 val_u8 = value & 0xff;
16229 resp_info->resp_data[resp_info->resp_len++] = val_u8;
16230}
16231
16232/**
16233 * wlan_hdd_mdns_format_response_u32() - Form uint32_t response data
16234 * @value: The uint32_t value is formed to the struct tSirMDNSResponseInfo
16235 * @resp_info: Pointer to a struct tSirMDNSResponseInfo
16236 *
16237 * Return: None
16238 */
16239static void wlan_hdd_mdns_format_response_u32(uint32_t value,
16240 sir_mdns_resp_info resp_info)
16241{
16242 uint8_t val_u8;
16243
16244 if ((resp_info == NULL) || (resp_info->resp_data == NULL))
16245 return;
16246 val_u8 = (value & 0xff000000) >> 24;
16247 resp_info->resp_data[resp_info->resp_len++] = val_u8;
16248 val_u8 = (value & 0xff0000) >> 16;
16249 resp_info->resp_data[resp_info->resp_len++] = val_u8;
16250 val_u8 = (value & 0xff00) >> 8;
16251 resp_info->resp_data[resp_info->resp_len++] = val_u8;
16252 val_u8 = value & 0xff;
16253 resp_info->resp_data[resp_info->resp_len++] = val_u8;
16254}
16255
16256/**
16257 * wlan_hdd_mdns_process_response_misc() - Process misc info in mDNS response
16258 * @resp_type: Response type for mDNS
16259 * @resp_info: Pointer to a struct tSirMDNSResponseInfo
16260 *
16261 * This function will pack the response type, class and TTL (Time To Live).
16262 *
16263 * Return: Return boolean. TRUE for success, FALSE for fail.
16264 */
16265static bool wlan_hdd_mdns_process_response_misc(uint16_t resp_type,
16266 sir_mdns_resp_info resp_info)
16267{
16268 uint16_t len;
16269
16270 if (resp_info == NULL) {
16271 hddLog(LOGE, FL("resp_info is NULL!"));
16272 return FALSE;
16273 }
16274
16275 len = resp_info->resp_len + (2 * sizeof(uint16_t) + sizeof(uint32_t));
16276 if (len >= MAX_MDNS_RESP_LEN) {
16277 hddLog(LOGE, FL("resp_len exceeds %d!"), MAX_MDNS_RESP_LEN);
16278 return FALSE;
16279 }
16280
16281 /* Fill Type, Class, TTL */
16282 wlan_hdd_mdns_format_response_u16(resp_type, resp_info);
16283 wlan_hdd_mdns_format_response_u16(MDNS_CLASS, resp_info);
16284 wlan_hdd_mdns_format_response_u32(MDNS_TTL, resp_info);
16285
16286 return TRUE;
16287}
16288
16289/**
16290 * wlan_hdd_mdns_compress_data() - Compress the domain name in mDNS response
16291 * @resp_info: Pointer to a struct tSirMDNSResponseInfo
16292 * @response_dst: The response which domain name is compressed.
16293 * @response_src: The response which domain name is matched with response_dst.
16294 * Its offset is used for data compression.
16295 * @num_matched: The number of matched entries between response_dst and
16296 * response_src
16297 *
16298 * This function will form the different fields of domain name in response_dst
16299 * if any. Then use the offset of the matched domain name in response_src to
16300 * compress the matched domain name.
16301 *
16302 * Return: Return boolean. TRUE for success, FALSE for fail.
16303 */
16304static bool
16305wlan_hdd_mdns_compress_data(sir_mdns_resp_info resp_info,
16306 struct hdd_mdns_resp_info *response_dst,
16307 struct hdd_mdns_resp_info *response_src,
16308 uint8_t num_matched)
16309{
16310 uint8_t num, num_diff;
16311 uint16_t value, idx;
16312 uint8_t len = 0;
16313
16314 if ((response_src == NULL) || (response_dst == NULL) ||
16315 (resp_info == NULL)) {
16316 hddLog(LOGE, FL("response info is NULL!"));
16317 return FALSE;
16318 }
16319
16320 if (response_dst->num_entries < num_matched) {
16321 hddLog(LOGE, FL("num_entries is less than num_matched!"));
16322 return FALSE;
16323 }
16324
16325 if (resp_info->resp_len >= MAX_MDNS_RESP_LEN) {
16326 hddLog(LOGE, FL("resp_len exceeds %d!"), MAX_MDNS_RESP_LEN);
16327 return FALSE;
16328 }
16329
16330 num_diff = response_dst->num_entries - num_matched;
16331 if ((num_diff > 0) && (response_dst->data == NULL)) {
16332 hddLog(LOGE, FL("response_dst->data is NULL!"));
16333 return FALSE;
16334 }
16335
16336 /*
16337 * Handle the unmatched string at the beginning
16338 * Store the length of octets and the octets
16339 */
16340 for (num = 0; num < num_diff; num++) {
16341 response_dst->offset[num] =
16342 resp_info->resp_len + MDNS_HEADER_LEN;
16343 idx = num * MAX_LEN_DOMAINNAME_FIELD;
16344 len = strlen((char *)&response_dst->data[idx]);
16345 if ((resp_info->resp_len + len + 1) >= MAX_MDNS_RESP_LEN) {
16346 hddLog(LOGE, FL("resp_len exceeds %d!"),
16347 MAX_MDNS_RESP_LEN);
16348 return FALSE;
16349 }
16350 resp_info->resp_data[resp_info->resp_len] = len;
16351 resp_info->resp_len++;
16352 vos_mem_copy(&resp_info->resp_data[resp_info->resp_len],
16353 &response_dst->data[idx], len);
16354 resp_info->resp_len += len;
16355 }
16356 /*
16357 * Handle the matched string from the end
16358 * Just keep the offset and mask the leading two bit
16359 */
16360 if (response_src->num_entries >= num_matched) {
16361 num_diff = response_src->num_entries - num_matched;
16362 value = response_src->offset[num_diff];
16363 if (value > 0) {
16364 value |= 0xc000;
16365 if ((resp_info->resp_len + sizeof(uint16_t)) >=
16366 MAX_MDNS_RESP_LEN) {
16367 hddLog(LOGE, FL("resp_len exceeds %d!"),
16368 MAX_MDNS_RESP_LEN);
16369 return FALSE;
16370 }
16371 wlan_hdd_mdns_format_response_u16(value, resp_info);
16372 return TRUE;
16373 }
16374 }
16375 return FALSE;
16376}
16377
16378/**
16379 * wlan_hdd_mdns_reset_response() - Reset the response info
16380 * @response: The response which info is reset.
16381 *
16382 * Return: None
16383 */
16384static void wlan_hdd_mdns_reset_response(struct hdd_mdns_resp_info *response)
16385{
16386 if (response == NULL)
16387 return;
16388 response->num_entries = 0;
16389 response->data = NULL;
16390 response->offset = NULL;
16391}
16392
16393/**
16394 * wlan_hdd_mdns_init_response() - Initialize the response info
16395 * @response: The response which info is initiatized.
16396 * @resp_dname: The domain name string which might be tokenized.
16397 *
16398 * This function will allocate the memory for both response->data and
16399 * response->offset. Besides, it will also tokenize the domain name to some
16400 * entries and fill response->num_entries with the num of entries.
16401 *
16402 * Return: Return boolean. TRUE for success, FALSE for fail.
16403 */
16404static bool wlan_hdd_mdns_init_response(struct hdd_mdns_resp_info *response,
16405 uint8_t *resp_dname, char separator)
16406{
16407 uint16_t size;
16408
16409 if ((resp_dname == NULL) || (response == NULL)) {
16410 hddLog(LOGE, FL("resp_dname or response is NULL!"));
16411 return FALSE;
16412 }
16413
16414 size = MAX_NUM_FIELD_DOMAINNAME * MAX_LEN_DOMAINNAME_FIELD;
16415 response->data = vos_mem_malloc(size);
16416 if (response->data) {
16417 vos_mem_zero(response->data, size);
16418 if (VOS_STATUS_SUCCESS !=
16419 hdd_string_to_string_array((char *)resp_dname,
16420 response->data,
16421 separator,
16422 &response->num_entries,
16423 MAX_NUM_FIELD_DOMAINNAME,
16424 MAX_LEN_DOMAINNAME_FIELD)) {
16425 hddLog(LOGE, FL("hdd_string_to_string_array fail!"));
16426 goto err_init_resp;
16427 }
16428
16429 if ((response->num_entries > 0) &&
16430 (strlen((char *)&response->data[0]) > 0)) {
16431 size = sizeof(uint16_t) * response->num_entries;
16432 response->offset = vos_mem_malloc(size);
16433 if (response->offset) {
16434 vos_mem_zero(response->offset, size);
16435 return TRUE;
16436 }
16437 }
16438 }
16439
16440err_init_resp:
16441 if (response->data)
16442 vos_mem_free(response->data);
16443 wlan_hdd_mdns_reset_response(response);
16444 return FALSE;
16445}
16446
16447/**
16448 * wlan_hdd_mdns_find_entries_from_end() - Find the matched entries
16449 * @response1: The response info is used to be compared.
16450 * @response2: The response info is used to be compared.
16451 *
16452 * This function will find the matched entries from the end.
16453 *
16454 * Return: Return the number of the matched entries.
16455 */
16456static uint8_t
16457wlan_hdd_mdns_find_entries_from_end(struct hdd_mdns_resp_info *response1,
16458 struct hdd_mdns_resp_info *response2)
16459{
16460 uint8_t min, len1, i;
16461 uint16_t num1, num2;
16462 uint8_t num_matched = 0;
16463
16464 min = VOS_MIN(response1->num_entries, response2->num_entries);
16465
16466 for (i = 1; i <= min; i++) {
16467 num1 = (response1->num_entries - i);
16468 num1 *= MAX_LEN_DOMAINNAME_FIELD;
16469 num2 = (response2->num_entries - i);
16470 num2 *= MAX_LEN_DOMAINNAME_FIELD;
16471 len1 = strlen((char *)&response1->data[num1]);
16472
16473 if ((len1 == 0) ||
16474 (len1 != strlen((char *)&response2->data[num2])))
16475 break;
16476 if (memcmp(&response1->data[num1],
16477 &response2->data[num2], len1))
16478 break;
16479 else
16480 num_matched++;
16481 }
16482
16483 return num_matched;
16484}
16485
16486/**
16487 * wlan_hdd_mdns_find_max() - Find the maximum number of the matched entries
16488 * @matchedlist: Pointer to the array of struct hdd_mdns_resp_matched
16489 * @numlist: The number of the elements in the array matchedlist.
16490 *
16491 * Find the max number of the matched entries among the array matchedlist.
16492 *
16493 * Return: None
16494 */
16495static void wlan_hdd_mdns_find_max(struct hdd_mdns_resp_matched *matchedlist,
16496 uint8_t numlist)
16497{
16498 int j;
16499 struct hdd_mdns_resp_matched tmp;
16500
16501 /* At least two values are used for sorting */
16502 if ((numlist < 2) || (matchedlist == NULL)) {
16503 hddLog(LOGE, FL("At least two values are used for sorting!"));
16504 return;
16505 }
16506
16507 for (j = 0; j < numlist-1; j++) {
16508 if (matchedlist[j].num_matched >
16509 matchedlist[j+1].num_matched) {
16510 vos_mem_copy(&tmp, &matchedlist[j],
16511 sizeof(struct hdd_mdns_resp_matched));
16512 vos_mem_copy(&matchedlist[j], &matchedlist[j+1],
16513 sizeof(struct hdd_mdns_resp_matched));
16514 vos_mem_copy(&matchedlist[j+1], &tmp,
16515 sizeof(struct hdd_mdns_resp_matched));
16516 }
16517 }
16518}
16519
16520/**
16521 * wlan_hdd_mdns_pack_response_type_a() - Pack Type A response
16522 * @ini_config: Pointer to the struct hdd_config_t
16523 * @resp_info: Pointer to the struct tSirMDNSResponseInfo
16524 * @resptype_a: Pointer to the struct hdd_mdns_resp_info of Type A
16525 *
16526 * Type A response include QName, response type, class, TTL and Ipv4.
16527 *
16528 * Return: Return boolean. TRUE for success, FALSE for fail.
16529 */
16530static bool
16531wlan_hdd_mdns_pack_response_type_a(hdd_config_t *ini_config,
16532 sir_mdns_resp_info resp_info,
16533 struct hdd_mdns_resp_info *resptype_a)
16534{
16535 uint16_t value;
16536 uint32_t len;
16537
16538 ENTER();
16539 if ((ini_config == NULL) || (resp_info == NULL) ||
16540 (resptype_a == NULL)) {
16541 hddLog(LOGE, FL("ini_config or response info is NULL!"));
16542 return FALSE;
16543 }
16544
16545 /* No Type A response */
16546 if (strlen((char *)ini_config->mdns_resp_type_a) <= 0)
16547 return TRUE;
16548
16549 /* Wrong response is assigned, just ignore this response */
16550 if (!wlan_hdd_mdns_init_response(resptype_a,
16551 ini_config->mdns_resp_type_a, '.'))
16552 return TRUE;
16553
16554 /* Process response domain name */
16555 if (!wlan_hdd_mdns_process_response_dname(resptype_a, resp_info)) {
16556 hddLog(LOGE, FL("Fail to process mDNS response (%d)!"),
16557 MDNS_TYPE_A);
16558 return FALSE;
16559 }
16560
16561 /* Process response Type, Class, TTL */
16562 if (!wlan_hdd_mdns_process_response_misc(MDNS_TYPE_A, resp_info)) {
16563 hddLog(LOGE, FL("Fail to process mDNS misc response (%d)!"),
16564 MDNS_TYPE_A);
16565 return FALSE;
16566 }
16567
16568 /* Process response RDLength, RData */
16569 len = sizeof(uint16_t) + sizeof(uint32_t);
16570 len += resp_info->resp_len;
16571 if (len >= MAX_MDNS_RESP_LEN) {
16572 hddLog(LOGE, FL("resp_len exceeds %d!"), MAX_MDNS_RESP_LEN);
16573 return FALSE;
16574 }
16575 value = sizeof(uint32_t);
16576 wlan_hdd_mdns_format_response_u16(value, resp_info);
16577 wlan_hdd_mdns_format_response_u32(ini_config->mdns_resp_type_a_ipv4,
16578 resp_info);
16579
16580 EXIT();
16581 return TRUE;
16582}
16583
16584/**
16585 * wlan_hdd_mdns_pack_response_type_txt() - Pack Type Txt response
16586 * @ini_config: Pointer to the struct hdd_config_t
16587 * @resp_info: Pointer to the struct tSirMDNSResponseInfo
16588 * @resptype_txt: Pointer to the struct hdd_mdns_resp_info of Type txt
16589 * @resptype_a: Pointer to the struct hdd_mdns_resp_info of Type A
16590 *
16591 * Type Txt response include QName, response type, class, TTL and text content.
16592 * Also, it will find the matched QName from resptype_A and compress the data.
16593 *
16594 * Return: Return boolean. TRUE for success, FALSE for fail.
16595 */
16596static bool
16597wlan_hdd_mdns_pack_response_type_txt(hdd_config_t *ini_config,
16598 sir_mdns_resp_info resp_info,
16599 struct hdd_mdns_resp_info *resptype_txt,
16600 struct hdd_mdns_resp_info *resptype_a)
16601{
16602 uint8_t num_matched;
16603 uint8_t num;
16604 uint16_t idx;
16605 uint16_t value = 0;
16606 uint32_t len;
16607 uint32_t total_len;
16608 bool status;
16609 struct hdd_mdns_resp_info resptype_content;
16610
16611 ENTER();
16612
16613 if ((ini_config == NULL) || (resp_info == NULL) ||
16614 (resptype_txt == NULL)) {
16615 hddLog(LOGE, FL("ini_config or response info is NULL!"));
16616 return FALSE;
16617 }
16618
16619 /* No Type Txt response */
16620 if (strlen((char *)ini_config->mdns_resp_type_txt) <= 0)
16621 return TRUE;
16622
16623 /* Wrong response is assigned, just ignore this response */
16624 if (!wlan_hdd_mdns_init_response(resptype_txt,
16625 ini_config->mdns_resp_type_txt, '.'))
16626 return TRUE;
16627
16628 /*
16629 * For data compression
16630 * Check if any strings are matched with Type A response
16631 */
16632 if (resptype_a && (resptype_a->num_entries > 0)) {
16633 num_matched = wlan_hdd_mdns_find_entries_from_end(resptype_txt,
16634 resptype_a);
16635 if (num_matched > 0) {
16636 if (!wlan_hdd_mdns_compress_data(resp_info,
16637 resptype_txt, resptype_a, num_matched)) {
16638 hddLog(LOGE, FL("Fail to compress mDNS "
16639 "response (%d)!"), MDNS_TYPE_TXT);
16640 return FALSE;
16641 }
16642 } else {
16643 /*
16644 * num_matched is zero. Error!
16645 * At least ".local" is needed.
16646 */
16647 hddLog(LOGE, FL("No matched string! Fail to pack mDNS "
16648 "response (%d)!"), MDNS_TYPE_TXT);
16649 return FALSE;
16650 }
16651 } else {
16652 /* no TypeA response, so show the whole data */
16653 if (!wlan_hdd_mdns_process_response_dname(resptype_txt,
16654 resp_info)) {
16655 hddLog(LOGE, FL("Fail to process mDNS response (%d)!"),
16656 MDNS_TYPE_TXT);
16657 return FALSE;
16658 }
16659 }
16660
16661 /* Process response Type, Class, TTL */
16662 if (!wlan_hdd_mdns_process_response_misc(MDNS_TYPE_TXT, resp_info)) {
16663 hddLog(LOGE, FL("Fail to process mDNS misc response (%d)!"),
16664 MDNS_TYPE_TXT);
16665 return FALSE;
16666 }
16667
16668 /*
16669 * Process response RDLength, RData.
16670 * TypeTxt RData include len.
16671 */
16672 status = wlan_hdd_mdns_init_response(&resptype_content,
16673 ini_config->mdns_resp_type_txt_content,
16674 '/');
16675 if (status == FALSE) {
16676 hddLog(LOGE, FL("wlan_hdd_mdns_init_response FAIL"));
16677 return FALSE;
16678 }
16679
16680 for (num = 0; num < resptype_content.num_entries; num++) {
16681 idx = num * MAX_LEN_DOMAINNAME_FIELD;
16682 value += strlen((char *)&resptype_content.data[idx]);
16683 }
16684
16685 /* content len is uint16_t */
16686 total_len = sizeof(uint16_t);
16687 total_len += resp_info->resp_len + value +
16688 resptype_content.num_entries;
16689
16690 if (total_len >= MAX_MDNS_RESP_LEN) {
16691 hddLog(LOGE, FL("resp_len exceeds %d!"), MAX_MDNS_RESP_LEN);
16692 return FALSE;
16693 }
16694 wlan_hdd_mdns_format_response_u16(value + resptype_content.num_entries,
16695 resp_info);
16696
16697 for (num = 0; num < resptype_content.num_entries; num++) {
16698 idx = num * MAX_LEN_DOMAINNAME_FIELD;
16699 len = strlen((char *)&resptype_content.data[idx]);
16700 resp_info->resp_data[resp_info->resp_len] = len;
16701 resp_info->resp_len++;
16702
16703 vos_mem_copy(&resp_info->resp_data[resp_info->resp_len],
16704 &resptype_content.data[idx], len);
16705
16706 resp_info->resp_len += len;
16707 hddLog(LOG1, FL("index = %d, len = %d, str = %s"),
16708 num, len, &resptype_content.data[idx]);
16709 }
16710
16711 EXIT();
16712 return TRUE;
16713}
16714
16715/**
16716 * wlan_hdd_mdns_pack_response_type_ptr_dname() - Pack Type PTR domain name
16717 * @ini_config: Pointer to the struct hdd_config_t
16718 * @resp_info: Pointer to the struct tSirMDNSResponseInfo
16719 * @resptype_ptr_dn: Pointer to the struct hdd_mdns_resp_info of Type Ptr
16720 * domain name
16721 * @resptype_ptr: Pointer to the struct hdd_mdns_resp_info of Type Ptr
16722 * @resptype_txt: Pointer to the struct hdd_mdns_resp_info of Type Txt
16723 * @resptype_a: Pointer to the struct hdd_mdns_resp_info of Type A
16724 *
16725 * The Type Ptr response include Type PTR domain name in its data field.
16726 * Also, it will find the matched QName from the existing resptype_ptr,
16727 * resptype_txt, resptype_a and then compress the data.
16728 *
16729 * Return: Return boolean. TRUE for success, FALSE for fail.
16730 */
16731static bool
16732wlan_hdd_mdns_pack_response_type_ptr_dname(hdd_config_t *ini_config,
16733 sir_mdns_resp_info resp_info,
16734 struct hdd_mdns_resp_info *resptype_ptr_dn,
16735 struct hdd_mdns_resp_info *resptype_ptr,
16736 struct hdd_mdns_resp_info *resptype_txt,
16737 struct hdd_mdns_resp_info *resptype_a)
16738{
16739 uint8_t num_matched, numlist, size;
16740 struct hdd_mdns_resp_matched matchedlist[MAX_MDNS_RESP_TYPE-1];
16741 struct hdd_mdns_resp_info *resp;
16742
16743 if ((ini_config == NULL) || (resp_info == NULL) ||
16744 (resptype_ptr == NULL) || (resptype_ptr_dn == NULL)) {
16745 hddLog(LOGE, FL("ini_config or response info is NULL!"));
16746 return FALSE;
16747 }
16748
16749 /* No Type Ptr domain name response */
16750 if (strlen((char *)ini_config->mdns_resp_type_ptr_dname) <= 0)
16751 return TRUE;
16752
16753 /* Wrong response is assigned, just ignore this response */
16754 if (!wlan_hdd_mdns_init_response(resptype_ptr_dn,
16755 ini_config->mdns_resp_type_ptr_dname, '.'))
16756 return TRUE;
16757
16758 /*
16759 * For data compression
16760 * Check if any strings are matched with previous
16761 * response.
16762 */
16763 numlist = 0;
16764 size = (MAX_MDNS_RESP_TYPE-1);
16765 size *= sizeof(struct hdd_mdns_resp_matched);
16766 vos_mem_zero(matchedlist, size);
16767 num_matched = wlan_hdd_mdns_find_entries_from_end(resptype_ptr_dn,
16768 resptype_ptr);
16769 if (num_matched > 0) {
16770 matchedlist[numlist].num_matched = num_matched;
16771 matchedlist[numlist].type = MDNS_TYPE_PTR;
16772 numlist++;
16773 }
16774 if (resptype_txt && (resptype_txt->num_entries > 0)) {
16775 num_matched = wlan_hdd_mdns_find_entries_from_end(
16776 resptype_ptr_dn, resptype_txt);
16777 if (num_matched > 0) {
16778 matchedlist[numlist].num_matched = num_matched;
16779 matchedlist[numlist].type = MDNS_TYPE_TXT;
16780 numlist++;
16781 }
16782 }
16783 if (resptype_a && (resptype_a->num_entries > 0)) {
16784 num_matched = wlan_hdd_mdns_find_entries_from_end(
16785 resptype_ptr_dn,resptype_a);
16786 if (num_matched > 0) {
16787 matchedlist[numlist].num_matched = num_matched;
16788 matchedlist[numlist].type = MDNS_TYPE_A;
16789 numlist++;
16790 }
16791 }
16792 if (numlist > 0) {
16793 if (numlist > 1)
16794 wlan_hdd_mdns_find_max(matchedlist, numlist);
16795 resp = NULL;
16796 switch (matchedlist[numlist-1].type) {
16797 case MDNS_TYPE_A:
16798 resp = resptype_a;
16799 break;
16800 case MDNS_TYPE_TXT:
16801 resp = resptype_txt;
16802 break;
16803 case MDNS_TYPE_PTR:
16804 resp = resptype_ptr;
16805 break;
16806 default:
16807 hddLog(LOGE, FL("Fail to compress mDNS response "
16808 "(%d)!"), MDNS_TYPE_PTR_DNAME);
16809 return FALSE;
16810 }
16811 num_matched = matchedlist[numlist-1].num_matched;
16812 if (!wlan_hdd_mdns_compress_data(resp_info, resptype_ptr_dn,
16813 resp, num_matched)) {
16814 hddLog(LOGE, FL("Fail to compress mDNS response "
16815 "(%d)!"), MDNS_TYPE_PTR_DNAME);
16816 return FALSE;
16817 }
16818 } else {
16819 /* num = 0 -> no matched string */
16820 if (!wlan_hdd_mdns_process_response_dname(resptype_ptr_dn,
16821 resp_info)) {
16822 hddLog(LOGE, FL("Fail to process mDNS response (%d)!"),
16823 MDNS_TYPE_PTR_DNAME);
16824 return FALSE;
16825 }
16826 }
16827
16828 return TRUE;
16829}
16830
16831/**
16832 * wlan_hdd_mdns_pack_response_type_ptr() - Pack Type PTR response
16833 * @ini_config: Pointer to the struct hdd_config_t
16834 * @resp_info: Pointer to the struct tSirMDNSResponseInfo
16835 * @resptype_ptr: Pointer to the struct hdd_mdns_resp_info of Type Ptr
16836 * @resptype_ptr_dn: Pointer to the struct hdd_mdns_resp_info of Type Ptr
16837 * domain name
16838 * @resptype_txt: Pointer to the struct hdd_mdns_resp_info of Type Txt
16839 * @resptype_a: Pointer to the struct hdd_mdns_resp_info of Type A
16840 *
16841 * The Type Ptr response include QName, response type, class, TTL and
16842 * Type PTR domain name. Also, it will find the matched QName from the
16843 * existing resptype_txt, resptype_a and then compress the data.
16844 *
16845 * Return: Return boolean. TRUE for success, FALSE for fail.
16846 */
16847static bool
16848wlan_hdd_mdns_pack_response_type_ptr(hdd_config_t *ini_config,
16849 sir_mdns_resp_info resp_info,
16850 struct hdd_mdns_resp_info *resptype_ptr,
16851 struct hdd_mdns_resp_info *resptype_ptr_dn,
16852 struct hdd_mdns_resp_info *resptype_txt,
16853 struct hdd_mdns_resp_info *resptype_a)
16854{
16855 uint8_t num_matched, num_matched1;
16856 uint16_t value;
16857 uint8_t val_u8;
16858 uint32_t offset_data_len, len;
16859
16860 ENTER();
16861 if ((ini_config == NULL) || (resp_info == NULL) ||
16862 (resptype_ptr == NULL) || (resptype_ptr_dn == NULL)) {
16863 hddLog(LOGE, FL("ini_config or response info is NULL!"));
16864 return FALSE;
16865 }
16866
16867 /* No Type Ptr response */
16868 if (strlen((char *)ini_config->mdns_resp_type_ptr) <= 0)
16869 return TRUE;
16870
16871 /* Wrong response is assigned, just ignore this response */
16872 if (!wlan_hdd_mdns_init_response(resptype_ptr,
16873 ini_config->mdns_resp_type_ptr, '.'))
16874 return TRUE;
16875
16876 /*
16877 * For data compression
16878 * Check if any strings are matched with Type A response
16879 */
16880 num_matched = 0;
16881 num_matched1 = 0;
16882 if (resptype_a && (resptype_a->num_entries > 0)) {
16883 num_matched = wlan_hdd_mdns_find_entries_from_end(resptype_ptr,
16884 resptype_a);
16885 }
16886 if (resptype_txt && (resptype_txt->num_entries > 0)) {
16887 num_matched1 = wlan_hdd_mdns_find_entries_from_end(
16888 resptype_ptr, resptype_txt);
16889 }
16890 if ((num_matched != num_matched1) ||
16891 ((num_matched > 0) && (num_matched1 > 0))) {
16892 if (num_matched >= num_matched1) {
16893 if (!wlan_hdd_mdns_compress_data(resp_info,
16894 resptype_ptr, resptype_a, num_matched)) {
16895 hddLog(LOGE, FL("Fail to compress mDNS "
16896 "response (%d)!"), MDNS_TYPE_PTR);
16897 return FALSE;
16898 }
16899 } else {
16900 /* num_matched is less than num_matched1 */
16901 if (!wlan_hdd_mdns_compress_data(resp_info,
16902 resptype_ptr, resptype_txt, num_matched1)) {
16903 hddLog(LOGE, FL("Fail to compress mDNS "
16904 "response (%d)!"), MDNS_TYPE_PTR);
16905 return FALSE;
16906 }
16907 }
16908 } else {
16909 /*
16910 * Both num_matched and num_matched1 are zero.
16911 * no TypeA & TypeTxt
16912 */
16913 if (!wlan_hdd_mdns_process_response_dname(resptype_ptr,
16914 resp_info)) {
16915 hddLog(LOGE, FL("Fail to process mDNS response (%d)!"),
16916 MDNS_TYPE_PTR);
16917 return FALSE;
16918 }
16919 }
16920
16921 /* Process response Type, Class, TTL */
16922 if (!wlan_hdd_mdns_process_response_misc(MDNS_TYPE_PTR, resp_info)) {
16923 hddLog(LOGE, FL("Fail to process mDNS misc response (%d)!"),
16924 MDNS_TYPE_PTR);
16925 return FALSE;
16926 }
16927
16928 /*
16929 * Process response RDLength, RData (Ptr domain name)
16930 * Save the offset of RData length
16931 */
16932 offset_data_len = resp_info->resp_len;
16933 resp_info->resp_len += sizeof(uint16_t);
16934
16935 if (!wlan_hdd_mdns_pack_response_type_ptr_dname(ini_config, resp_info,
16936 resptype_ptr_dn, resptype_ptr,
16937 resptype_txt, resptype_a)) {
16938 return FALSE;
16939 }
16940 /* Set the RData length */
16941 len = offset_data_len + sizeof(uint16_t);
16942 if ((resptype_ptr_dn->num_entries > 0) &&
16943 (resp_info->resp_len > len)) {
16944 value = resp_info->resp_len - len;
16945 val_u8 = (value & 0xff00) >> 8;
16946 resp_info->resp_data[offset_data_len] = val_u8;
16947 val_u8 = value & 0xff;
16948 resp_info->resp_data[offset_data_len+1] = val_u8;
16949 } else {
16950 hddLog(LOGE, FL("Fail to process mDNS response (%d)!"),
16951 MDNS_TYPE_PTR);
16952 return FALSE;
16953 }
16954
16955 EXIT();
16956 return TRUE;
16957}
16958
16959/**
16960 * wlan_hdd_mdns_pack_response_type_srv_target()- Pack Type Service Target
16961 * @ini_config: Pointer to the struct hdd_config_t
16962 * @resp_info: Pointer to the struct tSirMDNSResponseInfo
16963 * @resptype_srv_tgt: Pointer to the struct hdd_mdns_resp_info of Type Srv
16964 * target
16965 * @resptype_srv: Pointer to the struct hdd_mdns_resp_info of Type Srv
16966 * @resptype_ptr: Pointer to the struct hdd_mdns_resp_info of Type Ptr
16967 * @resptype_ptr_dn: Pointer to the struct hdd_mdns_resp_info of Type Ptr
16968 * domain name
16969 * @resptype_txt: Pointer to the struct hdd_mdns_resp_info of Type Txt
16970 * @resptype_a: Pointer to the struct hdd_mdns_resp_info of Type A
16971 *
16972 * The Type service target is one of the data field in the Type SRV response.
16973 * Also, it will find the matched QName from the existing resptype_srv,
16974 * resptype_ptr, resptype_ptr_dn, resptype_txt, resptype_a and then compress
16975 * the data.
16976 *
16977 * Return: Return boolean. TRUE for success, FALSE for fail.
16978 */
16979static bool
16980wlan_hdd_mdns_pack_response_type_srv_target(hdd_config_t *ini_config,
16981 sir_mdns_resp_info resp_info,
16982 struct hdd_mdns_resp_info *resptype_srv_tgt,
16983 struct hdd_mdns_resp_info *resptype_srv,
16984 struct hdd_mdns_resp_info *resptype_ptr,
16985 struct hdd_mdns_resp_info *resptype_ptr_dn,
16986 struct hdd_mdns_resp_info *resptype_txt,
16987 struct hdd_mdns_resp_info *resptype_a)
16988{
16989 uint8_t num_matched, num, size;
16990 struct hdd_mdns_resp_matched matchedlist[MAX_MDNS_RESP_TYPE-1];
16991 struct hdd_mdns_resp_info *resp;
16992
16993 if ((ini_config == NULL) || (resp_info == NULL) ||
16994 (resptype_srv == NULL) || (resptype_srv_tgt == NULL)) {
16995 hddLog(LOGE, FL("ini_config or response info is NULL!"));
16996 return FALSE;
16997 }
16998
16999 /* No Type Srv Target response */
17000 if (strlen((char *)ini_config->mdns_resp_type_srv_target) <= 0)
17001 return TRUE;
17002
17003 /* Wrong response is assigned, just ignore this response */
17004 if (!wlan_hdd_mdns_init_response(resptype_srv_tgt,
17005 ini_config->mdns_resp_type_srv_target, '.'))
17006 return TRUE;
17007
17008 /*
17009 * For data compression
17010 * Check if any strings are matched with previous response.
17011 */
17012 num = 0;
17013 size = (MAX_MDNS_RESP_TYPE-1);
17014 size *= sizeof(struct hdd_mdns_resp_matched);
17015 vos_mem_zero(matchedlist, size);
17016 num_matched = wlan_hdd_mdns_find_entries_from_end(resptype_srv_tgt,
17017 resptype_srv);
17018 if (num_matched > 0) {
17019 matchedlist[num].num_matched = num_matched;
17020 matchedlist[num].type = MDNS_TYPE_SRV;
17021 num++;
17022 }
17023 if (resptype_ptr && (resptype_ptr->num_entries > 0)) {
17024 if (resptype_ptr_dn && (resptype_ptr_dn->num_entries > 0)) {
17025 num_matched = wlan_hdd_mdns_find_entries_from_end(
17026 resptype_srv_tgt, resptype_ptr_dn);
17027 if (num_matched > 0) {
17028 matchedlist[num].num_matched = num_matched;
17029 matchedlist[num].type = MDNS_TYPE_PTR_DNAME;
17030 num++;
17031 }
17032 }
17033 num_matched = wlan_hdd_mdns_find_entries_from_end(
17034 resptype_srv_tgt, resptype_ptr);
17035 if (num_matched > 0) {
17036 matchedlist[num].num_matched = num_matched;
17037 matchedlist[num].type = MDNS_TYPE_PTR;
17038 num++;
17039 }
17040 }
17041 if (resptype_txt && (resptype_txt->num_entries > 0)) {
17042 num_matched = wlan_hdd_mdns_find_entries_from_end(
17043 resptype_srv_tgt, resptype_txt);
17044 if (num_matched > 0) {
17045 matchedlist[num].num_matched = num_matched;
17046 matchedlist[num].type = MDNS_TYPE_TXT;
17047 num++;
17048 }
17049 }
17050 if (resptype_a && (resptype_a->num_entries > 0)) {
17051 num_matched = wlan_hdd_mdns_find_entries_from_end(
17052 resptype_srv_tgt, resptype_a);
17053 if (num_matched > 0) {
17054 matchedlist[num].num_matched = num_matched;
17055 matchedlist[num].type = MDNS_TYPE_A;
17056 num++;
17057 }
17058 }
17059 if (num > 0) {
17060 if (num > 1)
17061 wlan_hdd_mdns_find_max(matchedlist, num);
17062 resp = NULL;
17063 switch (matchedlist[num-1].type) {
17064 case MDNS_TYPE_A:
17065 resp = resptype_a;
17066 break;
17067 case MDNS_TYPE_TXT:
17068 resp = resptype_txt;
17069 break;
17070 case MDNS_TYPE_PTR:
17071 resp = resptype_ptr;
17072 break;
17073 case MDNS_TYPE_PTR_DNAME:
17074 resp = resptype_ptr_dn;
17075 break;
17076 case MDNS_TYPE_SRV:
17077 resp = resptype_srv;
17078 break;
17079 default:
17080 hddLog(LOGE, FL("Fail to compress mDNS response "
17081 "(%d)!"), MDNS_TYPE_SRV_TARGET);
17082 return FALSE;
17083 }
17084 num_matched = matchedlist[num-1].num_matched;
17085 if (!wlan_hdd_mdns_compress_data(resp_info, resptype_srv_tgt,
17086 resp, num_matched)) {
17087 hddLog(LOGE, FL("Fail to compress mDNS response "
17088 "(%d)!"), MDNS_TYPE_SRV_TARGET);
17089 return FALSE;
17090 }
17091 } else {
17092 /* num = 0 -> no matched string */
17093 if (!wlan_hdd_mdns_process_response_dname(resptype_srv_tgt,
17094 resp_info)) {
17095 hddLog(LOGE, FL("Fail to process mDNS response (%d)!"),
17096 MDNS_TYPE_SRV_TARGET);
17097 return FALSE;
17098 }
17099 }
17100
17101 return TRUE;
17102}
17103
17104/**
17105 * wlan_hdd_mdns_pack_response_type_srv()- Pack Type Service response
17106 * @ini_config: Pointer to the struct hdd_config_t
17107 * @resp_info: Pointer to the struct tSirMDNSResponseInfo
17108 * @resptype_srv: Pointer to the struct hdd_mdns_resp_info of Type Srv
17109 * @resptype_srv_tgt: Pointer to the struct hdd_mdns_resp_info of Type Srv
17110 * target
17111 * @resptype_ptr: Pointer to the struct hdd_mdns_resp_info of Type Ptr
17112 * @resptype_ptr_dn: Pointer to the struct hdd_mdns_resp_info of Type Ptr
17113 * domain name
17114 * @resptype_txt: Pointer to the struct hdd_mdns_resp_info of Type Txt
17115 * @resptype_a: Pointer to the struct hdd_mdns_resp_info of Type A
17116 *
17117 * The Type SRV (Service) response include QName, response type, class, TTL
17118 * and four kinds of data fields. Also, it will find the matched QName from
17119 * the existing resptype_ptr, resptype_ptr_dn, resptype_txt, resptype_a and
17120 * then compress the data.
17121 *
17122 * Return: Return boolean. TRUE for success, FALSE for fail.
17123 */
17124static bool
17125wlan_hdd_mdns_pack_response_type_srv(hdd_config_t *ini_config,
17126 sir_mdns_resp_info resp_info,
17127 struct hdd_mdns_resp_info *resptype_srv,
17128 struct hdd_mdns_resp_info *resptype_srv_tgt,
17129 struct hdd_mdns_resp_info *resptype_ptr,
17130 struct hdd_mdns_resp_info *resptype_ptr_dn,
17131 struct hdd_mdns_resp_info *resptype_txt,
17132 struct hdd_mdns_resp_info *resptype_a)
17133{
17134 uint8_t num_matched, num, size;
17135 uint16_t value;
17136 uint8_t val_u8;
17137 uint32_t offset_data_len, len;
17138 struct hdd_mdns_resp_info *resp;
17139 struct hdd_mdns_resp_matched matchedlist[MAX_MDNS_RESP_TYPE-1];
17140
17141 ENTER();
17142
17143 if ((ini_config == NULL) || (resp_info == NULL) ||
17144 (resptype_srv == NULL) || (resptype_srv_tgt == NULL)) {
17145 hddLog(LOGE, FL("ini_config or response info is NULL!"));
17146 return FALSE;
17147 }
17148
17149 /* No Type Srv response */
17150 if (strlen((char *)ini_config->mdns_resp_type_srv) <= 0)
17151 return TRUE;
17152
17153 /* Wrong response is assigned, just ignore this response */
17154 if (!wlan_hdd_mdns_init_response(resptype_srv,
17155 ini_config->mdns_resp_type_srv, '.'))
17156 return TRUE;
17157
17158 /*
17159 * For data compression
17160 * Check if any strings are matched with Type A response
17161 */
17162 num = 0;
17163 size = (MAX_MDNS_RESP_TYPE-1);
17164 size *= sizeof(struct hdd_mdns_resp_matched);
17165 vos_mem_zero(matchedlist, size);
17166 if (resptype_ptr && (resptype_ptr->num_entries > 0)) {
17167 if (resptype_ptr_dn && (resptype_ptr_dn->num_entries > 0)) {
17168 num_matched = wlan_hdd_mdns_find_entries_from_end(
17169 resptype_srv,
17170 resptype_ptr_dn);
17171 if (num_matched > 0) {
17172 matchedlist[num].num_matched = num_matched;
17173 matchedlist[num].type = MDNS_TYPE_PTR_DNAME;
17174 num++;
17175 }
17176 }
17177 num_matched = wlan_hdd_mdns_find_entries_from_end(resptype_srv,
17178 resptype_ptr);
17179 if (num_matched > 0) {
17180 matchedlist[num].num_matched = num_matched;
17181 matchedlist[num].type = MDNS_TYPE_PTR;
17182 num++;
17183 }
17184 }
17185 if (resptype_txt && (resptype_txt->num_entries > 0)) {
17186 num_matched = wlan_hdd_mdns_find_entries_from_end(resptype_srv,
17187 resptype_txt);
17188 if (num_matched > 0) {
17189 matchedlist[num].num_matched =num_matched;
17190 matchedlist[num].type = MDNS_TYPE_TXT;
17191 num++;
17192 }
17193 }
17194 if (resptype_a && (resptype_a->num_entries > 0)) {
17195 num_matched = wlan_hdd_mdns_find_entries_from_end(resptype_srv,
17196 resptype_a);
17197 if (num_matched > 0) {
17198 matchedlist[num].num_matched = num_matched;
17199 matchedlist[num].type = MDNS_TYPE_A;
17200 num++;
17201 }
17202 }
17203 if (num > 0) {
17204 if (num > 1)
17205 wlan_hdd_mdns_find_max(matchedlist, num);
17206 resp = NULL;
17207 switch (matchedlist[num-1].type) {
17208 case MDNS_TYPE_A:
17209 resp = resptype_a;
17210 break;
17211 case MDNS_TYPE_TXT:
17212 resp = resptype_txt;
17213 break;
17214 case MDNS_TYPE_PTR:
17215 resp = resptype_ptr;
17216 break;
17217 case MDNS_TYPE_PTR_DNAME:
17218 resp = resptype_ptr_dn;
17219 break;
17220 default:
17221 hddLog(LOGE, FL("Fail to compress mDNS response "
17222 "(%d)!"), MDNS_TYPE_SRV);
17223 return FALSE;
17224 }
17225 num_matched = matchedlist[num-1].num_matched;
17226 if (!wlan_hdd_mdns_compress_data(resp_info, resptype_srv,
17227 resp, num_matched)) {
17228 hddLog(LOGE, FL("Fail to compress mDNS response "
17229 "(%d)!"), MDNS_TYPE_SRV);
17230 return FALSE;
17231 }
17232 } else {
17233 /* num = 0 -> no matched string */
17234 if (!wlan_hdd_mdns_process_response_dname(resptype_srv,
17235 resp_info)) {
17236 hddLog(LOGE, FL("Fail to process mDNS response (%d)!"),
17237 MDNS_TYPE_SRV);
17238 return FALSE;
17239 }
17240 }
17241
17242 /* Process response Type, Class, TTL */
17243 if (!wlan_hdd_mdns_process_response_misc(MDNS_TYPE_SRV, resp_info)) {
17244 hddLog(LOGE, FL("Fail to process mDNS misc response (%d)!"),
17245 MDNS_TYPE_SRV);
17246 return FALSE;
17247 }
17248
17249 /*
17250 * Process response RDLength, RData (Srv target name)
17251 * Save the offset of RData length
17252 */
17253 offset_data_len = resp_info->resp_len;
17254 resp_info->resp_len += sizeof(uint16_t);
17255
17256 len = resp_info->resp_len + (3 * sizeof(uint16_t));
17257 if (len >= MAX_MDNS_RESP_LEN) {
17258 hddLog(LOGE, FL("resp_len exceeds %d!"), MAX_MDNS_RESP_LEN);
17259 return FALSE;
17260 }
17261
17262 /* set Srv Priority */
17263 value = ini_config->mdns_resp_type_srv_priority;
17264 wlan_hdd_mdns_format_response_u16(value, resp_info);
17265 /* set Srv Weight */
17266 value = ini_config->mdns_resp_type_srv_weight;
17267 wlan_hdd_mdns_format_response_u16(value, resp_info);
17268 /* set Srv Port */
17269 value = ini_config->mdns_resp_type_srv_port;
17270 wlan_hdd_mdns_format_response_u16(value, resp_info);
17271
17272 if (!wlan_hdd_mdns_pack_response_type_srv_target(ini_config, resp_info,
17273 resptype_srv_tgt, resptype_srv,
17274 resptype_ptr, resptype_ptr_dn,
17275 resptype_txt, resptype_a)) {
17276 return FALSE;
17277 }
17278 /* Set the RData length */
17279 len = offset_data_len + sizeof(uint16_t);
17280 if ((resptype_srv_tgt->num_entries > 0) &&
17281 (resp_info->resp_len > len)) {
17282 value = resp_info->resp_len - len;
17283 val_u8 = (value & 0xff00) >> 8;
17284 resp_info->resp_data[offset_data_len] = val_u8;
17285 val_u8 = value & 0xff;
17286 resp_info->resp_data[offset_data_len+1] = val_u8;
17287 } else {
17288 hddLog(LOGE, FL("Fail to process mDNS response (%d)!"),
17289 MDNS_TYPE_SRV);
17290 return FALSE;
17291 }
17292
17293 EXIT();
17294 return TRUE;
17295}
17296
17297/**
17298 * wlan_hdd_mdns_free_mem() - Free the allocated memory
17299 * @response: Pointer to the struct hdd_mdns_resp_info
17300 *
17301 * Return: None
17302 */
17303static void wlan_hdd_mdns_free_mem(struct hdd_mdns_resp_info *response)
17304{
17305 if (response && response->data)
17306 vos_mem_free(response->data);
17307 if (response && response->offset)
17308 vos_mem_free(response->offset);
17309}
17310
17311/**
17312 * wlan_hdd_mdns_pack_response() - Pack mDNS response
17313 * @ini_config: Pointer to the struct hdd_config_t
17314 * @resp_info: Pointer to the struct tSirMDNSResponseInfo
17315 *
17316 * This function will pack four types of responses (Type A, Type Txt, Type Ptr
17317 * and Type Service). Each response contains QName, response type, class, TTL
17318 * and data fields.
17319 *
17320 * Return: Return boolean. TRUE for success, FALSE for fail.
17321 */
17322static bool wlan_hdd_mdns_pack_response(hdd_config_t *ini_config,
17323 sir_mdns_resp_info resp_info)
17324{
17325 struct hdd_mdns_resp_info resptype_a, resptype_txt;
17326 struct hdd_mdns_resp_info resptype_ptr, resptype_ptr_dn;
17327 struct hdd_mdns_resp_info resptype_srv, resptype_srv_tgt;
17328 uint32_t num_res_records = 0;
17329 bool status = FALSE;
17330
17331 ENTER();
17332
17333 wlan_hdd_mdns_reset_response(&resptype_a);
17334 wlan_hdd_mdns_reset_response(&resptype_txt);
17335 wlan_hdd_mdns_reset_response(&resptype_ptr);
17336 wlan_hdd_mdns_reset_response(&resptype_ptr_dn);
17337 wlan_hdd_mdns_reset_response(&resptype_srv);
17338 wlan_hdd_mdns_reset_response(&resptype_srv_tgt);
17339
17340 resp_info->resp_len = 0;
17341
17342 /* Process Type A response */
17343 if (!wlan_hdd_mdns_pack_response_type_a(ini_config, resp_info,
17344 &resptype_a))
17345 goto err_resptype_a;
17346
17347 if ((resptype_a.num_entries > 0) &&
17348 (strlen((char *)&resptype_a.data[0]) > 0))
17349 num_res_records++;
17350
17351 /* Process Type TXT response */
17352 if (!wlan_hdd_mdns_pack_response_type_txt(ini_config, resp_info,
17353 &resptype_txt, &resptype_a))
17354 goto err_resptype_txt;
17355
17356 if ((resptype_txt.num_entries > 0) &&
17357 (strlen((char *)&resptype_txt.data[0]) > 0))
17358 num_res_records++;
17359
17360 /* Process Type PTR response */
17361 if (!wlan_hdd_mdns_pack_response_type_ptr(ini_config, resp_info,
17362 &resptype_ptr, &resptype_ptr_dn,
17363 &resptype_txt, &resptype_a))
17364 goto err_resptype_ptr;
17365
17366 if ((resptype_ptr.num_entries > 0) &&
17367 (strlen((char *)&resptype_ptr.data[0]) > 0))
17368 num_res_records++;
17369
17370 /* Process Type SRV response */
17371 if (!wlan_hdd_mdns_pack_response_type_srv(ini_config, resp_info,
17372 &resptype_srv, &resptype_srv_tgt,
17373 &resptype_ptr, &resptype_ptr_dn,
17374 &resptype_txt, &resptype_a))
17375 goto err_resptype_srv;
17376
17377 if ((resptype_srv.num_entries > 0) &&
17378 (strlen((char *)&resptype_srv.data[0]) > 0))
17379 num_res_records++;
17380
17381 resp_info->resourceRecord_count = num_res_records;
17382 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
17383 "%s: Pack mDNS response data successfully!", __func__);
17384 status = TRUE;
17385
17386err_resptype_srv:
17387 wlan_hdd_mdns_free_mem(&resptype_srv);
17388 wlan_hdd_mdns_free_mem(&resptype_srv_tgt);
17389
17390err_resptype_ptr:
17391 wlan_hdd_mdns_free_mem(&resptype_ptr);
17392 wlan_hdd_mdns_free_mem(&resptype_ptr_dn);
17393
17394err_resptype_txt:
17395 wlan_hdd_mdns_free_mem(&resptype_txt);
17396
17397err_resptype_a:
17398 wlan_hdd_mdns_free_mem(&resptype_a);
17399
17400 EXIT();
17401 return status;
17402}
17403
17404/**
17405 * wlan_hdd_set_mdns_offload() - Enable mDNS offload
17406 * @hostapd_adapter: Pointer to the struct hdd_adapter_t
17407 *
17408 * This function will set FQDN/unique FQDN (full qualified domain name)
17409 * and the mDNS response. Then send them to SME.
17410 *
17411 * Return: Return boolean. TRUE for success, FALSE for fail.
17412 */
17413bool wlan_hdd_set_mdns_offload(hdd_adapter_t *hostapd_adapter)
17414{
17415 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(hostapd_adapter);
17416 sir_mdns_offload_info mdns_offload_info;
17417 sir_mdns_fqdn_info mdns_fqdn_info;
17418 sir_mdns_resp_info mdns_resp_info;
17419 uint32_t fqdn_len, ufqdn_len;
17420
17421 ENTER();
17422
17423 /* 1. Prepare the MDNS fqdn request to send to SME */
17424 fqdn_len = strlen(hdd_ctx->cfg_ini->mdns_fqdn);
17425 ufqdn_len = strlen(hdd_ctx->cfg_ini->mdns_uniquefqdn);
17426 if ((fqdn_len == 0) && (ufqdn_len == 0)) {
17427 hddLog(LOGE, FL("No mDNS FQDN or UFQDN is assigned fqdn_len %d,"
17428 "ufqdn_len %d!"), fqdn_len, ufqdn_len);
17429 return FALSE;
17430 }
17431
17432 mdns_fqdn_info = vos_mem_malloc(sizeof(*mdns_fqdn_info));
17433 if (NULL == mdns_fqdn_info) {
17434 hddLog(LOGE, FL("could not allocate tSirMDNSFqdnInfo!"));
17435 return FALSE;
17436 }
17437 /* MDNS fqdn request */
17438 if (fqdn_len > 0) {
17439 vos_mem_zero(mdns_fqdn_info, sizeof(*mdns_fqdn_info));
17440 mdns_fqdn_info->bss_idx = hostapd_adapter->sessionId;
17441 mdns_fqdn_info->fqdn_type = MDNS_FQDN_TYPE_GENERAL;
17442 mdns_fqdn_info->fqdn_len = fqdn_len;
17443 mdns_fqdn_info->mdns_fqdn_callback = hdd_mdns_fqdn_offload_done;
17444 mdns_fqdn_info->mdns_fqdn_cb_context = hostapd_adapter;
17445 vos_mem_copy(mdns_fqdn_info->fqdn_data,
17446 hdd_ctx->cfg_ini->mdns_fqdn,
17447 mdns_fqdn_info->fqdn_len);
17448
17449 if (eHAL_STATUS_SUCCESS !=
17450 sme_set_mdns_fqdn(hdd_ctx->hHal, mdns_fqdn_info)) {
17451 hddLog(LOGE, FL("sme_set_mdns_fqdn fail!"));
17452 vos_mem_free(mdns_fqdn_info);
17453 return FALSE;
17454 }
17455 }
17456 /* MDNS unique fqdn request */
17457 if (ufqdn_len > 0) {
17458 vos_mem_zero(mdns_fqdn_info, sizeof(*mdns_fqdn_info));
17459 mdns_fqdn_info->bss_idx = hostapd_adapter->sessionId;
17460 mdns_fqdn_info->fqdn_type = MDNS_FQDN_TYPE_UNIQUE;
17461 mdns_fqdn_info->fqdn_len = ufqdn_len;
17462 mdns_fqdn_info->mdns_fqdn_callback = hdd_mdns_fqdn_offload_done;
17463 mdns_fqdn_info->mdns_fqdn_cb_context = hostapd_adapter;
17464 vos_mem_copy(mdns_fqdn_info->fqdn_data,
17465 hdd_ctx->cfg_ini->mdns_uniquefqdn,
17466 mdns_fqdn_info->fqdn_len);
17467 if (eHAL_STATUS_SUCCESS !=
17468 sme_set_mdns_fqdn(hdd_ctx->hHal, mdns_fqdn_info)) {
17469 hddLog(LOGE, FL("sme_set_mdns_fqdn fail!"));
17470 vos_mem_free(mdns_fqdn_info);
17471 return FALSE;
17472 }
17473 }
17474 vos_mem_free(mdns_fqdn_info);
17475
17476 /* 2. Prepare the MDNS response request to send to SME */
17477 mdns_resp_info = vos_mem_malloc(sizeof(*mdns_resp_info));
17478 if (NULL == mdns_resp_info) {
17479 hddLog(LOGE, FL("could not allocate tSirMDNSResponseInfo!"));
17480 return FALSE;
17481 }
17482
17483 vos_mem_zero(mdns_resp_info, sizeof(*mdns_resp_info));
17484 mdns_resp_info->bss_idx = hostapd_adapter->sessionId;
17485 mdns_resp_info->mdns_resp_callback = hdd_mdns_resp_offload_done;
17486 mdns_resp_info->mdns_resp_cb_context = hostapd_adapter;
17487 if (!wlan_hdd_mdns_pack_response(hdd_ctx->cfg_ini, mdns_resp_info)) {
17488 hddLog(LOGE, FL("wlan_hdd_pack_mdns_response fail!"));
17489 vos_mem_free(mdns_resp_info);
17490 return FALSE;
17491 }
17492 if (eHAL_STATUS_SUCCESS !=
17493 sme_set_mdns_resp(hdd_ctx->hHal, mdns_resp_info)) {
17494 hddLog(LOGE, FL("sme_set_mdns_resp fail!"));
17495 vos_mem_free(mdns_resp_info);
17496 return FALSE;
17497 }
17498 vos_mem_free(mdns_resp_info);
17499
17500 /* 3. Prepare the MDNS Enable request to send to SME */
17501 mdns_offload_info = vos_mem_malloc(sizeof(*mdns_offload_info));
17502 if (NULL == mdns_offload_info) {
17503 hddLog(LOGE, FL("could not allocate tSirMDNSOffloadInfo!"));
17504 return FALSE;
17505 }
17506
17507 vos_mem_zero(mdns_offload_info, sizeof(*mdns_offload_info));
17508
17509 mdns_offload_info->bss_idx = hostapd_adapter->sessionId;
17510 mdns_offload_info->enable = hdd_ctx->cfg_ini->enable_mdns_offload;
17511 mdns_offload_info->mdns_enable_callback = hdd_mdns_enable_offload_done;
17512 mdns_offload_info->mdns_enable_cb_context = hostapd_adapter;
17513 if (eHAL_STATUS_SUCCESS !=
17514 sme_set_mdns_offload(hdd_ctx->hHal, mdns_offload_info)) {
17515 hddLog(LOGE, FL("sme_set_mdns_offload fail!"));
17516 vos_mem_free(mdns_offload_info);
17517 return FALSE;
17518 }
17519
17520 vos_mem_free(mdns_offload_info);
17521 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
17522 "%s: enable mDNS offload successfully!", __func__);
17523 return TRUE;
17524}
Manjeet Singh3ed79242017-01-11 19:04:32 +053017525
17526
Anurag Chouhan0b29de02016-12-16 13:18:40 +053017527#endif /* MDNS_OFFLOAD */
c_manjeecfd1efb2015-09-25 19:32:34 +053017528
Hanumanth Reddy Pothulad864f312017-01-18 16:16:08 +053017529/**
17530 * wlan_hdd_start_sap() - This function starts bss of SAP.
17531 * @ap_adapter: SAP adapter
17532 *
17533 * This function will process the starting of sap adapter.
17534 *
17535 * Return: void.
17536 */
17537void wlan_hdd_start_sap(hdd_adapter_t *ap_adapter)
17538{
17539 hdd_ap_ctx_t *hdd_ap_ctx;
17540 hdd_hostapd_state_t *hostapd_state;
17541 VOS_STATUS vos_status;
17542 hdd_context_t *hdd_ctx;
17543 tsap_Config_t *pConfig;
17544
17545 if (NULL == ap_adapter) {
17546 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
17547 FL("ap_adapter is NULL here"));
17548 return;
17549 }
17550
17551 hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter);
17552 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
17553 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
17554 pConfig = &ap_adapter->sessionCtx.ap.sapConfig;
17555
17556 mutex_lock(&hdd_ctx->sap_lock);
17557 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags))
17558 goto end;
17559
17560 if (0 != wlan_hdd_cfg80211_update_apies(ap_adapter)) {
17561 hddLog(LOGE, FL("SAP Not able to set AP IEs"));
17562 goto end;
17563 }
17564
17565 vos_event_reset(&hostapd_state->vosEvent);
17566 if (WLANSAP_StartBss(hdd_ctx->pvosContext, hdd_hostapd_SAPEventCB,
17567 &hdd_ap_ctx->sapConfig, (v_PVOID_t)ap_adapter->dev)
17568 != VOS_STATUS_SUCCESS) {
17569 goto end;
17570 }
17571
17572 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
17573 FL("Waiting for SAP to start"));
17574 vos_status = vos_wait_single_event(&hostapd_state->vosEvent, 10000);
17575 if (!VOS_IS_STATUS_SUCCESS(vos_status)) {
17576 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
17577 FL("SAP Start failed"));
17578 goto end;
17579 }
17580 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
17581 FL("SAP Start Success"));
17582 set_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
17583
17584 wlan_hdd_incr_active_session(hdd_ctx, ap_adapter->device_mode);
17585 hostapd_state->bCommit = TRUE;
17586
17587end:
17588 mutex_unlock(&hdd_ctx->sap_lock);
17589 return;
17590}
17591
Manjeet Singh3ed79242017-01-11 19:04:32 +053017592#ifdef WLAN_FEATURE_TSF
17593
17594/**
17595 * hdd_tsf_cb() - handle tsf request callback
17596 *
17597 * @pcb_cxt: pointer to the hdd_contex
17598 * @ptsf: pointer to struct stsf
17599 *
17600 * Based on the request sent .
17601 *
17602 * Return: Describe the execute result of this routine
17603 */
17604static int hdd_tsf_cb(void *pcb_ctx, struct stsf *ptsf)
17605{
17606 hdd_context_t *hddctx;
17607 int status;
17608 hdd_adapter_t* adapter = (hdd_adapter_t*)pcb_ctx;
17609
17610 if (pcb_ctx == NULL || ptsf == NULL) {
17611 hddLog(VOS_TRACE_LEVEL_ERROR,
17612 FL("HDD context is not valid"));
17613 return -EINVAL;
17614 }
17615
17616 hddctx = (hdd_context_t *)pcb_ctx;
17617 status = wlan_hdd_validate_context(hddctx);
17618 if (0 != status)
17619 return -EINVAL;
17620
17621 if (NULL == adapter) {
17622 hddLog(VOS_TRACE_LEVEL_ERROR,
17623 FL("failed to find adapter"));
17624 return -EINVAL;
17625 }
17626
17627 hddLog(VOS_TRACE_LEVEL_INFO,
17628 FL("tsf cb handle event, device_mode is %d"),
17629 adapter->device_mode);
17630
17631 /* copy the return value to hdd_tsf_ctx in adapter*/
17632 if (ptsf->tsf_req_status) {
17633
17634 vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
17635 adapter->tsf_cap_ctx.tsf_get_state = TSF_NOT_RETURNED_BY_FW;
17636 adapter->tsf_cap_ctx.tsf_capture_state = TSF_IDLE;
17637 vos_event_set (&adapter->tsf_cap_ctx.tsf_capture_done_event);
17638 vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
17639
17640 hddLog(VOS_TRACE_LEVEL_ERROR, FL("tsf req failure :%d"),
17641 ptsf->tsf_req_status);
17642 return ptsf->tsf_req_status;
17643 }
17644 /* If this is a get request.Store the tsf values in adapter. */
17645 if (!ptsf->set_tsf_req) {
17646 vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
17647 adapter->tsf_cap_ctx.tsf_low = ptsf->tsf_low;
17648 adapter->tsf_cap_ctx.tsf_high = ptsf->tsf_high;
17649 adapter->tsf_cap_ctx.tsf_get_state = TSF_RETURN;
17650 adapter->tsf_cap_ctx.tsf_capture_state = TSF_IDLE;
17651 vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
17652
17653 hddLog(VOS_TRACE_LEVEL_INFO,
17654 FL("hdd_get_tsf_cb sta=%u, tsf_low=%u, tsf_high=%u"),
17655 adapter->sessionId, ptsf->tsf_low, ptsf->tsf_high);
17656 }
17657 else {
17658 vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
17659 adapter->tsf_cap_ctx.tsf_capture_state = TSF_CAP_STATE;
17660 adapter->tsf_cap_ctx.tsf_get_state = TSF_CURRENT_IN_CAP_STATE;
17661 vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
17662 }
17663 vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
17664 vos_event_set (&adapter->tsf_cap_ctx.tsf_capture_done_event);
17665 vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
17666
17667 /* free allocated mem */
17668 vos_mem_free(ptsf);
17669
17670 return 0;
17671}
17672
17673/**
17674 * hdd_capture_tsf() - capture tsf
17675 *
17676 * @adapter: pointer to adapter
17677 * @buf: pointer to upper layer buf
17678 * @len : the length of buf
17679 *
17680 * This function returns tsf value to uplayer.
17681 *
17682 * Return: Describe the execute result of this routine
17683 */
17684int hdd_capture_tsf(hdd_adapter_t *adapter, uint32_t *buf, int len)
17685{
17686 int ret = 0;
17687 hdd_station_ctx_t *hdd_sta_ctx;
17688 hdd_context_t *hdd_ctx;
17689 tSirCapTsfParams cap_tsf_params;
17690 VOS_STATUS status;
17691
17692 if (adapter == NULL || buf == NULL) {
17693 hddLog(VOS_TRACE_LEVEL_ERROR,
17694 FL("invalid pointer"));
17695 return -EINVAL;
17696 }
17697 if (len != 1)
17698 return -EINVAL;
17699
17700 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
17701
17702 if (wlan_hdd_validate_context(hdd_ctx)) {
17703 hddLog(VOS_TRACE_LEVEL_ERROR,
17704 FL("invalid hdd ctx"));
17705 return -EINVAL;
17706 }
17707 if (adapter->device_mode == WLAN_HDD_INFRA_STATION ||
17708 adapter->device_mode == WLAN_HDD_P2P_CLIENT) {
17709 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
17710 if (hdd_sta_ctx->conn_info.connState !=
17711 eConnectionState_Associated) {
17712
17713 hddLog(VOS_TRACE_LEVEL_INFO,
17714 FL("failed to cap tsf, not connect with ap"));
17715 buf[0] = TSF_STA_NOT_CONNECTED_NO_TSF;
17716 return ret;
17717 }
17718 }
17719 if ((adapter->device_mode == WLAN_HDD_SOFTAP ||
17720 adapter->device_mode == WLAN_HDD_P2P_GO) &&
17721 !(test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags))) {
17722 hddLog(VOS_TRACE_LEVEL_INFO,
17723 FL("Soft AP / P2p GO not beaconing"));
17724 buf[0] = TSF_SAP_NOT_STARTED_NO_TSF;
17725 return ret;
17726 }
17727 if (adapter->tsf_cap_ctx.tsf_capture_state == TSF_CAP_STATE) {
17728 hddLog(VOS_TRACE_LEVEL_INFO,
17729 FL("current in capture state, pls reset"));
17730 buf[0] = TSF_CURRENT_IN_CAP_STATE;
17731 } else {
17732 hddLog(VOS_TRACE_LEVEL_INFO, FL("ioctl issue cap tsf cmd"));
17733 buf[0] = TSF_RETURN;
17734 cap_tsf_params.session_id = adapter->sessionId;
17735 cap_tsf_params.tsf_rsp_cb_func = hdd_tsf_cb;
17736 cap_tsf_params.tsf_rsp_cb_ctx = adapter;
17737
17738 vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
17739 adapter->tsf_cap_ctx.tsf_capture_state = TSF_CAP_STATE;
17740 adapter->tsf_cap_ctx.tsf_get_state = TSF_CURRENT_IN_CAP_STATE;
17741 vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
17742
17743 ret = sme_capture_tsf_req(hdd_ctx->hHal, cap_tsf_params);
17744
17745 if (ret != VOS_STATUS_SUCCESS) {
17746 hddLog(VOS_TRACE_LEVEL_ERROR, FL("capture fail"));
17747 buf[0] = TSF_CAPTURE_FAIL;
17748 vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
17749 adapter->tsf_cap_ctx.tsf_capture_state = TSF_IDLE;
17750 vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
17751 return -EINVAL;
17752 }
17753 /* wait till we get a response from fw */
17754 status = vos_wait_single_event(&adapter->tsf_cap_ctx.
17755 tsf_capture_done_event,
17756 HDD_TSF_CAP_REQ_TIMEOUT);
17757
17758 if (!VOS_IS_STATUS_SUCCESS(status)) {
17759 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
17760 ("capture tsf vos wait for single_event failed!! %d"),
17761 adapter->tsf_cap_ctx.tsf_get_state);
17762
17763 vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
17764 adapter->tsf_cap_ctx.tsf_capture_state = TSF_IDLE;
17765 vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
17766
17767 return -EINVAL;
17768 }
17769 }
17770 buf[0] = TSF_RETURN;
17771 hddLog(VOS_TRACE_LEVEL_INFO,
17772 FL("ioctl return cap tsf cmd, ret = %d"), ret);
17773 return ret;
17774}
17775
17776/**
17777 * hdd_indicate_tsf() - return tsf to uplayer
17778 *
17779 * @adapter: pointer to adapter
17780 * @buf: pointer to uplayer buf
17781 * @len : the length of buf
17782 *
17783 * This function returns tsf value to uplayer.
17784 *
17785 * Return: Describe the execute result of this routine
17786 */
17787int hdd_indicate_tsf(hdd_adapter_t *adapter, uint32_t *buf, int len)
17788{
17789 int ret = 0;
17790 hdd_station_ctx_t *hdd_sta_ctx;
17791 hdd_context_t *hdd_ctx;
17792 tSirCapTsfParams cap_tsf_params;
17793 VOS_STATUS status;
17794
17795 if (adapter == NULL || buf == NULL) {
17796 hddLog(VOS_TRACE_LEVEL_ERROR,
17797 FL("invalid pointer"));
17798 return -EINVAL;
17799 }
17800 if (len != 3)
17801 return -EINVAL;
17802
17803 buf [1] = 0;
17804 buf [2] = 0;
17805 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
17806
17807 if (wlan_hdd_validate_context(hdd_ctx)) {
17808 hddLog(VOS_TRACE_LEVEL_ERROR,
17809 FL("invalid hdd ctx"));
17810 return -EINVAL;
17811 }
17812 if (adapter->device_mode == WLAN_HDD_INFRA_STATION ||
17813 adapter->device_mode == WLAN_HDD_P2P_CLIENT) {
17814 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
17815 if (hdd_sta_ctx->conn_info.connState !=
17816 eConnectionState_Associated) {
17817
17818 hddLog(VOS_TRACE_LEVEL_INFO,
17819 FL("failed to cap tsf, not connect with ap"));
17820 buf[0] = TSF_STA_NOT_CONNECTED_NO_TSF;
17821 return ret;
17822 }
17823 }
17824 if ((adapter->device_mode == WLAN_HDD_SOFTAP ||
17825 adapter->device_mode == WLAN_HDD_P2P_GO) &&
17826 !(test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags))) {
17827 hddLog(VOS_TRACE_LEVEL_INFO,
17828 FL("Soft AP / P2p GO not beaconing"));
17829 buf[0] = TSF_SAP_NOT_STARTED_NO_TSF;
17830 return ret;
17831 }
17832
17833 if (adapter->tsf_cap_ctx.tsf_capture_state != TSF_CAP_STATE ||
17834 adapter->tsf_cap_ctx.tsf_get_state != TSF_CURRENT_IN_CAP_STATE ) {
17835 hddLog(VOS_TRACE_LEVEL_INFO,
17836 FL("Not in capture state,Enter capture state first"));
17837 buf[0] = TSF_GET_FAIL;
17838 } else {
17839 hddLog(VOS_TRACE_LEVEL_INFO, FL("ioctl issue cap tsf cmd"));
17840 cap_tsf_params.session_id = adapter->sessionId;
17841 cap_tsf_params.tsf_rsp_cb_func = hdd_tsf_cb;
17842 cap_tsf_params.tsf_rsp_cb_ctx = adapter;
17843
17844 ret = sme_get_tsf_req(hdd_ctx->hHal, cap_tsf_params);
17845
17846 if (ret != VOS_STATUS_SUCCESS) {
17847 hddLog(VOS_TRACE_LEVEL_ERROR, FL("capture fail"));
17848 buf[0] = TSF_CAPTURE_FAIL;
17849 vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
17850 adapter->tsf_cap_ctx.tsf_capture_state = TSF_IDLE;
17851 vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
17852 return -EINVAL;
17853 }
17854 /* wait till we get a response from fw */
17855 status = vos_wait_single_event(&adapter->tsf_cap_ctx.
17856 tsf_capture_done_event,
17857 HDD_TSF_GET_REQ_TIMEOUT);
17858
17859 if (!VOS_IS_STATUS_SUCCESS(status)) {
17860 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
17861 ("capture tsf vos wait for single_event failed!! %d"),
17862 status);
17863
17864 vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
17865 adapter->tsf_cap_ctx.tsf_capture_state = TSF_IDLE;
17866 vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
17867 return status;
17868 }
17869 buf[1] = adapter->tsf_cap_ctx.tsf_low;
17870 buf[2] = adapter->tsf_cap_ctx.tsf_high;
17871
17872 hddLog(VOS_TRACE_LEVEL_INFO,
17873 FL("get tsf cmd,status=%u, tsf_low=%u, tsf_high=%u"),
17874 buf[0], buf[1], buf[2]);
17875 }
17876 hddLog(VOS_TRACE_LEVEL_INFO,
17877 FL("ioctl return cap tsf cmd, ret = %d"), ret);
17878 return ret;
17879}
17880
17881void wlan_hdd_tsf_init(hdd_adapter_t *adapter)
17882{
17883
17884 if (adapter == NULL) {
17885 hddLog(VOS_TRACE_LEVEL_ERROR,
17886 FL("TSF init on a null adapter!"));
17887 return;
17888 }
17889
17890 adapter->tsf_cap_ctx.tsf_get_state = TSF_RETURN;
17891 adapter->tsf_cap_ctx.tsf_capture_state = TSF_IDLE;
17892 vos_event_init(&adapter->tsf_cap_ctx.tsf_capture_done_event);
17893 vos_spin_lock_init(&adapter->tsf_cap_ctx.tsf_lock);
17894 adapter->tsf_cap_ctx.tsf_high = 0;
17895 adapter->tsf_cap_ctx.tsf_low = 0;
17896}
17897
17898#endif
17899
Jeff Johnson295189b2012-06-20 16:38:30 -070017900//Register the module init/exit functions
17901module_init(hdd_module_init);
17902module_exit(hdd_module_exit);
17903
17904MODULE_LICENSE("Dual BSD/GPL");
17905MODULE_AUTHOR("Qualcomm Atheros, Inc.");
17906MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
17907
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070017908module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
17909 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -070017910
Jeff Johnson76052702013-04-16 13:55:05 -070017911module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -070017912 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Arif Hussain66559122013-11-21 10:11:40 -080017913
17914module_param(enable_dfs_chan_scan, int,
17915 S_IRUSR | S_IRGRP | S_IROTH);
17916
17917module_param(enable_11d, int,
17918 S_IRUSR | S_IRGRP | S_IROTH);
17919
17920module_param(country_code, charp,
17921 S_IRUSR | S_IRGRP | S_IROTH);