blob: 9199439a99b781624a4f9f94b6081dfffbaf7dcd [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"
Jeff Johnson295189b2012-06-20 16:38:30 -0700123
124#ifdef MODULE
125#define WLAN_MODULE_NAME module_name(THIS_MODULE)
126#else
127#define WLAN_MODULE_NAME "wlan"
128#endif
129
130#ifdef TIMER_MANAGER
131#define TIMER_MANAGER_STR " +TIMER_MANAGER"
132#else
133#define TIMER_MANAGER_STR ""
134#endif
135
136#ifdef MEMORY_DEBUG
137#define MEMORY_DEBUG_STR " +MEMORY_DEBUG"
138#else
139#define MEMORY_DEBUG_STR ""
140#endif
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530141#define MAX_WAIT_FOR_ROC_COMPLETION 3
Jeff Johnson295189b2012-06-20 16:38:30 -0700142/* the Android framework expects this param even though we don't use it */
143#define BUF_LEN 20
Jeff Johnson76052702013-04-16 13:55:05 -0700144static char fwpath_buffer[BUF_LEN];
145static struct kparam_string fwpath = {
146 .string = fwpath_buffer,
147 .maxlen = BUF_LEN,
148};
Arif Hussain66559122013-11-21 10:11:40 -0800149
150static char *country_code;
151static int enable_11d = -1;
152static int enable_dfs_chan_scan = -1;
c_hpothu92367912014-05-01 15:18:17 +0530153static int gbcnMissRate = -1;
Arif Hussain66559122013-11-21 10:11:40 -0800154
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700155#ifndef MODULE
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700156static int wlan_hdd_inited;
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700157#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700158
Jeff Johnsone7245742012-09-05 17:12:55 -0700159/*
Jeff Johnson72a40512013-12-19 10:14:15 -0800160 * spinlock for synchronizing asynchronous request/response
161 * (full description of use in wlan_hdd_main.h)
162 */
163DEFINE_SPINLOCK(hdd_context_lock);
164
165/*
Jeff Johnsone7245742012-09-05 17:12:55 -0700166 * The rate at which the driver sends RESTART event to supplicant
167 * once the function 'vos_wlanRestart()' is called
168 *
169 */
170#define WLAN_HDD_RESTART_RETRY_DELAY_MS 5000 /* 5 second */
171#define WLAN_HDD_RESTART_RETRY_MAX_CNT 5 /* 5 retries */
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -0700172
173/*
174 * Size of Driver command strings from upper layer
175 */
176#define SIZE_OF_SETROAMMODE 11 /* size of SETROAMMODE */
177#define SIZE_OF_GETROAMMODE 11 /* size of GETROAMMODE */
178
Abhishek Singh00b71972016-01-07 10:51:04 +0530179#ifdef WLAN_FEATURE_RMC
180/*
181 * Ibss prop IE from command will be of size:
182 * size = sizeof(oui) + sizeof(oui_data) + 1(Element ID) + 1(EID Length)
183 * OUI_DATA should be at least 3 bytes long
184 */
185#define WLAN_HDD_IBSS_MIN_OUI_DATA_LENGTH (3)
186#endif
187
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -0800188#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda5cecb202013-10-08 09:13:25 -0700189#define TID_MIN_VALUE 0
190#define TID_MAX_VALUE 15
191static VOS_STATUS hdd_get_tsm_stats(hdd_adapter_t *pAdapter, const tANI_U8 tid,
192 tAniTrafStrmMetrics* pTsmMetrics);
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -0800193static VOS_STATUS hdd_parse_ese_beacon_req(tANI_U8 *pValue,
194 tCsrEseBeaconReq *pEseBcnReq);
195#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -0700196
Atul Mittal1d722422014-03-19 11:15:07 +0530197/*
198 * Maximum buffer size used for returning the data back to user space
199 */
200#define WLAN_MAX_BUF_SIZE 1024
201#define WLAN_PRIV_DATA_MAX_LEN 8192
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -0700202
Abhishek Singh00b71972016-01-07 10:51:04 +0530203/*
204 * When ever we need to print IBSSPEERINFOALL for morethan 16 STA
205 * we will split the printing.
206 */
207#define NUM_OF_STA_DATA_TO_PRINT 16
208
209#ifdef WLAN_FEATURE_RMC
210#define WLAN_NLINK_CESIUM 30
211#endif
212
c_hpothu92367912014-05-01 15:18:17 +0530213//wait time for beacon miss rate.
214#define BCN_MISS_RATE_TIME 500
215
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +0530216/*
217 * Android DRIVER command structures
218 */
219struct android_wifi_reassoc_params {
220 unsigned char bssid[18];
221 int channel;
222};
223
Sushant Kaushik83392fa2015-05-05 17:44:40 +0530224static vos_wake_lock_t wlan_wake_lock;
225
Jeff Johnson295189b2012-06-20 16:38:30 -0700226/* set when SSR is needed after unload */
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -0700227static e_hdd_ssr_required isSsrRequired = HDD_SSR_NOT_REQUIRED;
Jeff Johnson295189b2012-06-20 16:38:30 -0700228
229//internal function declaration
Jeff Johnsone7245742012-09-05 17:12:55 -0700230static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx);
231static void wlan_hdd_restart_init(hdd_context_t *pHddCtx);
232static void wlan_hdd_restart_deinit(hdd_context_t *pHddCtx);
Abhishek Singh00b71972016-01-07 10:51:04 +0530233
234#ifdef WLAN_FEATURE_RMC
235static void hdd_tx_fail_ind_callback(v_U8_t *MacAddr, v_U8_t seqNo);
236
237static int hdd_open_cesium_nl_sock(void);
238static void hdd_close_cesium_nl_sock(void);
239static struct sock *cesium_nl_srv_sock;
240static v_U16_t cesium_pid;
241
242static int hdd_ParseIBSSTXFailEventParams(tANI_U8 *pValue,
243 tANI_U8 *tx_fail_count,
244 tANI_U16 *pid);
245
246static int hdd_ParseUserParams(tANI_U8 *pValue, tANI_U8 **ppArg);
247
248#endif /* WLAN_FEATURE_RMC */
Jeff Johnsone7245742012-09-05 17:12:55 -0700249void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback);
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800250void hdd_set_wlan_suspend_mode(bool suspend);
Jeff Johnsone7245742012-09-05 17:12:55 -0700251
Jeff Johnson295189b2012-06-20 16:38:30 -0700252v_U16_t hdd_select_queue(struct net_device *dev,
Anand N Sunkade9adb1b2015-07-29 09:56:45 +0530253 struct sk_buff *skb
254#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0))
255 , void *accel_priv
256#endif
257#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0))
258 , select_queue_fallback_t fallback
259#endif
260);
Jeff Johnson295189b2012-06-20 16:38:30 -0700261
262#ifdef WLAN_FEATURE_PACKET_FILTERING
263static void hdd_set_multicast_list(struct net_device *dev);
264#endif
265
266void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter);
267
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -0800268#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -0800269void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand);
270static VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels);
Srinivas Girigowda100eb322013-03-15 16:48:20 -0700271static VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid,
272 tANI_U8 *pChannel, tANI_U8 *pDwellTime,
273 tANI_U8 **pBuf, tANI_U8 *pBufLen);
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +0530274static int hdd_parse_reassoc_command_v1_data(const tANI_U8 *pValue,
275 tANI_U8 *pTargetApBssid, tANI_U8 *pChannel);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800276#endif
Ratheesh S P21280412015-05-19 14:21:52 +0530277
278/* Store WLAN driver info in a global variable such that crash debugger
279 can extract it from driver debug symbol and crashdump for post processing */
280tANI_U8 g_wlan_driver[ ] = "pronto_driver";
281
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -0800282#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda5cecb202013-10-08 09:13:25 -0700283VOS_STATUS hdd_parse_get_cckm_ie(tANI_U8 *pValue, tANI_U8 **pCckmIe, tANI_U8 *pCckmIeLen);
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -0800284#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -0700285
Mihir Shetee1093ba2014-01-21 20:13:32 +0530286static VOS_STATUS wlan_hdd_init_channels(hdd_context_t *pHddCtx);
Sushant Kaushik8bc7df22014-04-09 17:55:29 +0530287const char * hdd_device_modetoString(v_U8_t device_mode)
288{
289 switch(device_mode)
290 {
291 CASE_RETURN_STRING( WLAN_HDD_INFRA_STATION );
292 CASE_RETURN_STRING( WLAN_HDD_SOFTAP );
293 CASE_RETURN_STRING( WLAN_HDD_P2P_CLIENT );
294 CASE_RETURN_STRING( WLAN_HDD_P2P_GO );
295 CASE_RETURN_STRING( WLAN_HDD_MONITOR);
296 CASE_RETURN_STRING( WLAN_HDD_FTM );
297 CASE_RETURN_STRING( WLAN_HDD_IBSS );
298 CASE_RETURN_STRING( WLAN_HDD_P2P_DEVICE );
299 default:
300 return "device_mode Unknown";
301 }
302}
Mihir Shetee1093ba2014-01-21 20:13:32 +0530303
Mukul Sharmaa78cf6b2015-02-24 16:59:01 +0530304static int __hdd_netdev_notifier_call(struct notifier_block * nb,
Jeff Johnson295189b2012-06-20 16:38:30 -0700305 unsigned long state,
306 void *ndev)
307{
308 struct net_device *dev = ndev;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700309 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson27cee452013-03-27 11:10:24 -0700310 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700311#ifdef WLAN_BTAMP_FEATURE
312 VOS_STATUS status;
Jeff Johnson295189b2012-06-20 16:38:30 -0700313#endif
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +0530314 long result;
Jeff Johnson295189b2012-06-20 16:38:30 -0700315
316 //Make sure that this callback corresponds to our device.
Jeff Johnson27cee452013-03-27 11:10:24 -0700317 if ((strncmp(dev->name, "wlan", 4)) &&
Amar Singhal4c723bd2013-03-25 18:14:15 -0700318 (strncmp(dev->name, "p2p", 3)))
319 return NOTIFY_DONE;
320
Jeff Johnson295189b2012-06-20 16:38:30 -0700321 if (!dev->ieee80211_ptr)
Jeff Johnson27cee452013-03-27 11:10:24 -0700322 return NOTIFY_DONE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700323
Jeff Johnson27cee452013-03-27 11:10:24 -0700324 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -0700325 {
Jeff Johnsona8a1a482012-12-12 16:49:33 -0800326 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Adapter Null Pointer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700327 VOS_ASSERT(0);
328 return NOTIFY_DONE;
329 }
330
Jeff Johnson27cee452013-03-27 11:10:24 -0700331 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
332 if (NULL == pHddCtx)
333 {
334 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Context Null Pointer", __func__);
335 VOS_ASSERT(0);
336 return NOTIFY_DONE;
337 }
Sameer Thalappil14067972014-01-23 14:54:54 -0800338 if (pHddCtx->isLogpInProgress)
339 return NOTIFY_DONE;
340
Jeff Johnson27cee452013-03-27 11:10:24 -0700341
342 hddLog(VOS_TRACE_LEVEL_INFO, "%s: %s New Net Device State = %lu",
343 __func__, dev->name, state);
Jeff Johnson295189b2012-06-20 16:38:30 -0700344
345 switch (state) {
346 case NETDEV_REGISTER:
347 break;
348
349 case NETDEV_UNREGISTER:
350 break;
351
352 case NETDEV_UP:
353 break;
354
355 case NETDEV_DOWN:
356 break;
357
358 case NETDEV_CHANGE:
Jeff Johnsone7245742012-09-05 17:12:55 -0700359 if(TRUE == pAdapter->isLinkUpSvcNeeded)
360 complete(&pAdapter->linkup_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700361 break;
362
363 case NETDEV_GOING_DOWN:
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +0530364 result = wlan_hdd_scan_abort(pAdapter);
Girish Gowli4bf7a632014-06-12 13:42:11 +0530365 if (result < 0)
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +0530366 {
367 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
368 "%s: Timeout occurred while waiting for abortscan %ld",
369 __func__, result);
Jeff Johnson295189b2012-06-20 16:38:30 -0700370 }
371 else
372 {
373 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +0530374 "%s: Scan Abort Successful" , __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700375 }
376#ifdef WLAN_BTAMP_FEATURE
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700377 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: disabling AMP", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700378 status = WLANBAP_StopAmp();
379 if(VOS_STATUS_SUCCESS != status )
380 {
381 pHddCtx->isAmpAllowed = VOS_TRUE;
382 hddLog(VOS_TRACE_LEVEL_FATAL,
383 "%s: Failed to stop AMP", __func__);
384 }
385 else
386 {
387 //a state m/c implementation in PAL is TBD to avoid this delay
388 msleep(500);
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700389 if ( pHddCtx->isAmpAllowed )
390 {
391 WLANBAP_DeregisterFromHCI();
392 pHddCtx->isAmpAllowed = VOS_FALSE;
393 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700394 }
395#endif //WLAN_BTAMP_FEATURE
396 break;
397
398 default:
399 break;
400 }
401
402 return NOTIFY_DONE;
403}
404
Mukul Sharmaa78cf6b2015-02-24 16:59:01 +0530405static int hdd_netdev_notifier_call(struct notifier_block * nb,
406 unsigned long state,
407 void *ndev)
408{
409 int ret;
410 vos_ssr_protect(__func__);
411 ret = __hdd_netdev_notifier_call( nb, state, ndev);
412 vos_ssr_unprotect(__func__);
413 return ret;
414}
415
Jeff Johnson295189b2012-06-20 16:38:30 -0700416struct notifier_block hdd_netdev_notifier = {
417 .notifier_call = hdd_netdev_notifier_call,
418};
419
420/*---------------------------------------------------------------------------
421 * Function definitions
422 *-------------------------------------------------------------------------*/
Jeff Johnson295189b2012-06-20 16:38:30 -0700423void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx);
424void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -0700425//variable to hold the insmod parameters
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700426static int con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -0700427#ifndef MODULE
428/* current con_mode - used only for statically linked driver
429 * con_mode is changed by userspace to indicate a mode change which will
430 * result in calling the module exit and init functions. The module
431 * exit function will clean up based on the value of con_mode prior to it
432 * being changed by userspace. So curr_con_mode records the current con_mode
433 * for exit when con_mode becomes the next mode for init
434 */
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700435static int curr_con_mode;
Jeff Johnson295189b2012-06-20 16:38:30 -0700436#endif
437
Srinivas Girigowda8bf64cb2015-09-30 19:50:09 +0530438#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
439/**
440 * hdd_init_offloaded_packets_ctx() - Initialize offload packets context
441 * @hdd_ctx: hdd global context
442 *
443 * Return: none
444 */
445static void hdd_init_offloaded_packets_ctx(hdd_context_t *hdd_ctx)
446{
447 uint8_t i;
448
449 mutex_init(&hdd_ctx->op_ctx.op_lock);
450 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++)
451 {
452 hdd_ctx->op_ctx.op_table[i].request_id = 0;
453 hdd_ctx->op_ctx.op_table[i].pattern_id = i;
454 }
455}
456#else
457static void hdd_init_offloaded_packets_ctx(hdd_context_t *hdd_ctx)
458{
459}
460#endif
461
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -0800462/**---------------------------------------------------------------------------
463
464 \brief hdd_vos_trace_enable() - Configure initial VOS Trace enable
465
466 Called immediately after the cfg.ini is read in order to configure
467 the desired trace levels.
468
469 \param - moduleId - module whose trace level is being configured
470 \param - bitmask - bitmask of log levels to be enabled
471
472 \return - void
473
474 --------------------------------------------------------------------------*/
475static void hdd_vos_trace_enable(VOS_MODULE_ID moduleId, v_U32_t bitmask)
476{
477 wpt_tracelevel level;
478
479 /* if the bitmask is the default value, then a bitmask was not
480 specified in cfg.ini, so leave the logging level alone (it
481 will remain at the "compiled in" default value) */
482 if (CFG_VOS_TRACE_ENABLE_DEFAULT == bitmask)
483 {
484 return;
485 }
486
487 /* a mask was specified. start by disabling all logging */
488 vos_trace_setValue(moduleId, VOS_TRACE_LEVEL_NONE, 0);
489
490 /* now cycle through the bitmask until all "set" bits are serviced */
491 level = VOS_TRACE_LEVEL_FATAL;
492 while (0 != bitmask)
493 {
494 if (bitmask & 1)
495 {
496 vos_trace_setValue(moduleId, level, 1);
497 }
498 level++;
499 bitmask >>= 1;
500 }
501}
502
503
Jeff Johnson295189b2012-06-20 16:38:30 -0700504/**---------------------------------------------------------------------------
505
506 \brief hdd_wdi_trace_enable() - Configure initial WDI Trace enable
507
508 Called immediately after the cfg.ini is read in order to configure
509 the desired trace levels in the WDI.
510
511 \param - moduleId - module whose trace level is being configured
512 \param - bitmask - bitmask of log levels to be enabled
513
514 \return - void
515
516 --------------------------------------------------------------------------*/
517static void hdd_wdi_trace_enable(wpt_moduleid moduleId, v_U32_t bitmask)
518{
519 wpt_tracelevel level;
520
521 /* if the bitmask is the default value, then a bitmask was not
522 specified in cfg.ini, so leave the logging level alone (it
523 will remain at the "compiled in" default value) */
524 if (CFG_WDI_TRACE_ENABLE_DEFAULT == bitmask)
525 {
526 return;
527 }
528
529 /* a mask was specified. start by disabling all logging */
530 wpalTraceSetLevel(moduleId, eWLAN_PAL_TRACE_LEVEL_NONE, 0);
531
532 /* now cycle through the bitmask until all "set" bits are serviced */
533 level = eWLAN_PAL_TRACE_LEVEL_FATAL;
534 while (0 != bitmask)
535 {
536 if (bitmask & 1)
537 {
538 wpalTraceSetLevel(moduleId, level, 1);
539 }
540 level++;
541 bitmask >>= 1;
542 }
543}
Jeff Johnson295189b2012-06-20 16:38:30 -0700544
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530545/*
546 * FUNCTION: wlan_hdd_validate_context
547 * This function is used to check the HDD context
548 */
549int wlan_hdd_validate_context(hdd_context_t *pHddCtx)
550{
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530551
552 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
553 {
Mahesh A Saptasagar886997a2015-03-04 13:15:51 +0530554 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530555 "%s: HDD context is Null", __func__);
556 return -ENODEV;
557 }
558
559 if (pHddCtx->isLogpInProgress)
560 {
Mahesh A Saptasagar886997a2015-03-04 13:15:51 +0530561 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
c_hpothu8adb97b2014-12-08 19:38:20 +0530562 "%s: LOGP %s. Ignore!!", __func__,
563 vos_is_wlan_in_badState(VOS_MODULE_ID_HDD, NULL)
564 ?"failed":"in Progress");
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530565 return -EAGAIN;
566 }
567
Mihir Shete18156292014-03-11 15:38:30 +0530568 if (WLAN_HDD_IS_LOAD_UNLOAD_IN_PROGRESS(pHddCtx))
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530569 {
Mahesh A Saptasagar886997a2015-03-04 13:15:51 +0530570 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530571 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
572 return -EAGAIN;
573 }
574 return 0;
575}
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700576#ifdef CONFIG_ENABLE_LINUX_REG
577void hdd_checkandupdate_phymode( hdd_context_t *pHddCtx)
578{
579 hdd_adapter_t *pAdapter = NULL;
580 hdd_station_ctx_t *pHddStaCtx = NULL;
581 eCsrPhyMode phyMode;
582 hdd_config_t *cfg_param = NULL;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530583
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700584 if (NULL == pHddCtx)
585 {
586 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
587 "HDD Context is null !!");
588 return ;
589 }
590
591 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
592 if (NULL == pAdapter)
593 {
594 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
595 "pAdapter is null !!");
596 return ;
597 }
598
599 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
600 if (NULL == pHddStaCtx)
601 {
602 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
603 "pHddStaCtx is null !!");
604 return ;
605 }
606
607 cfg_param = pHddCtx->cfg_ini;
608 if (NULL == cfg_param)
609 {
610 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
611 "cfg_params not available !!");
612 return ;
613 }
614
615 phyMode = sme_GetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter));
616
617 if (!pHddCtx->isVHT80Allowed)
618 {
619 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
620 (eCSR_DOT11_MODE_11ac == phyMode) ||
621 (eCSR_DOT11_MODE_11ac_ONLY == phyMode))
622 {
623 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
624 "Setting phymode to 11n!!");
625 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter), eCSR_DOT11_MODE_11n);
626 }
627 }
628 else
629 {
630 /*New country Supports 11ac as well resetting value back from .ini*/
631 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter),
632 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->dot11Mode));
633 return ;
634 }
635
636 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
637 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode) ||
638 (eCSR_CFG_DOT11_MODE_11AC == pHddStaCtx->conn_info.dot11Mode)))
639 {
640 VOS_STATUS vosStatus;
641
642 // need to issue a disconnect to CSR.
643 INIT_COMPLETION(pAdapter->disconnect_comp_var);
644 vosStatus = sme_RoamDisconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
645 pAdapter->sessionId,
646 eCSR_DISCONNECT_REASON_UNSPECIFIED );
647
648 if (VOS_STATUS_SUCCESS == vosStatus)
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530649 {
650 long ret;
651
652 ret = wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700653 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530654 if (0 >= ret)
655 hddLog(LOGE, FL("failure waiting for disconnect_comp_var %ld"),
656 ret);
657 }
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700658
659 }
660}
661#else
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530662void hdd_checkandupdate_phymode( hdd_adapter_t *pAdapter, char *country_code)
663{
664 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
665 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
666 hdd_config_t *cfg_param;
667 eCsrPhyMode phyMode;
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530668 long ret;
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530669
670 if (NULL == pHddCtx)
671 {
672 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
673 "HDD Context is null !!");
674 return ;
675 }
676
677 cfg_param = pHddCtx->cfg_ini;
678
679 if (NULL == cfg_param)
680 {
681 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
682 "cfg_params not available !!");
683 return ;
684 }
685
686 phyMode = sme_GetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter));
687
688 if (NULL != strstr(cfg_param->listOfNon11acCountryCode, country_code))
689 {
690 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
691 (eCSR_DOT11_MODE_11ac == phyMode) ||
692 (eCSR_DOT11_MODE_11ac_ONLY == phyMode))
693 {
694 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
695 "Setting phymode to 11n!!");
696 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter), eCSR_DOT11_MODE_11n);
697 }
698 }
699 else
700 {
701 /*New country Supports 11ac as well resetting value back from .ini*/
702 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter),
703 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->dot11Mode));
704 return ;
705 }
706
707 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
708 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode) ||
709 (eCSR_CFG_DOT11_MODE_11AC == pHddStaCtx->conn_info.dot11Mode)))
710 {
711 VOS_STATUS vosStatus;
712
713 // need to issue a disconnect to CSR.
714 INIT_COMPLETION(pAdapter->disconnect_comp_var);
715 vosStatus = sme_RoamDisconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
716 pAdapter->sessionId,
717 eCSR_DISCONNECT_REASON_UNSPECIFIED );
718
719 if (VOS_STATUS_SUCCESS == vosStatus)
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530720 {
721 ret = wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530722 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530723 if (ret <= 0)
724 {
725 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
726 "wait on disconnect_comp_var is failed %ld", ret);
727 }
728 }
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530729
730 }
731}
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700732#endif //CONFIG_ENABLE_LINUX_REG
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530733
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700734void hdd_checkandupdate_dfssetting( hdd_adapter_t *pAdapter, char *country_code)
735{
736 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
737 hdd_config_t *cfg_param;
738
739 if (NULL == pHddCtx)
740 {
741 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
742 "HDD Context is null !!");
743 return ;
744 }
745
746 cfg_param = pHddCtx->cfg_ini;
747
748 if (NULL == cfg_param)
749 {
750 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
751 "cfg_params not available !!");
752 return ;
753 }
754
Agarwal Ashish738843c2014-09-25 12:27:56 +0530755 if (NULL != strstr(cfg_param->listOfNonDfsCountryCode, country_code) ||
756 pHddCtx->disable_dfs_flag == TRUE)
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700757 {
758 /*New country doesn't support DFS */
759 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), 0);
760 }
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700761
762}
763
Abhishek Singh00b71972016-01-07 10:51:04 +0530764#ifdef WLAN_FEATURE_RMC
765static int hdd_parse_setrmcenable_command(tANI_U8 *pValue, tANI_U8 *pRmcEnable)
766{
767 tANI_U8 *inPtr = pValue;
768 int tempInt;
769 int v = 0;
770 char buf[32];
771 *pRmcEnable = 0;
772
773 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
774 /*no argument after the command*/
775 if (NULL == inPtr)
776 {
777 return 0;
778 }
779
780 /*no space after the command*/
781 else if (SPACE_ASCII_VALUE != *inPtr)
782 {
783 return 0;
784 }
785
786 /*removing empty spaces*/
787 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
788
789 /*no argument followed by spaces*/
790 if ('\0' == *inPtr)
791 {
792 return 0;
793 }
794
795 /* getting the first argument which enables or disables RMC
796 * for input IP v4 address*/
Ashish Kumar Dhanotiya54d31a32017-08-04 17:12:44 +0530797 sscanf(inPtr, "%31s ", buf);
Abhishek Singh00b71972016-01-07 10:51:04 +0530798 v = kstrtos32(buf, 10, &tempInt);
799 if ( v < 0)
800 {
801 return -EINVAL;
802 }
803
804 *pRmcEnable = tempInt;
805
806 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
807 "ucRmcEnable: %d", *pRmcEnable);
808
809 return 0;
810}
811
812/* Function header left blank Intentionally */
813static int hdd_parse_setrmcactionperiod_command(tANI_U8 *pValue,
814 tANI_U32 *pActionPeriod)
815{
816 tANI_U8 *inPtr = pValue;
817 int tempInt;
818 int v = 0;
819 char buf[32];
820 *pActionPeriod = 0;
821
822 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
823 /*no argument after the command*/
824 if (NULL == inPtr)
825 {
826 return -EINVAL;
827 }
828
829 /*no space after the command*/
830 else if (SPACE_ASCII_VALUE != *inPtr)
831 {
832 return -EINVAL;
833 }
834
835 /*removing empty spaces*/
836 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
837
838 /*no argument followed by spaces*/
839 if ('\0' == *inPtr)
840 {
841 return 0;
842 }
843
844 /* getting the first argument which enables or disables RMC
845 * for input IP v4 address*/
Ashish Kumar Dhanotiya54d31a32017-08-04 17:12:44 +0530846 sscanf(inPtr, "%31s ", buf);
Abhishek Singh00b71972016-01-07 10:51:04 +0530847 v = kstrtos32(buf, 10, &tempInt);
848 if ( v < 0)
849 {
850 return -EINVAL;
851 }
852
853 /* Range checking for passed paramter */
854 if (tempInt < WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY_STAMIN ||
855 tempInt > WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY_STAMAX)
856 {
857 return -EINVAL;
858 }
859
860 *pActionPeriod = tempInt;
861
862 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
863 "uActionPeriod: %d", *pActionPeriod);
864
865 return 0;
866}
867
868/* Function header left blank Intentionally */
869static int hdd_parse_setrmcrate_command(tANI_U8 *pValue,
870 tANI_U32 *pRate, tTxrateinfoflags *pTxFlags)
871{
872 tANI_U8 *inPtr = pValue;
873 int tempInt;
874 int v = 0;
875 char buf[32];
876 *pRate = 0;
877 *pTxFlags = 0;
878
879 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
880 /*no argument after the command*/
881 if (NULL == inPtr)
882 {
883 return -EINVAL;
884 }
885
886 /*no space after the command*/
887 else if (SPACE_ASCII_VALUE != *inPtr)
888 {
889 return -EINVAL;
890 }
891
892 /*removing empty spaces*/
893 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
894
895 /*no argument followed by spaces*/
896 if ('\0' == *inPtr)
897 {
898 return 0;
899 }
900
901 /*
902 * getting the first argument which sets multicast rate.
903 */
Ashish Kumar Dhanotiya06f9f202017-08-04 15:26:27 +0530904 sscanf(inPtr, "%31s ", buf);
Abhishek Singh00b71972016-01-07 10:51:04 +0530905 v = kstrtos32(buf, 10, &tempInt);
906 if ( v < 0)
907 {
908 return -EINVAL;
909 }
910
911 /*
912 * Validate the multicast rate.
913 */
914 switch (tempInt)
915 {
916 default:
917 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
918 "Unsupported rate: %d", tempInt);
919 return -EINVAL;
920 case 0:
921 case 6:
922 case 9:
923 case 12:
924 case 18:
925 case 24:
926 case 36:
927 case 48:
928 case 54:
929 *pTxFlags = eHAL_TX_RATE_LEGACY;
930 *pRate = tempInt * 10;
931 break;
932 case 65:
933 *pTxFlags = eHAL_TX_RATE_HT20;
934 *pRate = tempInt * 10;
935 break;
936 case 72:
937 *pTxFlags = eHAL_TX_RATE_HT20 | eHAL_TX_RATE_SGI;
938 *pRate = 722; /* fractional rate 72.2 Mbps */
939 break;
940 }
941
942 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
943 "Rate: %d", *pRate);
944
945 return 0;
946}
947
948/**---------------------------------------------------------------------------
949
950 \brief hdd_cfg80211_get_ibss_peer_info_cb() - Callback function for IBSS
951 Peer Info request
952
953 This is an asynchronous callback function from SME when the peer info
954 is received
955
956 \pUserData -> Adapter private data
957 \pPeerInfoRsp -> Peer info response
958
959 \return - 0 for success non-zero for failure
960 --------------------------------------------------------------------------*/
961static void
962hdd_cfg80211_get_ibss_peer_info_cb(v_VOID_t *pUserData, v_VOID_t *pPeerInfoRsp)
963{
964 hdd_adapter_t *pAdapter = (hdd_adapter_t *)pUserData;
965 tSirPeerInfoRspParams *pPeerInfo = (tSirPeerInfoRspParams *)pPeerInfoRsp;
966 hdd_station_ctx_t *pStaCtx;
967 v_U8_t i;
968
969 /*Sanity check*/
970 if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
971 {
972 hddLog(LOGE,
973 FL("invalid adapter or adapter has invalid magic"));
974 return;
975 }
976
977 pStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
978 if (NULL != pStaCtx && NULL != pPeerInfo &&
979 eHAL_STATUS_SUCCESS == pPeerInfo->status)
980 {
981 pStaCtx->ibss_peer_info.status = pPeerInfo->status;
982 pStaCtx->ibss_peer_info.numIBSSPeers = pPeerInfo->numPeers;
983
984 /* Paranoia check */
985 if (pPeerInfo->numPeers < HDD_MAX_NUM_IBSS_STA)
986 {
987 for (i = 0; i < pPeerInfo->numPeers; i++)
988 {
989 memcpy(&pStaCtx->ibss_peer_info.ibssPeerList[i],
990 &pPeerInfo->peerInfoParams[i],
991 sizeof(hdd_ibss_peer_info_params_t));
992 }
993 hddLog(LOG1,
994 FL("Peer Info copied in HDD"));
995 }
996 else
997 {
998 hddLog(LOGE,
999 FL(" Number of peers %d returned is more than limit %d"),
1000 pPeerInfo->numPeers, HDD_MAX_NUM_IBSS_STA);
1001 }
1002 }
1003 else
1004 {
1005 hddLog(LOG1,
1006 FL("peerInfo returned is NULL"));
1007 }
1008
1009 complete(&pAdapter->ibss_peer_info_comp);
1010}
1011
1012/**---------------------------------------------------------------------------
1013
1014 \brief hdd_cfg80211_get_ibss_peer_info_all() -
1015
1016 Request function to get IBSS peer info from lower layers
1017
1018 \pAdapter -> Adapter context
1019
1020 \return - 0 for success non-zero for failure
1021 --------------------------------------------------------------------------*/
1022static
1023VOS_STATUS hdd_cfg80211_get_ibss_peer_info_all(hdd_adapter_t *pAdapter)
1024{
1025 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1026 long status;
1027 VOS_STATUS retStatus = VOS_STATUS_E_FAILURE;
1028
1029 INIT_COMPLETION(pAdapter->ibss_peer_info_comp);
1030
1031 retStatus = sme_RequestIBSSPeerInfo(hHal, pAdapter,
1032 hdd_cfg80211_get_ibss_peer_info_cb,
1033 VOS_TRUE, 0xFF);
1034
1035 if (VOS_STATUS_SUCCESS == retStatus)
1036 {
1037 status = wait_for_completion_interruptible_timeout
1038 (&pAdapter->ibss_peer_info_comp,
1039 msecs_to_jiffies(IBSS_PEER_INFO_REQ_TIMOEUT));
1040
1041 /* status will be 0 if timed out */
1042 if (status <= 0)
1043 {
1044 hddLog(VOS_TRACE_LEVEL_WARN, "%s: Warning: IBSS_PEER_INFO_TIMEOUT %ld",
1045 __func__, status);
1046 retStatus = VOS_STATUS_E_FAILURE;
1047 return retStatus;
1048 }
1049 }
1050 else
1051 {
1052 hddLog(VOS_TRACE_LEVEL_WARN,
1053 "%s: Warning: sme_RequestIBSSPeerInfo Request failed", __func__);
1054 }
1055
1056 return retStatus;
1057}
1058
1059/**---------------------------------------------------------------------------
1060
1061 \brief hdd_cfg80211_get_ibss_peer_info() -
1062
1063 Request function to get IBSS peer info from lower layers
1064
1065 \pAdapter -> Adapter context
1066 \staIdx -> Sta index for which the peer info is requested
1067
1068 \return - 0 for success non-zero for failure
1069 --------------------------------------------------------------------------*/
1070static VOS_STATUS
1071hdd_cfg80211_get_ibss_peer_info(hdd_adapter_t *pAdapter, v_U8_t staIdx)
1072{
1073 long status;
1074 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1075 VOS_STATUS retStatus = VOS_STATUS_E_FAILURE;
1076
1077 INIT_COMPLETION(pAdapter->ibss_peer_info_comp);
1078
1079 retStatus = sme_RequestIBSSPeerInfo(hHal, pAdapter,
1080 hdd_cfg80211_get_ibss_peer_info_cb,
1081 VOS_FALSE, staIdx);
1082
1083 if (VOS_STATUS_SUCCESS == retStatus)
1084 {
1085 status = wait_for_completion_interruptible_timeout
1086 (&pAdapter->ibss_peer_info_comp,
1087 msecs_to_jiffies(IBSS_PEER_INFO_REQ_TIMOEUT));
1088
1089 /* status = 0 on timeout */
1090 if (status <= 0)
1091 {
1092 hddLog(VOS_TRACE_LEVEL_WARN, "%s: Warning: IBSS_PEER_INFO_TIMEOUT %ld",
1093 __func__, status);
1094 retStatus = VOS_STATUS_E_FAILURE;
1095 return retStatus;
1096 }
1097 }
1098 else
1099 {
1100 hddLog(VOS_TRACE_LEVEL_WARN,
1101 "%s: Warning: sme_RequestIBSSPeerInfo Request failed", __func__);
1102 }
1103
1104 return retStatus;
1105}
1106
1107/* Function header left blank Intentionally */
1108VOS_STATUS
1109hdd_parse_get_ibss_peer_info(tANI_U8 *pValue, v_MACADDR_t *pPeerMacAddr)
1110{
1111 tANI_U8 *inPtr = pValue;
1112 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
1113
1114 /*no argument after the command*/
1115 if (NULL == inPtr)
1116 {
1117 return VOS_STATUS_E_FAILURE;;
1118 }
1119
1120 /*no space after the command*/
1121 else if (SPACE_ASCII_VALUE != *inPtr)
1122 {
1123 return VOS_STATUS_E_FAILURE;;
1124 }
1125
1126 /*removing empty spaces*/
1127 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
1128
1129 /*no argument followed by spaces*/
1130 if ('\0' == *inPtr)
1131 {
1132 return VOS_STATUS_E_FAILURE;;
1133 }
1134
1135 /*getting the first argument ie the peer mac address */
1136 if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' ||
1137 inPtr[11] != ':' || inPtr[14] != ':')
1138 {
1139 return VOS_STATUS_E_FAILURE;;
1140 }
1141 sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x",
1142 (unsigned int *)&pPeerMacAddr->bytes[0],
1143 (unsigned int *)&pPeerMacAddr->bytes[1],
1144 (unsigned int *)&pPeerMacAddr->bytes[2],
1145 (unsigned int *)&pPeerMacAddr->bytes[3],
1146 (unsigned int *)&pPeerMacAddr->bytes[4],
1147 (unsigned int *)&pPeerMacAddr->bytes[5]);
1148
1149 /* The command buffer seems to be fine */
1150 return VOS_STATUS_SUCCESS;
1151}
1152
1153/* Function header left blank Intentionally */
1154static int hdd_parse_set_ibss_oui_data_command(tANI_U8 *command, tANI_U8 *ie,
1155 tANI_U32 limit)
1156{
1157 tANI_U8 len;
1158 tANI_U8 data;
1159
1160 /* skip white space */
1161 while ((SPACE_ASCII_VALUE == *command) && ('\0' != *command))
1162 {
1163 command++;
1164 limit--;
1165 }
1166
1167 /* skip element id and element length */
1168 len = 2;
1169
1170 /* extract oui */
1171 while ((SPACE_ASCII_VALUE != *command) && ('\0' != *command) &&
1172 (limit > 1))
1173 {
1174 /* Convert ASCII to decimal */
1175 data = ((*command -'0') << 4) | (*(command + 1) - '0');
1176 ie[len++] = data;
1177 command += 2;
1178 limit -= 2;
1179 }
1180
1181 /* skip white space */
1182 while ((SPACE_ASCII_VALUE == *command) && ('\0' != *command))
1183 {
1184 command++;
1185 limit--;
1186 }
1187
1188 /* extract data */
1189 while ((SPACE_ASCII_VALUE != *command) && ('\0' != *command) &&
1190 (limit > 1))
1191 {
1192 /* Convert ASCII to decimal */
1193 data = ((*command -'0') << 4) | (*(command + 1) - '0');
1194 ie[len++] = data;
1195 command += 2;
1196 limit -= 2;
1197 }
1198
1199 /* fill element id and element length */
1200 ie[0] = IE_EID_VENDOR;
1201 ie[1] = len - 2;
1202
1203 return len;
1204}
1205
1206static tANI_U32 hdd_find_ibss_wpa_ie_pos(tANI_U8 *addIePtr, tANI_U32 addIeLen)
1207{
1208 tANI_U32 ieLenPresent = 0;
1209 int left = addIeLen;
1210 v_U8_t *ptr = addIePtr;
1211 v_U8_t elem_id,elem_len;
1212
1213 while(left >= 2)
1214 {
1215 elem_id = ptr[0];
1216 elem_len = ptr[1];
1217 left -= 2;
1218 if(elem_len > left)
1219 {
1220 hddLog(LOGE,
1221 FL("****Invalid elem_len=%d left=%d*****"),
1222 elem_len,left);
1223 return 0;
1224 }
1225 if ((elem_id == IE_EID_VENDOR) &&
1226 (left >= WPA_OUI_TYPE_SIZE))
1227 {
1228 if (!memcmp(&ptr[2], WPA_OUI_TYPE,
1229 WPA_OUI_TYPE_SIZE))
1230 {
1231 ieLenPresent += elem_len + 2;
1232 return ieLenPresent;
1233 }
1234 }
1235 ieLenPresent += (elem_len + 2);
1236 left -= elem_len;
1237 ptr += (elem_len + 2);
1238 }
1239 return 0;
1240}
1241
1242#endif /* WLAN_FEATURE_RMC */
1243
Rajeev79dbe4c2013-10-05 11:03:42 +05301244#ifdef FEATURE_WLAN_BATCH_SCAN
1245
1246/**---------------------------------------------------------------------------
1247
1248 \brief hdd_extract_assigned_int_from_str() - Extracts assigned integer from
1249 input string
1250
1251 This function extracts assigned integer from string in below format:
1252 "STRING=10" : extracts integer 10 from this string
1253
1254 \param - pInPtr Pointer to input string
1255 \param - base Base for string to int conversion(10 for decimal 16 for hex)
1256 \param - pOutPtr Pointer to variable in which extracted integer needs to be
1257 assigned
1258 \param - pLastArg to tell whether it is last arguement in input string or
1259 not
1260
1261 \return - NULL for failure cases
1262 pointer to next arguement in input string for success cases
1263 --------------------------------------------------------------------------*/
1264static tANI_U8 *
1265hdd_extract_assigned_int_from_str
1266(
1267 tANI_U8 *pInPtr,
1268 tANI_U8 base,
1269 tANI_U32 *pOutPtr,
1270 tANI_U8 *pLastArg
1271)
1272{
1273 int tempInt;
1274 int v = 0;
1275 char buf[32];
1276 int val = 0;
1277 *pLastArg = FALSE;
1278
1279 pInPtr = strnchr(pInPtr, strlen(pInPtr), EQUALS_TO_ASCII_VALUE);
1280 if (NULL == pInPtr)
1281 {
1282 return NULL;
1283 }
1284
1285 pInPtr++;
1286
1287 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
1288
1289 val = sscanf(pInPtr, "%32s ", buf);
1290 if (val < 0 && val > strlen(pInPtr))
1291 {
1292 return NULL;
1293 }
1294 pInPtr += val;
1295 v = kstrtos32(buf, base, &tempInt);
1296 if (v < 0)
1297 {
1298 return NULL;
1299 }
Rajeev Kumar4d93d842014-01-02 18:31:21 -08001300 if (tempInt < 0)
1301 {
1302 tempInt = 0;
1303 }
Rajeev79dbe4c2013-10-05 11:03:42 +05301304 *pOutPtr = tempInt;
1305
1306 pInPtr = strnchr(pInPtr, strlen(pInPtr), SPACE_ASCII_VALUE);
1307 if (NULL == pInPtr)
1308 {
1309 *pLastArg = TRUE;
1310 return NULL;
1311 }
1312 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
1313
1314 return pInPtr;
1315}
1316
1317/**---------------------------------------------------------------------------
1318
1319 \brief hdd_extract_assigned_char_from_str() - Extracts assigned char from
1320 input string
1321
1322 This function extracts assigned character from string in below format:
1323 "STRING=A" : extracts char 'A' from this string
1324
1325 \param - pInPtr Pointer to input string
1326 \param - pOutPtr Pointer to variable in which extracted char needs to be
1327 assigned
1328 \param - pLastArg to tell whether it is last arguement in input string or
1329 not
1330
1331 \return - NULL for failure cases
1332 pointer to next arguement in input string for success cases
1333 --------------------------------------------------------------------------*/
1334static tANI_U8 *
1335hdd_extract_assigned_char_from_str
1336(
1337 tANI_U8 *pInPtr,
1338 tANI_U8 *pOutPtr,
1339 tANI_U8 *pLastArg
1340)
1341{
1342 *pLastArg = FALSE;
1343
1344 pInPtr = strnchr(pInPtr, strlen(pInPtr), EQUALS_TO_ASCII_VALUE);
1345 if (NULL == pInPtr)
1346 {
1347 return NULL;
1348 }
1349
1350 pInPtr++;
1351
1352 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
1353
1354 *pOutPtr = *pInPtr;
1355
1356 pInPtr = strnchr(pInPtr, strlen(pInPtr), SPACE_ASCII_VALUE);
1357 if (NULL == pInPtr)
1358 {
1359 *pLastArg = TRUE;
1360 return NULL;
1361 }
1362 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
1363
1364 return pInPtr;
1365}
1366
1367
1368/**---------------------------------------------------------------------------
1369
1370 \brief hdd_parse_set_batchscan_command () - HDD parse set batch scan command
1371
1372 This function parses set batch scan command in below format:
1373 WLS_BATCHING_SET <space> followed by below arguements
1374 "SCANFREQ=XX" : Optional defaults to 30 sec
1375 "MSCAN=XX" : Required number of scans to attempt to batch
1376 "BESTN=XX" : Best Network (RSSI) defaults to 16
1377 "CHANNEL=<X,Y>" : optional defaults to all channels, can list 'A'or` B.
1378 A. implies only 5 GHz , B. implies only 2.4GHz
1379 "RTT=X" : optional defaults to 0
1380 returns the MIN of MSCAN or the max # of scans firmware can cache or -1 on
1381 error
1382
1383 For example input commands:
1384 1) WLS_BATCHING_SET SCANFREQ=60 MSCAN=10 BESTN=20 CHANNEL=A RTT=0 -> This is
1385 translated into set batch scan with following parameters:
1386 a) Frequence 60 seconds
1387 b) Batch 10 scans together
1388 c) Best RSSI to be 20
1389 d) 5GHz band only
1390 e) RTT is equal to 0
1391
1392 \param - pValue Pointer to input channel list
1393 \param - pHddSetBatchScanReq Pointer to HDD batch scan request structure
1394
1395 \return - 0 for success non-zero for failure
1396
1397 --------------------------------------------------------------------------*/
1398static int
1399hdd_parse_set_batchscan_command
1400(
1401 tANI_U8 *pValue,
1402 tSirSetBatchScanReq *pHddSetBatchScanReq
1403)
1404{
1405 tANI_U8 *inPtr = pValue;
1406 tANI_U8 val = 0;
1407 tANI_U8 lastArg = 0;
Abhishek Singh00b71972016-01-07 10:51:04 +05301408 tANI_U32 nScanFreq = HDD_SET_BATCH_SCAN_DEFAULT_FREQ;
Rajeev Kumar45e64a72013-11-18 19:48:15 -08001409 tANI_U32 nMscan;
Abhishek Singh00b71972016-01-07 10:51:04 +05301410 tANI_U32 nBestN = HDD_SET_BATCH_SCAN_BEST_NETWORK;
1411 tANI_U8 ucRfBand = HDD_SET_BATCH_SCAN_DEFAULT_BAND;
1412 tANI_U32 nRtt = 0;
Rajeev Kumarc933d982013-11-18 20:04:20 -08001413 tANI_U32 temp;
Rajeev79dbe4c2013-10-05 11:03:42 +05301414
Rajeev79dbe4c2013-10-05 11:03:42 +05301415 /*go to space after WLS_BATCHING_SET command*/
1416 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
1417 /*no argument after the command*/
1418 if (NULL == inPtr)
1419 {
1420 return -EINVAL;
1421 }
1422
1423 /*no space after the command*/
1424 else if (SPACE_ASCII_VALUE != *inPtr)
1425 {
1426 return -EINVAL;
1427 }
1428
1429 /*removing empty spaces*/
1430 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
1431
1432 /*no argument followed by spaces*/
1433 if ('\0' == *inPtr)
1434 {
1435 return -EINVAL;
1436 }
1437
1438 /*check and parse SCANFREQ*/
1439 if ((strncmp(inPtr, "SCANFREQ", 8) == 0))
1440 {
1441 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumarc933d982013-11-18 20:04:20 -08001442 &temp, &lastArg);
Rajeev Kumar45e64a72013-11-18 19:48:15 -08001443
Rajeev Kumarc933d982013-11-18 20:04:20 -08001444 if (0 != temp)
Rajeev Kumar45e64a72013-11-18 19:48:15 -08001445 {
Rajeev Kumarc933d982013-11-18 20:04:20 -08001446 nScanFreq = temp;
Rajeev Kumar45e64a72013-11-18 19:48:15 -08001447 }
1448
Rajeev79dbe4c2013-10-05 11:03:42 +05301449 if ( (NULL == inPtr) || (TRUE == lastArg))
1450 {
1451 return -EINVAL;
1452 }
1453 }
1454
1455 /*check and parse MSCAN*/
1456 if ((strncmp(inPtr, "MSCAN", 5) == 0))
1457 {
1458 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumar45e64a72013-11-18 19:48:15 -08001459 &nMscan, &lastArg);
1460
1461 if (0 == nMscan)
1462 {
1463 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1464 "invalid MSCAN=%d", nMscan);
1465 return -EINVAL;
1466 }
1467
Rajeev79dbe4c2013-10-05 11:03:42 +05301468 if (TRUE == lastArg)
1469 {
1470 goto done;
1471 }
1472 else if (NULL == inPtr)
1473 {
1474 return -EINVAL;
1475 }
1476 }
1477 else
1478 {
1479 return -EINVAL;
1480 }
1481
1482 /*check and parse BESTN*/
1483 if ((strncmp(inPtr, "BESTN", 5) == 0))
1484 {
1485 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumarc933d982013-11-18 20:04:20 -08001486 &temp, &lastArg);
Rajeev Kumar45e64a72013-11-18 19:48:15 -08001487
Rajeev Kumarc933d982013-11-18 20:04:20 -08001488 if (0 != temp)
Rajeev Kumar45e64a72013-11-18 19:48:15 -08001489 {
Rajeev Kumarc933d982013-11-18 20:04:20 -08001490 nBestN = temp;
Rajeev Kumar45e64a72013-11-18 19:48:15 -08001491 }
1492
Rajeev79dbe4c2013-10-05 11:03:42 +05301493 if (TRUE == lastArg)
1494 {
1495 goto done;
1496 }
1497 else if (NULL == inPtr)
1498 {
1499 return -EINVAL;
1500 }
1501 }
1502
1503 /*check and parse CHANNEL*/
1504 if ((strncmp(inPtr, "CHANNEL", 7) == 0))
1505 {
1506 inPtr = hdd_extract_assigned_char_from_str(inPtr, &val, &lastArg);
Rajeev Kumarc933d982013-11-18 20:04:20 -08001507
Rajeev79dbe4c2013-10-05 11:03:42 +05301508 if (('A' == val) || ('a' == val))
1509 {
c_hpothuebf89732014-02-25 13:00:24 +05301510 ucRfBand = HDD_SET_BATCH_SCAN_5GHz_BAND_ONLY;
Rajeev79dbe4c2013-10-05 11:03:42 +05301511 }
1512 else if (('B' == val) || ('b' == val))
1513 {
c_hpothuebf89732014-02-25 13:00:24 +05301514 ucRfBand = HDD_SET_BATCH_SCAN_24GHz_BAND_ONLY;
Rajeev79dbe4c2013-10-05 11:03:42 +05301515 }
1516 else
1517 {
Rajeev Kumarc933d982013-11-18 20:04:20 -08001518 ucRfBand = HDD_SET_BATCH_SCAN_DEFAULT_BAND;
1519 }
1520
1521 if (TRUE == lastArg)
1522 {
1523 goto done;
1524 }
1525 else if (NULL == inPtr)
1526 {
Rajeev79dbe4c2013-10-05 11:03:42 +05301527 return -EINVAL;
1528 }
1529 }
1530
1531 /*check and parse RTT*/
1532 if ((strncmp(inPtr, "RTT", 3) == 0))
1533 {
1534 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumar45e64a72013-11-18 19:48:15 -08001535 &nRtt, &lastArg);
Rajeev79dbe4c2013-10-05 11:03:42 +05301536 if (TRUE == lastArg)
1537 {
1538 goto done;
1539 }
1540 if (NULL == inPtr)
1541 {
1542 return -EINVAL;
1543 }
1544 }
1545
1546
1547done:
1548
Rajeev Kumar45e64a72013-11-18 19:48:15 -08001549 pHddSetBatchScanReq->scanFrequency = nScanFreq;
1550 pHddSetBatchScanReq->numberOfScansToBatch = nMscan;
1551 pHddSetBatchScanReq->bestNetwork = nBestN;
1552 pHddSetBatchScanReq->rfBand = ucRfBand;
1553 pHddSetBatchScanReq->rtt = nRtt;
1554
Rajeev79dbe4c2013-10-05 11:03:42 +05301555 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1556 "Received WLS_BATCHING_SET with SCANFREQ=%d "
1557 "MSCAN=%d BESTN=%d CHANNEL=%d RTT=%d",
1558 pHddSetBatchScanReq->scanFrequency,
1559 pHddSetBatchScanReq->numberOfScansToBatch,
1560 pHddSetBatchScanReq->bestNetwork,
1561 pHddSetBatchScanReq->rfBand,
1562 pHddSetBatchScanReq->rtt);
1563
1564 return 0;
1565}/*End of hdd_parse_set_batchscan_command*/
1566
1567/**---------------------------------------------------------------------------
1568
1569 \brief hdd_set_batch_scan_req_callback () - This function is called after
1570 receiving set batch scan response from FW and it saves set batch scan
1571 response data FW to HDD context and sets the completion event on
1572 which hdd_ioctl is waiting
1573
1574 \param - callbackContext Pointer to HDD adapter
1575 \param - pRsp Pointer to set batch scan response data received from FW
1576
1577 \return - nothing
1578
1579 --------------------------------------------------------------------------*/
1580static void hdd_set_batch_scan_req_callback
1581(
1582 void *callbackContext,
1583 tSirSetBatchScanRsp *pRsp
1584)
1585{
1586 hdd_adapter_t* pAdapter = (hdd_adapter_t*)callbackContext;
1587 tSirSetBatchScanRsp *pHddSetBatchScanRsp;
1588
1589 /*sanity check*/
1590 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
1591 {
1592 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1593 "%s: Invalid pAdapter magic", __func__);
1594 VOS_ASSERT(0);
1595 return;
1596 }
1597 pHddSetBatchScanRsp = &pAdapter->hddSetBatchScanRsp;
1598
1599 /*save set batch scan response*/
1600 pHddSetBatchScanRsp->nScansToBatch = pRsp->nScansToBatch;
1601
1602 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1603 "Received set batch scan rsp from FW with nScansToBatch=%d",
1604 pHddSetBatchScanRsp->nScansToBatch);
1605
1606 pAdapter->hdd_wait_for_set_batch_scan_rsp = FALSE;
1607 complete(&pAdapter->hdd_set_batch_scan_req_var);
1608
1609 return;
1610}/*End of hdd_set_batch_scan_req_callback*/
1611
1612
1613/**---------------------------------------------------------------------------
1614
1615 \brief hdd_populate_batch_scan_rsp_queue () - This function stores AP meta
1616 info in hdd batch scan response queue
1617
1618 \param - pAdapter Pointer to hdd adapter
1619 \param - pAPMetaInfo Pointer to access point meta info
1620 \param - scanId scan ID of batch scan response
1621 \param - isLastAp tells whether AP is last AP in batch scan response or not
1622
1623 \return - nothing
1624
1625 --------------------------------------------------------------------------*/
1626static void hdd_populate_batch_scan_rsp_queue( hdd_adapter_t* pAdapter,
1627 tpSirBatchScanNetworkInfo pApMetaInfo, tANI_U32 scanId, v_BOOL_t isLastAp)
1628{
1629 tHddBatchScanRsp *pHead;
1630 tHddBatchScanRsp *pNode;
1631 tHddBatchScanRsp *pPrev;
1632 tHddBatchScanRsp *pTemp;
1633 tANI_U8 ssidLen;
1634
1635 /*head of hdd batch scan response queue*/
1636 pHead = pAdapter->pBatchScanRsp;
1637
1638 pNode = (tHddBatchScanRsp *)vos_mem_malloc(sizeof(tHddBatchScanRsp));
1639 if (NULL == pNode)
1640 {
1641 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1642 "%s: Could not allocate memory", __func__);
1643 VOS_ASSERT(0);
1644 return;
1645 }
1646
1647 vos_mem_copy(pNode->ApInfo.bssid, pApMetaInfo->bssid,
1648 sizeof(pNode->ApInfo.bssid));
1649 ssidLen = strlen(pApMetaInfo->ssid);
1650 if (SIR_MAX_SSID_SIZE < ssidLen)
1651 {
1652 /*invalid scan result*/
1653 vos_mem_free(pNode);
1654 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1655 "%s: Invalid AP meta info ssidlen %d", __func__, ssidLen);
1656 return;
1657 }
1658 vos_mem_copy(pNode->ApInfo.ssid, pApMetaInfo->ssid, ssidLen);
1659 /*null terminate ssid*/
1660 pNode->ApInfo.ssid[ssidLen] = '\0';
1661 pNode->ApInfo.ch = pApMetaInfo->ch;
1662 pNode->ApInfo.rssi = pApMetaInfo->rssi;
1663 pNode->ApInfo.age = pApMetaInfo->timestamp;
1664 pNode->ApInfo.batchId = scanId;
1665 pNode->ApInfo.isLastAp = isLastAp;
1666
1667 pNode->pNext = NULL;
1668 if (NULL == pHead)
1669 {
1670 pAdapter->pBatchScanRsp = pNode;
1671 }
1672 else
1673 {
1674 pTemp = pHead;
1675 while (NULL != pTemp)
1676 {
1677 pPrev = pTemp;
1678 pTemp = pTemp->pNext;
1679 }
1680 pPrev->pNext = pNode;
1681 }
1682
1683 return;
1684}/*End of hdd_populate_batch_scan_rsp_queue*/
1685
1686/**---------------------------------------------------------------------------
1687
1688 \brief hdd_batch_scan_result_ind_callback () - This function is called after
1689 receiving batch scan response indication from FW. It saves get batch scan
1690 response data in HDD batch scan response queue. This callback sets the
1691 completion event on which hdd_ioctl is waiting only after getting complete
1692 batch scan response data from FW
1693
1694 \param - callbackContext Pointer to HDD adapter
1695 \param - pRsp Pointer to get batch scan response data received from FW
1696
1697 \return - nothing
1698
1699 --------------------------------------------------------------------------*/
1700static void hdd_batch_scan_result_ind_callback
1701(
1702 void *callbackContext,
1703 void *pRsp
1704)
1705{
1706 v_BOOL_t isLastAp;
1707 tANI_U32 numApMetaInfo;
Rajeev Kumarce651e42013-10-21 18:57:15 -07001708 tANI_U32 numNetworkInScanList;
Rajeev79dbe4c2013-10-05 11:03:42 +05301709 tANI_U32 numberScanList;
1710 tANI_U32 nextScanListOffset;
1711 tANI_U32 nextApMetaInfoOffset;
1712 hdd_adapter_t* pAdapter;
1713 tpSirBatchScanList pScanList;
1714 tpSirBatchScanNetworkInfo pApMetaInfo;
1715 tpSirBatchScanResultIndParam pBatchScanRsp;/*batch scan rsp data from FW*/
1716 tSirSetBatchScanReq *pReq;
1717
1718 pAdapter = (hdd_adapter_t *)callbackContext;
1719 /*sanity check*/
Rajeev Kumar5286bb92013-12-05 11:52:10 -08001720 if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
Rajeev79dbe4c2013-10-05 11:03:42 +05301721 {
1722 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1723 "%s: Invalid pAdapter magic", __func__);
1724 VOS_ASSERT(0);
1725 return;
1726 }
1727
1728 /*initialize locals*/
1729 pReq = &pAdapter->hddSetBatchScanReq;
1730 pBatchScanRsp = (tpSirBatchScanResultIndParam)pRsp;
1731 isLastAp = FALSE;
1732 numApMetaInfo = 0;
Rajeev Kumarce651e42013-10-21 18:57:15 -07001733 numNetworkInScanList = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05301734 numberScanList = 0;
1735 nextScanListOffset = 0;
1736 nextApMetaInfoOffset = 0;
1737 pScanList = NULL;
1738 pApMetaInfo = NULL;
1739
1740 if ((NULL == pBatchScanRsp) || (NULL == pReq))
1741 {
1742 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnsonc135a9a2017-09-19 08:37:24 -07001743 "%s: pBatchScanRsp is %pK pReq %pK", __func__, pBatchScanRsp, pReq);
Rajeev79dbe4c2013-10-05 11:03:42 +05301744 isLastAp = TRUE;
1745 goto done;
1746 }
1747
1748 pAdapter->numScanList = numberScanList = pBatchScanRsp->numScanLists;
1749 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1750 "Batch scan rsp: numberScalList %d", numberScanList);
1751
1752 if ((!numberScanList) || (numberScanList > pReq->numberOfScansToBatch))
1753 {
1754 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1755 "%s: numberScanList %d", __func__, numberScanList);
1756 isLastAp = TRUE;
1757 goto done;
1758 }
1759
1760 while (numberScanList)
1761 {
Rajeev Kumarce651e42013-10-21 18:57:15 -07001762 pScanList = (tpSirBatchScanList)((tANI_U8 *)pBatchScanRsp->scanResults +
Rajeev79dbe4c2013-10-05 11:03:42 +05301763 nextScanListOffset);
1764 if (NULL == pScanList)
1765 {
1766 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnsonc135a9a2017-09-19 08:37:24 -07001767 "%s: pScanList is %pK", __func__, pScanList);
Rajeev79dbe4c2013-10-05 11:03:42 +05301768 isLastAp = TRUE;
1769 goto done;
1770 }
Rajeev Kumarce651e42013-10-21 18:57:15 -07001771 numNetworkInScanList = numApMetaInfo = pScanList->numNetworksInScanList;
Rajeev79dbe4c2013-10-05 11:03:42 +05301772 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumarce651e42013-10-21 18:57:15 -07001773 "Batch scan rsp: numApMetaInfo %d scanId %d",
1774 numApMetaInfo, pScanList->scanId);
Rajeev79dbe4c2013-10-05 11:03:42 +05301775
1776 if ((!numApMetaInfo) || (numApMetaInfo > pReq->bestNetwork))
1777 {
1778 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1779 "%s: numApMetaInfo %d", __func__, numApMetaInfo);
1780 isLastAp = TRUE;
1781 goto done;
1782 }
1783
Rajeev Kumarce651e42013-10-21 18:57:15 -07001784 /*Initialize next AP meta info offset for next scan list*/
1785 nextApMetaInfoOffset = 0;
1786
Rajeev79dbe4c2013-10-05 11:03:42 +05301787 while (numApMetaInfo)
1788 {
1789 pApMetaInfo = (tpSirBatchScanNetworkInfo)(pScanList->scanList +
1790 nextApMetaInfoOffset);
1791 if (NULL == pApMetaInfo)
1792 {
1793 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnsonc135a9a2017-09-19 08:37:24 -07001794 "%s: pApMetaInfo is %pK", __func__, pApMetaInfo);
Rajeev79dbe4c2013-10-05 11:03:42 +05301795 isLastAp = TRUE;
1796 goto done;
1797 }
1798 /*calculate AP age*/
1799 pApMetaInfo->timestamp =
1800 pBatchScanRsp->timestamp - pApMetaInfo->timestamp;
1801
1802 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
Arif Hussaina7c8e412013-11-20 11:06:42 -08001803 "%s: bssId "MAC_ADDRESS_STR
1804 " ch %d rssi %d timestamp %d", __func__,
1805 MAC_ADDR_ARRAY(pApMetaInfo->bssid),
1806 pApMetaInfo->ch, pApMetaInfo->rssi,
1807 pApMetaInfo->timestamp);
Rajeev79dbe4c2013-10-05 11:03:42 +05301808
1809 /*mark last AP in batch scan response*/
1810 if ((TRUE == pBatchScanRsp->isLastResult) &&
1811 (1 == numberScanList) && (1 == numApMetaInfo))
1812 {
1813 isLastAp = TRUE;
1814 }
1815
1816 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1817 /*store batch scan repsonse in hdd queue*/
1818 hdd_populate_batch_scan_rsp_queue(pAdapter, pApMetaInfo,
1819 pScanList->scanId, isLastAp);
1820 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1821
1822 nextApMetaInfoOffset += sizeof(tSirBatchScanNetworkInfo);
1823 numApMetaInfo--;
1824 }
1825
Rajeev Kumarce651e42013-10-21 18:57:15 -07001826 nextScanListOffset += ((sizeof(tSirBatchScanList) - sizeof(tANI_U8))
1827 + (sizeof(tSirBatchScanNetworkInfo)
1828 * numNetworkInScanList));
Rajeev79dbe4c2013-10-05 11:03:42 +05301829 numberScanList--;
1830 }
1831
1832done:
1833
1834 /*notify hdd_ioctl only if complete batch scan rsp is received and it was
1835 requested from hdd_ioctl*/
1836 if ((TRUE == pAdapter->hdd_wait_for_get_batch_scan_rsp) &&
1837 (TRUE == isLastAp))
1838 {
1839 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
1840 complete(&pAdapter->hdd_get_batch_scan_req_var);
1841 }
1842
1843 return;
1844}/*End of hdd_batch_scan_result_ind_callback*/
1845
1846/**---------------------------------------------------------------------------
1847
1848 \brief hdd_format_batch_scan_rsp () - This function formats batch scan
1849 response as per batch scan FR request format by putting proper markers
1850
1851 \param - pDest pointer to destination buffer
1852 \param - cur_len current length
1853 \param - tot_len total remaining size which can be written to user space
1854 \param - pApMetaInfo Pointer to get batch scan response AP meta info
1855 \param - pAdapter Pointer to HDD adapter
1856
1857 \return - ret no of characters written
1858
1859 --------------------------------------------------------------------------*/
1860static tANI_U32
1861hdd_format_batch_scan_rsp
1862(
1863 tANI_U8 *pDest,
1864 tANI_U32 cur_len,
1865 tANI_U32 tot_len,
1866 tHddBatchScanRsp *pApMetaInfo,
1867 hdd_adapter_t* pAdapter
1868)
1869{
1870 tANI_U32 ret = 0;
1871 tANI_U32 rem_len = 0;
1872 tANI_U8 temp_len = 0;
1873 tANI_U8 temp_total_len = 0;
1874 tANI_U8 temp[HDD_BATCH_SCAN_AP_META_INFO_SIZE];
1875 tANI_U8 *pTemp = temp;
1876
1877 /*Batch scan reponse needs to be returned to user space in
1878 following format:
1879 "scancount=X\n" where X is the number of scans in current batch
1880 batch
1881 "trunc\n" optional present if current scan truncated
1882 "bssid=XX:XX:XX:XX:XX:XX\n"
1883 "ssid=XXXX\n"
1884 "freq=X\n" frequency in Mhz
1885 "level=XX\n"
1886 "age=X\n" ms
1887 "dist=X\n" cm (-1 if not available)
1888 "errror=X\n" (-1if not available)
1889 "====\n" (end of ap marker)
1890 "####\n" (end of scan marker)
1891 "----\n" (end of results)*/
1892 /*send scan result in above format to user space based on
1893 available length*/
1894 /*The GET response may have more data than the driver can return in its
1895 buffer. In that case the buffer should be filled to the nearest complete
1896 scan, ending with "%%%%".Subsequent callsshould return the remaining data
1897 starting with the next scan (optional .trunc\n., .apcount=X\n., etc).
1898 The final buffer should end with "----\n"*/
1899
1900 /*sanity*/
1901 if (cur_len > tot_len)
1902 {
1903 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1904 "%s: invaid cur_len %d tot_len %d", __func__, cur_len, tot_len);
1905 return 0;
1906 }
1907 else
1908 {
1909 rem_len = (tot_len - cur_len);
1910 }
1911
1912 /*end scan marker*/
1913 if (pApMetaInfo->ApInfo.batchId != pAdapter->prev_batch_id)
1914 {
1915 temp_len = snprintf(pTemp, sizeof(temp), "####\n");
1916 pTemp += temp_len;
1917 temp_total_len += temp_len;
1918 }
1919
1920 /*bssid*/
1921 temp_len = snprintf(pTemp, sizeof(temp),
1922 "bssid=0x%x:0x%x:0x%x:0x%x:0x%x:0x%x\n",
1923 pApMetaInfo->ApInfo.bssid[0], pApMetaInfo->ApInfo.bssid[1],
1924 pApMetaInfo->ApInfo.bssid[2], pApMetaInfo->ApInfo.bssid[3],
1925 pApMetaInfo->ApInfo.bssid[4], pApMetaInfo->ApInfo.bssid[5]);
1926 pTemp += temp_len;
1927 temp_total_len += temp_len;
1928
1929 /*ssid*/
1930 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "ssid=%s\n",
1931 pApMetaInfo->ApInfo.ssid);
1932 pTemp += temp_len;
1933 temp_total_len += temp_len;
1934
1935 /*freq*/
1936 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "freq=%d\n",
Rajeev Kumarc40f7512013-11-04 14:13:23 -08001937 sme_ChnToFreq(pApMetaInfo->ApInfo.ch));
Rajeev79dbe4c2013-10-05 11:03:42 +05301938 pTemp += temp_len;
1939 temp_total_len += temp_len;
1940
1941 /*level*/
1942 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "level=%d\n",
1943 pApMetaInfo->ApInfo.rssi);
1944 pTemp += temp_len;
1945 temp_total_len += temp_len;
1946
1947 /*age*/
Jeff Johnson02797792013-10-26 19:17:13 -07001948 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "age=%d\n",
Rajeev79dbe4c2013-10-05 11:03:42 +05301949 pApMetaInfo->ApInfo.age);
1950 pTemp += temp_len;
1951 temp_total_len += temp_len;
1952
1953 /*dist*/
1954 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "dist=-1\n");
1955 pTemp += temp_len;
1956 temp_total_len += temp_len;
1957
1958 /*error*/
1959 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "error=-1\n");
1960 pTemp += temp_len;
1961 temp_total_len += temp_len;
1962
1963 /*end AP marker*/
1964 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "====\n");
1965 pTemp += temp_len;
1966 temp_total_len += temp_len;
1967
1968 /*last AP in batch scan response*/
1969 if(TRUE == pApMetaInfo->ApInfo.isLastAp)
1970 {
1971 /*end scan marker*/
1972 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "####\n");
1973 pTemp += temp_len;
1974 temp_total_len += temp_len;
1975
1976 /*end batch scan result marker*/
1977 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "----\n");
1978 pTemp += temp_len;
1979 temp_total_len += temp_len;
Kiet Lamaa8e15a2014-02-11 23:30:06 -08001980
Rajeev79dbe4c2013-10-05 11:03:42 +05301981 }
1982
1983 if (temp_total_len < rem_len)
1984 {
1985 ret = temp_total_len + 1;
1986 strlcpy(pDest, temp, ret);
1987 pAdapter->isTruncated = FALSE;
1988 }
1989 else
1990 {
1991 pAdapter->isTruncated = TRUE;
1992 if (rem_len >= strlen("%%%%"))
1993 {
Rajeev Kumarc933d982013-11-18 20:04:20 -08001994 ret = snprintf(pDest, sizeof(temp), "%%%%");
Rajeev79dbe4c2013-10-05 11:03:42 +05301995 }
Rajeev Kumarc933d982013-11-18 20:04:20 -08001996 else
Rajeev79dbe4c2013-10-05 11:03:42 +05301997 {
1998 ret = 0;
1999 }
2000 }
2001
2002 return ret;
2003
2004}/*End of hdd_format_batch_scan_rsp*/
2005
2006/**---------------------------------------------------------------------------
2007
2008 \brief hdd_populate_user_batch_scan_rsp() - This function populates user data
2009 buffer starting with head of hdd batch scan response queue
2010
2011 \param - pAdapter Pointer to HDD adapter
2012 \param - pDest Pointer to user data buffer
2013 \param - cur_len current offset in user buffer
2014 \param - rem_len remaining no of bytes in user buffer
2015
2016 \return - number of bytes written in user buffer
2017
2018 --------------------------------------------------------------------------*/
2019
2020tANI_U32 hdd_populate_user_batch_scan_rsp
2021(
2022 hdd_adapter_t* pAdapter,
2023 tANI_U8 *pDest,
2024 tANI_U32 cur_len,
2025 tANI_U32 rem_len
2026)
2027{
2028 tHddBatchScanRsp *pHead;
2029 tHddBatchScanRsp *pPrev;
2030 tANI_U32 len;
2031
Rajeev79dbe4c2013-10-05 11:03:42 +05302032 pAdapter->isTruncated = FALSE;
2033
2034 /*head of hdd batch scan response queue*/
2035 pHead = pAdapter->pBatchScanRsp;
2036 while (pHead)
2037 {
2038 len = hdd_format_batch_scan_rsp(pDest, cur_len, rem_len, pHead,
2039 pAdapter);
2040 pDest += len;
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07002041 pDest--;
Rajeev79dbe4c2013-10-05 11:03:42 +05302042 cur_len += len;
2043 if(TRUE == pAdapter->isTruncated)
2044 {
2045 /*result is truncated return rest of scan rsp in next req*/
2046 cur_len = rem_len;
2047 break;
2048 }
2049 pPrev = pHead;
2050 pHead = pHead->pNext;
2051 pAdapter->pBatchScanRsp = pHead;
Rajeev Kumarbe17d8b2014-01-10 15:39:45 -08002052 if (TRUE == pPrev->ApInfo.isLastAp)
2053 {
2054 pAdapter->prev_batch_id = 0;
2055 }
2056 else
2057 {
2058 pAdapter->prev_batch_id = pPrev->ApInfo.batchId;
2059 }
Rajeev79dbe4c2013-10-05 11:03:42 +05302060 vos_mem_free(pPrev);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002061 pPrev = NULL;
Rajeev79dbe4c2013-10-05 11:03:42 +05302062 }
2063
2064 return cur_len;
2065}/*End of hdd_populate_user_batch_scan_rsp*/
2066
2067/**---------------------------------------------------------------------------
2068
2069 \brief hdd_return_batch_scan_rsp_to_user () - This function returns batch
2070 scan response data from HDD queue to user space
2071 It does following in detail:
2072 a) if HDD has enough data in its queue then it 1st copies data to user
2073 space and then send get batch scan indication message to FW. In this
2074 case it does not wait on any event and batch scan response data will
2075 be populated in HDD response queue in MC thread context after receiving
2076 indication from FW
2077 b) else send get batch scan indication message to FW and wait on an event
2078 which will be set once HDD receives complete batch scan response from
2079 FW and then this function returns batch scan response to user space
2080
2081 \param - pAdapter Pointer to HDD adapter
2082 \param - pPrivData Pointer to priv_data
2083
2084 \return - 0 for success -EFAULT for failure
2085
2086 --------------------------------------------------------------------------*/
2087
2088int hdd_return_batch_scan_rsp_to_user
2089(
2090 hdd_adapter_t* pAdapter,
2091 hdd_priv_data_t *pPrivData,
2092 tANI_U8 *command
2093)
2094{
2095 tANI_U8 *pDest;
2096 tANI_U32 count = 0;
2097 tANI_U32 len = 0;
2098 tANI_U32 cur_len = 0;
2099 tANI_U32 rem_len = 0;
2100 eHalStatus halStatus;
2101 unsigned long rc;
2102 tSirTriggerBatchScanResultInd *pReq;
2103
2104 pReq = &pAdapter->hddTriggerBatchScanResultInd;
2105 pReq->param = 0;/*batch scan client*/
2106 pDest = (tANI_U8 *)(command + pPrivData->used_len);
2107 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
2108
2109 cur_len = pPrivData->used_len;
2110 if (pPrivData->total_len > pPrivData->used_len)
2111 {
2112 rem_len = pPrivData->total_len - pPrivData->used_len;
2113 }
2114 else
2115 {
2116 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2117 "%s: Invalid user data buffer total_len %d used_len %d",
2118 __func__, pPrivData->total_len, pPrivData->used_len);
2119 return -EFAULT;
2120 }
2121
2122 mutex_lock(&pAdapter->hdd_batch_scan_lock);
2123 len = hdd_populate_user_batch_scan_rsp(pAdapter, pDest,
2124 cur_len, rem_len);
2125 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
2126
2127 /*enough scan result available in cache to return to user space or
2128 scan result needs to be fetched 1st from fw and then return*/
Rajeev Kumar99db6262013-11-11 15:23:36 -08002129 if (len == cur_len)
Rajeev79dbe4c2013-10-05 11:03:42 +05302130 {
2131 pAdapter->hdd_wait_for_get_batch_scan_rsp = TRUE;
2132 halStatus = sme_TriggerBatchScanResultInd(
2133 WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
2134 pAdapter->sessionId, hdd_batch_scan_result_ind_callback,
2135 pAdapter);
2136 if ( eHAL_STATUS_SUCCESS == halStatus )
2137 {
2138 if (TRUE == pAdapter->hdd_wait_for_get_batch_scan_rsp)
2139 {
2140 INIT_COMPLETION(pAdapter->hdd_get_batch_scan_req_var);
2141 rc = wait_for_completion_timeout(
2142 &pAdapter->hdd_get_batch_scan_req_var,
2143 msecs_to_jiffies(HDD_GET_BATCH_SCAN_RSP_TIME_OUT));
Abhishek Singh00b71972016-01-07 10:51:04 +05302144 if (0 >= rc)
Rajeev79dbe4c2013-10-05 11:03:42 +05302145 {
2146 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Abhishek Singh00b71972016-01-07 10:51:04 +05302147 "%s: wait on hdd_get_batch_scan_req_var failed %ld",
2148 __func__, rc);
Rajeev79dbe4c2013-10-05 11:03:42 +05302149 return -EFAULT;
2150 }
2151 }
2152
2153 len = snprintf(pDest, HDD_BATCH_SCAN_AP_META_INFO_SIZE,
Jeff Johnson02797792013-10-26 19:17:13 -07002154 "scancount=%u\n", pAdapter->numScanList);
Rajeev79dbe4c2013-10-05 11:03:42 +05302155 pDest += len;
2156 cur_len += len;
2157
2158 mutex_lock(&pAdapter->hdd_batch_scan_lock);
2159 len = hdd_populate_user_batch_scan_rsp(pAdapter, pDest,
2160 cur_len, rem_len);
2161 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
2162
2163 count = 0;
2164 len = (len - pPrivData->used_len);
2165 pDest = (command + pPrivData->used_len);
2166 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar99db6262013-11-11 15:23:36 -08002167 "NEW BATCH SCAN RESULT:");
Rajeev79dbe4c2013-10-05 11:03:42 +05302168 while(count < len)
2169 {
2170 printk("%c", *(pDest + count));
2171 count++;
2172 }
2173 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2174 "%s: copy %d data to user buffer", __func__, len);
2175 if (copy_to_user(pPrivData->buf, pDest, len))
2176 {
2177 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2178 "%s: failed to copy data to user buffer", __func__);
2179 return -EFAULT;
2180 }
2181 }
2182 else
2183 {
2184 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2185 "sme_GetBatchScanScan returned failure halStatus %d",
2186 halStatus);
2187 return -EINVAL;
2188 }
2189 }
2190 else
2191 {
Rajeev79dbe4c2013-10-05 11:03:42 +05302192 count = 0;
2193 len = (len - pPrivData->used_len);
2194 pDest = (command + pPrivData->used_len);
2195 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar99db6262013-11-11 15:23:36 -08002196 "REMAINING TRUNCATED BATCH SCAN RESULT:");
Rajeev79dbe4c2013-10-05 11:03:42 +05302197 while(count < len)
2198 {
2199 printk("%c", *(pDest + count));
2200 count++;
2201 }
Rajeev Kumar99db6262013-11-11 15:23:36 -08002202 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2203 "%s: copy %d data to user buffer", __func__, len);
Rajeev79dbe4c2013-10-05 11:03:42 +05302204 if (copy_to_user(pPrivData->buf, pDest, len))
2205 {
2206 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2207 "%s: failed to copy data to user buffer", __func__);
2208 return -EFAULT;
2209 }
Rajeev79dbe4c2013-10-05 11:03:42 +05302210 }
2211
2212 return 0;
2213} /*End of hdd_return_batch_scan_rsp_to_user*/
2214
Rajeev Kumar8b373292014-01-08 20:36:55 -08002215/**---------------------------------------------------------------------------
2216
2217 \brief hdd_handle_batch_scan_ioctl () - This function handles WLS_BATCHING
2218 IOCTLs from user space. Following BATCH SCAN DEV IOCTs are handled:
2219 WLS_BATCHING VERSION
2220 WLS_BATCHING SET
2221 WLS_BATCHING GET
2222 WLS_BATCHING STOP
2223
2224 \param - pAdapter Pointer to HDD adapter
2225 \param - pPrivdata Pointer to priv_data
2226 \param - command Pointer to command
2227
2228 \return - 0 for success -EFAULT for failure
2229
2230 --------------------------------------------------------------------------*/
2231
2232int hdd_handle_batch_scan_ioctl
2233(
2234 hdd_adapter_t *pAdapter,
2235 hdd_priv_data_t *pPrivdata,
2236 tANI_U8 *command
2237)
2238{
2239 int ret = 0;
Yue Mae36e3552014-03-05 17:06:20 -08002240 hdd_context_t *pHddCtx;
2241
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05302242 ENTER();
2243
Yue Mae36e3552014-03-05 17:06:20 -08002244 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2245 ret = wlan_hdd_validate_context(pHddCtx);
2246 if (ret)
2247 {
Yue Mae36e3552014-03-05 17:06:20 -08002248 goto exit;
2249 }
Rajeev Kumar8b373292014-01-08 20:36:55 -08002250
2251 if (strncmp(command, "WLS_BATCHING VERSION", 20) == 0)
2252 {
2253 char extra[32];
2254 tANI_U8 len = 0;
2255 tANI_U8 version = HDD_BATCH_SCAN_VERSION;
2256
2257 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
2258 {
2259 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2260 "%s: Batch scan feature is not supported by FW", __func__);
2261 ret = -EINVAL;
2262 goto exit;
2263 }
2264
2265 len = scnprintf(extra, sizeof(extra), "WLS_BATCHING_VERSION %d",
2266 version);
2267 if (copy_to_user(pPrivdata->buf, &extra, len + 1))
2268 {
2269 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2270 "%s: failed to copy data to user buffer", __func__);
2271 ret = -EFAULT;
2272 goto exit;
2273 }
2274 ret = HDD_BATCH_SCAN_VERSION;
2275 }
2276 else if (strncmp(command, "WLS_BATCHING SET", 16) == 0)
2277 {
2278 int status;
2279 tANI_U8 *value = (command + 16);
2280 eHalStatus halStatus;
2281 unsigned long rc;
2282 tSirSetBatchScanReq *pReq = &pAdapter->hddSetBatchScanReq;
2283 tSirSetBatchScanRsp *pRsp = &pAdapter->hddSetBatchScanRsp;
2284
2285 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
2286 {
2287 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2288 "%s: Batch scan feature is not supported by FW", __func__);
2289 ret = -EINVAL;
2290 goto exit;
2291 }
2292
2293 if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) &&
2294 (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) &&
2295 (WLAN_HDD_P2P_GO != pAdapter->device_mode) &&
2296 (WLAN_HDD_P2P_DEVICE != pAdapter->device_mode))
2297 {
2298 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Sushant Kaushik8bc7df22014-04-09 17:55:29 +05302299 "Received WLS_BATCHING SET command in invalid mode %s (%d) "
Rajeev Kumar8b373292014-01-08 20:36:55 -08002300 "WLS_BATCHING_SET is only allowed in infra STA/P2P client mode",
Sushant Kaushik8bc7df22014-04-09 17:55:29 +05302301 hdd_device_modetoString(pAdapter->device_mode),
2302 pAdapter->device_mode);
Rajeev Kumar8b373292014-01-08 20:36:55 -08002303 ret = -EINVAL;
2304 goto exit;
2305 }
2306
2307 status = hdd_parse_set_batchscan_command(value, pReq);
2308 if (status)
2309 {
2310 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2311 "Invalid WLS_BATCHING SET command");
2312 ret = -EINVAL;
2313 goto exit;
2314 }
2315
2316
2317 pAdapter->hdd_wait_for_set_batch_scan_rsp = TRUE;
2318 halStatus = sme_SetBatchScanReq(WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
2319 pAdapter->sessionId, hdd_set_batch_scan_req_callback,
2320 pAdapter);
2321
2322 if ( eHAL_STATUS_SUCCESS == halStatus )
2323 {
Mahesh A Saptasagar5f568172014-05-14 17:02:33 +05302324 char extra[32];
2325 tANI_U8 len = 0;
2326 tANI_U8 mScan = 0;
2327
Rajeev Kumar8b373292014-01-08 20:36:55 -08002328 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2329 "sme_SetBatchScanReq returned success halStatus %d",
2330 halStatus);
2331 if (TRUE == pAdapter->hdd_wait_for_set_batch_scan_rsp)
2332 {
2333 INIT_COMPLETION(pAdapter->hdd_set_batch_scan_req_var);
2334 rc = wait_for_completion_timeout(
2335 &pAdapter->hdd_set_batch_scan_req_var,
2336 msecs_to_jiffies(HDD_SET_BATCH_SCAN_REQ_TIME_OUT));
2337 if (0 == rc)
2338 {
2339 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2340 "%s: Timeout waiting for set batch scan to complete",
2341 __func__);
2342 ret = -EINVAL;
2343 goto exit;
2344 }
2345 }
2346 if ( !pRsp->nScansToBatch )
2347 {
2348 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2349 "%s: Received set batch scan failure response from FW",
2350 __func__);
2351 ret = -EINVAL;
2352 goto exit;
2353 }
2354 /*As per the Batch Scan Framework API we should return the MIN of
2355 either MSCAN or the max # of scans firmware can cache*/
Mahesh A Saptasagar5f568172014-05-14 17:02:33 +05302356 mScan = MIN(pReq->numberOfScansToBatch , pRsp->nScansToBatch);
Rajeev Kumar8b373292014-01-08 20:36:55 -08002357
2358 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STARTED;
2359
2360 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2361 "%s: request MSCAN %d response MSCAN %d ret %d",
Mahesh A Saptasagar5f568172014-05-14 17:02:33 +05302362 __func__, pReq->numberOfScansToBatch, pRsp->nScansToBatch, mScan);
2363 len = scnprintf(extra, sizeof(extra), "%d", mScan);
2364 if (copy_to_user(pPrivdata->buf, &extra, len + 1))
2365 {
2366 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2367 "%s: failed to copy MSCAN value to user buffer", __func__);
2368 ret = -EFAULT;
2369 goto exit;
2370 }
Rajeev Kumar8b373292014-01-08 20:36:55 -08002371 }
2372 else
2373 {
2374 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2375 "sme_SetBatchScanReq returned failure halStatus %d",
2376 halStatus);
2377 ret = -EINVAL;
2378 goto exit;
2379 }
2380 }
2381 else if (strncmp(command, "WLS_BATCHING STOP", 17) == 0)
2382 {
2383 eHalStatus halStatus;
2384 tSirStopBatchScanInd *pInd = &pAdapter->hddStopBatchScanInd;
2385 pInd->param = 0;
2386
2387 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
2388 {
2389 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2390 "%s: Batch scan feature is not supported by FW", __func__);
2391 ret = -EINVAL;
2392 goto exit;
2393 }
2394
2395 if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState)
2396 {
Deepthi Gowribfd17132014-11-14 17:59:04 +05302397 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Rajeev Kumar8b373292014-01-08 20:36:55 -08002398 "Batch scan is not yet enabled batch scan state %d",
2399 pAdapter->batchScanState);
2400 ret = -EINVAL;
2401 goto exit;
2402 }
2403
Kiet Lamaa8e15a2014-02-11 23:30:06 -08002404 mutex_lock(&pAdapter->hdd_batch_scan_lock);
2405 hdd_deinit_batch_scan(pAdapter);
2406 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
2407
Rajeev Kumar8b373292014-01-08 20:36:55 -08002408 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
2409
2410 halStatus = sme_StopBatchScanInd(WLAN_HDD_GET_HAL_CTX(pAdapter), pInd,
2411 pAdapter->sessionId);
2412 if ( eHAL_STATUS_SUCCESS == halStatus )
2413 {
2414 ret = 0;
2415 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2416 "sme_StopBatchScanInd returned success halStatus %d",
2417 halStatus);
2418 }
2419 else
2420 {
2421 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2422 "sme_StopBatchScanInd returned failure halStatus %d",
2423 halStatus);
2424 ret = -EINVAL;
2425 goto exit;
2426 }
2427 }
2428 else if (strncmp(command, "WLS_BATCHING GET", 16) == 0)
2429 {
2430 tANI_U32 remain_len;
2431
2432 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
2433 {
2434 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2435 "%s: Batch scan feature is not supported by FW", __func__);
2436 ret = -EINVAL;
2437 goto exit;
2438 }
2439
2440 if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState)
2441 {
Deepthi Gowribfd17132014-11-14 17:59:04 +05302442 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Rajeev Kumar8b373292014-01-08 20:36:55 -08002443 "Batch scan is not yet enabled could not return results"
2444 "Batch Scan state %d",
2445 pAdapter->batchScanState);
2446 ret = -EINVAL;
2447 goto exit;
2448 }
2449
2450 pPrivdata->used_len = 16;
2451 remain_len = pPrivdata->total_len - pPrivdata->used_len;
2452 if (remain_len < pPrivdata->total_len)
2453 {
2454 /*Clear previous batch scan response data if any*/
2455 vos_mem_zero((tANI_U8 *)(command + pPrivdata->used_len), remain_len);
2456 }
2457 else
2458 {
2459 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2460 "Invalid total length from user space can't fetch batch"
2461 " scan response total_len %d used_len %d remain len %d",
2462 pPrivdata->total_len, pPrivdata->used_len, remain_len);
2463 ret = -EINVAL;
2464 goto exit;
2465 }
2466 ret = hdd_return_batch_scan_rsp_to_user(pAdapter, pPrivdata, command);
2467 }
2468
2469exit:
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05302470 EXIT();
Rajeev Kumar8b373292014-01-08 20:36:55 -08002471 return ret;
2472}
2473
2474
Rajeev79dbe4c2013-10-05 11:03:42 +05302475#endif/*End of FEATURE_WLAN_BATCH_SCAN*/
2476
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05302477#if defined(WLAN_FEATURE_VOWIFI_11R) || defined(FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
2478/**
2479 * hdd_assign_handoff_src_reassoc - Set handoff source as REASSOC
2480 * to Handoff request
2481 * @handoffInfo: Pointer to Handoff request
2482 * @src: enum of handoff_src
2483 * Return: None
2484 */
2485#ifndef QCA_WIFI_ISOC
2486static inline void hdd_assign_handoff_src_reassoc(tCsrHandoffRequest
2487 *handoffInfo, handoff_src src)
2488{
2489 handoffInfo->src = src;
2490}
2491#else
2492static inline void hdd_assign_handoff_src_reassoc(tCsrHandoffRequest
2493 *handoffInfo, handoff_src src)
2494{
2495}
2496#endif
2497
2498/**
Selvaraj, Sridhar4fa15232016-06-18 12:27:25 +05302499 * hdd_reassoc() - perform a user space-directed reassoc
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05302500 *
2501 * @pAdapter: Adapter upon which the command was received
2502 * @bssid: BSSID with which to reassociate
2503 * @channel: channel upon which to reassociate
Selvaraj, Sridhar4fa15232016-06-18 12:27:25 +05302504 * @src: The source for the trigger of this action
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05302505 *
2506 * Return: 0 for success non-zero for failure
2507 */
2508#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
Selvaraj, Sridhar8ecb4192016-06-23 17:50:49 +05302509int hdd_reassoc(hdd_adapter_t *pAdapter, const tANI_U8 *bssid,
Selvaraj, Sridhar4fa15232016-06-18 12:27:25 +05302510 const tANI_U8 channel, const handoff_src src)
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05302511{
2512 hdd_station_ctx_t *pHddStaCtx;
2513 tCsrHandoffRequest handoffInfo;
2514 hdd_context_t *pHddCtx = NULL;
2515 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2516
2517 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2518
2519 /* if not associated, no need to proceed with reassoc */
2520 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
2521 hddLog(LOG1, FL("Not associated"));
2522 return -EINVAL;
2523 }
2524
2525 /* if the target bssid is same as currently associated AP,
2526 then no need to proceed with reassoc */
2527 if (!memcmp(bssid, pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr))) {
2528 hddLog(LOG1, FL("Reassoc BSSID is same as currently associated AP bssid"));
2529 return -EINVAL;
2530 }
2531
2532 /* Check channel number is a valid channel number */
2533 if (VOS_STATUS_SUCCESS !=
2534 wlan_hdd_validate_operation_channel(pAdapter, channel)) {
2535 hddLog(LOGE, FL("Invalid Channel %d"), channel);
2536 return -EINVAL;
2537 }
2538
2539 /* Proceed with reassoc */
2540 handoffInfo.channel = channel;
Selvaraj, Sridhar4fa15232016-06-18 12:27:25 +05302541 hdd_assign_handoff_src_reassoc(&handoffInfo, src);
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05302542 memcpy(handoffInfo.bssid, bssid, sizeof(tSirMacAddr));
2543 sme_HandoffRequest(pHddCtx->hHal, &handoffInfo);
2544 return 0;
2545}
2546#else
Selvaraj, Sridhar8ecb4192016-06-23 17:50:49 +05302547int hdd_reassoc(hdd_adapter_t *pAdapter, const tANI_U8 *bssid,
Selvaraj, Sridhar4fa15232016-06-18 12:27:25 +05302548 const tANI_U8 channel, const handoff_src src)
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05302549{
2550 return -EPERM;
2551}
2552#endif
2553
2554/**
2555 * hdd_parse_reassoc_v1() - parse version 1 of the REASSOC command
2556 * This function parses the v1 REASSOC command with the format
2557 * REASSOC xx:xx:xx:xx:xx:xx CH where "xx:xx:xx:xx:xx:xx" is the
2558 * Hex-ASCII representation of the BSSID and CH is the ASCII
2559 * representation of the channel. For example
2560 * REASSOC 00:0a:0b:11:22:33 48
2561 *
2562 * @pAdapter: Adapter upon which the command was received
2563 * @command: ASCII text command that was received
2564 *
2565 * Return: 0 for success non-zero for failure
2566 */
2567static int
2568hdd_parse_reassoc_v1(hdd_adapter_t *pAdapter, const char *command)
2569{
2570 tANI_U8 channel = 0;
2571 tSirMacAddr bssid;
2572 int ret;
2573
2574 ret = hdd_parse_reassoc_command_v1_data(command, bssid, &channel);
2575 if (ret)
2576 hddLog(LOGE, FL("Failed to parse reassoc command data"));
2577 else
Selvaraj, Sridhar4fa15232016-06-18 12:27:25 +05302578 ret = hdd_reassoc(pAdapter, bssid, channel, REASSOC);
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05302579
2580 return ret;
2581}
2582
2583/**
2584 * hdd_parse_reassoc_v2() - parse version 2 of the REASSOC command
2585 * This function parses the v2 REASSOC command with the format
2586 * REASSOC <android_wifi_reassoc_params>
2587 *
2588 * @pAdapter: Adapter upon which the command was received
2589 * @command: command that was received, ASCII command followed
2590 * by binary data
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05302591 * @total_len: Total length of the command received
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05302592 *
2593 * Return: 0 for success non-zero for failure
2594 */
2595static int
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05302596hdd_parse_reassoc_v2(hdd_adapter_t *pAdapter, const char *command,
2597 int total_len)
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05302598{
2599 struct android_wifi_reassoc_params params;
2600 tSirMacAddr bssid;
2601 int ret;
2602
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05302603 if (total_len < sizeof(params) + 8) {
2604 hddLog(LOGE, FL("Invalid command length"));
2605 return -EINVAL;
2606 }
2607
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05302608 /* The params are located after "REASSOC " */
2609 memcpy(&params, command + 8, sizeof(params));
2610
2611 if (!mac_pton(params.bssid, (u8 *)&bssid)) {
2612 hddLog(LOGE, FL("MAC address parsing failed"));
2613 ret = -EINVAL;
2614 } else {
Selvaraj, Sridhar4fa15232016-06-18 12:27:25 +05302615 ret = hdd_reassoc(pAdapter, bssid, params.channel, REASSOC);
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05302616 }
2617 return ret;
2618}
2619
2620/**
2621 * hdd_parse_reassoc() - parse the REASSOC command
2622 * There are two different versions of the REASSOC command.Version 1
2623 * of the command contains a parameter list that is ASCII characters
2624 * whereas version 2 contains a combination of ASCII and binary
2625 * payload. Determine if a version 1 or a version 2 command is being
2626 * parsed by examining the parameters, and then dispatch the parser
2627 * that is appropriate for the command.
2628 *
2629 * @pAdapter: Adapter upon which the command was received
2630 * @command: command that was received
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05302631 * @total_len: Total length of the command received
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05302632 *
2633 * Return: 0 for success non-zero for failure
2634 */
2635static int
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05302636hdd_parse_reassoc(hdd_adapter_t *pAdapter, const char *command, int total_len)
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05302637{
2638 int ret;
2639
2640 /*
2641 * both versions start with "REASSOC"
2642 * v1 has a bssid and channel # as an ASCII string
2643 * REASSOC xx:xx:xx:xx:xx:xx CH
2644 * v2 has a C struct
2645 * REASSOC <binary c struct>
2646 *
2647 * The first field in the v2 struct is also the bssid in ASCII.
2648 * But in the case of a v2 message the BSSID is NUL-terminated.
2649 * Hence we can peek at that offset to see if this is V1 or V2
2650 * REASSOC xx:xx:xx:xx:xx:xx*
2651 * 1111111111222222
2652 * 01234567890123456789012345
2653 */
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05302654
2655 if (total_len < 26) {
2656 hddLog(LOGE, FL("Invalid command (total_len=%d)"), total_len);
2657 return -EINVAL;
2658 }
2659
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05302660 if (command[25])
2661 ret = hdd_parse_reassoc_v1(pAdapter, command);
2662 else
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05302663 ret = hdd_parse_reassoc_v2(pAdapter, command, total_len);
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05302664
2665 return ret;
2666}
2667#endif /* WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_ESE FEATURE_WLAN_LFR */
2668
c_hpothu92367912014-05-01 15:18:17 +05302669static void getBcnMissRateCB(VOS_STATUS status, int bcnMissRate, void *data)
2670{
c_hpothu39eb1e32014-06-26 16:31:50 +05302671 bcnMissRateContext_t *pCBCtx;
2672
2673 if (NULL == data)
2674 {
2675 hddLog(VOS_TRACE_LEVEL_ERROR, FL("argument data is NULL"));
2676 return;
2677 }
c_hpothu92367912014-05-01 15:18:17 +05302678
2679 /* there is a race condition that exists between this callback
2680 function and the caller since the caller could time out either
2681 before or while this code is executing. we use a spinlock to
2682 serialize these actions */
2683 spin_lock(&hdd_context_lock);
2684
c_hpothu39eb1e32014-06-26 16:31:50 +05302685 pCBCtx = (bcnMissRateContext_t *)data;
c_hpothu92367912014-05-01 15:18:17 +05302686 gbcnMissRate = -1;
2687
c_hpothu39eb1e32014-06-26 16:31:50 +05302688 if (pCBCtx->magic != BCN_MISS_RATE_CONTEXT_MAGIC)
c_hpothu92367912014-05-01 15:18:17 +05302689 {
2690 hddLog(VOS_TRACE_LEVEL_ERROR,
c_hpothu39eb1e32014-06-26 16:31:50 +05302691 FL("invalid context magic: %08x"), pCBCtx->magic);
c_hpothu92367912014-05-01 15:18:17 +05302692 spin_unlock(&hdd_context_lock);
2693 return ;
2694 }
2695
2696 if (VOS_STATUS_SUCCESS == status)
2697 {
c_hpothu39eb1e32014-06-26 16:31:50 +05302698 gbcnMissRate = bcnMissRate;
c_hpothu92367912014-05-01 15:18:17 +05302699 }
c_hpothu39eb1e32014-06-26 16:31:50 +05302700 else
2701 {
2702 hddLog(VOS_TRACE_LEVEL_ERROR, FL("failed to get bcnMissRate"));
2703 }
2704
c_hpothu92367912014-05-01 15:18:17 +05302705 complete(&(pCBCtx->completion));
2706 spin_unlock(&hdd_context_lock);
2707
2708 return;
2709}
2710
Abhishek Singh08aa7762014-12-16 13:59:03 +05302711void hdd_FWStatisCB( VOS_STATUS status,
2712 tSirFwStatsResult *fwStatsResult, void *pContext )
Satyanarayana Dash72806012014-12-02 14:30:08 +05302713{
2714 fwStatsContext_t *fwStatsCtx;
Satyanarayana Dash72806012014-12-02 14:30:08 +05302715 hdd_adapter_t *pAdapter;
2716
2717 hddLog(VOS_TRACE_LEVEL_INFO, FL(" with status = %d"),status);
2718
Abhishek Singh08aa7762014-12-16 13:59:03 +05302719 if (NULL == pContext)
Satyanarayana Dash72806012014-12-02 14:30:08 +05302720 {
2721 hddLog(VOS_TRACE_LEVEL_ERROR, FL("argument data is NULL"));
2722 return;
2723 }
2724 /* there is a race condition that exists between this callback
2725 function and the caller since the caller could time out either
2726 before or while this code is executing. we use a spinlock to
2727 serialize these actions */
2728 spin_lock(&hdd_context_lock);
Abhishek Singh08aa7762014-12-16 13:59:03 +05302729 fwStatsCtx = (fwStatsContext_t *) pContext;
Satyanarayana Dash72806012014-12-02 14:30:08 +05302730 if (fwStatsCtx->magic != FW_STATS_CONTEXT_MAGIC)
2731 {
2732 hddLog(VOS_TRACE_LEVEL_ERROR,
2733 FL("invalid context magic: %08x"), fwStatsCtx->magic);
2734 spin_unlock(&hdd_context_lock);
2735 return;
2736 }
2737 pAdapter = fwStatsCtx->pAdapter;
2738 if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
2739 {
2740 hddLog(VOS_TRACE_LEVEL_ERROR,
2741 FL("pAdapter returned is NULL or invalid"));
2742 spin_unlock(&hdd_context_lock);
2743 return;
2744 }
2745 pAdapter->fwStatsRsp.type = 0;
Abhishek Singh08aa7762014-12-16 13:59:03 +05302746 if ((VOS_STATUS_SUCCESS == status) && (NULL != fwStatsResult))
Satyanarayana Dash72806012014-12-02 14:30:08 +05302747 {
Satyanarayana Dash72806012014-12-02 14:30:08 +05302748 switch( fwStatsResult->type )
2749 {
2750 case FW_UBSP_STATS:
2751 {
Abhishek Singh08aa7762014-12-16 13:59:03 +05302752 memcpy(&pAdapter->fwStatsRsp,fwStatsResult,sizeof(tSirFwStatsResult));
Satyanarayana Dash72806012014-12-02 14:30:08 +05302753 hddLog(VOS_TRACE_LEVEL_INFO,
2754 FL("ubsp_enter_cnt = %d ubsp_jump_ddr_cnt = %d"),
Abhishek Singh08aa7762014-12-16 13:59:03 +05302755 pAdapter->fwStatsRsp.fwStatsData.ubspStats.ubsp_enter_cnt,
2756 pAdapter->fwStatsRsp.fwStatsData.ubspStats.ubsp_jump_ddr_cnt);
Satyanarayana Dash72806012014-12-02 14:30:08 +05302757 }
2758 break;
2759 default:
2760 {
2761 hddLog(VOS_TRACE_LEVEL_ERROR,
2762 FL(" No handling for stats type %d"),fwStatsResult->type);
2763 }
2764 }
2765 }
2766 complete(&(fwStatsCtx->completion));
2767 spin_unlock(&hdd_context_lock);
2768 return;
2769}
2770
jge35567202017-06-21 16:39:38 +08002771/*
2772 *hdd_parse_setmaxtxpower_command() - HDD Parse MAXTXPOWER command
2773 *@pValue Pointer to MAXTXPOWER command
2774 *@pTxPower Pointer to tx power
2775 *
2776 *This function parses the MAXTXPOWER command passed in the format
2777 * MAXTXPOWER<space>X(Tx power in dbm)
2778 * For example input commands:
2779 * 1) MAXTXPOWER -8 -> This is translated into set max TX power to -8 dbm
2780 * 2) MAXTXPOWER -23 -> This is translated into set max TX power to -23 dbm
2781 *
2782 *return - 0 for success non-zero for failure
2783 */
2784static int hdd_parse_setmaxtxpower_command(unsigned char *pValue, int *pTxPower)
2785{
2786 unsigned char *inPtr = pValue;
2787 int tempInt;
2788 int v = 0;
2789 *pTxPower = 0;
2790
2791 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2792 /* no argument after the command */
2793 if (NULL == inPtr)
2794 return -EINVAL;
2795 /* no space after the command */
2796 else if (SPACE_ASCII_VALUE != *inPtr)
2797 return -EINVAL;
2798
2799 /* removing empty spaces */
2800 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
2801
2802 /* no argument followed by spaces */
2803 if ('\0' == *inPtr)
2804 return 0;
2805
2806 v = kstrtos32(inPtr, 10, &tempInt);
2807
2808 /* Range checking for passed parameter */
2809 if ((tempInt < HDD_MIN_TX_POWER) || (tempInt > HDD_MAX_TX_POWER))
2810 return -EINVAL;
2811
2812 *pTxPower = tempInt;
2813
2814 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2815 "SETMAXTXPOWER: %d", *pTxPower);
2816
2817 return 0;
2818}
2819
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302820static int hdd_get_dwell_time(hdd_config_t *pCfg, tANI_U8 *command, char *extra, tANI_U8 n, tANI_U8 *len)
2821{
2822 int ret = 0;
2823
2824 if (!pCfg || !command || !extra || !len)
2825 {
2826 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2827 "%s: argument passsed for GETDWELLTIME is incorrect", __func__);
2828 ret = -EINVAL;
2829 return ret;
2830 }
2831
2832 if (strncmp(command, "GETDWELLTIME ACTIVE MAX", 23) == 0)
2833 {
2834 *len = scnprintf(extra, n, "GETDWELLTIME ACTIVE MAX %u\n",
2835 (int)pCfg->nActiveMaxChnTime);
2836 return ret;
2837 }
2838 else if (strncmp(command, "GETDWELLTIME ACTIVE MIN", 23) == 0)
2839 {
2840 *len = scnprintf(extra, n, "GETDWELLTIME ACTIVE MIN %u\n",
2841 (int)pCfg->nActiveMinChnTime);
2842 return ret;
2843 }
2844 else if (strncmp(command, "GETDWELLTIME PASSIVE MAX", 24) == 0)
2845 {
2846 *len = scnprintf(extra, n, "GETDWELLTIME PASSIVE MAX %u\n",
2847 (int)pCfg->nPassiveMaxChnTime);
2848 return ret;
2849 }
2850 else if (strncmp(command, "GETDWELLTIME PASSIVE MIN", 24) == 0)
2851 {
2852 *len = scnprintf(extra, n, "GETDWELLTIME PASSIVE MIN %u\n",
2853 (int)pCfg->nPassiveMinChnTime);
2854 return ret;
2855 }
Rajesh Babu Prathipati0fd227e2014-07-05 12:50:00 +05302856 else if (strncmp(command, "GETDWELLTIME", 12) == 0)
2857 {
2858 *len = scnprintf(extra, n, "GETDWELLTIME %u \n",
2859 (int)pCfg->nActiveMaxChnTime);
2860 return ret;
2861 }
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302862 else
2863 {
2864 ret = -EINVAL;
2865 }
2866
2867 return ret;
2868}
2869
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05302870int hdd_drv_cmd_validate(tANI_U8 *command, int len)
2871{
2872 if (command[len] != ' ')
2873 return -EINVAL;
2874
2875 return 0;
2876}
2877
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302878static int hdd_set_dwell_time(hdd_adapter_t *pAdapter, tANI_U8 *command)
2879{
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302880 tHalHandle hHal;
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302881 hdd_config_t *pCfg;
2882 tANI_U8 *value = command;
2883 int val = 0, ret = 0, temp = 0;
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302884 tSmeConfigParams smeConfig;
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302885
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302886 if (!pAdapter || !command || !(pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini)
2887 || !(hHal = (WLAN_HDD_GET_HAL_CTX(pAdapter))))
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302888 {
2889 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2890 "%s: argument passed for SETDWELLTIME is incorrect", __func__);
2891 ret = -EINVAL;
2892 return ret;
2893 }
2894
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302895 vos_mem_zero(&smeConfig, sizeof(smeConfig));
2896 sme_GetConfigParam(hHal, &smeConfig);
2897
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302898 if (strncmp(command, "SETDWELLTIME ACTIVE MAX", 23) == 0 )
2899 {
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05302900 if (hdd_drv_cmd_validate(command, 23))
2901 return -EINVAL;
2902
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302903 value = value + 24;
2904 temp = kstrtou32(value, 10, &val);
2905 if (temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_MIN ||
2906 val > CFG_ACTIVE_MAX_CHANNEL_TIME_MAX )
2907 {
2908 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2909 "%s: argument passed for SETDWELLTIME ACTIVE MAX is incorrect", __func__);
2910 ret = -EFAULT;
2911 return ret;
2912 }
2913 pCfg->nActiveMaxChnTime = val;
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302914 smeConfig.csrConfig.nActiveMaxChnTime = val;
2915 sme_UpdateConfig(hHal, &smeConfig);
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302916 }
2917 else if (strncmp(command, "SETDWELLTIME ACTIVE MIN", 23) == 0)
2918 {
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05302919 if (hdd_drv_cmd_validate(command, 23))
2920 return -EINVAL;
2921
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302922 value = value + 24;
2923 temp = kstrtou32(value, 10, &val);
2924 if (temp !=0 || val < CFG_ACTIVE_MIN_CHANNEL_TIME_MIN ||
2925 val > CFG_ACTIVE_MIN_CHANNEL_TIME_MAX )
2926 {
2927 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2928 "%s: argument passsed for SETDWELLTIME ACTIVE MIN is incorrect", __func__);
2929 ret = -EFAULT;
2930 return ret;
2931 }
2932 pCfg->nActiveMinChnTime = val;
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302933 smeConfig.csrConfig.nActiveMinChnTime = val;
2934 sme_UpdateConfig(hHal, &smeConfig);
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302935 }
2936 else if (strncmp(command, "SETDWELLTIME PASSIVE MAX", 24) == 0)
2937 {
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05302938 if (hdd_drv_cmd_validate(command, 24))
2939 return -EINVAL;
2940
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302941 value = value + 25;
2942 temp = kstrtou32(value, 10, &val);
2943 if (temp != 0 || val < CFG_PASSIVE_MAX_CHANNEL_TIME_MIN ||
2944 val > CFG_PASSIVE_MAX_CHANNEL_TIME_MAX )
2945 {
2946 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2947 "%s: argument passed for SETDWELLTIME PASSIVE MAX is incorrect", __func__);
2948 ret = -EFAULT;
2949 return ret;
2950 }
2951 pCfg->nPassiveMaxChnTime = val;
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302952 smeConfig.csrConfig.nPassiveMaxChnTime = val;
2953 sme_UpdateConfig(hHal, &smeConfig);
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302954 }
2955 else if (strncmp(command, "SETDWELLTIME PASSIVE MIN", 24) == 0)
2956 {
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05302957 if (hdd_drv_cmd_validate(command, 24))
2958 return -EINVAL;
2959
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302960 value = value + 25;
2961 temp = kstrtou32(value, 10, &val);
2962 if (temp != 0 || val < CFG_PASSIVE_MIN_CHANNEL_TIME_MIN ||
2963 val > CFG_PASSIVE_MIN_CHANNEL_TIME_MAX )
2964 {
2965 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2966 "%s: argument passed for SETDWELLTIME PASSIVE MIN is incorrect", __func__);
2967 ret = -EFAULT;
2968 return ret;
2969 }
2970 pCfg->nPassiveMinChnTime = val;
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302971 smeConfig.csrConfig.nPassiveMinChnTime = val;
2972 sme_UpdateConfig(hHal, &smeConfig);
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302973 }
Rajesh Babu Prathipati0fd227e2014-07-05 12:50:00 +05302974 else if (strncmp(command, "SETDWELLTIME", 12) == 0)
2975 {
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05302976 if (hdd_drv_cmd_validate(command, 12))
2977 return -EINVAL;
2978
Rajesh Babu Prathipati0fd227e2014-07-05 12:50:00 +05302979 value = value + 13;
2980 temp = kstrtou32(value, 10, &val);
2981 if (temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_MIN ||
2982 val > CFG_ACTIVE_MAX_CHANNEL_TIME_MAX )
2983 {
2984 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2985 "%s: argument passed for SETDWELLTIME is incorrect", __func__);
2986 ret = -EFAULT;
2987 return ret;
2988 }
2989 pCfg->nActiveMaxChnTime = val;
2990 smeConfig.csrConfig.nActiveMaxChnTime = val;
2991 sme_UpdateConfig(hHal, &smeConfig);
2992 }
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302993 else
2994 {
2995 ret = -EINVAL;
2996 }
2997
2998 return ret;
2999}
Agarwal Ashish8bd53ae2015-06-12 18:03:45 +05303000static int hdd_cmd_setFccChannel(hdd_context_t *pHddCtx, tANI_U8 *cmd,
3001 tANI_U8 cmd_len)
3002{
3003 tANI_U8 *value;
3004 tANI_U8 fcc_constraint;
3005
3006 eHalStatus status;
3007 int ret = 0;
3008 value = cmd + cmd_len + 1;
3009
3010 ret = kstrtou8(value, 10, &fcc_constraint);
3011 if ((ret < 0) || (fcc_constraint > 1)) {
3012 /*
3013 * If the input value is greater than max value of datatype,
3014 * then also it is a failure
3015 */
3016 hddLog(VOS_TRACE_LEVEL_ERROR,
3017 "%s: value out of range", __func__);
3018 return -EINVAL;
3019 }
3020
Agrawal Ashish842eea82016-02-04 17:56:16 +05303021 status = sme_handleSetFccChannel(pHddCtx->hHal, fcc_constraint,
3022 pHddCtx->scan_info.mScanPending);
Agarwal Ashish8bd53ae2015-06-12 18:03:45 +05303023 if (status != eHAL_STATUS_SUCCESS)
3024 ret = -EPERM;
3025
3026 return ret;
3027}
3028
Mahesh A Saptasagarbeca12c2015-09-07 16:21:06 +05303029/**---------------------------------------------------------------------------
Agarwal Ashish8bd53ae2015-06-12 18:03:45 +05303030
Mahesh A Saptasagarbeca12c2015-09-07 16:21:06 +05303031 \brief hdd_enable_disable_ca_event() - When Host sends IOCTL (enabled),
3032 FW will send *ONE* CA ind to Host(even though it is duplicate).
3033 When Host send IOCTL (disable), FW doesn't perform any action.
3034 Whenever any change in CA *and* WLAN is in SAP/P2P-GO mode, FW
3035 sends CA ind to host. (regard less of IOCTL status)
3036 \param - pHddCtx - HDD context
3037 \param - command - command received from framework
3038 \param - cmd_len - len of the command
3039
3040 \return - 0 on success, appropriate error values on failure.
3041
3042 --------------------------------------------------------------------------*/
3043int hdd_enable_disable_ca_event(hdd_context_t *pHddCtx, tANI_U8* command, tANI_U8 cmd_len)
3044{
3045 tANI_U8 set_value;
3046 int ret = 0;
3047 eHalStatus status;
3048
3049 ret = wlan_hdd_validate_context(pHddCtx);
3050 if (0 != ret)
3051 {
3052 ret = -EINVAL;
3053 goto exit;
3054 }
3055
3056 if (pHddCtx->cfg_ini->gOptimizeCAevent == 0)
3057 {
3058 hddLog(VOS_TRACE_LEVEL_ERROR, "Enable gOptimizeCAevent"
3059 " ini param to control channel avooidance indication");
3060 ret = 0;
3061 goto exit;
3062 }
3063
3064 set_value = command[cmd_len + 1] - '0';
3065 status = sme_enableDisableChanAvoidIndEvent(pHddCtx->hHal, set_value);
3066 if (status != eHAL_STATUS_SUCCESS)
3067 {
3068 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to send"
3069 " enableDisableChanAoidance command to SME\n", __func__);
3070 ret = -EINVAL;
3071 }
3072
3073exit:
3074 return ret;
3075}
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05303076
Selvaraj, Sridhar3714c4d2016-06-22 15:19:12 +05303077/**
3078 * wlan_hdd_fastreassoc_handoff_request() - Post Handoff request to SME
3079 * @pHddCtx: Pointer to the HDD context
3080 * @channel: channel to reassociate
3081 * @targetApBssid: Target AP/BSSID to reassociate
3082 *
3083 * Return: None
3084 */
3085#if defined(WLAN_FEATURE_ROAM_SCAN_OFFLOAD) && !defined(QCA_WIFI_ISOC)
3086static void wlan_hdd_fastreassoc_handoff_request(hdd_context_t *pHddCtx,
3087 uint8_t channel, tSirMacAddr targetApBssid)
3088{
3089 tCsrHandoffRequest handoffInfo;
3090 handoffInfo.channel = channel;
3091 handoffInfo.src = FASTREASSOC;
3092 vos_mem_copy(handoffInfo.bssid, targetApBssid, sizeof(tSirMacAddr));
3093 sme_HandoffRequest(pHddCtx->hHal, &handoffInfo);
3094}
3095#else
3096static void wlan_hdd_fastreassoc_handoff_request(hdd_context_t *pHddCtx,
3097 uint8_t channel, tSirMacAddr targetApBssid)
3098{
3099}
3100#endif
3101
3102/**
3103 * csr_fastroam_neighbor_ap_event() - Function to trigger scan/roam
3104 * @pAdapter: Pointer to HDD adapter
3105 * @channel: Channel to scan/roam
3106 * @targetApBssid: BSSID to roam
3107 *
3108 * Return: None
3109 */
3110#ifdef QCA_WIFI_ISOC
3111static void csr_fastroam_neighbor_ap_event(hdd_adapter_t *pAdapter,
3112 uint8_t channel, tSirMacAddr targetApBssid)
3113{
3114 smeIssueFastRoamNeighborAPEvent(WLAN_HDD_GET_HAL_CTX(pAdapter),
3115 &targetApBssid[0], eSME_ROAM_TRIGGER_SCAN, channel);
3116}
3117#else
3118static void csr_fastroam_neighbor_ap_event(hdd_adapter_t *pAdapter,
3119 uint8_t channel, tSirMacAddr targetApBssid)
3120{
3121}
3122#endif
3123
3124/**
3125 * wlan_hdd_handle_fastreassoc() - Handle fastreassoc command
3126 * @pAdapter: pointer to hdd adapter
3127 * @command: pointer to the command received
3128 *
3129 * Return: VOS_STATUS enum
3130 */
3131static VOS_STATUS wlan_hdd_handle_fastreassoc(hdd_adapter_t *pAdapter,
3132 uint8_t *command)
3133{
3134 tANI_U8 *value = command;
3135 tANI_U8 channel = 0;
3136 tSirMacAddr targetApBssid;
Selvaraj, Sridhar3714c4d2016-06-22 15:19:12 +05303137 hdd_station_ctx_t *pHddStaCtx = NULL;
3138 hdd_context_t *pHddCtx = NULL;
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05303139 int ret;
Selvaraj, Sridhar349b8fe2017-01-18 13:11:25 +05303140 tCsrRoamModifyProfileFields mod_profile_fields;
3141 uint32_t roam_id = 0;
Selvaraj, Sridhar3714c4d2016-06-22 15:19:12 +05303142 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3143 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3144
3145 /* if not associated, no need to proceed with reassoc */
3146 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
3147 hddLog(LOG1, FL("Not associated!"));
3148 return eHAL_STATUS_FAILURE;
3149 }
3150
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05303151 ret = hdd_parse_reassoc_command_v1_data(value, targetApBssid, &channel);
3152 if (ret) {
Selvaraj, Sridhar3714c4d2016-06-22 15:19:12 +05303153 hddLog(LOGE, FL("Failed to parse reassoc command data"));
3154 return eHAL_STATUS_FAILURE;
3155 }
3156
3157 /* if the target bssid is same as currently associated AP,
3158 then no need to proceed with reassoc */
3159 if (vos_mem_compare(targetApBssid,
3160 pHddStaCtx->conn_info.bssId,
3161 sizeof(tSirMacAddr))) {
Selvaraj, Sridhar349b8fe2017-01-18 13:11:25 +05303162 sme_GetModifyProfileFields(pHddCtx->hHal, pAdapter->sessionId,
3163 &mod_profile_fields);
3164 sme_RoamReassoc(pHddCtx->hHal, pAdapter->sessionId, NULL,
3165 mod_profile_fields, &roam_id, 1);
Selvaraj, Sridhar3714c4d2016-06-22 15:19:12 +05303166 hddLog(LOG1, FL("Reassoc BSSID is same as currently associated AP bssid"));
Selvaraj, Sridhar349b8fe2017-01-18 13:11:25 +05303167 return eHAL_STATUS_SUCCESS;
Selvaraj, Sridhar3714c4d2016-06-22 15:19:12 +05303168 }
3169
3170 /* Check channel number is a valid channel number */
3171 if (VOS_STATUS_SUCCESS !=
3172 wlan_hdd_validate_operation_channel(pAdapter, channel)) {
3173 hddLog(LOGE, FL("Invalid Channel [%d]"), channel);
3174 return eHAL_STATUS_FAILURE;
3175 }
3176
3177 /* Proceed with reassoc */
3178 wlan_hdd_fastreassoc_handoff_request(pHddCtx, channel, targetApBssid);
3179
3180 /* Proceed with scan/roam */
3181 csr_fastroam_neighbor_ap_event(pAdapter, channel, targetApBssid);
3182
3183 return eHAL_STATUS_SUCCESS;
3184}
3185
3186/**
3187 * hdd_assign_reassoc_handoff - Set handoff source as REASSOC
3188 * @handoffInfo: Pointer to the csr Handoff Request.
3189 *
3190 * Return: None
3191 */
3192#ifndef QCA_WIFI_ISOC
3193static inline void hdd_assign_reassoc_handoff(tCsrHandoffRequest *handoffInfo)
3194{
3195 handoffInfo->src = REASSOC;
3196}
3197#else
3198static inline void hdd_assign_reassoc_handoff(tCsrHandoffRequest *handoffInfo)
3199{
3200}
3201#endif
3202
Ashish Kumar Dhanotiya32d092b2018-02-20 21:43:57 +05303203/**
3204 * wlan_hdd_free_cache_channels() - Free the cache channels list
3205 * @hdd_ctx: Pointer to HDD context
3206 *
3207 * Return: None
3208 */
3209
3210static void wlan_hdd_free_cache_channels(hdd_context_t *hdd_ctx)
3211{
3212 mutex_lock(&hdd_ctx->cache_channel_lock);
3213 hdd_ctx->orginal_channels->num_channels = 0;
3214 vos_mem_free(hdd_ctx->orginal_channels->channel_info);
3215 hdd_ctx->orginal_channels->channel_info = NULL;
3216 vos_mem_free(hdd_ctx->orginal_channels);
3217 hdd_ctx->orginal_channels = NULL;
3218 mutex_unlock(&hdd_ctx->cache_channel_lock);
3219}
3220
3221/**
3222 * hdd_alloc_chan_cache() - Allocate the memory to cache the channel
3223 * info for the channels received in command SET_DISABLE_CHANNEL_LIST
3224 * @hdd_ctx: Pointer to HDD context
3225 * @num_chan: Number of channels for which memory needs to
3226 * be allocated
3227 *
3228 * Return: 0 on success and error code on failure
3229 */
3230
3231int hdd_alloc_chan_cache(hdd_context_t *hdd_ctx, int num_chan)
3232{
3233 if (NULL == hdd_ctx->orginal_channels) {
3234 hdd_ctx->orginal_channels =
3235 vos_mem_malloc(sizeof(struct hdd_cache_channels));
3236 if (NULL == hdd_ctx->orginal_channels) {
3237 hddLog(VOS_TRACE_LEVEL_ERROR,
3238 "In %s, VOS_MALLOC_ERR", __func__);
3239 return -EINVAL;
3240 }
3241 hdd_ctx->orginal_channels->num_channels = num_chan;
3242 hdd_ctx->orginal_channels->channel_info =
3243 vos_mem_malloc(num_chan *
3244 sizeof(struct hdd_cache_channel_info));
3245 if (NULL == hdd_ctx->orginal_channels->channel_info) {
3246 hddLog(VOS_TRACE_LEVEL_ERROR,
3247 "In %s, VOS_MALLOC_ERR", __func__);
3248 hdd_ctx->orginal_channels->num_channels = 0;
3249 vos_mem_free(hdd_ctx->orginal_channels);
3250 hdd_ctx->orginal_channels = NULL;
3251 return -EINVAL;
3252 }
3253 } else {
3254 /* Same command comes multiple times */
3255 struct hdd_cache_channel_info *temp_chan_info;
3256
3257 if (hdd_ctx->orginal_channels->num_channels + num_chan >
3258 MAX_CHANNEL) {
3259 hddLog(VOS_TRACE_LEVEL_ERROR,
3260 "%s: Invalid Number of channel received",
3261 __func__);
3262 return -EINVAL;
3263 }
3264
3265 temp_chan_info = vos_mem_malloc((
3266 hdd_ctx->orginal_channels->
3267 num_channels + num_chan) *
3268 sizeof(struct hdd_cache_channel_info));
3269 if (NULL == temp_chan_info) {
3270 hddLog(VOS_TRACE_LEVEL_ERROR,
3271 "In %s, VOS_MALLOC_ERR",
3272 __func__);
3273 return -EINVAL;
3274 }
3275
3276 vos_mem_copy(temp_chan_info, hdd_ctx->orginal_channels->
3277 channel_info, hdd_ctx->orginal_channels->
3278 num_channels *
3279 sizeof(struct hdd_cache_channel_info));
3280
3281 hdd_ctx->orginal_channels->num_channels += num_chan;
3282 vos_mem_free(hdd_ctx->orginal_channels->channel_info);
3283 hdd_ctx->orginal_channels->channel_info = temp_chan_info;
3284 temp_chan_info = NULL;
3285 }
3286 return 0;
3287
3288}
3289
3290
3291int hdd_parse_disable_chan_cmd(hdd_adapter_t *adapter, tANI_U8 *ptr)
3292{
3293 v_PVOID_t pvosGCtx = vos_get_global_context(VOS_MODULE_ID_HDD, NULL);
3294 hdd_context_t *hdd_ctx = vos_get_context(VOS_MODULE_ID_HDD, pvosGCtx);
3295 tANI_U8 *param;
3296 int j, tempInt, index = 0, ret = 0;
3297
3298 if (NULL == pvosGCtx) {
3299 hddLog(VOS_TRACE_LEVEL_FATAL,
3300 "VOS Global Context is NULL");
3301 return -EINVAL;
3302 }
3303
3304 if (NULL == hdd_ctx) {
3305 hddLog(VOS_TRACE_LEVEL_FATAL, "HDD Context is NULL");
3306 return -EINVAL;
3307 }
3308
3309 param = strchr(ptr, ' ');
3310 /*no argument after the command*/
3311 if (NULL == param)
3312 return -EINVAL;
3313
3314 /*no space after the command*/
3315 else if (SPACE_ASCII_VALUE != *param)
3316 return -EINVAL;
3317
3318 param++;
3319
3320 /*removing empty spaces*/
3321 while ((SPACE_ASCII_VALUE == *param) && ('\0' != *param))
3322 param++;
3323
3324 /*no argument followed by spaces*/
3325 if ('\0' == *param)
3326 return -EINVAL;
3327
3328 /*getting the first argument ie the number of channels*/
3329 if (sscanf(param, "%d ", &tempInt) != 1) {
3330 hddLog(VOS_TRACE_LEVEL_ERROR,
3331 "%s: Cannot get number of channels from input",
3332 __func__);
3333 return -EINVAL;
3334 }
3335
3336 if (tempInt < 0 || tempInt > MAX_CHANNEL) {
3337 hddLog(VOS_TRACE_LEVEL_ERROR,
3338 "%s: Invalid Number of channel received", __func__);
3339 return -EINVAL;
3340 }
3341
3342 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
3343 "%s: Number of channel to disable are: %d",
3344 __func__, tempInt);
3345
3346 if (!tempInt) {
3347 if (!wlan_hdd_restore_channels(hdd_ctx)) {
3348 /*
3349 * Free the cache channels only when the command is
3350 * received with num channels as 0
3351 */
3352 wlan_hdd_free_cache_channels(hdd_ctx);
3353 }
3354 return 0;
3355 }
3356
3357 mutex_lock(&hdd_ctx->cache_channel_lock);
3358 if (hdd_alloc_chan_cache(hdd_ctx, tempInt)) {
3359 ret = -ENOMEM;
3360 goto parse_done;
3361 }
3362 index = hdd_ctx->orginal_channels->num_channels - tempInt;
3363
3364 for (j = index; j < hdd_ctx->orginal_channels->num_channels; j++) {
3365 /*
3366 * param pointing to the beginning of first space
3367 * after number of channels
3368 */
3369 param = strpbrk(param, " ");
3370 /*no channel list after the number of channels argument*/
3371 if (NULL == param) {
3372 hddLog(VOS_TRACE_LEVEL_ERROR,
3373 "%s, Invalid No of channel provided in the list",
3374 __func__);
3375 ret = -EINVAL;
3376 goto parse_done;
3377 }
3378
3379 param++;
3380
3381 /*removing empty space*/
3382 while ((SPACE_ASCII_VALUE == *param) && ('\0' != *param))
3383 param++;
3384
3385 if ('\0' == *param) {
3386 hddLog(VOS_TRACE_LEVEL_ERROR,
3387 "%s, No channel is provided in the list",
3388 __func__);
3389 ret = -EINVAL;
3390 goto parse_done;
3391
3392 }
3393
3394 if (sscanf(param, "%d ", &tempInt) != 1) {
3395 hddLog(VOS_TRACE_LEVEL_ERROR,
3396 "%s: Cannot read channel number",
3397 __func__);
3398 ret = -EINVAL;
3399 goto parse_done;
3400
3401 }
3402
3403 if (!IS_CHANNEL_VALID(tempInt)) {
3404 hddLog(VOS_TRACE_LEVEL_ERROR,
3405 "%s: Invalid channel number received",
3406 __func__);
3407 ret = -EINVAL;
3408 goto parse_done;
3409
3410 }
3411
3412 hddLog(VOS_TRACE_LEVEL_INFO, "%s: channel[%d] = %d", __func__,
3413 j, tempInt);
3414 hdd_ctx->orginal_channels->channel_info[j].channel_num =
3415 tempInt;
3416 }
3417
3418 /*extra arguments check*/
3419 param = strchr(param, ' ');
3420 if (NULL != param) {
3421 while ((SPACE_ASCII_VALUE == *param) && ('\0' != *param))
3422 param++;
3423
3424 if ('\0' != *param) {
3425 hddLog(VOS_TRACE_LEVEL_ERROR,
3426 "%s: Invalid argument received", __func__);
3427 ret = -EINVAL;
3428 goto parse_done;
3429 }
3430 }
3431
3432parse_done:
3433 mutex_unlock(&hdd_ctx->cache_channel_lock);
3434 EXIT();
3435
3436 return ret;
3437}
3438
Hanumanth Reddy Pothula8ae38bb2018-03-07 18:59:30 +05303439int hdd_get_disable_ch_list(hdd_context_t *hdd_ctx, tANI_U8 *buf,
3440 tANI_U8 buf_len)
3441{
3442 struct hdd_cache_channel_info *ch_list;
3443 unsigned char i, num_ch;
3444 int len = 0;
3445
3446 mutex_lock(&hdd_ctx->cache_channel_lock);
3447 if (hdd_ctx->orginal_channels &&
3448 hdd_ctx->orginal_channels->num_channels) {
3449 num_ch = hdd_ctx->orginal_channels->num_channels;
3450
3451 if (num_ch == 0) {
3452 mutex_unlock(&hdd_ctx->cache_channel_lock);
3453 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3454 FL("no disable channels programed"));
3455 return 0;
3456 }
3457
3458 len = scnprintf(buf, buf_len, "%s %hhu",
3459 "GET_DISABLE_CHANNEL_LIST", num_ch);
3460
3461 ch_list = hdd_ctx->orginal_channels->channel_info;
3462 if (!ch_list) {
3463 mutex_unlock(&hdd_ctx->cache_channel_lock);
3464 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3465 FL("disable channel list is NULL"));
3466 return 0;
3467 }
3468
3469 for (i = 0; (i < num_ch) && len <= buf_len; i++) {
3470 len += scnprintf(buf + len, buf_len - len,
3471 " %d", ch_list[i].channel_num);
3472 }
3473 }
3474 mutex_unlock(&hdd_ctx->cache_channel_lock);
3475
3476 return len;
3477}
3478
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003479static int hdd_driver_command(hdd_adapter_t *pAdapter,
3480 hdd_priv_data_t *ppriv_data)
Jeff Johnson295189b2012-06-20 16:38:30 -07003481{
Jeff Johnson295189b2012-06-20 16:38:30 -07003482 hdd_priv_data_t priv_data;
3483 tANI_U8 *command = NULL;
Kaushik, Sushant96122442014-10-21 16:40:18 +05303484 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3485 hdd_scaninfo_t *pScanInfo = NULL;
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003486 int ret = 0;
Kaushik, Sushant96122442014-10-21 16:40:18 +05303487 int status;
Anand N Sunkade9adb1b2015-07-29 09:56:45 +05303488#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0))
3489 struct cfg80211_mgmt_tx_params params;
3490#endif
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05303491
3492 ENTER();
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003493 /*
3494 * Note that valid pointers are provided by caller
3495 */
Jeff Johnson295189b2012-06-20 16:38:30 -07003496
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003497 /* copy to local struct to avoid numerous changes to legacy code */
3498 priv_data = *ppriv_data;
Jeff Johnson295189b2012-06-20 16:38:30 -07003499
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003500 if (priv_data.total_len <= 0 ||
3501 priv_data.total_len > WLAN_PRIV_DATA_MAX_LEN)
Sameer Thalappil8ef3a0e2013-04-05 14:36:04 -07003502 {
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003503 hddLog(VOS_TRACE_LEVEL_WARN,
3504 "%s:invalid priv_data.total_len(%d)!!!", __func__,
3505 priv_data.total_len);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003506 ret = -EINVAL;
3507 goto exit;
3508 }
Kaushik, Sushant96122442014-10-21 16:40:18 +05303509 status = wlan_hdd_validate_context(pHddCtx);
3510 if (0 != status)
3511 {
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05303512 ret = -EINVAL;
3513 goto exit;
Kaushik, Sushant96122442014-10-21 16:40:18 +05303514 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003515 /* Allocate +1 for '\0' */
3516 command = kmalloc(priv_data.total_len + 1, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07003517 if (!command)
3518 {
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003519 hddLog(VOS_TRACE_LEVEL_ERROR,
3520 "%s: failed to allocate memory", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003521 ret = -ENOMEM;
3522 goto exit;
3523 }
3524
3525 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
3526 {
3527 ret = -EFAULT;
3528 goto exit;
3529 }
3530
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003531 /* Make sure the command is NUL-terminated */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003532 command[priv_data.total_len] = '\0';
3533
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003534 /* at one time the following block of code was conditional. braces
3535 * have been retained to avoid re-indenting the legacy code
3536 */
Jeff Johnson295189b2012-06-20 16:38:30 -07003537 {
3538 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
3539
3540 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07003541 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -07003542
3543 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
3544 {
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303545 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3546 TRACE_CODE_HDD_P2P_DEV_ADDR_IOCTL,
3547 pAdapter->sessionId, (unsigned)
3548 (*(pHddCtx->p2pDeviceAddress.bytes+2)<<24 |
3549 *(pHddCtx->p2pDeviceAddress.bytes+3)<<16 |
3550 *(pHddCtx->p2pDeviceAddress.bytes+4)<<8 |
3551 *(pHddCtx->p2pDeviceAddress.bytes+5))));
Jeff Johnson295189b2012-06-20 16:38:30 -07003552 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
3553 sizeof(tSirMacAddr)))
3554 {
3555 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Arif Hussain6d2a3322013-11-17 19:50:10 -08003556 "%s: failed to copy data to user buffer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003557 ret = -EFAULT;
3558 }
3559 }
Amar Singhal0974e402013-02-12 14:27:46 -08003560 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07003561 {
Amar Singhal0974e402013-02-12 14:27:46 -08003562 tANI_U8 *ptr = command ;
Srinivas Girigowdade697412013-02-14 16:31:48 -08003563
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05303564 ret = hdd_drv_cmd_validate(command, 7);
3565 if (ret)
3566 goto exit;
3567
Jeff Johnson295189b2012-06-20 16:38:30 -07003568 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -08003569
3570 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -07003571 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07003572 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -08003573 "%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 +05303574 if(VOS_FTM_MODE != hdd_get_conparam())
3575 {
3576 /* Change band request received */
3577 ret = hdd_setBand_helper(pAdapter->dev, ptr);
3578 if(ret < 0)
3579 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
3580 "%s: failed to set band ret=%d", __func__, ret);
3581 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08003582 }
Kiet Lamf040f472013-11-20 21:15:23 +05303583 else if(strncmp(command, "SETWMMPS", 8) == 0)
3584 {
3585 tANI_U8 *ptr = command;
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05303586
3587 ret = hdd_drv_cmd_validate(command, 8);
3588 if (ret)
3589 goto exit;
3590
Kiet Lamf040f472013-11-20 21:15:23 +05303591 ret = hdd_wmmps_helper(pAdapter, ptr);
3592 }
Agarwal Ashishef54a182014-12-16 15:07:31 +05303593
3594 else if(strncmp(command, "TDLSSCAN", 8) == 0)
3595 {
3596 tANI_U8 *ptr = command;
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05303597
3598 ret = hdd_drv_cmd_validate(command, 8);
3599 if (ret)
3600 goto exit;
3601
Agarwal Ashishef54a182014-12-16 15:07:31 +05303602 ret = hdd_set_tdls_scan_type(pAdapter, ptr);
3603 }
3604
Jeff Johnson32d95a32012-09-10 13:15:23 -07003605 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
3606 {
3607 char *country_code;
3608
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05303609 ret = hdd_drv_cmd_validate(command, 7);
3610 if (ret)
3611 goto exit;
3612
Jeff Johnson32d95a32012-09-10 13:15:23 -07003613 country_code = command + 8;
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07003614
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07003615 INIT_COMPLETION(pAdapter->change_country_code);
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07003616 hdd_checkandupdate_dfssetting(pAdapter, country_code);
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -07003617#ifndef CONFIG_ENABLE_LINUX_REG
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +05303618 hdd_checkandupdate_phymode(pAdapter, country_code);
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -07003619#endif
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07003620 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal,
3621 (void *)(tSmeChangeCountryCallback)
3622 wlan_hdd_change_country_code_callback,
Abhishek Singha306a442013-11-07 18:39:01 +05303623 country_code, pAdapter, pHddCtx->pvosContext, eSIR_TRUE, eSIR_TRUE);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07003624 if (eHAL_STATUS_SUCCESS == ret)
3625 {
3626 ret = wait_for_completion_interruptible_timeout(
3627 &pAdapter->change_country_code,
3628 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
3629 if (0 >= ret)
3630 {
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003631 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: SME while setting country code timed out %d",
c_hpothu6ff1c3c2013-10-01 19:01:57 +05303632 __func__, ret);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07003633 }
3634 }
3635 else
Jeff Johnson32d95a32012-09-10 13:15:23 -07003636 {
3637 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003638 "%s: SME Change Country code fail ret=%d", __func__, ret);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07003639 ret = -EINVAL;
Jeff Johnson32d95a32012-09-10 13:15:23 -07003640 }
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07003641
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07003642 }
3643 /*
3644 command should be a string having format
3645 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
3646 */
Amar Singhal0974e402013-02-12 14:27:46 -08003647 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07003648 {
Amar Singhal0974e402013-02-12 14:27:46 -08003649 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07003650
3651 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003652 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07003653
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -08003654 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -07003655 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -08003656 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
3657 {
3658 int suspend = 0;
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05303659 tANI_U8 *ptr;
3660
3661 ret = hdd_drv_cmd_validate(command, 14);
3662 if (ret)
3663 goto exit;
3664
3665 ptr = (tANI_U8*)command + 15;
Sameer Thalappil45931fb2013-02-01 11:18:05 -08003666
3667 suspend = *ptr - '0';
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303668 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3669 TRACE_CODE_HDD_SETSUSPENDMODE_IOCTL,
3670 pAdapter->sessionId, suspend));
Sameer Thalappil45931fb2013-02-01 11:18:05 -08003671 hdd_set_wlan_suspend_mode(suspend);
3672 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08003673#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
3674 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
3675 {
3676 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003677 tANI_S8 rssi = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08003678 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
3679 eHalStatus status = eHAL_STATUS_SUCCESS;
3680
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05303681 ret = hdd_drv_cmd_validate(command, 14);
3682 if (ret)
3683 goto exit;
3684
Srinivas Girigowdade697412013-02-14 16:31:48 -08003685 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
3686 value = value + 15;
3687
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003688 /* Convert the value from ascii to integer */
3689 ret = kstrtos8(value, 10, &rssi);
3690 if (ret < 0)
3691 {
3692 /* If the input value is greater than max value of datatype, then also
3693 kstrtou8 fails */
3694 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3695 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdafa7157d2013-10-31 10:14:22 -07003696 __func__,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003697 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
3698 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
3699 ret = -EINVAL;
3700 goto exit;
3701 }
3702
Srinivas Girigowdade697412013-02-14 16:31:48 -08003703 lookUpThreshold = abs(rssi);
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003704
Srinivas Girigowdade697412013-02-14 16:31:48 -08003705 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
3706 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
3707 {
3708 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3709 "Neighbor lookup threshold value %d is out of range"
3710 " (Min: %d Max: %d)", lookUpThreshold,
3711 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
3712 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
3713 ret = -EINVAL;
3714 goto exit;
3715 }
3716
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303717 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3718 TRACE_CODE_HDD_SETROAMTRIGGER_IOCTL,
3719 pAdapter->sessionId, lookUpThreshold));
Srinivas Girigowdade697412013-02-14 16:31:48 -08003720 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3721 "%s: Received Command to Set Roam trigger"
3722 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
3723
3724 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
3725 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
3726 if (eHAL_STATUS_SUCCESS != status)
3727 {
3728 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3729 "%s: Failed to set roam trigger, try again", __func__);
3730 ret = -EPERM;
3731 goto exit;
3732 }
3733
3734 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
mukul sharmad6e1fdd2014-06-23 19:19:09 +05303735 pHddCtx->cfg_ini->nNeighborReassocRssiThreshold = lookUpThreshold + 5;
Srinivas Girigowdade697412013-02-14 16:31:48 -08003736 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
3737 }
3738 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
3739 {
3740 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
3741 int rssi = (-1) * lookUpThreshold;
3742 char extra[32];
3743 tANI_U8 len = 0;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303744 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3745 TRACE_CODE_HDD_GETROAMTRIGGER_IOCTL,
3746 pAdapter->sessionId, lookUpThreshold));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003747 len = scnprintf(extra, sizeof(extra), "%s %d", command, rssi);
Srinivas Girigowda91719232015-07-13 15:10:10 +05303748 len = VOS_MIN(priv_data.total_len, len + 1);
3749 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdade697412013-02-14 16:31:48 -08003750 {
3751 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3752 "%s: failed to copy data to user buffer", __func__);
3753 ret = -EFAULT;
3754 goto exit;
3755 }
3756 }
3757 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
3758 {
3759 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003760 tANI_U8 roamScanPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003761 tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003762
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05303763 ret = hdd_drv_cmd_validate(command, 17);
3764 if (ret)
3765 goto exit;
3766
Srinivas Girigowdade697412013-02-14 16:31:48 -08003767 /* input refresh period is in terms of seconds */
3768 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
3769 value = value + 18;
3770 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003771 ret = kstrtou8(value, 10, &roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08003772 if (ret < 0)
3773 {
3774 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003775 kstrtou8 fails */
Srinivas Girigowdade697412013-02-14 16:31:48 -08003776 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003777 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdade697412013-02-14 16:31:48 -08003778 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07003779 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
3780 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08003781 ret = -EINVAL;
3782 goto exit;
3783 }
3784
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003785 if ((roamScanPeriod < (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000)) ||
3786 (roamScanPeriod > (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000)))
Srinivas Girigowdade697412013-02-14 16:31:48 -08003787 {
3788 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003789 "Roam scan period value %d is out of range"
3790 " (Min: %d Max: %d)", roamScanPeriod,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07003791 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
3792 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08003793 ret = -EINVAL;
3794 goto exit;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303795 }
3796 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3797 TRACE_CODE_HDD_SETROAMSCANPERIOD_IOCTL,
3798 pAdapter->sessionId, roamScanPeriod));
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003799 neighborEmptyScanRefreshPeriod = roamScanPeriod * 1000;
Srinivas Girigowdade697412013-02-14 16:31:48 -08003800
3801 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3802 "%s: Received Command to Set roam scan period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003803 " (Empty Scan refresh period) = %d", __func__, roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08003804
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003805 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod;
3806 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08003807 }
3808 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
3809 {
3810 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
3811 char extra[32];
3812 tANI_U8 len = 0;
3813
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303814 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3815 TRACE_CODE_HDD_GETROAMSCANPERIOD_IOCTL,
3816 pAdapter->sessionId, nEmptyScanRefreshPeriod));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003817 len = scnprintf(extra, sizeof(extra), "%s %d",
3818 "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08003819 /* Returned value is in units of seconds */
Ratnam Rachuria72ba112015-07-17 13:27:03 +05303820 len = VOS_MIN(priv_data.total_len, len + 1);
3821 if (copy_to_user(priv_data.buf, &extra, len)) {
Srinivas Girigowdade697412013-02-14 16:31:48 -08003822 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3823 "%s: failed to copy data to user buffer", __func__);
3824 ret = -EFAULT;
3825 goto exit;
3826 }
3827 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003828 else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0)
3829 {
3830 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003831 tANI_U8 roamScanRefreshPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003832 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003833
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05303834 ret = hdd_drv_cmd_validate(command, 24);
3835 if (ret)
3836 goto exit;
3837
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003838 /* input refresh period is in terms of seconds */
3839 /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */
3840 value = value + 25;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003841
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003842 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003843 ret = kstrtou8(value, 10, &roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003844 if (ret < 0)
3845 {
3846 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003847 kstrtou8 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003848 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003849 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003850 __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003851 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
3852 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
3853 ret = -EINVAL;
3854 goto exit;
3855 }
3856
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003857 if ((roamScanRefreshPeriod < (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000)) ||
3858 (roamScanRefreshPeriod > (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000)))
3859 {
3860 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3861 "Neighbor scan results refresh period value %d is out of range"
3862 " (Min: %d Max: %d)", roamScanRefreshPeriod,
3863 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
3864 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
3865 ret = -EINVAL;
3866 goto exit;
3867 }
3868 neighborScanRefreshPeriod = roamScanRefreshPeriod * 1000;
3869
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003870 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3871 "%s: Received Command to Set roam scan refresh period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003872 " (Scan refresh period) = %d", __func__, roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003873
3874 pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod;
3875 sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
3876 }
3877 else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0)
3878 {
3879 tANI_U16 value = sme_getNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
3880 char extra[32];
3881 tANI_U8 len = 0;
3882
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003883 len = scnprintf(extra, sizeof(extra), "%s %d",
3884 "GETROAMSCANREFRESHPERIOD", (value/1000));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003885 /* Returned value is in units of seconds */
Ratnam Rachuri2c9d6702015-07-17 13:25:16 +05303886 len = VOS_MIN(priv_data.total_len, len + 1);
3887 if (copy_to_user(priv_data.buf, &extra, len)) {
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003888 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3889 "%s: failed to copy data to user buffer", __func__);
3890 ret = -EFAULT;
3891 goto exit;
3892 }
3893 }
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07003894#ifdef FEATURE_WLAN_LFR
3895 /* SETROAMMODE */
3896 else if (strncmp(command, "SETROAMMODE", SIZE_OF_SETROAMMODE) == 0)
3897 {
3898 tANI_U8 *value = command;
3899 tANI_BOOLEAN roamMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
3900
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05303901 if (pHddCtx->concurrency_mode == VOS_STA_MON) {
3902 hddLog(LOGE,
3903 FL("Roaming is always disabled in STA + MON concurrency"));
3904 ret = -EINVAL;
3905 goto exit;
3906 }
3907
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05303908 ret = hdd_drv_cmd_validate(command, SIZE_OF_SETROAMMODE);
3909 if (ret)
3910 goto exit;
3911
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07003912 /* Move pointer to ahead of SETROAMMODE<delimiter> */
3913 value = value + SIZE_OF_SETROAMMODE + 1;
3914
3915 /* Convert the value from ascii to integer */
3916 ret = kstrtou8(value, SIZE_OF_SETROAMMODE, &roamMode);
3917 if (ret < 0)
3918 {
3919 /* If the input value is greater than max value of datatype, then also
3920 kstrtou8 fails */
3921 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3922 "%s: kstrtou8 failed range [%d - %d]", __func__,
3923 CFG_LFR_FEATURE_ENABLED_MIN,
3924 CFG_LFR_FEATURE_ENABLED_MAX);
3925 ret = -EINVAL;
3926 goto exit;
3927 }
3928 if ((roamMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
3929 (roamMode > CFG_LFR_FEATURE_ENABLED_MAX))
3930 {
3931 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3932 "Roam Mode value %d is out of range"
3933 " (Min: %d Max: %d)", roamMode,
3934 CFG_LFR_FEATURE_ENABLED_MIN,
3935 CFG_LFR_FEATURE_ENABLED_MAX);
3936 ret = -EINVAL;
3937 goto exit;
3938 }
3939
3940 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3941 "%s: Received Command to Set Roam Mode = %d", __func__, roamMode);
3942 /*
3943 * Note that
3944 * SETROAMMODE 0 is to enable LFR while
3945 * SETROAMMODE 1 is to disable LFR, but
3946 * NotifyIsFastRoamIniFeatureEnabled 0/1 is to enable/disable.
3947 * So, we have to invert the value to call sme_UpdateIsFastRoamIniFeatureEnabled.
3948 */
3949 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
3950 roamMode = CFG_LFR_FEATURE_ENABLED_MAX; /* Roam enable */
3951 else
3952 roamMode = CFG_LFR_FEATURE_ENABLED_MIN; /* Roam disable */
3953
3954 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = roamMode;
3955 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), roamMode);
3956 }
3957 /* GETROAMMODE */
Mahesh A Saptasagarec7d1092015-04-02 13:41:34 +05303958 else if (strncmp(command, "GETROAMMODE", SIZE_OF_GETROAMMODE) == 0)
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07003959 {
3960 tANI_BOOLEAN roamMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
3961 char extra[32];
3962 tANI_U8 len = 0;
3963
3964 /*
3965 * roamMode value shall be inverted because the sementics is different.
3966 */
3967 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
3968 roamMode = CFG_LFR_FEATURE_ENABLED_MAX;
3969 else
3970 roamMode = CFG_LFR_FEATURE_ENABLED_MIN;
3971
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003972 len = scnprintf(extra, sizeof(extra), "%s %d", command, roamMode);
Ratnam Rachuri28693eb2015-07-17 13:23:42 +05303973 len = VOS_MIN(priv_data.total_len, len + 1);
3974 if (copy_to_user(priv_data.buf, &extra, len)) {
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07003975 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3976 "%s: failed to copy data to user buffer", __func__);
3977 ret = -EFAULT;
3978 goto exit;
3979 }
3980 }
3981#endif
Srinivas Girigowdade697412013-02-14 16:31:48 -08003982#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003983#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -08003984 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
3985 {
3986 tANI_U8 *value = command;
3987 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
3988
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05303989 ret = hdd_drv_cmd_validate(command, 12);
3990 if (ret)
3991 goto exit;
3992
Srinivas Girigowdade697412013-02-14 16:31:48 -08003993 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
3994 value = value + 13;
3995 /* Convert the value from ascii to integer */
3996 ret = kstrtou8(value, 10, &roamRssiDiff);
3997 if (ret < 0)
3998 {
3999 /* If the input value is greater than max value of datatype, then also
4000 kstrtou8 fails */
4001 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4002 "%s: kstrtou8 failed range [%d - %d]", __func__,
4003 CFG_ROAM_RSSI_DIFF_MIN,
4004 CFG_ROAM_RSSI_DIFF_MAX);
4005 ret = -EINVAL;
4006 goto exit;
4007 }
4008
4009 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
4010 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
4011 {
4012 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4013 "Roam rssi diff value %d is out of range"
4014 " (Min: %d Max: %d)", roamRssiDiff,
4015 CFG_ROAM_RSSI_DIFF_MIN,
4016 CFG_ROAM_RSSI_DIFF_MAX);
4017 ret = -EINVAL;
4018 goto exit;
4019 }
4020
4021 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4022 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
4023
4024 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
4025 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
4026 }
Mahesh A Saptasagarec7d1092015-04-02 13:41:34 +05304027 else if (strncmp(command, "GETROAMDELTA", 12) == 0)
Srinivas Girigowdade697412013-02-14 16:31:48 -08004028 {
4029 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
4030 char extra[32];
4031 tANI_U8 len = 0;
4032
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05304033 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
4034 TRACE_CODE_HDD_GETROAMDELTA_IOCTL,
4035 pAdapter->sessionId, roamRssiDiff));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004036 len = scnprintf(extra, sizeof(extra), "%s %d",
4037 command, roamRssiDiff);
Ratnam Rachuri22a3b402015-07-17 13:21:49 +05304038 len = VOS_MIN(priv_data.total_len, len + 1);
4039 if (copy_to_user(priv_data.buf, &extra, len)) {
Srinivas Girigowdade697412013-02-14 16:31:48 -08004040 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4041 "%s: failed to copy data to user buffer", __func__);
4042 ret = -EFAULT;
4043 goto exit;
4044 }
4045 }
4046#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004047#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -08004048 else if (strncmp(command, "GETBAND", 7) == 0)
4049 {
4050 int band = -1;
4051 char extra[32];
4052 tANI_U8 len = 0;
4053 hdd_getBand_helper(pHddCtx, &band);
4054
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05304055 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
4056 TRACE_CODE_HDD_GETBAND_IOCTL,
4057 pAdapter->sessionId, band));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004058 len = scnprintf(extra, sizeof(extra), "%s %d", command, band);
Ratnam Rachuri52139592015-07-17 13:17:29 +05304059 len = VOS_MIN(priv_data.total_len, len + 1);
4060 if (copy_to_user(priv_data.buf, &extra, len)) {
Srinivas Girigowdade697412013-02-14 16:31:48 -08004061 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4062 "%s: failed to copy data to user buffer", __func__);
4063 ret = -EFAULT;
4064 goto exit;
4065 }
4066 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004067 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
4068 {
4069 tANI_U8 *value = command;
4070 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
4071 tANI_U8 numChannels = 0;
4072 eHalStatus status = eHAL_STATUS_SUCCESS;
4073
4074 status = hdd_parse_channellist(value, ChannelList, &numChannels);
4075 if (eHAL_STATUS_SUCCESS != status)
4076 {
4077 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4078 "%s: Failed to parse channel list information", __func__);
4079 ret = -EINVAL;
4080 goto exit;
4081 }
4082
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05304083 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
4084 TRACE_CODE_HDD_SETROAMSCANCHANNELS_IOCTL,
4085 pAdapter->sessionId, numChannels));
Srinivas Girigowdade697412013-02-14 16:31:48 -08004086 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
4087 {
4088 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4089 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
4090 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
4091 ret = -EINVAL;
4092 goto exit;
4093 }
4094 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
4095 numChannels);
4096 if (eHAL_STATUS_SUCCESS != status)
4097 {
4098 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4099 "%s: Failed to update channel list information", __func__);
4100 ret = -EINVAL;
4101 goto exit;
4102 }
4103 }
4104 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
4105 {
4106 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
4107 tANI_U8 numChannels = 0;
Jeff Johnson51b67782013-04-05 12:35:41 -07004108 tANI_U8 j = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08004109 char extra[128] = {0};
Jeff Johnson51b67782013-04-05 12:35:41 -07004110 int len;
Srinivas Girigowdade697412013-02-14 16:31:48 -08004111
4112 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
4113 ChannelList, &numChannels ))
4114 {
4115 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4116 "%s: failed to get roam scan channel list", __func__);
4117 ret = -EFAULT;
4118 goto exit;
4119 }
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05304120 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
4121 TRACE_CODE_HDD_GETROAMSCANCHANNELS_IOCTL,
4122 pAdapter->sessionId, numChannels));
Srinivas Girigowdade697412013-02-14 16:31:48 -08004123 /* output channel list is of the format
4124 [Number of roam scan channels][Channel1][Channel2]... */
4125 /* copy the number of channels in the 0th index */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004126 len = scnprintf(extra, sizeof(extra), "%s %d", command, numChannels);
Sushant Kaushika08ca192015-09-16 15:52:04 +05304127 for (j = 0; (j < numChannels) && len <= sizeof(extra); j++)
Srinivas Girigowdade697412013-02-14 16:31:48 -08004128 {
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004129 len += scnprintf(extra + len, sizeof(extra) - len, " %d",
4130 ChannelList[j]);
Srinivas Girigowdade697412013-02-14 16:31:48 -08004131 }
4132
Sushant Kaushikc9b8be52015-07-15 16:41:27 +05304133 len = VOS_MIN(priv_data.total_len, len + 1);
4134 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdade697412013-02-14 16:31:48 -08004135 {
4136 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4137 "%s: failed to copy data to user buffer", __func__);
4138 ret = -EFAULT;
4139 goto exit;
4140 }
4141 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004142 else if (strncmp(command, "GETCCXMODE", 10) == 0)
4143 {
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004144 tANI_BOOLEAN eseMode = sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004145 char extra[32];
4146 tANI_U8 len = 0;
4147
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004148 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07004149 then this operation is not permitted (return FAILURE) */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004150 if (eseMode &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07004151 hdd_is_okc_mode_enabled(pHddCtx) &&
4152 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
4153 {
4154 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004155 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07004156 " hence this operation is not permitted!", __func__);
4157 ret = -EPERM;
4158 goto exit;
4159 }
4160
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004161 len = scnprintf(extra, sizeof(extra), "%s %d",
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004162 "GETCCXMODE", eseMode);
Sushant Kaushikf8abd352015-07-15 16:37:49 +05304163 len = VOS_MIN(priv_data.total_len, len + 1);
4164 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004165 {
4166 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4167 "%s: failed to copy data to user buffer", __func__);
4168 ret = -EFAULT;
4169 goto exit;
4170 }
4171 }
4172 else if (strncmp(command, "GETOKCMODE", 10) == 0)
4173 {
4174 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
4175 char extra[32];
4176 tANI_U8 len = 0;
4177
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004178 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07004179 then this operation is not permitted (return FAILURE) */
4180 if (okcMode &&
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004181 sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07004182 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
4183 {
4184 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004185 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07004186 " hence this operation is not permitted!", __func__);
4187 ret = -EPERM;
4188 goto exit;
4189 }
4190
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004191 len = scnprintf(extra, sizeof(extra), "%s %d",
4192 "GETOKCMODE", okcMode);
Sushant Kaushikbc2fb5c2015-07-15 16:43:16 +05304193 len = VOS_MIN(priv_data.total_len, len + 1);
4194 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004195 {
4196 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4197 "%s: failed to copy data to user buffer", __func__);
4198 ret = -EFAULT;
4199 goto exit;
4200 }
4201 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07004202 else if (strncmp(command, "GETFASTROAM", 11) == 0)
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004203 {
4204 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
4205 char extra[32];
4206 tANI_U8 len = 0;
4207
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004208 len = scnprintf(extra, sizeof(extra), "%s %d",
4209 "GETFASTROAM", lfrMode);
Sushant Kaushik4da7ec92015-07-15 16:39:32 +05304210 len = VOS_MIN(priv_data.total_len, len + 1);
4211 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004212 {
4213 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4214 "%s: failed to copy data to user buffer", __func__);
4215 ret = -EFAULT;
4216 goto exit;
4217 }
4218 }
4219 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
4220 {
4221 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
4222 char extra[32];
4223 tANI_U8 len = 0;
4224
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004225 len = scnprintf(extra, sizeof(extra), "%s %d",
4226 "GETFASTTRANSITION", ft);
Sushant Kaushik231a4452015-07-15 16:23:56 +05304227 len = VOS_MIN(priv_data.total_len, len + 1);
4228 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004229 {
4230 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4231 "%s: failed to copy data to user buffer", __func__);
4232 ret = -EFAULT;
4233 goto exit;
4234 }
4235 }
4236 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
4237 {
4238 tANI_U8 *value = command;
4239 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
4240
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304241 ret = hdd_drv_cmd_validate(command, 25);
4242 if (ret)
4243 goto exit;
4244
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004245 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
4246 value = value + 26;
4247 /* Convert the value from ascii to integer */
4248 ret = kstrtou8(value, 10, &minTime);
4249 if (ret < 0)
4250 {
4251 /* If the input value is greater than max value of datatype, then also
4252 kstrtou8 fails */
4253 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4254 "%s: kstrtou8 failed range [%d - %d]", __func__,
4255 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
4256 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
4257 ret = -EINVAL;
4258 goto exit;
4259 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004260 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
4261 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
4262 {
4263 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4264 "scan min channel time value %d is out of range"
4265 " (Min: %d Max: %d)", minTime,
4266 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
4267 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
4268 ret = -EINVAL;
4269 goto exit;
4270 }
4271
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05304272 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
4273 TRACE_CODE_HDD_SETROAMSCANCHANNELMINTIME_IOCTL,
4274 pAdapter->sessionId, minTime));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004275 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4276 "%s: Received Command to change channel min time = %d", __func__, minTime);
4277
4278 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
4279 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
4280 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004281 else if (strncmp(command, "SENDACTIONFRAME", 15) == 0)
4282 {
4283 tANI_U8 *value = command;
4284 tANI_U8 channel = 0;
4285 tANI_U8 dwellTime = 0;
4286 tANI_U8 bufLen = 0;
4287 tANI_U8 *buf = NULL;
4288 tSirMacAddr targetApBssid;
4289 eHalStatus status = eHAL_STATUS_SUCCESS;
4290 struct ieee80211_channel chan;
4291 tANI_U8 finalLen = 0;
4292 tANI_U8 *finalBuf = NULL;
4293 tANI_U8 temp = 0;
4294 u64 cookie;
4295 hdd_station_ctx_t *pHddStaCtx = NULL;
4296 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4297
4298 /* if not associated, no need to send action frame */
4299 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
4300 {
4301 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
4302 ret = -EINVAL;
4303 goto exit;
4304 }
4305
4306 status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel,
4307 &dwellTime, &buf, &bufLen);
4308 if (eHAL_STATUS_SUCCESS != status)
4309 {
4310 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4311 "%s: Failed to parse send action frame data", __func__);
4312 ret = -EINVAL;
4313 goto exit;
4314 }
4315
4316 /* if the target bssid is different from currently associated AP,
4317 then no need to send action frame */
4318 if (VOS_TRUE != vos_mem_compare(targetApBssid,
4319 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
4320 {
4321 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__);
4322 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07004323 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08004324 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004325 goto exit;
4326 }
4327
4328 /* if the channel number is different from operating channel then
4329 no need to send action frame */
4330 if (channel != pHddStaCtx->conn_info.operationChannel)
4331 {
4332 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4333 "%s: channel(%d) is different from operating channel(%d)",
4334 __func__, channel, pHddStaCtx->conn_info.operationChannel);
4335 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07004336 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08004337 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004338 goto exit;
4339 }
4340 chan.center_freq = sme_ChnToFreq(channel);
4341
4342 finalLen = bufLen + 24;
4343 finalBuf = vos_mem_malloc(finalLen);
4344 if (NULL == finalBuf)
4345 {
4346 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__);
4347 ret = -ENOMEM;
Jeff Johnson11c33152013-04-16 17:52:40 -07004348 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08004349 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004350 goto exit;
4351 }
4352 vos_mem_zero(finalBuf, finalLen);
4353
4354 /* Fill subtype */
4355 temp = SIR_MAC_MGMT_ACTION << 4;
4356 vos_mem_copy(finalBuf + 0, &temp, sizeof(temp));
4357
4358 /* Fill type */
4359 temp = SIR_MAC_MGMT_FRAME;
4360 vos_mem_copy(finalBuf + 2, &temp, sizeof(temp));
4361
4362 /* Fill destination address (bssid of the AP) */
4363 vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid));
4364
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07004365 /* Fill source address (STA mac address) */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004366 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
4367
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07004368 /* Fill BSSID (AP mac address) */
4369 vos_mem_copy(finalBuf + 16, targetApBssid, sizeof(targetApBssid));
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004370
4371 /* Fill received buffer from 24th address */
4372 vos_mem_copy(finalBuf + 24, buf, bufLen);
4373
Jeff Johnson11c33152013-04-16 17:52:40 -07004374 /* done with the parsed buffer */
4375 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08004376 buf = NULL;
Jeff Johnson11c33152013-04-16 17:52:40 -07004377
Anand N Sunkade9adb1b2015-07-29 09:56:45 +05304378#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0))
4379 params.chan = &chan;
4380 params.offchan = 0;
4381 params.wait = dwellTime;
4382 params.buf = finalBuf;
4383 params.len = finalLen;
4384 params.no_cck = 1;
4385 params.dont_wait_for_ack = 1;
4386 ret = wlan_hdd_mgmt_tx(NULL, &pAdapter->wdev, &params, &cookie);
4387#else
DARAM SUDHA39eede62014-02-12 11:16:40 +05304388 wlan_hdd_mgmt_tx( NULL,
Yue Maf49ba872013-08-19 12:04:25 -07004389#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
4390 &(pAdapter->wdev),
4391#else
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07004392 pAdapter->dev,
Yue Maf49ba872013-08-19 12:04:25 -07004393#endif
4394 &chan, 0,
4395#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
4396 NL80211_CHAN_HT20, 1,
4397#endif
4398 dwellTime, finalBuf, finalLen, 1,
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004399 1, &cookie );
Anand N Sunkade9adb1b2015-07-29 09:56:45 +05304400#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0)*/
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004401 vos_mem_free(finalBuf);
4402 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004403 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
4404 {
4405 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
4406 char extra[32];
4407 tANI_U8 len = 0;
4408
4409 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004410 len = scnprintf(extra, sizeof(extra), "%s %d",
4411 "GETROAMSCANCHANNELMINTIME", val);
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05304412 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
4413 TRACE_CODE_HDD_GETROAMSCANCHANNELMINTIME_IOCTL,
4414 pAdapter->sessionId, val));
Sushant Kaushikbb8c52c2015-07-15 16:36:23 +05304415 len = VOS_MIN(priv_data.total_len, len + 1);
4416 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004417 {
4418 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4419 "%s: failed to copy data to user buffer", __func__);
4420 ret = -EFAULT;
4421 goto exit;
4422 }
4423 }
4424 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
4425 {
4426 tANI_U8 *value = command;
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07004427 tANI_U16 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004428
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304429 ret = hdd_drv_cmd_validate(command, 18);
4430 if (ret)
4431 goto exit;
4432
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004433 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
4434 value = value + 19;
4435 /* Convert the value from ascii to integer */
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07004436 ret = kstrtou16(value, 10, &maxTime);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004437 if (ret < 0)
4438 {
4439 /* If the input value is greater than max value of datatype, then also
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07004440 kstrtou16 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004441 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07004442 "%s: kstrtou16 failed range [%d - %d]", __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004443 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
4444 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
4445 ret = -EINVAL;
4446 goto exit;
4447 }
4448
4449 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
4450 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
4451 {
4452 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4453 "lfr mode value %d is out of range"
4454 " (Min: %d Max: %d)", maxTime,
4455 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
4456 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
4457 ret = -EINVAL;
4458 goto exit;
4459 }
4460
4461 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4462 "%s: Received Command to change channel max time = %d", __func__, maxTime);
4463
4464 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
4465 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
4466 }
4467 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
4468 {
4469 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
4470 char extra[32];
4471 tANI_U8 len = 0;
4472
4473 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004474 len = scnprintf(extra, sizeof(extra), "%s %d",
4475 "GETSCANCHANNELTIME", val);
Ratheesh S Pacbfa932015-07-16 15:27:18 +05304476 len = VOS_MIN(priv_data.total_len, len + 1);
4477 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004478 {
4479 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4480 "%s: failed to copy data to user buffer", __func__);
4481 ret = -EFAULT;
4482 goto exit;
4483 }
4484 }
4485 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
4486 {
4487 tANI_U8 *value = command;
4488 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
4489
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304490 ret = hdd_drv_cmd_validate(command, 15);
4491 if (ret)
4492 goto exit;
4493
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004494 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
4495 value = value + 16;
4496 /* Convert the value from ascii to integer */
4497 ret = kstrtou16(value, 10, &val);
4498 if (ret < 0)
4499 {
4500 /* If the input value is greater than max value of datatype, then also
4501 kstrtou16 fails */
4502 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4503 "%s: kstrtou16 failed range [%d - %d]", __func__,
4504 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
4505 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
4506 ret = -EINVAL;
4507 goto exit;
4508 }
4509
4510 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
4511 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
4512 {
4513 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4514 "scan home time value %d is out of range"
4515 " (Min: %d Max: %d)", val,
4516 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
4517 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
4518 ret = -EINVAL;
4519 goto exit;
4520 }
4521
4522 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4523 "%s: Received Command to change scan home time = %d", __func__, val);
4524
4525 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
4526 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
4527 }
4528 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
4529 {
4530 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
4531 char extra[32];
4532 tANI_U8 len = 0;
4533
4534 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004535 len = scnprintf(extra, sizeof(extra), "%s %d",
4536 "GETSCANHOMETIME", val);
Ratheesh S P728d7c62015-07-16 15:38:58 +05304537 len = VOS_MIN(priv_data.total_len, len + 1);
4538 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004539 {
4540 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4541 "%s: failed to copy data to user buffer", __func__);
4542 ret = -EFAULT;
4543 goto exit;
4544 }
4545 }
4546 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
4547 {
4548 tANI_U8 *value = command;
4549 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
4550
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304551 ret = hdd_drv_cmd_validate(command, 16);
4552 if (ret)
4553 goto exit;
4554
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004555 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
4556 value = value + 17;
4557 /* Convert the value from ascii to integer */
4558 ret = kstrtou8(value, 10, &val);
4559 if (ret < 0)
4560 {
4561 /* If the input value is greater than max value of datatype, then also
4562 kstrtou8 fails */
4563 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4564 "%s: kstrtou8 failed range [%d - %d]", __func__,
4565 CFG_ROAM_INTRA_BAND_MIN,
4566 CFG_ROAM_INTRA_BAND_MAX);
4567 ret = -EINVAL;
4568 goto exit;
4569 }
4570
4571 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
4572 (val > CFG_ROAM_INTRA_BAND_MAX))
4573 {
4574 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4575 "intra band mode value %d is out of range"
4576 " (Min: %d Max: %d)", val,
4577 CFG_ROAM_INTRA_BAND_MIN,
4578 CFG_ROAM_INTRA_BAND_MAX);
4579 ret = -EINVAL;
4580 goto exit;
4581 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004582 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4583 "%s: Received Command to change intra band = %d", __func__, val);
4584
4585 pHddCtx->cfg_ini->nRoamIntraBand = val;
4586 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
4587 }
4588 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
4589 {
4590 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
4591 char extra[32];
4592 tANI_U8 len = 0;
4593
4594 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004595 len = scnprintf(extra, sizeof(extra), "%s %d",
4596 "GETROAMINTRABAND", val);
Ratheesh S P2dd2a3e2015-07-16 15:34:23 +05304597 len = VOS_MIN(priv_data.total_len, len + 1);
4598 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004599 {
4600 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4601 "%s: failed to copy data to user buffer", __func__);
4602 ret = -EFAULT;
4603 goto exit;
4604 }
4605 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004606 else if (strncmp(command, "SETSCANNPROBES", 14) == 0)
4607 {
4608 tANI_U8 *value = command;
4609 tANI_U8 nProbes = CFG_ROAM_SCAN_N_PROBES_DEFAULT;
4610
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304611 ret = hdd_drv_cmd_validate(command, 14);
4612 if (ret)
4613 goto exit;
4614
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004615 /* Move pointer to ahead of SETSCANNPROBES<delimiter> */
4616 value = value + 15;
4617 /* Convert the value from ascii to integer */
4618 ret = kstrtou8(value, 10, &nProbes);
4619 if (ret < 0)
4620 {
4621 /* If the input value is greater than max value of datatype, then also
4622 kstrtou8 fails */
4623 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4624 "%s: kstrtou8 failed range [%d - %d]", __func__,
4625 CFG_ROAM_SCAN_N_PROBES_MIN,
4626 CFG_ROAM_SCAN_N_PROBES_MAX);
4627 ret = -EINVAL;
4628 goto exit;
4629 }
4630
4631 if ((nProbes < CFG_ROAM_SCAN_N_PROBES_MIN) ||
4632 (nProbes > CFG_ROAM_SCAN_N_PROBES_MAX))
4633 {
4634 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4635 "NProbes value %d is out of range"
4636 " (Min: %d Max: %d)", nProbes,
4637 CFG_ROAM_SCAN_N_PROBES_MIN,
4638 CFG_ROAM_SCAN_N_PROBES_MAX);
4639 ret = -EINVAL;
4640 goto exit;
4641 }
4642
4643 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4644 "%s: Received Command to Set nProbes = %d", __func__, nProbes);
4645
4646 pHddCtx->cfg_ini->nProbes = nProbes;
4647 sme_UpdateRoamScanNProbes((tHalHandle)(pHddCtx->hHal), nProbes);
4648 }
Mahesh A Saptasagarec7d1092015-04-02 13:41:34 +05304649 else if (strncmp(command, "GETSCANNPROBES", 14) == 0)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004650 {
4651 tANI_U8 val = sme_getRoamScanNProbes((tHalHandle)(pHddCtx->hHal));
4652 char extra[32];
4653 tANI_U8 len = 0;
4654
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004655 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Ratnam Rachuri6da525d2015-08-07 13:55:54 +05304656 len = VOS_MIN(priv_data.total_len, len + 1);
4657 if (copy_to_user(priv_data.buf, &extra, len)) {
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004658 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4659 "%s: failed to copy data to user buffer", __func__);
4660 ret = -EFAULT;
4661 goto exit;
4662 }
4663 }
4664 else if (strncmp(command, "SETSCANHOMEAWAYTIME", 19) == 0)
4665 {
4666 tANI_U8 *value = command;
4667 tANI_U16 homeAwayTime = CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT;
4668
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304669 ret = hdd_drv_cmd_validate(command, 19);
4670 if (ret)
4671 goto exit;
4672
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004673 /* Move pointer to ahead of SETSCANHOMEAWAYTIME<delimiter> */
4674 /* input value is in units of msec */
4675 value = value + 20;
4676 /* Convert the value from ascii to integer */
4677 ret = kstrtou16(value, 10, &homeAwayTime);
4678 if (ret < 0)
4679 {
4680 /* If the input value is greater than max value of datatype, then also
4681 kstrtou8 fails */
4682 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4683 "%s: kstrtou8 failed range [%d - %d]", __func__,
4684 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
4685 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
4686 ret = -EINVAL;
4687 goto exit;
4688 }
4689
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004690 if ((homeAwayTime < CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN) ||
4691 (homeAwayTime > CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX))
4692 {
4693 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4694 "homeAwayTime value %d is out of range"
4695 " (Min: %d Max: %d)", homeAwayTime,
4696 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
4697 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
4698 ret = -EINVAL;
4699 goto exit;
4700 }
4701
4702 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4703 "%s: Received Command to Set scan away time = %d", __func__, homeAwayTime);
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07004704 if (pHddCtx->cfg_ini->nRoamScanHomeAwayTime != homeAwayTime)
4705 {
4706 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
4707 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_TRUE);
4708 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004709 }
Mahesh A Saptasagarec7d1092015-04-02 13:41:34 +05304710 else if (strncmp(command, "GETSCANHOMEAWAYTIME", 19) == 0)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004711 {
4712 tANI_U16 val = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
4713 char extra[32];
4714 tANI_U8 len = 0;
4715
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004716 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Ratnam Rachuri51a5ad12015-08-07 14:06:37 +05304717 len = VOS_MIN(priv_data.total_len, len + 1);
4718 if (copy_to_user(priv_data.buf, &extra, len)) {
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004719 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4720 "%s: failed to copy data to user buffer", __func__);
4721 ret = -EFAULT;
4722 goto exit;
4723 }
4724 }
4725 else if (strncmp(command, "REASSOC", 7) == 0)
4726 {
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304727 ret = hdd_drv_cmd_validate(command, 7);
4728 if (ret)
4729 goto exit;
4730
4731 ret = hdd_parse_reassoc(pAdapter, command, priv_data.total_len);
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05304732 if (!ret)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004733 goto exit;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004734 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07004735 else if (strncmp(command, "SETWESMODE", 10) == 0)
4736 {
4737 tANI_U8 *value = command;
4738 tANI_BOOLEAN wesMode = CFG_ENABLE_WES_MODE_NAME_DEFAULT;
4739
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304740 ret = hdd_drv_cmd_validate(command, 10);
4741 if (ret)
4742 goto exit;
4743
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07004744 /* Move pointer to ahead of SETWESMODE<delimiter> */
4745 value = value + 11;
4746 /* Convert the value from ascii to integer */
4747 ret = kstrtou8(value, 10, &wesMode);
4748 if (ret < 0)
4749 {
4750 /* If the input value is greater than max value of datatype, then also
4751 kstrtou8 fails */
4752 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4753 "%s: kstrtou8 failed range [%d - %d]", __func__,
4754 CFG_ENABLE_WES_MODE_NAME_MIN,
4755 CFG_ENABLE_WES_MODE_NAME_MAX);
4756 ret = -EINVAL;
4757 goto exit;
4758 }
4759
4760 if ((wesMode < CFG_ENABLE_WES_MODE_NAME_MIN) ||
4761 (wesMode > CFG_ENABLE_WES_MODE_NAME_MAX))
4762 {
4763 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4764 "WES Mode value %d is out of range"
4765 " (Min: %d Max: %d)", wesMode,
4766 CFG_ENABLE_WES_MODE_NAME_MIN,
4767 CFG_ENABLE_WES_MODE_NAME_MAX);
4768 ret = -EINVAL;
4769 goto exit;
4770 }
4771 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4772 "%s: Received Command to Set WES Mode rssi diff = %d", __func__, wesMode);
4773
4774 pHddCtx->cfg_ini->isWESModeEnabled = wesMode;
4775 sme_UpdateWESMode((tHalHandle)(pHddCtx->hHal), wesMode);
4776 }
Mahesh A Saptasagarec7d1092015-04-02 13:41:34 +05304777 else if (strncmp(command, "GETWESMODE", 10) == 0)
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07004778 {
4779 tANI_BOOLEAN wesMode = sme_GetWESMode((tHalHandle)(pHddCtx->hHal));
4780 char extra[32];
4781 tANI_U8 len = 0;
4782
Arif Hussain826d9412013-11-12 16:44:54 -08004783 len = scnprintf(extra, sizeof(extra), "%s %d", command, wesMode);
Ratnam Rachuri8fe90c62015-08-07 14:03:26 +05304784 len = VOS_MIN(priv_data.total_len, len + 1);
4785 if (copy_to_user(priv_data.buf, &extra, len)) {
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07004786 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4787 "%s: failed to copy data to user buffer", __func__);
4788 ret = -EFAULT;
4789 goto exit;
4790 }
4791 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004792#endif /* WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_ESE || FEATURE_WLAN_LFR */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004793#ifdef FEATURE_WLAN_LFR
4794 else if (strncmp(command, "SETFASTROAM", 11) == 0)
4795 {
4796 tANI_U8 *value = command;
4797 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
4798
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05304799 if (pHddCtx->concurrency_mode == VOS_STA_MON) {
4800 hddLog(LOGE,
4801 FL("Roaming is always disabled in STA + MON concurrency"));
4802 ret = -EINVAL;
4803 goto exit;
4804 }
4805
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304806 ret = hdd_drv_cmd_validate(command, 11);
4807 if (ret)
4808 goto exit;
4809
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004810 /* Move pointer to ahead of SETFASTROAM<delimiter> */
4811 value = value + 12;
4812 /* Convert the value from ascii to integer */
4813 ret = kstrtou8(value, 10, &lfrMode);
4814 if (ret < 0)
4815 {
4816 /* If the input value is greater than max value of datatype, then also
4817 kstrtou8 fails */
4818 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4819 "%s: kstrtou8 failed range [%d - %d]", __func__,
4820 CFG_LFR_FEATURE_ENABLED_MIN,
4821 CFG_LFR_FEATURE_ENABLED_MAX);
4822 ret = -EINVAL;
4823 goto exit;
4824 }
4825
4826 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
4827 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
4828 {
4829 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4830 "lfr mode value %d is out of range"
4831 " (Min: %d Max: %d)", lfrMode,
4832 CFG_LFR_FEATURE_ENABLED_MIN,
4833 CFG_LFR_FEATURE_ENABLED_MAX);
4834 ret = -EINVAL;
4835 goto exit;
4836 }
4837
4838 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4839 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
4840
4841 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
4842 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
4843 }
4844#endif
4845#ifdef WLAN_FEATURE_VOWIFI_11R
4846 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
4847 {
4848 tANI_U8 *value = command;
4849 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
4850
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304851 ret = hdd_drv_cmd_validate(command, 17);
4852 if (ret)
4853 goto exit;
4854
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004855 /* Move pointer to ahead of SETFASTROAM<delimiter> */
4856 value = value + 18;
4857 /* Convert the value from ascii to integer */
4858 ret = kstrtou8(value, 10, &ft);
4859 if (ret < 0)
4860 {
4861 /* If the input value is greater than max value of datatype, then also
4862 kstrtou8 fails */
4863 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4864 "%s: kstrtou8 failed range [%d - %d]", __func__,
4865 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
4866 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
4867 ret = -EINVAL;
4868 goto exit;
4869 }
4870
4871 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
4872 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
4873 {
4874 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4875 "ft mode value %d is out of range"
4876 " (Min: %d Max: %d)", ft,
4877 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
4878 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
4879 ret = -EINVAL;
4880 goto exit;
4881 }
4882
4883 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4884 "%s: Received Command to change ft mode = %d", __func__, ft);
4885
4886 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
4887 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
4888 }
Padma, Santhosh Kumar778d8382015-03-04 17:41:22 +05304889 else if (strncmp(command, "SETDFSSCANMODE", 14) == 0)
4890 {
4891 tANI_U8 *value = command;
4892 tANI_U8 dfsScanMode = DFS_CHNL_SCAN_ENABLED_NORMAL;
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05304893
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304894 ret = hdd_drv_cmd_validate(command, 14);
4895 if (ret)
4896 goto exit;
4897
Padma, Santhosh Kumar778d8382015-03-04 17:41:22 +05304898 /* Move pointer to ahead of SETDFSSCANMODE<delimiter> */
4899 value = value + 15;
4900 /* Convert the value from ascii to integer */
4901 ret = kstrtou8(value, 10, &dfsScanMode);
4902 if (ret < 0)
4903 {
4904 /* If the input value is greater than max value of
4905 datatype, then also kstrtou8 fails
4906 */
4907 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4908 "%s: kstrtou8 failed range [%d - %d]", __func__,
4909 CFG_ENABLE_DFS_CHNL_SCAN_MIN,
4910 CFG_ENABLE_DFS_CHNL_SCAN_MAX);
4911 ret = -EINVAL;
4912 goto exit;
4913 }
4914
4915 if ((dfsScanMode < CFG_ENABLE_DFS_CHNL_SCAN_MIN) ||
4916 (dfsScanMode > CFG_ENABLE_DFS_CHNL_SCAN_MAX))
4917 {
4918 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4919 "dfsScanMode value %d is out of range"
4920 " (Min: %d Max: %d)", dfsScanMode,
4921 CFG_ENABLE_DFS_CHNL_SCAN_MIN,
4922 CFG_ENABLE_DFS_CHNL_SCAN_MAX);
4923 ret = -EINVAL;
4924 goto exit;
4925 }
4926 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4927 "%s: Received Command to Set DFS Scan Mode = %d",
4928 __func__, dfsScanMode);
4929
4930 ret = wlan_hdd_handle_dfs_chan_scan(pHddCtx, dfsScanMode);
4931 }
4932 else if (strncmp(command, "GETDFSSCANMODE", 14) == 0)
4933 {
4934 tANI_U8 dfsScanMode = sme_GetDFSScanMode(pHddCtx->hHal);
4935 char extra[32];
4936 tANI_U8 len = 0;
4937
4938 len = scnprintf(extra, sizeof(extra), "%s %d", command, dfsScanMode);
Ratheesh S P767224e2015-07-16 15:35:51 +05304939 len = VOS_MIN(priv_data.total_len, len + 1);
4940 if (copy_to_user(priv_data.buf, &extra, len))
Padma, Santhosh Kumar778d8382015-03-04 17:41:22 +05304941 {
4942 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4943 "%s: failed to copy data to user buffer", __func__);
4944 ret = -EFAULT;
4945 goto exit;
4946 }
4947 }
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05304948 else if (strncmp(command, "FASTREASSOC", 11) == 0)
4949 {
Selvaraj, Sridhar3714c4d2016-06-22 15:19:12 +05304950 ret = wlan_hdd_handle_fastreassoc(pAdapter, command);
4951 if (!ret)
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05304952 goto exit;
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05304953 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004954#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004955#ifdef FEATURE_WLAN_ESE
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004956 else if (strncmp(command, "SETCCXMODE", 10) == 0)
4957 {
4958 tANI_U8 *value = command;
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004959 tANI_U8 eseMode = CFG_ESE_FEATURE_ENABLED_DEFAULT;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004960
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304961 ret = hdd_drv_cmd_validate(command, 10);
4962 if (ret)
4963 goto exit;
4964
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004965 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07004966 then this operation is not permitted (return FAILURE) */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004967 if (sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07004968 hdd_is_okc_mode_enabled(pHddCtx) &&
4969 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
4970 {
4971 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004972 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07004973 " hence this operation is not permitted!", __func__);
4974 ret = -EPERM;
4975 goto exit;
4976 }
4977
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004978 /* Move pointer to ahead of SETCCXMODE<delimiter> */
4979 value = value + 11;
4980 /* Convert the value from ascii to integer */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004981 ret = kstrtou8(value, 10, &eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004982 if (ret < 0)
4983 {
4984 /* If the input value is greater than max value of datatype, then also
4985 kstrtou8 fails */
4986 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4987 "%s: kstrtou8 failed range [%d - %d]", __func__,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004988 CFG_ESE_FEATURE_ENABLED_MIN,
4989 CFG_ESE_FEATURE_ENABLED_MAX);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004990 ret = -EINVAL;
4991 goto exit;
4992 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004993 if ((eseMode < CFG_ESE_FEATURE_ENABLED_MIN) ||
4994 (eseMode > CFG_ESE_FEATURE_ENABLED_MAX))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004995 {
4996 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004997 "Ese mode value %d is out of range"
4998 " (Min: %d Max: %d)", eseMode,
4999 CFG_ESE_FEATURE_ENABLED_MIN,
5000 CFG_ESE_FEATURE_ENABLED_MAX);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07005001 ret = -EINVAL;
5002 goto exit;
5003 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07005004 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08005005 "%s: Received Command to change ese mode = %d", __func__, eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07005006
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08005007 pHddCtx->cfg_ini->isEseIniFeatureEnabled = eseMode;
5008 sme_UpdateIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal), eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07005009 }
5010#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07005011 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
5012 {
5013 tANI_U8 *value = command;
5014 tANI_BOOLEAN roamScanControl = 0;
5015
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05305016 ret = hdd_drv_cmd_validate(command, 18);
5017 if (ret)
5018 goto exit;
5019
Srinivas Girigowda100eb322013-03-15 16:48:20 -07005020 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
5021 value = value + 19;
5022 /* Convert the value from ascii to integer */
5023 ret = kstrtou8(value, 10, &roamScanControl);
5024 if (ret < 0)
5025 {
5026 /* If the input value is greater than max value of datatype, then also
5027 kstrtou8 fails */
5028 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5029 "%s: kstrtou8 failed ", __func__);
5030 ret = -EINVAL;
5031 goto exit;
5032 }
5033
5034 if (0 != roamScanControl)
5035 {
5036 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5037 "roam scan control invalid value = %d",
5038 roamScanControl);
5039 ret = -EINVAL;
5040 goto exit;
5041 }
5042 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5043 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
5044
5045 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
5046 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07005047#ifdef FEATURE_WLAN_OKC
5048 else if (strncmp(command, "SETOKCMODE", 10) == 0)
5049 {
5050 tANI_U8 *value = command;
5051 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
5052
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05305053 ret = hdd_drv_cmd_validate(command, 10);
5054 if (ret)
5055 goto exit;
5056
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08005057 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07005058 then this operation is not permitted (return FAILURE) */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08005059 if (sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07005060 hdd_is_okc_mode_enabled(pHddCtx) &&
5061 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
5062 {
5063 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08005064 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07005065 " hence this operation is not permitted!", __func__);
5066 ret = -EPERM;
5067 goto exit;
5068 }
5069
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07005070 /* Move pointer to ahead of SETOKCMODE<delimiter> */
5071 value = value + 11;
5072 /* Convert the value from ascii to integer */
5073 ret = kstrtou8(value, 10, &okcMode);
5074 if (ret < 0)
5075 {
5076 /* If the input value is greater than max value of datatype, then also
5077 kstrtou8 fails */
5078 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5079 "%s: kstrtou8 failed range [%d - %d]", __func__,
5080 CFG_OKC_FEATURE_ENABLED_MIN,
5081 CFG_OKC_FEATURE_ENABLED_MAX);
5082 ret = -EINVAL;
5083 goto exit;
5084 }
5085
5086 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
5087 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
5088 {
5089 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5090 "Okc mode value %d is out of range"
5091 " (Min: %d Max: %d)", okcMode,
5092 CFG_OKC_FEATURE_ENABLED_MIN,
5093 CFG_OKC_FEATURE_ENABLED_MAX);
5094 ret = -EINVAL;
5095 goto exit;
5096 }
5097
5098 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5099 "%s: Received Command to change okc mode = %d", __func__, okcMode);
5100
5101 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
5102 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07005103#endif /* FEATURE_WLAN_OKC */
Mahesh A Saptasagarec7d1092015-04-02 13:41:34 +05305104 else if (strncmp(command, "GETROAMSCANCONTROL", 18) == 0)
Srinivas Girigowda100eb322013-03-15 16:48:20 -07005105 {
5106 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
5107 char extra[32];
5108 tANI_U8 len = 0;
5109
Sameer Thalappilb0a30232013-09-27 15:37:48 -07005110 len = scnprintf(extra, sizeof(extra), "%s %d",
5111 command, roamScanControl);
Ratnam Rachuri083ada82015-08-07 14:01:05 +05305112 len = VOS_MIN(priv_data.total_len, len + 1);
5113 if (copy_to_user(priv_data.buf, &extra, len)) {
Srinivas Girigowda100eb322013-03-15 16:48:20 -07005114 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5115 "%s: failed to copy data to user buffer", __func__);
5116 ret = -EFAULT;
5117 goto exit;
5118 }
5119 }
Gopichand Nakkala227c7f32013-06-26 22:44:57 +05305120#ifdef WLAN_FEATURE_PACKET_FILTERING
5121 else if (strncmp(command, "ENABLE_PKTFILTER_IPV6", 21) == 0)
5122 {
5123 tANI_U8 filterType = 0;
5124 tANI_U8 *value = command;
5125
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05305126 ret = hdd_drv_cmd_validate(command, 21);
5127 if (ret)
5128 goto exit;
5129
Gopichand Nakkala227c7f32013-06-26 22:44:57 +05305130 /* Move pointer to ahead of ENABLE_PKTFILTER_IPV6<delimiter> */
5131 value = value + 22;
5132
5133 /* Convert the value from ascii to integer */
5134 ret = kstrtou8(value, 10, &filterType);
5135 if (ret < 0)
5136 {
5137 /* If the input value is greater than max value of datatype,
5138 * then also kstrtou8 fails
5139 */
5140 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5141 "%s: kstrtou8 failed range ", __func__);
5142 ret = -EINVAL;
5143 goto exit;
5144 }
5145
5146 if (filterType != 0 && filterType != 1)
5147 {
5148 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5149 "%s: Accepted Values are 0 and 1 ", __func__);
5150 ret = -EINVAL;
5151 goto exit;
5152 }
5153 wlan_hdd_setIPv6Filter(WLAN_HDD_GET_CTX(pAdapter), filterType,
5154 pAdapter->sessionId);
5155 }
5156#endif
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05305157 else if (strncmp(command, "BTCOEXMODE", 10) == 0 )
5158 {
Kiet Lamad161252014-07-22 11:23:32 -07005159 char *dhcpPhase;
Satyanarayana Dash1faea4f2014-09-22 16:21:04 +05305160 int ret;
5161
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05305162 ret = hdd_drv_cmd_validate(command, 10);
5163 if (ret)
5164 goto exit;
5165
Kiet Lamad161252014-07-22 11:23:32 -07005166 dhcpPhase = command + 11;
5167 if ('1' == *dhcpPhase)
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05305168 {
Deepthi Gowribfd17132014-11-14 17:59:04 +05305169 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Kiet Lamad161252014-07-22 11:23:32 -07005170 FL("send DHCP START indication"));
c_hpothu9b781ba2013-12-30 20:57:45 +05305171
5172 pHddCtx->btCoexModeSet = TRUE;
Kiet Lamad161252014-07-22 11:23:32 -07005173
Satyanarayana Dash1faea4f2014-09-22 16:21:04 +05305174 ret = wlan_hdd_scan_abort(pAdapter);
5175 if (ret < 0)
5176 {
5177 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5178 FL("failed to abort existing scan %d"), ret);
5179 }
5180
Kiet Lamad161252014-07-22 11:23:32 -07005181 sme_DHCPStartInd(pHddCtx->hHal, pAdapter->device_mode,
5182 pAdapter->sessionId);
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05305183 }
Kiet Lamad161252014-07-22 11:23:32 -07005184 else if ('2' == *dhcpPhase)
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05305185 {
Deepthi Gowribfd17132014-11-14 17:59:04 +05305186 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Kiet Lamad161252014-07-22 11:23:32 -07005187 FL("send DHCP STOP indication"));
c_hpothu9b781ba2013-12-30 20:57:45 +05305188
5189 pHddCtx->btCoexModeSet = FALSE;
Kiet Lamad161252014-07-22 11:23:32 -07005190
5191 sme_DHCPStopInd(pHddCtx->hHal, pAdapter->device_mode,
5192 pAdapter->sessionId);
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05305193 }
5194 }
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07005195 else if (strncmp(command, "SCAN-ACTIVE", 11) == 0)
5196 {
Abhishek Singh58749d62016-02-03 15:27:20 +05305197 hddLog(LOG1,
5198 FL("making default scan to ACTIVE"));
c_hpothudbefd3e2014-04-28 15:59:47 +05305199 pHddCtx->scan_info.scan_mode = eSIR_ACTIVE_SCAN;
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07005200 }
5201 else if (strncmp(command, "SCAN-PASSIVE", 12) == 0)
5202 {
Abhishek Singh58749d62016-02-03 15:27:20 +05305203 hddLog(LOG1,
5204 FL("making default scan to PASSIVE"));
c_hpothudbefd3e2014-04-28 15:59:47 +05305205 pHddCtx->scan_info.scan_mode = eSIR_PASSIVE_SCAN;
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07005206 }
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05305207 else if (strncmp(command, "GETDWELLTIME", 12) == 0)
5208 {
5209 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
5210 char extra[32];
5211 tANI_U8 len = 0;
5212
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05305213 memset(extra, 0, sizeof(extra));
5214 ret = hdd_get_dwell_time(pCfg, command, extra, sizeof(extra), &len);
Ratnam Rachuri12d5d462015-08-07 14:10:23 +05305215 len = VOS_MIN(priv_data.total_len, len + 1);
5216 if (ret != 0 || copy_to_user(priv_data.buf, &extra, len)) {
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05305217 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5218 "%s: failed to copy data to user buffer", __func__);
5219 ret = -EFAULT;
5220 goto exit;
5221 }
5222 ret = len;
5223 }
5224 else if (strncmp(command, "SETDWELLTIME", 12) == 0)
5225 {
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05305226 ret = hdd_set_dwell_time(pAdapter, command);
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05305227 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07005228 else if ( strncasecmp(command, "MIRACAST", 8) == 0 )
5229 {
5230 tANI_U8 filterType = 0;
5231 tANI_U8 *value;
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05305232
5233 ret = hdd_drv_cmd_validate(command, 8);
5234 if (ret)
5235 goto exit;
5236
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07005237 value = command + 9;
5238
5239 /* Convert the value from ascii to integer */
5240 ret = kstrtou8(value, 10, &filterType);
5241 if (ret < 0)
5242 {
5243 /* If the input value is greater than max value of datatype,
5244 * then also kstrtou8 fails
5245 */
5246 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5247 "%s: kstrtou8 failed range ", __func__);
5248 ret = -EINVAL;
5249 goto exit;
5250 }
5251 if ((filterType < WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL ) ||
5252 (filterType > WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL))
5253 {
5254 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5255 "%s: Accepted Values are 0 to 2. 0-Disabled, 1-Source,"
5256 " 2-Sink ", __func__);
5257 ret = -EINVAL;
5258 goto exit;
5259 }
5260 //Filtertype value should be either 0-Disabled, 1-Source, 2-sink
5261 pHddCtx->drvr_miracast = filterType;
Kaushik, Sushant96122442014-10-21 16:40:18 +05305262 pScanInfo = &pHddCtx->scan_info;
5263 if (filterType && pScanInfo != NULL &&
5264 pHddCtx->scan_info.mScanPending)
5265 {
5266 /*Miracast Session started. Abort Scan */
5267 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5268 "%s, Aborting Scan For Miracast",__func__);
5269 hdd_abort_mac_scan(pHddCtx, pScanInfo->sessionId,
5270 eCSR_SCAN_ABORT_DEFAULT);
5271 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07005272 hdd_tx_rx_pkt_cnt_stat_timer_handler(pHddCtx);
Ganesh Kondabattini8f6e3b32014-08-25 16:07:54 +05305273 sme_SetMiracastMode(pHddCtx->hHal, pHddCtx->drvr_miracast);
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07005274 }
Leo Chang614d2072013-08-22 14:59:44 -07005275 else if (strncmp(command, "SETMCRATE", 9) == 0)
5276 {
Leo Chang614d2072013-08-22 14:59:44 -07005277 tANI_U8 *value = command;
5278 int targetRate;
Leo Chang1f98cbd2013-10-17 15:03:52 -07005279 tSirRateUpdateInd *rateUpdate;
5280 eHalStatus status;
Leo Chang614d2072013-08-22 14:59:44 -07005281
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05305282 ret = hdd_drv_cmd_validate(command, 9);
5283 if (ret)
5284 goto exit;
5285
Leo Chang614d2072013-08-22 14:59:44 -07005286 /* Only valid for SAP mode */
5287 if (WLAN_HDD_SOFTAP != pAdapter->device_mode)
5288 {
5289 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5290 "%s: SAP mode is not running", __func__);
5291 ret = -EFAULT;
5292 goto exit;
5293 }
5294
5295 /* Move pointer to ahead of SETMCRATE<delimiter> */
5296 /* input value is in units of hundred kbps */
5297 value = value + 10;
5298 /* Convert the value from ascii to integer, decimal base */
5299 ret = kstrtouint(value, 10, &targetRate);
5300
Leo Chang1f98cbd2013-10-17 15:03:52 -07005301 rateUpdate = (tSirRateUpdateInd *)vos_mem_malloc(sizeof(tSirRateUpdateInd));
5302 if (NULL == rateUpdate)
Leo Chang614d2072013-08-22 14:59:44 -07005303 {
Leo Chang1f98cbd2013-10-17 15:03:52 -07005304 hddLog(VOS_TRACE_LEVEL_ERROR,
5305 "%s: SETMCRATE indication alloc fail", __func__);
5306 ret = -EFAULT;
5307 goto exit;
5308 }
5309 vos_mem_zero(rateUpdate, sizeof(tSirRateUpdateInd ));
5310
5311 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5312 "MC Target rate %d", targetRate);
5313 /* Ignore unicast */
5314 rateUpdate->ucastDataRate = -1;
5315 rateUpdate->mcastDataRate24GHz = targetRate;
5316 rateUpdate->mcastDataRate5GHz = targetRate;
5317 rateUpdate->mcastDataRate24GHzTxFlag = 0;
5318 rateUpdate->mcastDataRate5GHzTxFlag = 0;
5319 status = sme_SendRateUpdateInd(pHddCtx->hHal, rateUpdate);
5320 if (eHAL_STATUS_SUCCESS != status)
5321 {
5322 hddLog(VOS_TRACE_LEVEL_ERROR,
5323 "%s: SET_MC_RATE failed", __func__);
5324 vos_mem_free(rateUpdate);
5325 ret = -EFAULT;
5326 goto exit;
Leo Chang614d2072013-08-22 14:59:44 -07005327 }
5328 }
jge35567202017-06-21 16:39:38 +08005329 else if (strncmp(command, "MAXTXPOWER", 10) == 0)
5330 {
5331 int status;
5332 int txPower;
5333 eHalStatus smeStatus;
5334 tANI_U8 *value = command;
5335 tSirMacAddr bssid = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
5336 tSirMacAddr selfMac = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
5337
5338 status = hdd_parse_setmaxtxpower_command(value, &txPower);
5339 if (status)
5340 {
5341 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5342 "Invalid MAXTXPOWER command ");
5343 ret = -EINVAL;
5344 goto exit;
5345 }
5346
5347 hddLog(VOS_TRACE_LEVEL_INFO, "max tx power %d selfMac: "
5348 MAC_ADDRESS_STR " bssId: " MAC_ADDRESS_STR " ",
5349 txPower, MAC_ADDR_ARRAY(selfMac),
5350 MAC_ADDR_ARRAY(bssid));
5351 smeStatus = sme_SetMaxTxPower((tHalHandle)(pHddCtx->hHal),
5352 bssid, selfMac, txPower) ;
5353 if( smeStatus != eHAL_STATUS_SUCCESS )
5354 {
5355 hddLog(VOS_TRACE_LEVEL_ERROR, "%s:Set max tx power failed",
5356 __func__);
5357 ret = -EINVAL;
5358 goto exit;
5359 }
5360
5361 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Set max tx power success",
5362 __func__);
5363 }
Rajeev79dbe4c2013-10-05 11:03:42 +05305364#ifdef FEATURE_WLAN_BATCH_SCAN
Rajeev Kumar8b373292014-01-08 20:36:55 -08005365 else if (strncmp(command, "WLS_BATCHING", 12) == 0)
Rajeev79dbe4c2013-10-05 11:03:42 +05305366 {
Rajeev Kumar8b373292014-01-08 20:36:55 -08005367 ret = hdd_handle_batch_scan_ioctl(pAdapter, &priv_data, command);
Rajeev79dbe4c2013-10-05 11:03:42 +05305368 }
5369#endif
Abhishek Singh00b71972016-01-07 10:51:04 +05305370#ifdef WLAN_FEATURE_RMC
5371 else if ((strncasecmp(command, "SETIBSSBEACONOUIDATA", 20) == 0) &&
5372 (WLAN_HDD_IBSS == pAdapter->device_mode))
5373 {
5374 int i = 0;
5375 tANI_U8 *ibss_ie;
5376 tANI_U32 command_len;
5377 tANI_U8 *value = command;
5378 tHalHandle hHal = pHddCtx->hHal;
5379 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
5380 tANI_U32 ibss_ie_length;
5381 tANI_U32 len, present;
5382 tANI_U8 *addIE;
5383 tANI_U8 *addIEData;
5384
5385 hddLog(LOG1,
5386 FL(" received command %s"),((char *) value));
5387 /* validate argument of command */
5388 if (strlen(value) <= 21)
5389 {
5390 hddLog(LOGE,
5391 FL("No arguements in command length %zu"), strlen(value));
5392 ret = -EFAULT;
5393 goto exit;
5394 }
5395
5396 /* moving to arguments of commands */
5397 value = value + 21;
5398 command_len = strlen(value);
5399
5400 /* oui_data can't be less than 3 bytes */
5401 if (command_len <= (2 * WLAN_HDD_IBSS_MIN_OUI_DATA_LENGTH))
5402 {
5403 hddLog(LOGE,
5404 FL("Invalid SETIBSSBEACONOUIDATA command length %d"),
5405 command_len);
5406 ret = -EFAULT;
5407 goto exit;
5408 }
5409 ibss_ie = vos_mem_malloc(command_len);
5410 if (!ibss_ie) {
5411 hddLog(LOGE,
5412 FL("Could not allocate memory for command length %d"),
5413 command_len);
5414 ret = -ENOMEM;
5415 goto exit;
5416 }
5417 vos_mem_zero(ibss_ie, command_len);
5418
5419 ibss_ie_length = hdd_parse_set_ibss_oui_data_command(value, ibss_ie,
5420 command_len);
5421 if (ibss_ie_length < (2 * WLAN_HDD_IBSS_MIN_OUI_DATA_LENGTH)) {
5422 hddLog(LOGE, FL("Could not parse command %s return length %d"),
5423 value, ibss_ie_length);
5424 ret = -EFAULT;
5425 vos_mem_free(ibss_ie);
5426 goto exit;
5427 }
5428
5429 hddLog(LOG1, FL("ibss_ie length %d ibss_ie:"), ibss_ie_length);
5430 while (i < ibss_ie_length)
5431 hddLog(LOG1, FL("0x%x"), ibss_ie[i++]);
5432
5433 /* Populate Vendor IE in Beacon */
5434 if ((ccmCfgGetInt(hHal,
5435 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
5436 &present)) != eHAL_STATUS_SUCCESS)
5437 {
5438 hddLog(LOGE,
5439 FL("unable to ftch WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG"));
5440 ret = -EFAULT;
5441 vos_mem_free(ibss_ie);
5442 goto exit;
5443 }
5444
5445 addIE = vos_mem_malloc(WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN);
5446 if (!addIE) {
5447 hddLog(LOGE,
5448 FL("Could not allocate memory for command length %d"),
5449 command_len);
5450 vos_mem_free(ibss_ie);
5451 ret = -ENOMEM;
5452 goto exit;
5453 }
5454 vos_mem_zero(addIE, WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN);
5455
5456 if (present)
5457 {
5458 if ((wlan_cfgGetStrLen(pMac,
5459 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, &len)) != eSIR_SUCCESS)
5460 {
5461 hddLog(LOGE,
5462 FL("unable to fetch WNI_CFG_PROBE_RSP_BCN_ADDNIE_LEN"));
5463 ret = -EFAULT;
5464 vos_mem_free(ibss_ie);
5465 vos_mem_free(addIE);
5466 goto exit;
5467 }
5468
5469 if (len <= WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN && len &&
5470 ((len + ibss_ie_length) <=
5471 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN))
5472 {
5473 if ((ccmCfgGetStr(hHal,
5474 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, addIE, &len))
5475 != eHAL_STATUS_SUCCESS)
5476 {
5477 hddLog(LOGE,
5478 FL("unable to fetch WNI_PROBE_RSP_BCN_ADDNIE_DATA"));
5479 ret = -EFAULT;
5480 vos_mem_free(ibss_ie);
5481 vos_mem_free(addIE);
5482 goto exit;
5483 }
5484 else
5485 {
5486 /* Curruntly only WPA IE is added before Vendor IE
5487 * so we can blindly place the Vendor IE after WPA
5488 * IE. If no WPA IE found replace all with Vendor IE.
5489 */
5490 len = hdd_find_ibss_wpa_ie_pos(addIE, len);
5491 }
5492 }
5493 else
5494 {
5495 hddLog(LOGE,
5496 FL("IE len exceed limit len %d,ibss_ie_length %d "),
5497 len, ibss_ie_length);
5498 ret = -EFAULT;
5499 vos_mem_free(addIE);
5500 vos_mem_free(ibss_ie);
5501 goto exit;
5502 }
5503 }
5504 else {
5505 len = 0;
5506 }
5507
5508 vos_mem_copy (addIE + len , ibss_ie, ibss_ie_length);
5509 len += ibss_ie_length;
5510
5511 if (ccmCfgSetStr(hHal,
5512 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, addIE, len, NULL,
5513 eANI_BOOLEAN_FALSE) != eHAL_STATUS_SUCCESS)
5514 {
5515 hddLog(LOGE,
5516 FL("unable to set WNI_CFG_PRBE_RSP_BCN_ADDNIE_DATA"));
5517 ret = -EFAULT;
5518 vos_mem_free(ibss_ie);
5519 vos_mem_free(addIE);
5520 goto exit;
5521 }
5522 vos_mem_free(addIE);
5523 if (ccmCfgSetInt(hHal,
5524 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 1,NULL,
5525 eANI_BOOLEAN_FALSE) != eHAL_STATUS_SUCCESS)
5526 {
5527 hddLog(LOGE,
5528 FL("unble to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG"));
5529 ret = -EFAULT;
5530 vos_mem_free(ibss_ie);
5531 goto exit;
5532 }
5533
5534 /* Populate Vendor IE in probe resp */
5535 if ((ccmCfgGetInt(hHal,
5536 WNI_CFG_PROBE_RSP_ADDNIE_FLAG,
5537 &present)) != eHAL_STATUS_SUCCESS)
5538 {
5539 hddLog(LOGE,
5540 FL("unable to fetch WNI_CFG_PROBE_RSP_ADDNIE_FLAG"));
5541 ret = -EFAULT;
5542 vos_mem_free(ibss_ie);
5543 goto exit;
5544 }
5545
5546 addIEData = vos_mem_malloc(WNI_CFG_PROBE_RSP_ADDNIE_DATA1_LEN);
5547 if (!addIEData) {
5548 hddLog(LOGE,
5549 FL("Could not allocate memory for command length %d"),
5550 command_len);
5551 vos_mem_free(ibss_ie);
5552 ret = -ENOMEM;
5553 goto exit;
5554 }
5555 vos_mem_zero(addIEData, WNI_CFG_PROBE_RSP_ADDNIE_DATA1_LEN);
5556
5557 if (present) {
5558 if (eSIR_SUCCESS != wlan_cfgGetStrLen(pMac,
5559 WNI_CFG_PROBE_RSP_ADDNIE_DATA1, &len)) {
5560 hddLog(LOGE,
5561 FL("unable to fetch WNI_CFG_PROBE_RSP_ADDNIE_DATA1"));
5562 ret = -EFAULT;
5563 vos_mem_free(ibss_ie);
5564 vos_mem_free(addIEData);
5565 goto exit;
5566 }
5567 if (len < WNI_CFG_PROBE_RSP_ADDNIE_DATA1_LEN && len &&
5568 (ibss_ie_length + len) <=
5569 WNI_CFG_PROBE_RSP_ADDNIE_DATA1_LEN) {
5570
5571 if ((ccmCfgGetStr(hHal,
5572 WNI_CFG_PROBE_RSP_ADDNIE_DATA1, addIEData, &len))
5573 != eHAL_STATUS_SUCCESS) {
5574 hddLog(LOGE,
5575 FL("unable fetch WNI_CFG_PROBE_RSP_ADDNIE_DATA1"));
5576 ret = -EFAULT;
5577 vos_mem_free(ibss_ie);
5578 vos_mem_free(addIEData);
5579 goto exit;
5580 }
5581 else {
5582 /* Curruntly only WPA IE is added before Vendor IE
5583 * so we can blindly place the Vendor IE after WPA
5584 * IE. If no WPA IE found replace all with Vendor IE.
5585 */
5586 len = hdd_find_ibss_wpa_ie_pos(addIEData, len);
5587 }
5588 }
5589 else
5590 {
5591 hddLog(LOGE,
5592 FL("IE len exceed limit len %d,ibss_ie_length %d "),
5593 len, ibss_ie_length);
5594 ret = -EFAULT;
5595 vos_mem_free(addIEData);
5596 vos_mem_free(ibss_ie);
5597 goto exit;
5598 }
5599 } /* probe rsp ADD IE present */
5600 else {
5601 /* probe rsp add IE is not present */
5602 len = 0;
5603 }
5604
5605 vos_mem_copy(addIEData +len , ibss_ie, ibss_ie_length);
5606 len += ibss_ie_length;
5607
5608 vos_mem_free(ibss_ie);
5609
5610 if (ccmCfgSetStr(hHal,
5611 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,
5612 (tANI_U8*)(addIEData),
5613 len, NULL,
5614 eANI_BOOLEAN_FALSE)
5615 == eHAL_STATUS_FAILURE) {
5616 hddLog(LOGE,
5617 FL("unable to copy to WNI_CFG_PROBE_RSP_ADDNIE_DATA1"));
5618 ret = -EFAULT;
5619 vos_mem_free(addIEData);
5620 goto exit;
5621 }
5622 vos_mem_free(addIEData);
5623 if (ccmCfgSetInt(WLAN_HDD_GET_HAL_CTX(pAdapter),
5624 WNI_CFG_PROBE_RSP_ADDNIE_FLAG, 1,NULL,
5625 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
5626 {
5627 hddLog(LOGE,
5628 FL("unable to copy WNI_CFG_PROBE_RSP_ADDNIE_FLAG"));
5629 ret = -EFAULT;
5630 goto exit;
5631 }
5632 }
5633 else if (strncasecmp(command, "SETRMCENABLE", 12) == 0)
5634 {
5635 tANI_U8 *value = command;
5636 tANI_U8 ucRmcEnable = 0;
5637 int status;
5638
5639 if ((WLAN_HDD_IBSS != pAdapter->device_mode) &&
5640 (WLAN_HDD_SOFTAP != pAdapter->device_mode))
5641 {
5642 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5643 "Received SETRMCENABLE command in invalid mode %d "
5644 "SETRMCENABLE command is only allowed in IBSS or SOFTAP mode",
5645 pAdapter->device_mode);
5646 ret = -EINVAL;
5647 goto exit;
5648 }
5649
5650 status = hdd_parse_setrmcenable_command(value, &ucRmcEnable);
5651 if (status)
5652 {
5653 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5654 "Invalid SETRMCENABLE command ");
5655 ret = -EINVAL;
5656 goto exit;
5657 }
5658
5659 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5660 "%s: ucRmcEnable %d ", __func__, ucRmcEnable);
5661
5662 if (TRUE == ucRmcEnable)
5663 {
5664 status = sme_EnableRMC( (tHalHandle)(pHddCtx->hHal),
5665 pAdapter->sessionId );
5666 }
5667 else if(FALSE == ucRmcEnable)
5668 {
5669 status = sme_DisableRMC( (tHalHandle)(pHddCtx->hHal),
5670 pAdapter->sessionId );
5671 }
5672 else
5673 {
5674 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5675 "Invalid SETRMCENABLE command %d", ucRmcEnable);
5676 ret = -EINVAL;
5677 goto exit;
5678 }
5679
5680 if (VOS_STATUS_SUCCESS != status)
5681 {
5682 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5683 "%s: SETRMC %d failed status %d", __func__, ucRmcEnable,
5684 status);
5685 ret = -EINVAL;
5686 goto exit;
5687 }
5688 }
5689 else if (strncasecmp(command, "SETRMCACTIONPERIOD", 18) == 0)
5690 {
5691 tANI_U8 *value = command;
5692 tANI_U32 uActionPeriod = 0;
5693 int status;
5694
5695 if ((WLAN_HDD_IBSS != pAdapter->device_mode) &&
5696 (WLAN_HDD_SOFTAP != pAdapter->device_mode))
5697 {
5698 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5699 "Received SETRMC command in invalid mode %d "
5700 "SETRMC command is only allowed in IBSS or SOFTAP mode",
5701 pAdapter->device_mode);
5702 ret = -EINVAL;
5703 goto exit;
5704 }
5705
5706 status = hdd_parse_setrmcactionperiod_command(value, &uActionPeriod);
5707 if (status)
5708 {
5709 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5710 "Invalid SETRMCACTIONPERIOD command ");
5711 ret = -EINVAL;
5712 goto exit;
5713 }
5714
5715 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5716 "%s: uActionPeriod %d ", __func__, uActionPeriod);
5717
5718 if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY,
5719 uActionPeriod, NULL, eANI_BOOLEAN_FALSE))
5720 {
5721 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5722 "%s: Could not set SETRMCACTIONPERIOD %d", __func__, uActionPeriod);
5723 ret = -EINVAL;
5724 goto exit;
5725 }
5726
5727 }
5728 else if (strncasecmp(command, "GETIBSSPEERINFOALL", 18) == 0)
5729 {
5730 /* Peer Info All Command */
5731 int status = eHAL_STATUS_SUCCESS;
5732 hdd_station_ctx_t *pHddStaCtx = NULL;
5733 char *extra = NULL;
5734 int idx = 0, length = 0;
5735 v_MACADDR_t *macAddr;
5736 v_U32_t txRateMbps = 0, numOfBytestoPrint = 0;
5737
5738 if (WLAN_HDD_IBSS == pAdapter->device_mode)
5739 {
5740 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5741 }
5742 else
5743 {
5744 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5745 "%s: pAdapter is not valid for this device mode",
5746 __func__);
5747 ret = -EINVAL;
5748 goto exit;
5749 }
5750
5751 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5752 "%s: Received GETIBSSPEERINFOALL Command", __func__);
5753
5754
5755 /* Handle the command */
5756 status = hdd_cfg80211_get_ibss_peer_info_all(pAdapter);
5757 if (VOS_STATUS_SUCCESS == status)
5758 {
5759 /* The variable extra needed to be allocated on the heap since
5760 * amount of memory required to copy the data for 32 devices
5761 * exceeds the size of 1024 bytes of default stack size. On
5762 * 64 bit devices, the default max stack size of 2048 bytes
5763 */
5764 extra = kmalloc(WLAN_MAX_BUF_SIZE, GFP_KERNEL);
5765
5766 if (NULL == extra)
5767 {
5768 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5769 "%s:kmalloc failed", __func__);
5770 ret = -EINVAL;
5771 goto exit;
5772 }
5773
5774 /* Copy number of stations */
5775 length = scnprintf( extra, WLAN_MAX_BUF_SIZE, "%d ",
5776 pHddStaCtx->ibss_peer_info.numIBSSPeers);
5777 numOfBytestoPrint = length;
5778 for (idx = 0; idx < pHddStaCtx->ibss_peer_info.numIBSSPeers; idx++)
5779 {
5780 macAddr =
5781 hdd_wlan_get_ibss_mac_addr_from_staid(pAdapter,
5782 pHddStaCtx->ibss_peer_info.ibssPeerList[idx].staIdx);
5783 if (NULL != macAddr)
5784 {
5785 txRateMbps =
5786 ((pHddStaCtx->ibss_peer_info.ibssPeerList[idx].txRate)*500*1000)/1000000;
5787
5788 length += scnprintf( (extra + length), WLAN_MAX_BUF_SIZE - length,
5789 "%02x:%02x:%02x:%02x:%02x:%02x %d %d ",
5790 macAddr->bytes[0], macAddr->bytes[1], macAddr->bytes[2],
5791 macAddr->bytes[3], macAddr->bytes[4], macAddr->bytes[5],
5792 (int)txRateMbps,
5793 (int)pHddStaCtx->ibss_peer_info.ibssPeerList[idx].rssi);
5794 }
5795 else
5796 {
5797 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5798 "%s: MAC ADDR is NULL for staIdx: %d", __func__,
5799 pHddStaCtx->ibss_peer_info.ibssPeerList[idx].staIdx);
5800 }
5801
5802 /*
5803 * VOS_TRACE() macro has limitation of 512 bytes for the print
5804 * buffer. Hence printing the data in two chunks. The first chunk
5805 * will have the data for 16 devices and the second chunk will
5806 * have the rest.
5807 */
5808 if (idx < NUM_OF_STA_DATA_TO_PRINT)
5809 {
5810 numOfBytestoPrint = length;
5811 }
5812 }
5813
5814 /*
5815 * Copy the data back into buffer, if the data to copy is
5816 * morethan 512 bytes than we will split the data and do
5817 * it in two shots
5818 */
5819 if (copy_to_user(priv_data.buf, extra, numOfBytestoPrint))
5820 {
5821 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5822 "%s: Copy into user data buffer failed ", __func__);
5823 ret = -EFAULT;
5824 kfree(extra);
5825 goto exit;
5826 }
5827 priv_data.buf[numOfBytestoPrint] = '\0';
5828 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED,
5829 "%s", priv_data.buf);
5830
5831 if (length > numOfBytestoPrint)
5832 {
5833 if (copy_to_user(priv_data.buf + numOfBytestoPrint,
5834 extra + numOfBytestoPrint,
5835 length - numOfBytestoPrint + 1))
5836 {
5837 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5838 "%s: Copy into user data buffer failed ", __func__);
5839 ret = -EFAULT;
5840 kfree(extra);
5841 goto exit;
5842 }
5843 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED,
5844 "%s", &priv_data.buf[numOfBytestoPrint]);
5845 }
5846
5847 /* Free temporary buffer */
5848 kfree(extra);
5849 }
5850
5851 else
5852 {
5853 /* Command failed, log error */
5854 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5855 "%s: GETIBSSPEERINFOALL command failed with status code %d",
5856 __func__, status);
5857 ret = -EINVAL;
5858 goto exit;
5859 }
5860 ret = 0;
5861 }
5862 else if(strncasecmp(command, "GETIBSSPEERINFO", 15) == 0)
5863 {
5864 /* Peer Info <Peer Addr> command */
5865 tANI_U8 *value = command;
5866 VOS_STATUS status;
5867 hdd_station_ctx_t *pHddStaCtx = NULL;
5868 char extra[128] = { 0 };
5869 v_U32_t length = 0;
5870 v_U8_t staIdx = 0;
5871 v_U32_t txRateMbps = 0;
5872 v_MACADDR_t peerMacAddr;
5873
5874 if (WLAN_HDD_IBSS == pAdapter->device_mode)
5875 {
5876 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5877 }
5878 else
5879 {
5880 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5881 "%s: pAdapter is not valid for this device mode",
5882 __func__);
5883 ret = -EINVAL;
5884 goto exit;
5885 }
5886
5887 /* if there are no peers, no need to continue with the command */
5888 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5889 "%s: Received GETIBSSPEERINFO Command", __func__);
5890
5891 if (eConnectionState_IbssConnected != pHddStaCtx->conn_info.connState)
5892 {
5893 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5894 "%s:No IBSS Peers coalesced", __func__);
5895 ret = -EINVAL;
5896 goto exit;
5897 }
5898
5899 /* Parse the incoming command buffer */
5900 status = hdd_parse_get_ibss_peer_info(value, &peerMacAddr);
5901 if (VOS_STATUS_SUCCESS != status)
5902 {
5903 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5904 "%s: Invalid GETIBSSPEERINFO command", __func__);
5905 ret = -EINVAL;
5906 goto exit;
5907 }
5908
5909 /* Get station index for the peer mac address */
5910 hdd_Ibss_GetStaId(pHddStaCtx, &peerMacAddr, &staIdx);
5911
5912 if (staIdx > HDD_MAX_NUM_IBSS_STA)
5913 {
5914 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5915 "%s: Invalid StaIdx %d returned", __func__, staIdx);
5916 ret = -EINVAL;
5917 goto exit;
5918 }
5919
5920 /* Handle the command */
5921 status = hdd_cfg80211_get_ibss_peer_info(pAdapter, staIdx);
5922 if (VOS_STATUS_SUCCESS == status)
5923 {
5924 v_U32_t txRate = pHddStaCtx->ibss_peer_info.ibssPeerList[0].txRate;
5925 txRateMbps = (txRate * 500 * 1000)/1000000;
5926
5927 length = scnprintf( extra, sizeof(extra), "%d %d", (int)txRateMbps,
5928 (int)pHddStaCtx->ibss_peer_info.ibssPeerList[0].rssi);
5929
5930 /* Copy the data back into buffer */
5931 if (copy_to_user(priv_data.buf, &extra, length+ 1))
5932 {
5933 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5934 "%s: copy data to user buffer failed GETIBSSPEERINFO command",
5935 __func__);
5936 ret = -EFAULT;
5937 goto exit;
5938 }
5939 }
5940 else
5941 {
5942 /* Command failed, log error */
5943 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5944 "%s: GETIBSSPEERINFO command failed with status code %d",
5945 __func__, status);
5946 ret = -EINVAL;
5947 goto exit;
5948 }
5949
5950 /* Success ! */
5951 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED,
5952 "%s", priv_data.buf);
5953 ret = 0;
5954 }
5955 else if (strncasecmp(command, "SETRMCTXRATE", 12) == 0)
5956 {
5957 tANI_U8 *value = command;
5958 tANI_U32 uRate = 0;
5959 tTxrateinfoflags txFlags = 0;
5960 tSirRateUpdateInd *rateUpdateParams;
5961 int status;
5962
5963 if ((WLAN_HDD_IBSS != pAdapter->device_mode) &&
5964 (WLAN_HDD_SOFTAP != pAdapter->device_mode))
5965 {
5966 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5967 "Received SETRMCTXRATE command in invalid mode %d "
5968 "SETRMC command is only allowed in IBSS or SOFTAP mode",
5969 pAdapter->device_mode);
5970 ret = -EINVAL;
5971 goto exit;
5972 }
5973
5974 status = hdd_parse_setrmcrate_command(value, &uRate, &txFlags);
5975 if (status)
5976 {
5977 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5978 "Invalid SETRMCTXRATE command ");
5979 ret = -EINVAL;
5980 goto exit;
5981 }
5982
5983 rateUpdateParams = vos_mem_malloc(sizeof(tSirRateUpdateInd));
5984 if (NULL == rateUpdateParams)
5985 {
5986 ret = -EINVAL;
5987 goto exit;
5988 }
5989
5990 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5991 "%s: uRate %d ", __func__, uRate);
5992
5993 vos_mem_zero(rateUpdateParams, sizeof(tSirRateUpdateInd ));
5994
5995 /* -1 implies ignore this param */
5996 rateUpdateParams->ucastDataRate = -1;
5997
5998 /*
5999 * Fill the user specifieed RMC rate param
6000 * and the derived tx flags.
6001 */
6002 rateUpdateParams->rmcDataRate = uRate;
6003 rateUpdateParams->rmcDataRateTxFlag = txFlags;
6004
6005 status = sme_SendRateUpdateInd((tHalHandle)(pHddCtx->hHal), rateUpdateParams);
6006 }
6007 else if (strncasecmp(command, "SETIBSSTXFAILEVENT", 18) == 0 )
6008 {
6009 char *value;
6010 tANI_U8 tx_fail_count = 0;
6011 tANI_U16 pid = 0;
6012
6013 value = command;
6014
6015 ret = hdd_ParseIBSSTXFailEventParams(value, &tx_fail_count, &pid);
6016
6017 if (0 != ret)
6018 {
6019 hddLog(VOS_TRACE_LEVEL_INFO,
6020 "%s: Failed to parse SETIBSSTXFAILEVENT arguments",
6021 __func__);
6022 goto exit;
6023 }
6024
6025 hddLog(VOS_TRACE_LEVEL_INFO, "%s: tx_fail_cnt=%hhu, pid=%hu",
6026 __func__, tx_fail_count, pid);
6027
6028 if (0 == tx_fail_count)
6029 {
6030 // Disable TX Fail Indication
6031 if (eHAL_STATUS_SUCCESS ==
6032 sme_TXFailMonitorStartStopInd(pHddCtx->hHal,
6033 tx_fail_count,
6034 NULL))
6035 {
6036 cesium_pid = 0;
6037 }
6038 else
6039 {
6040 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6041 "%s: failed to disable TX Fail Event ", __func__);
6042 ret = -EINVAL;
6043 }
6044 }
6045 else
6046 {
6047 if (eHAL_STATUS_SUCCESS ==
6048 sme_TXFailMonitorStartStopInd(pHddCtx->hHal,
6049 tx_fail_count,
6050 (void*)hdd_tx_fail_ind_callback))
6051 {
6052 cesium_pid = pid;
6053 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6054 "%s: Registered Cesium pid %u", __func__,
6055 cesium_pid);
6056 }
6057 else
6058 {
6059 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6060 "%s: Failed to enable TX Fail Monitoring", __func__);
6061 ret = -EINVAL;
6062 }
6063 }
6064 }
6065
6066#endif /* WLAN_FEATURE_RMC */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006067#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006068 else if (strncmp(command, "SETCCXROAMSCANCHANNELS", 22) == 0)
6069 {
6070 tANI_U8 *value = command;
6071 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
6072 tANI_U8 numChannels = 0;
6073 eHalStatus status = eHAL_STATUS_SUCCESS;
6074
6075 status = hdd_parse_channellist(value, ChannelList, &numChannels);
6076 if (eHAL_STATUS_SUCCESS != status)
6077 {
6078 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6079 "%s: Failed to parse channel list information", __func__);
6080 ret = -EINVAL;
6081 goto exit;
6082 }
6083
6084 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
6085 {
6086 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6087 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
6088 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
6089 ret = -EINVAL;
6090 goto exit;
6091 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006092 status = sme_SetEseRoamScanChannelList((tHalHandle)(pHddCtx->hHal),
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006093 ChannelList,
6094 numChannels);
6095 if (eHAL_STATUS_SUCCESS != status)
6096 {
6097 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6098 "%s: Failed to update channel list information", __func__);
6099 ret = -EINVAL;
6100 goto exit;
6101 }
6102 }
6103 else if (strncmp(command, "GETTSMSTATS", 11) == 0)
6104 {
6105 tANI_U8 *value = command;
6106 char extra[128] = {0};
6107 int len = 0;
6108 tANI_U8 tid = 0;
6109 hdd_station_ctx_t *pHddStaCtx = NULL;
6110 tAniTrafStrmMetrics tsmMetrics;
6111 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6112
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05306113 ret = hdd_drv_cmd_validate(command, 11);
6114 if (ret)
6115 goto exit;
6116
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006117 /* if not associated, return error */
6118 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
6119 {
6120 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:Not associated!",__func__);
6121 ret = -EINVAL;
6122 goto exit;
6123 }
6124
6125 /* Move pointer to ahead of GETTSMSTATS<delimiter> */
6126 value = value + 12;
6127 /* Convert the value from ascii to integer */
6128 ret = kstrtou8(value, 10, &tid);
6129 if (ret < 0)
6130 {
6131 /* If the input value is greater than max value of datatype, then also
6132 kstrtou8 fails */
6133 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6134 "%s: kstrtou8 failed range [%d - %d]", __func__,
6135 TID_MIN_VALUE,
6136 TID_MAX_VALUE);
6137 ret = -EINVAL;
6138 goto exit;
6139 }
6140
6141 if ((tid < TID_MIN_VALUE) || (tid > TID_MAX_VALUE))
6142 {
6143 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6144 "tid value %d is out of range"
6145 " (Min: %d Max: %d)", tid,
6146 TID_MIN_VALUE,
6147 TID_MAX_VALUE);
6148 ret = -EINVAL;
6149 goto exit;
6150 }
6151
6152 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6153 "%s: Received Command to get tsm stats tid = %d", __func__, tid);
6154
6155 if (VOS_STATUS_SUCCESS != hdd_get_tsm_stats(pAdapter, tid, &tsmMetrics))
6156 {
6157 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6158 "%s: failed to get tsm stats", __func__);
6159 ret = -EFAULT;
6160 goto exit;
6161 }
6162
6163 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6164 "UplinkPktQueueDly(%d)\n"
6165 "UplinkPktQueueDlyHist[0](%d)\n"
6166 "UplinkPktQueueDlyHist[1](%d)\n"
6167 "UplinkPktQueueDlyHist[2](%d)\n"
6168 "UplinkPktQueueDlyHist[3](%d)\n"
Arun Kumar Khandavallie8768212014-02-17 16:43:34 +05306169 "UplinkPktTxDly(%u)\n"
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006170 "UplinkPktLoss(%d)\n"
6171 "UplinkPktCount(%d)\n"
6172 "RoamingCount(%d)\n"
6173 "RoamingDly(%d)", tsmMetrics.UplinkPktQueueDly,
6174 tsmMetrics.UplinkPktQueueDlyHist[0],
6175 tsmMetrics.UplinkPktQueueDlyHist[1],
6176 tsmMetrics.UplinkPktQueueDlyHist[2],
6177 tsmMetrics.UplinkPktQueueDlyHist[3],
6178 tsmMetrics.UplinkPktTxDly, tsmMetrics.UplinkPktLoss,
6179 tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount, tsmMetrics.RoamingDly);
6180
6181 /* Output TSM stats is of the format
6182 GETTSMSTATS [PktQueueDly] [PktQueueDlyHist[0]]:[PktQueueDlyHist[1]] ...[RoamingDly]
6183 eg., GETTSMSTATS 10 1:0:0:161 20 1 17 8 39800 */
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006184 len = scnprintf(extra, sizeof(extra), "%s %d %d:%d:%d:%d %u %d %d %d %d", command,
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006185 tsmMetrics.UplinkPktQueueDly, tsmMetrics.UplinkPktQueueDlyHist[0],
6186 tsmMetrics.UplinkPktQueueDlyHist[1], tsmMetrics.UplinkPktQueueDlyHist[2],
6187 tsmMetrics.UplinkPktQueueDlyHist[3], tsmMetrics.UplinkPktTxDly,
6188 tsmMetrics.UplinkPktLoss, tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount,
6189 tsmMetrics.RoamingDly);
6190
Ratnam Rachurid53009c2015-08-07 13:59:00 +05306191 len = VOS_MIN(priv_data.total_len, len + 1);
6192 if (copy_to_user(priv_data.buf, &extra, len)) {
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006193 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6194 "%s: failed to copy data to user buffer", __func__);
6195 ret = -EFAULT;
6196 goto exit;
6197 }
6198 }
6199 else if (strncmp(command, "SETCCKMIE", 9) == 0)
6200 {
6201 tANI_U8 *value = command;
6202 tANI_U8 *cckmIe = NULL;
6203 tANI_U8 cckmIeLen = 0;
6204 eHalStatus status = eHAL_STATUS_SUCCESS;
6205
6206 status = hdd_parse_get_cckm_ie(value, &cckmIe, &cckmIeLen);
6207 if (eHAL_STATUS_SUCCESS != status)
6208 {
6209 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6210 "%s: Failed to parse cckm ie data", __func__);
6211 ret = -EINVAL;
6212 goto exit;
6213 }
6214
6215 if (cckmIeLen > DOT11F_IE_RSN_MAX_LEN)
6216 {
6217 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6218 "%s: CCKM Ie input length is more than max[%d]", __func__,
6219 DOT11F_IE_RSN_MAX_LEN);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08006220 vos_mem_free(cckmIe);
6221 cckmIe = NULL;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006222 ret = -EINVAL;
6223 goto exit;
6224 }
6225 sme_SetCCKMIe((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, cckmIe, cckmIeLen);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08006226 vos_mem_free(cckmIe);
6227 cckmIe = NULL;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006228 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006229 else if (strncmp(command, "CCXBEACONREQ", 12) == 0)
6230 {
6231 tANI_U8 *value = command;
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006232 tCsrEseBeaconReq eseBcnReq;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006233 eHalStatus status = eHAL_STATUS_SUCCESS;
Srinivas Girigowda0c6d7fe2014-05-28 18:18:10 -07006234
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006235 status = hdd_parse_ese_beacon_req(value, &eseBcnReq);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006236 if (eHAL_STATUS_SUCCESS != status)
6237 {
6238 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006239 "%s: Failed to parse ese beacon req", __func__);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006240 ret = -EINVAL;
6241 goto exit;
6242 }
Srinivas Girigowda0c6d7fe2014-05-28 18:18:10 -07006243 if (!hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))) {
6244 hddLog(VOS_TRACE_LEVEL_INFO, FL("Not associated"));
6245 hdd_indicateEseBcnReportNoResults (pAdapter,
6246 eseBcnReq.bcnReq[0].measurementToken,
6247 0x02, //BIT(1) set for measurement done
6248 0); // no BSS
6249 goto exit;
6250 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006251
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006252 status = sme_SetEseBeaconRequest((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, &eseBcnReq);
6253 if (eHAL_STATUS_SUCCESS != status)
6254 {
6255 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6256 "%s: sme_SetEseBeaconRequest failed (%d)", __func__, status);
6257 ret = -EINVAL;
6258 goto exit;
6259 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006260 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006261#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
c_hpothu92367912014-05-01 15:18:17 +05306262 else if (strncmp(command, "GETBCNMISSRATE", 14) == 0)
6263 {
6264 eHalStatus status;
6265 char buf[32], len;
6266 long waitRet;
6267 bcnMissRateContext_t getBcnMissRateCtx;
6268
6269 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6270
6271 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
6272 {
6273 hddLog(VOS_TRACE_LEVEL_WARN,
6274 FL("GETBCNMISSRATE: STA is not in connected state"));
6275 ret = -1;
6276 goto exit;
6277 }
6278
6279 init_completion(&(getBcnMissRateCtx.completion));
6280 getBcnMissRateCtx.magic = BCN_MISS_RATE_CONTEXT_MAGIC;
6281
6282 status = sme_getBcnMissRate((tHalHandle)(pHddCtx->hHal),
6283 pAdapter->sessionId,
6284 (void *)getBcnMissRateCB,
6285 (void *)(&getBcnMissRateCtx));
6286 if( eHAL_STATUS_SUCCESS != status)
6287 {
6288 hddLog(VOS_TRACE_LEVEL_INFO,
6289 FL("GETBCNMISSRATE: fail to post WDA cmd"));
6290 ret = -EINVAL;
6291 goto exit;
6292 }
6293
6294 waitRet = wait_for_completion_interruptible_timeout
6295 (&getBcnMissRateCtx.completion, BCN_MISS_RATE_TIME);
6296 if(waitRet <= 0)
6297 {
6298 hddLog(VOS_TRACE_LEVEL_ERROR,
6299 FL("failed to wait on bcnMissRateComp %d"), ret);
6300
6301 //Make magic number to zero so that callback is not called.
6302 spin_lock(&hdd_context_lock);
6303 getBcnMissRateCtx.magic = 0x0;
6304 spin_unlock(&hdd_context_lock);
6305 ret = -EINVAL;
6306 goto exit;
6307 }
6308
6309 hddLog(VOS_TRACE_LEVEL_INFO,
6310 FL("GETBCNMISSRATE: bcnMissRate: %d"), gbcnMissRate);
6311
6312 len = snprintf(buf, sizeof(buf), "GETBCNMISSRATE %d", gbcnMissRate);
6313 if (copy_to_user(priv_data.buf, &buf, len + 1))
6314 {
6315 hddLog(VOS_TRACE_LEVEL_ERROR,
6316 "%s: failed to copy data to user buffer", __func__);
6317 ret = -EFAULT;
6318 goto exit;
6319 }
6320 ret = len;
6321 }
Atul Mittal87ec2422014-09-24 13:12:50 +05306322#ifdef FEATURE_WLAN_TDLS
6323 else if (strncmp(command, "TDLSSECONDARYCHANNELOFFSET", 26) == 0) {
6324 tANI_U8 *value = command;
6325 int set_value;
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05306326
6327 ret = hdd_drv_cmd_validate(command, 26);
6328 if (ret)
6329 goto exit;
6330
Atul Mittal87ec2422014-09-24 13:12:50 +05306331 /* Move pointer to ahead of TDLSOFFCH*/
6332 value += 26;
c_manjeebbc40212015-12-08 13:52:59 +05306333 if (!(sscanf(value, "%d", &set_value))) {
6334 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6335 FL("No input identified"));
6336 ret = -EINVAL;
6337 goto exit;
6338 }
6339
Atul Mittal87ec2422014-09-24 13:12:50 +05306340 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6341 "%s: Tdls offchannel offset:%d",
6342 __func__, set_value);
6343 ret = iw_set_tdlssecoffchanneloffset(pHddCtx, set_value);
6344 if (ret < 0)
6345 {
6346 ret = -EINVAL;
6347 goto exit;
6348 }
6349
6350 } else if (strncmp(command, "TDLSOFFCHANNELMODE", 18) == 0) {
6351 tANI_U8 *value = command;
6352 int set_value;
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05306353
6354 ret = hdd_drv_cmd_validate(command, 18);
6355 if (ret)
6356 goto exit;
6357
Atul Mittal87ec2422014-09-24 13:12:50 +05306358 /* Move pointer to ahead of tdlsoffchnmode*/
6359 value += 18;
c_manjee82323892015-12-08 12:40:34 +05306360 ret = sscanf(value, "%d", &set_value);
6361 if (ret != 1) {
6362 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6363 FL("No input identified"));
6364 ret = -EINVAL;
6365 goto exit;
6366 }
Atul Mittal87ec2422014-09-24 13:12:50 +05306367 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6368 "%s: Tdls offchannel mode:%d",
6369 __func__, set_value);
6370 ret = iw_set_tdlsoffchannelmode(pAdapter, set_value);
6371 if (ret < 0)
6372 {
6373 ret = -EINVAL;
6374 goto exit;
6375 }
6376 } else if (strncmp(command, "TDLSOFFCHANNEL", 14) == 0) {
6377 tANI_U8 *value = command;
6378 int set_value;
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05306379
6380 ret = hdd_drv_cmd_validate(command, 14);
6381 if (ret)
6382 goto exit;
6383
Atul Mittal87ec2422014-09-24 13:12:50 +05306384 /* Move pointer to ahead of TDLSOFFCH*/
6385 value += 14;
c_manjeef6ccaf52015-12-08 11:52:11 +05306386 ret = sscanf(value, "%d", &set_value);
6387 if (ret != 1) {
6388 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6389 "Wrong value is given for hdd_set_tdls_offchannel");
6390 ret = -EINVAL;
6391 goto exit;
6392 }
6393
Atul Mittal87ec2422014-09-24 13:12:50 +05306394 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6395 "%s: Tdls offchannel num: %d",
6396 __func__, set_value);
6397 ret = iw_set_tdlsoffchannel(pHddCtx, set_value);
6398 if (ret < 0)
6399 {
6400 ret = -EINVAL;
6401 goto exit;
6402 }
6403 }
6404#endif
Satyanarayana Dash72806012014-12-02 14:30:08 +05306405 else if (strncmp(command, "GETFWSTATS", 10) == 0)
6406 {
6407 eHalStatus status;
6408 char *buf = NULL;
6409 char len;
6410 long waitRet;
6411 fwStatsContext_t fwStatsCtx;
Abhishek Singh08aa7762014-12-16 13:59:03 +05306412 tSirFwStatsResult *fwStatsRsp = &(pAdapter->fwStatsRsp);
Satyanarayana Dash72806012014-12-02 14:30:08 +05306413 tANI_U8 *ptr = command;
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05306414 int stats;
Satyanarayana Dash72806012014-12-02 14:30:08 +05306415
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05306416 ret = hdd_drv_cmd_validate(command, 10);
6417 if (ret)
6418 goto exit;
6419
6420 stats = *(ptr + 11) - '0';
Satyanarayana Dash72806012014-12-02 14:30:08 +05306421 hddLog(VOS_TRACE_LEVEL_INFO, FL("stats = %d "),stats);
6422 if (!IS_FEATURE_FW_STATS_ENABLE)
6423 {
6424 hddLog(VOS_TRACE_LEVEL_INFO,
6425 FL("Get Firmware stats feature not supported"));
6426 ret = -EINVAL;
6427 goto exit;
6428 }
6429
6430 if (FW_STATS_MAX <= stats || 0 >= stats)
6431 {
6432 hddLog(VOS_TRACE_LEVEL_INFO,
6433 FL(" stats %d not supported"),stats);
6434 ret = -EINVAL;
6435 goto exit;
6436 }
6437
6438 init_completion(&(fwStatsCtx.completion));
6439 fwStatsCtx.magic = FW_STATS_CONTEXT_MAGIC;
6440 fwStatsCtx.pAdapter = pAdapter;
6441 fwStatsRsp->type = 0;
6442 status = sme_GetFwStats( (tHalHandle)pHddCtx->hHal, stats,
Abhishek Singh08aa7762014-12-16 13:59:03 +05306443 &fwStatsCtx, hdd_FWStatisCB);
Satyanarayana Dash72806012014-12-02 14:30:08 +05306444 if (eHAL_STATUS_SUCCESS != status)
6445 {
6446 hddLog(VOS_TRACE_LEVEL_ERROR,
6447 FL(" fail to post WDA cmd status = %d"), status);
6448 ret = -EINVAL;
6449 goto exit;
6450 }
6451 waitRet = wait_for_completion_timeout
6452 (&(fwStatsCtx.completion), FW_STATE_WAIT_TIME);
6453 if (waitRet <= 0)
6454 {
6455 hddLog(VOS_TRACE_LEVEL_ERROR,
6456 FL("failed to wait on GwtFwstats"));
6457 //Make magic number to zero so that callback is not executed.
6458 spin_lock(&hdd_context_lock);
6459 fwStatsCtx.magic = 0x0;
6460 spin_unlock(&hdd_context_lock);
6461 ret = -EINVAL;
6462 goto exit;
6463 }
6464 if (fwStatsRsp->type)
6465 {
6466 buf = kmalloc(FW_STATE_RSP_LEN, GFP_KERNEL);
6467 if (!buf)
6468 {
6469 hddLog(VOS_TRACE_LEVEL_ERROR,
6470 FL(" failed to allocate memory"));
6471 ret = -ENOMEM;
6472 goto exit;
6473 }
6474 switch( fwStatsRsp->type )
6475 {
6476 case FW_UBSP_STATS:
6477 {
6478 len = snprintf(buf, FW_STATE_RSP_LEN,
6479 "GETFWSTATS: ubsp_enter_cnt %d ubsp_jump_ddr_cnt %d",
Abhishek Singh08aa7762014-12-16 13:59:03 +05306480 fwStatsRsp->fwStatsData.ubspStats.ubsp_enter_cnt,
6481 fwStatsRsp->fwStatsData.ubspStats.ubsp_jump_ddr_cnt);
Satyanarayana Dash72806012014-12-02 14:30:08 +05306482 }
6483 break;
6484 default:
6485 {
6486 hddLog(VOS_TRACE_LEVEL_ERROR, FL( "No handling for stats type %d"),fwStatsRsp->type);
6487 ret = -EFAULT;
6488 kfree(buf);
6489 goto exit;
6490 }
6491 }
6492 if (copy_to_user(priv_data.buf, buf, len + 1))
6493 {
6494 hddLog(VOS_TRACE_LEVEL_ERROR,
6495 FL(" failed to copy data to user buffer"));
6496 ret = -EFAULT;
6497 kfree(buf);
6498 goto exit;
6499 }
6500 ret = len;
6501 kfree(buf);
6502 }
6503 else
6504 {
6505 hddLog(VOS_TRACE_LEVEL_ERROR,
6506 FL("failed to fetch the stats"));
6507 ret = -EFAULT;
6508 goto exit;
6509 }
6510
6511 }
Agarwal Ashish8bd53ae2015-06-12 18:03:45 +05306512 else if (strncasecmp(command, "SET_FCC_CHANNEL", 15) == 0)
6513 {
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05306514 ret = hdd_drv_cmd_validate(command, 15);
6515 if (ret)
6516 goto exit;
6517
Agarwal Ashish8bd53ae2015-06-12 18:03:45 +05306518 /*
6519 * this command wld be called by user-space when it detects WLAN
6520 * ON after airplane mode is set. When APM is set, WLAN turns off.
6521 * But it can be turned back on. Otherwise; when APM is turned back
6522 * off, WLAN wld turn back on. So at that point the command is
6523 * expected to come down. 0 means disable, 1 means enable. The
6524 * constraint is removed when parameter 1 is set or different
6525 * country code is set
6526 */
6527 ret = hdd_cmd_setFccChannel(pHddCtx, command, 15);
6528 }
Mahesh A Saptasagarbeca12c2015-09-07 16:21:06 +05306529 else if (strncasecmp(command, "DISABLE_CA_EVENT", 16) == 0)
6530 {
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05306531 ret = hdd_drv_cmd_validate(command, 16);
6532 if (ret)
6533 goto exit;
6534
Mahesh A Saptasagarbeca12c2015-09-07 16:21:06 +05306535 ret = hdd_enable_disable_ca_event(pHddCtx, command, 16);
6536 }
Ashish Kumar Dhanotiya32d092b2018-02-20 21:43:57 +05306537 /*
6538 * command should be a string having format
6539 * SET_DISABLE_CHANNEL_LIST <num of channels>
6540 * <channels separated by spaces>
6541 */
6542 else if (strncmp(command, "SET_DISABLE_CHANNEL_LIST", 24) == 0) {
6543 tANI_U8 *ptr = command;
6544 ret = hdd_drv_cmd_validate(command, 24);
6545 if (ret)
6546 goto exit;
6547
6548 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6549 " Received Command to disable Channels %s",
6550 __func__);
6551 ret = hdd_parse_disable_chan_cmd(pAdapter, ptr);
6552 if (ret)
6553 goto exit;
6554 }
Hanumanth Reddy Pothula8ae38bb2018-03-07 18:59:30 +05306555 else if (strncmp(command, "GET_DISABLE_CHANNEL_LIST", 24) == 0) {
6556 char extra[128] = {0};
6557 int len;
Ashish Kumar Dhanotiya32d092b2018-02-20 21:43:57 +05306558
Hanumanth Reddy Pothula8ae38bb2018-03-07 18:59:30 +05306559 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6560 " Received Command to get disable Channels list %s",
6561 __func__);
6562
6563 len = hdd_get_disable_ch_list(pHddCtx, extra, sizeof(extra));
6564 if (len == 0) {
6565 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6566 FL("disable channel list are not yet programed"));
6567 ret = -EINVAL;
6568 goto exit;
6569 }
6570
6571 len = VOS_MIN(priv_data.total_len, len + 1);
6572 if (copy_to_user(priv_data.buf, &extra, len)) {
6573 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6574 "%s: failed to copy data to user buffer", __func__);
6575 ret = -EFAULT;
6576 goto exit;
6577 }
6578
6579 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6580 FL("data:%s"), extra);
6581 }
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07006582 else {
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05306583 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
6584 TRACE_CODE_HDD_UNSUPPORTED_IOCTL,
6585 pAdapter->sessionId, 0));
Satyanarayana Dash72806012014-12-02 14:30:08 +05306586 hddLog( VOS_TRACE_LEVEL_WARN, FL("Unsupported GUI command %s"),
6587 command);
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07006588 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006589 }
6590exit:
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05306591 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07006592 if (command)
6593 {
6594 kfree(command);
6595 }
6596 return ret;
6597}
6598
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07006599#ifdef CONFIG_COMPAT
6600static int hdd_driver_compat_ioctl(hdd_adapter_t *pAdapter, struct ifreq *ifr)
6601{
6602 struct {
6603 compat_uptr_t buf;
6604 int used_len;
6605 int total_len;
6606 } compat_priv_data;
6607 hdd_priv_data_t priv_data;
6608 int ret = 0;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006609
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07006610 /*
6611 * Note that pAdapter and ifr have already been verified by caller,
6612 * and HDD context has also been validated
6613 */
6614 if (copy_from_user(&compat_priv_data, ifr->ifr_data,
6615 sizeof(compat_priv_data))) {
6616 ret = -EFAULT;
6617 goto exit;
6618 }
6619 priv_data.buf = compat_ptr(compat_priv_data.buf);
6620 priv_data.used_len = compat_priv_data.used_len;
6621 priv_data.total_len = compat_priv_data.total_len;
6622 ret = hdd_driver_command(pAdapter, &priv_data);
6623 exit:
6624 return ret;
6625}
6626#else /* CONFIG_COMPAT */
6627static int hdd_driver_compat_ioctl(hdd_adapter_t *pAdapter, struct ifreq *ifr)
6628{
6629 /* will never be invoked */
6630 return 0;
6631}
6632#endif /* CONFIG_COMPAT */
6633
6634static int hdd_driver_ioctl(hdd_adapter_t *pAdapter, struct ifreq *ifr)
6635{
6636 hdd_priv_data_t priv_data;
6637 int ret = 0;
6638
6639 /*
6640 * Note that pAdapter and ifr have already been verified by caller,
6641 * and HDD context has also been validated
6642 */
6643 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(priv_data))) {
6644 ret = -EFAULT;
6645 } else {
6646 ret = hdd_driver_command(pAdapter, &priv_data);
6647 }
6648 return ret;
6649}
6650
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05306651int __hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07006652{
6653 hdd_adapter_t *pAdapter;
6654 hdd_context_t *pHddCtx;
6655 int ret;
6656
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05306657 ENTER();
6658
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07006659 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6660 if (NULL == pAdapter) {
6661 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6662 "%s: HDD adapter context is Null", __func__);
6663 ret = -ENODEV;
6664 goto exit;
6665 }
6666 if (dev != pAdapter->dev) {
6667 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6668 "%s: HDD adapter/dev inconsistency", __func__);
6669 ret = -ENODEV;
6670 goto exit;
6671 }
6672
6673 if ((!ifr) || (!ifr->ifr_data)) {
6674 ret = -EINVAL;
6675 goto exit;
6676 }
6677
6678 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6679 ret = wlan_hdd_validate_context(pHddCtx);
6680 if (ret) {
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07006681 ret = -EBUSY;
6682 goto exit;
6683 }
6684
6685 switch (cmd) {
6686 case (SIOCDEVPRIVATE + 1):
6687 if (is_compat_task())
6688 ret = hdd_driver_compat_ioctl(pAdapter, ifr);
6689 else
6690 ret = hdd_driver_ioctl(pAdapter, ifr);
6691 break;
6692 default:
6693 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unknown ioctl %d",
6694 __func__, cmd);
6695 ret = -EINVAL;
6696 break;
6697 }
6698 exit:
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05306699 EXIT();
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07006700 return ret;
6701}
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006702
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05306703int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
6704{
6705 int ret;
6706
6707 vos_ssr_protect(__func__);
6708 ret = __hdd_ioctl(dev, ifr, cmd);
6709 vos_ssr_unprotect(__func__);
6710
6711 return ret;
6712}
6713
Katya Nigame7b69a82015-04-28 15:24:06 +05306714int hdd_mon_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
6715{
6716 return 0;
6717}
6718
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006719#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006720/**---------------------------------------------------------------------------
6721
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006722 \brief hdd_parse_ese_beacon_req() - Parse ese beacon request
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006723
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006724 This function parses the ese beacon request passed in the format
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006725 CCXBEACONREQ<space><Number of fields><space><Measurement token>
6726 <space>Channel 1<space>Scan Mode <space>Meas Duration<space>Channel N
6727 <space>Scan Mode N<space>Meas Duration N
6728 if the Number of bcn req fields (N) does not match with the actual number of fields passed
6729 then take N.
6730 <Meas Token><Channel><Scan Mode> and <Meas Duration> are treated as one pair
6731 For example, CCXBEACONREQ 2 1 1 1 30 2 44 0 40.
6732 This function does not take care of removing duplicate channels from the list
6733
6734 \param - pValue Pointer to data
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006735 \param - pEseBcnReq output pointer to store parsed ie information
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006736
6737 \return - 0 for success non-zero for failure
6738
6739 --------------------------------------------------------------------------*/
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006740static VOS_STATUS hdd_parse_ese_beacon_req(tANI_U8 *pValue,
6741 tCsrEseBeaconReq *pEseBcnReq)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006742{
6743 tANI_U8 *inPtr = pValue;
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306744 uint8_t input = 0;
6745 uint32_t tempInt = 0;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006746 int j = 0, i = 0, v = 0;
6747 char buf[32];
6748
6749 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
6750 /*no argument after the command*/
6751 if (NULL == inPtr)
6752 {
6753 return -EINVAL;
6754 }
6755 /*no space after the command*/
6756 else if (SPACE_ASCII_VALUE != *inPtr)
6757 {
6758 return -EINVAL;
6759 }
6760
6761 /*removing empty spaces*/
6762 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
6763
6764 /*no argument followed by spaces*/
6765 if ('\0' == *inPtr) return -EINVAL;
6766
6767 /*getting the first argument ie measurement token*/
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08006768 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006769 if (1 != v) return -EINVAL;
6770
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306771 v = kstrtos8(buf, 10, &input);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006772 if ( v < 0) return -EINVAL;
6773
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306774 input = VOS_MIN(input, SIR_ESE_MAX_MEAS_IE_REQS);
6775 pEseBcnReq->numBcnReqIe = input;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006776
Srinivas Girigowda725a88e2016-03-31 19:24:25 +05306777 hddLog(LOG1, "Number of Bcn Req Ie fields: %d", pEseBcnReq->numBcnReqIe);
6778
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006779
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006780 for (j = 0; j < (pEseBcnReq->numBcnReqIe); j++)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006781 {
6782 for (i = 0; i < 4; i++)
6783 {
6784 /*inPtr pointing to the beginning of first space after number of ie fields*/
6785 inPtr = strpbrk( inPtr, " " );
6786 /*no ie data after the number of ie fields argument*/
6787 if (NULL == inPtr) return -EINVAL;
6788
6789 /*removing empty space*/
6790 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
6791
6792 /*no ie data after the number of ie fields argument and spaces*/
6793 if ( '\0' == *inPtr ) return -EINVAL;
6794
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08006795 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006796 if (1 != v) return -EINVAL;
6797
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306798 v = kstrtou32(buf, 10, &tempInt);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006799 if (v < 0) return -EINVAL;
6800
6801 switch (i)
6802 {
6803 case 0: /* Measurement token */
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306804 if (!tempInt)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006805 {
6806 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306807 "Invalid Measurement Token: %u", tempInt);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006808 return -EINVAL;
6809 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006810 pEseBcnReq->bcnReq[j].measurementToken = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006811 break;
6812
6813 case 1: /* Channel number */
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306814 if ((!tempInt) ||
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006815 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
6816 {
6817 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306818 "Invalid Channel Number: %u", tempInt);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006819 return -EINVAL;
6820 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006821 pEseBcnReq->bcnReq[j].channel = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006822 break;
6823
6824 case 2: /* Scan mode */
Varun Reddy Yeturu0b18d5a2013-12-04 11:42:23 -08006825 if ((tempInt < eSIR_PASSIVE_SCAN) || (tempInt > eSIR_BEACON_TABLE))
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006826 {
6827 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306828 "Invalid Scan Mode(%u) Expected{0|1|2}", tempInt);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006829 return -EINVAL;
6830 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006831 pEseBcnReq->bcnReq[j].scanMode= tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006832 break;
6833
6834 case 3: /* Measurement duration */
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306835 if (((!tempInt) && (pEseBcnReq->bcnReq[j].scanMode != eSIR_BEACON_TABLE)) ||
6836 ((pEseBcnReq->bcnReq[j].scanMode == eSIR_BEACON_TABLE)))
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006837 {
6838 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306839 "Invalid Measurement Duration: %u", tempInt);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006840 return -EINVAL;
6841 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006842 pEseBcnReq->bcnReq[j].measurementDuration = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006843 break;
6844 }
6845 }
6846 }
6847
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006848 for (j = 0; j < pEseBcnReq->numBcnReqIe; j++)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006849 {
6850 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arun Kumar Khandavallie8768212014-02-17 16:43:34 +05306851 "Index(%d) Measurement Token(%u)Channel(%u) Scan Mode(%u) Measurement Duration(%u)\n",
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006852 j,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006853 pEseBcnReq->bcnReq[j].measurementToken,
6854 pEseBcnReq->bcnReq[j].channel,
6855 pEseBcnReq->bcnReq[j].scanMode,
6856 pEseBcnReq->bcnReq[j].measurementDuration);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006857 }
6858
6859 return VOS_STATUS_SUCCESS;
6860}
6861
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006862static void hdd_GetTsmStatsCB( tAniTrafStrmMetrics tsmMetrics, const tANI_U32 staId, void *pContext )
6863{
6864 struct statsContext *pStatsContext = NULL;
6865 hdd_adapter_t *pAdapter = NULL;
6866
6867 if (NULL == pContext)
6868 {
6869 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnsonc135a9a2017-09-19 08:37:24 -07006870 "%s: Bad param, pContext [%pK]",
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006871 __func__, pContext);
6872 return;
6873 }
6874
Jeff Johnson72a40512013-12-19 10:14:15 -08006875 /* there is a race condition that exists between this callback
6876 function and the caller since the caller could time out either
6877 before or while this code is executing. we use a spinlock to
6878 serialize these actions */
6879 spin_lock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006880
6881 pStatsContext = pContext;
6882 pAdapter = pStatsContext->pAdapter;
6883 if ((NULL == pAdapter) || (STATS_CONTEXT_MAGIC != pStatsContext->magic))
6884 {
6885 /* the caller presumably timed out so there is nothing we can do */
Jeff Johnson72a40512013-12-19 10:14:15 -08006886 spin_unlock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006887 hddLog(VOS_TRACE_LEVEL_WARN,
Jeff Johnsonc135a9a2017-09-19 08:37:24 -07006888 "%s: Invalid context, pAdapter [%pK] magic [%08x]",
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006889 __func__, pAdapter, pStatsContext->magic);
6890 return;
6891 }
6892
Jeff Johnson72a40512013-12-19 10:14:15 -08006893 /* context is valid so caller is still waiting */
6894
6895 /* paranoia: invalidate the magic */
6896 pStatsContext->magic = 0;
6897
6898 /* copy over the tsm stats */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006899 pAdapter->tsmStats.UplinkPktQueueDly = tsmMetrics.UplinkPktQueueDly;
6900 vos_mem_copy(pAdapter->tsmStats.UplinkPktQueueDlyHist,
6901 tsmMetrics.UplinkPktQueueDlyHist,
6902 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
6903 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
6904 pAdapter->tsmStats.UplinkPktTxDly = tsmMetrics.UplinkPktTxDly;
6905 pAdapter->tsmStats.UplinkPktLoss = tsmMetrics.UplinkPktLoss;
6906 pAdapter->tsmStats.UplinkPktCount = tsmMetrics.UplinkPktCount;
6907 pAdapter->tsmStats.RoamingCount = tsmMetrics.RoamingCount;
6908 pAdapter->tsmStats.RoamingDly = tsmMetrics.RoamingDly;
6909
Jeff Johnson72a40512013-12-19 10:14:15 -08006910 /* notify the caller */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006911 complete(&pStatsContext->completion);
Jeff Johnson72a40512013-12-19 10:14:15 -08006912
6913 /* serialization is complete */
6914 spin_unlock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006915}
6916
6917
6918
6919static VOS_STATUS hdd_get_tsm_stats(hdd_adapter_t *pAdapter, const tANI_U8 tid,
6920 tAniTrafStrmMetrics* pTsmMetrics)
6921{
6922 hdd_station_ctx_t *pHddStaCtx = NULL;
6923 eHalStatus hstatus;
Jeff Johnson72a40512013-12-19 10:14:15 -08006924 VOS_STATUS vstatus = VOS_STATUS_SUCCESS;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006925 long lrc;
6926 struct statsContext context;
6927 hdd_context_t *pHddCtx = NULL;
6928
6929 if (NULL == pAdapter)
6930 {
6931 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: pAdapter is NULL", __func__);
6932 return VOS_STATUS_E_FAULT;
6933 }
6934
6935 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6936 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6937
6938 /* we are connected prepare our callback context */
6939 init_completion(&context.completion);
6940 context.pAdapter = pAdapter;
6941 context.magic = STATS_CONTEXT_MAGIC;
6942
6943 /* query tsm stats */
6944 hstatus = sme_GetTsmStats(pHddCtx->hHal, hdd_GetTsmStatsCB,
6945 pHddStaCtx->conn_info.staId[ 0 ],
6946 pHddStaCtx->conn_info.bssId,
6947 &context, pHddCtx->pvosContext, tid);
6948
6949 if (eHAL_STATUS_SUCCESS != hstatus)
6950 {
Jeff Johnson72a40512013-12-19 10:14:15 -08006951 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unable to retrieve statistics",
6952 __func__);
6953 vstatus = VOS_STATUS_E_FAULT;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006954 }
6955 else
6956 {
6957 /* request was sent -- wait for the response */
6958 lrc = wait_for_completion_interruptible_timeout(&context.completion,
6959 msecs_to_jiffies(WLAN_WAIT_TIME_STATS));
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006960 if (lrc <= 0)
6961 {
6962 hddLog(VOS_TRACE_LEVEL_ERROR,
6963 "%s: SME %s while retrieving statistics",
6964 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson72a40512013-12-19 10:14:15 -08006965 vstatus = VOS_STATUS_E_TIMEOUT;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006966 }
6967 }
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006968
Jeff Johnson72a40512013-12-19 10:14:15 -08006969 /* either we never sent a request, we sent a request and received a
6970 response or we sent a request and timed out. if we never sent a
6971 request or if we sent a request and got a response, we want to
6972 clear the magic out of paranoia. if we timed out there is a
6973 race condition such that the callback function could be
6974 executing at the same time we are. of primary concern is if the
6975 callback function had already verified the "magic" but had not
6976 yet set the completion variable when a timeout occurred. we
6977 serialize these activities by invalidating the magic while
6978 holding a shared spinlock which will cause us to block if the
6979 callback is currently executing */
6980 spin_lock(&hdd_context_lock);
6981 context.magic = 0;
6982 spin_unlock(&hdd_context_lock);
6983
6984 if (VOS_STATUS_SUCCESS == vstatus)
6985 {
6986 pTsmMetrics->UplinkPktQueueDly = pAdapter->tsmStats.UplinkPktQueueDly;
6987 vos_mem_copy(pTsmMetrics->UplinkPktQueueDlyHist,
6988 pAdapter->tsmStats.UplinkPktQueueDlyHist,
6989 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
6990 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
6991 pTsmMetrics->UplinkPktTxDly = pAdapter->tsmStats.UplinkPktTxDly;
6992 pTsmMetrics->UplinkPktLoss = pAdapter->tsmStats.UplinkPktLoss;
6993 pTsmMetrics->UplinkPktCount = pAdapter->tsmStats.UplinkPktCount;
6994 pTsmMetrics->RoamingCount = pAdapter->tsmStats.RoamingCount;
6995 pTsmMetrics->RoamingDly = pAdapter->tsmStats.RoamingDly;
6996 }
6997 return vstatus;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006998}
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006999#endif /*FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07007000
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08007001#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -08007002void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
7003{
7004 eCsrBand band = -1;
7005 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
7006 switch (band)
7007 {
7008 case eCSR_BAND_ALL:
7009 *pBand = WLAN_HDD_UI_BAND_AUTO;
7010 break;
7011
7012 case eCSR_BAND_24:
7013 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
7014 break;
7015
7016 case eCSR_BAND_5G:
7017 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
7018 break;
7019
7020 default:
7021 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
7022 *pBand = -1;
7023 break;
7024 }
7025}
7026
7027/**---------------------------------------------------------------------------
7028
Srinivas Girigowda100eb322013-03-15 16:48:20 -07007029 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
7030
7031 This function parses the send action frame data passed in the format
7032 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
7033
Srinivas Girigowda56076852013-08-20 14:00:50 -07007034 \param - pValue Pointer to input data
Srinivas Girigowda100eb322013-03-15 16:48:20 -07007035 \param - pTargetApBssid Pointer to target Ap bssid
7036 \param - pChannel Pointer to the Target AP channel
7037 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
7038 \param - pBuf Pointer to data
7039 \param - pBufLen Pointer to data length
7040
7041 \return - 0 for success non-zero for failure
7042
7043 --------------------------------------------------------------------------*/
7044VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
7045 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
7046{
7047 tANI_U8 *inPtr = pValue;
7048 tANI_U8 *dataEnd;
7049 int tempInt;
7050 int j = 0;
7051 int i = 0;
7052 int v = 0;
7053 tANI_U8 tempBuf[32];
7054 tANI_U8 tempByte = 0;
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08007055 /* 12 hexa decimal digits, 5 ':' and '\0' */
7056 tANI_U8 macAddress[18];
Srinivas Girigowda100eb322013-03-15 16:48:20 -07007057
7058 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
7059 /*no argument after the command*/
7060 if (NULL == inPtr)
7061 {
7062 return -EINVAL;
7063 }
7064
7065 /*no space after the command*/
7066 else if (SPACE_ASCII_VALUE != *inPtr)
7067 {
7068 return -EINVAL;
7069 }
7070
7071 /*removing empty spaces*/
7072 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
7073
7074 /*no argument followed by spaces*/
7075 if ('\0' == *inPtr)
7076 {
7077 return -EINVAL;
7078 }
7079
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07007080 v = sscanf(inPtr, "%17s", macAddress);
7081 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Srinivas Girigowda100eb322013-03-15 16:48:20 -07007082 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07007083 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7084 "Invalid MAC address or All hex inputs are not read (%d)", v);
7085 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07007086 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07007087
7088 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
7089 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
7090 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
7091 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
7092 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
7093 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07007094
7095 /* point to the next argument */
7096 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
7097 /*no argument after the command*/
7098 if (NULL == inPtr) return -EINVAL;
7099
7100 /*removing empty spaces*/
7101 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
7102
7103 /*no argument followed by spaces*/
7104 if ('\0' == *inPtr)
7105 {
7106 return -EINVAL;
7107 }
7108
7109 /*getting the next argument ie the channel number */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08007110 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07007111 if (1 != v) return -EINVAL;
7112
Srinivas Girigowda100eb322013-03-15 16:48:20 -07007113 v = kstrtos32(tempBuf, 10, &tempInt);
Agarwal Ashish353b3a82014-04-08 14:55:11 +05307114 if ( v < 0 || tempInt <= 0 || tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX )
Kiet Lambe150c22013-11-21 16:30:32 +05307115 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07007116
7117 *pChannel = tempInt;
7118
7119 /* point to the next argument */
7120 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
7121 /*no argument after the command*/
7122 if (NULL == inPtr) return -EINVAL;
7123 /*removing empty spaces*/
7124 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
7125
7126 /*no argument followed by spaces*/
7127 if ('\0' == *inPtr)
7128 {
7129 return -EINVAL;
7130 }
7131
7132 /*getting the next argument ie the dwell time */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08007133 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07007134 if (1 != v) return -EINVAL;
7135
Srinivas Girigowda100eb322013-03-15 16:48:20 -07007136 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda5a6e0672014-01-09 14:42:57 -08007137 if ( v < 0 || tempInt < 0) return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07007138
7139 *pDwellTime = tempInt;
7140
7141 /* point to the next argument */
7142 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
7143 /*no argument after the command*/
7144 if (NULL == inPtr) return -EINVAL;
7145 /*removing empty spaces*/
7146 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
7147
7148 /*no argument followed by spaces*/
7149 if ('\0' == *inPtr)
7150 {
7151 return -EINVAL;
7152 }
7153
7154 /* find the length of data */
7155 dataEnd = inPtr;
7156 while(('\0' != *dataEnd) )
7157 {
7158 dataEnd++;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07007159 }
Kiet Lambe150c22013-11-21 16:30:32 +05307160 *pBufLen = dataEnd - inPtr ;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07007161 if ( *pBufLen <= 0) return -EINVAL;
7162
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07007163 /* Allocate the number of bytes based on the number of input characters
7164 whether it is even or odd.
7165 if the number of input characters are even, then we need N/2 byte.
7166 if the number of input characters are odd, then we need do (N+1)/2 to
7167 compensate rounding off.
7168 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
7169 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
7170 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07007171 if (NULL == *pBuf)
7172 {
7173 hddLog(VOS_TRACE_LEVEL_FATAL,
7174 "%s: vos_mem_alloc failed ", __func__);
7175 return -EINVAL;
7176 }
7177
7178 /* the buffer received from the upper layer is character buffer,
7179 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
7180 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
7181 and f0 in 3rd location */
7182 for (i = 0, j = 0; j < *pBufLen; j += 2)
7183 {
Kiet Lambe150c22013-11-21 16:30:32 +05307184 if( j+1 == *pBufLen)
7185 {
7186 tempByte = hdd_parse_hex(inPtr[j]);
7187 }
7188 else
7189 {
7190 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
7191 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07007192 (*pBuf)[i++] = tempByte;
7193 }
7194 *pBufLen = i;
7195 return VOS_STATUS_SUCCESS;
7196}
7197
Srinivas Girigowda100eb322013-03-15 16:48:20 -07007198/**---------------------------------------------------------------------------
7199
Srinivas Girigowdade697412013-02-14 16:31:48 -08007200 \brief hdd_parse_channellist() - HDD Parse channel list
7201
7202 This function parses the channel list passed in the format
7203 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07007204 if the Number of channels (N) does not match with the actual number of channels passed
7205 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
7206 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
7207 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
7208 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08007209
7210 \param - pValue Pointer to input channel list
7211 \param - ChannelList Pointer to local output array to record channel list
7212 \param - pNumChannels Pointer to number of roam scan channels
7213
7214 \return - 0 for success non-zero for failure
7215
7216 --------------------------------------------------------------------------*/
7217VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
7218{
7219 tANI_U8 *inPtr = pValue;
7220 int tempInt;
7221 int j = 0;
7222 int v = 0;
7223 char buf[32];
7224
7225 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
7226 /*no argument after the command*/
7227 if (NULL == inPtr)
7228 {
7229 return -EINVAL;
7230 }
7231
7232 /*no space after the command*/
7233 else if (SPACE_ASCII_VALUE != *inPtr)
7234 {
7235 return -EINVAL;
7236 }
7237
7238 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07007239 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08007240
7241 /*no argument followed by spaces*/
7242 if ('\0' == *inPtr)
7243 {
7244 return -EINVAL;
7245 }
7246
7247 /*getting the first argument ie the number of channels*/
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08007248 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07007249 if (1 != v) return -EINVAL;
7250
Srinivas Girigowdade697412013-02-14 16:31:48 -08007251 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07007252 if ((v < 0) ||
7253 (tempInt <= 0) ||
7254 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
7255 {
7256 return -EINVAL;
7257 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08007258
7259 *pNumChannels = tempInt;
7260
7261 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
7262 "Number of channels are: %d", *pNumChannels);
7263
7264 for (j = 0; j < (*pNumChannels); j++)
7265 {
7266 /*inPtr pointing to the beginning of first space after number of channels*/
7267 inPtr = strpbrk( inPtr, " " );
7268 /*no channel list after the number of channels argument*/
7269 if (NULL == inPtr)
7270 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07007271 if (0 != j)
7272 {
7273 *pNumChannels = j;
7274 return VOS_STATUS_SUCCESS;
7275 }
7276 else
7277 {
7278 return -EINVAL;
7279 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08007280 }
7281
7282 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07007283 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08007284
7285 /*no channel list after the number of channels argument and spaces*/
7286 if ( '\0' == *inPtr )
7287 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07007288 if (0 != j)
7289 {
7290 *pNumChannels = j;
7291 return VOS_STATUS_SUCCESS;
7292 }
7293 else
7294 {
7295 return -EINVAL;
7296 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08007297 }
7298
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08007299 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07007300 if (1 != v) return -EINVAL;
7301
Srinivas Girigowdade697412013-02-14 16:31:48 -08007302 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07007303 if ((v < 0) ||
7304 (tempInt <= 0) ||
7305 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
7306 {
7307 return -EINVAL;
7308 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08007309 pChannelList[j] = tempInt;
7310
7311 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
7312 "Channel %d added to preferred channel list",
7313 pChannelList[j] );
7314 }
7315
Srinivas Girigowdade697412013-02-14 16:31:48 -08007316 return VOS_STATUS_SUCCESS;
7317}
7318
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07007319
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05307320/**
7321 * hdd_parse_reassoc_command_v1_data() - HDD Parse reassoc command data
7322 * This function parses the reasoc command data passed in the format
7323 * REASSOC<space><bssid><space><channel>
7324 *
7325 * @pValue: Pointer to input data (its a NUL terminated string)
7326 * @pTargetApBssid: Pointer to target Ap bssid
7327 * @pChannel: Pointer to the Target AP channel
7328 *
7329 * Return: 0 for success non-zero for failure
7330 */
7331static int hdd_parse_reassoc_command_v1_data(const tANI_U8 *pValue,
7332 tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07007333{
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05307334 const tANI_U8 *inPtr = pValue;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07007335 int tempInt;
7336 int v = 0;
7337 tANI_U8 tempBuf[32];
Kiet Lamaa8e15a2014-02-11 23:30:06 -08007338 /* 12 hexa decimal digits, 5 ':' and '\0' */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08007339 tANI_U8 macAddress[18];
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07007340
7341 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
7342 /*no argument after the command*/
7343 if (NULL == inPtr)
7344 {
7345 return -EINVAL;
7346 }
7347
7348 /*no space after the command*/
7349 else if (SPACE_ASCII_VALUE != *inPtr)
7350 {
7351 return -EINVAL;
7352 }
7353
7354 /*removing empty spaces*/
7355 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
7356
7357 /*no argument followed by spaces*/
7358 if ('\0' == *inPtr)
7359 {
7360 return -EINVAL;
7361 }
7362
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07007363 v = sscanf(inPtr, "%17s", macAddress);
7364 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07007365 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07007366 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7367 "Invalid MAC address or All hex inputs are not read (%d)", v);
7368 return -EINVAL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07007369 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07007370
7371 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
7372 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
7373 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
7374 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
7375 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
7376 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07007377
7378 /* point to the next argument */
7379 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
7380 /*no argument after the command*/
7381 if (NULL == inPtr) return -EINVAL;
7382
7383 /*removing empty spaces*/
7384 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
7385
7386 /*no argument followed by spaces*/
7387 if ('\0' == *inPtr)
7388 {
7389 return -EINVAL;
7390 }
7391
7392 /*getting the next argument ie the channel number */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08007393 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07007394 if (1 != v) return -EINVAL;
7395
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07007396 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07007397 if ((v < 0) ||
Padma, Santhosh Kumar0fa809b2014-11-13 14:56:56 +05307398 (tempInt < 0) ||
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07007399 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
7400 {
7401 return -EINVAL;
7402 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07007403
7404 *pChannel = tempInt;
7405 return VOS_STATUS_SUCCESS;
7406}
7407
7408#endif
7409
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08007410#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07007411/**---------------------------------------------------------------------------
7412
7413 \brief hdd_parse_get_cckm_ie() - HDD Parse and fetch the CCKM IE
7414
7415 This function parses the SETCCKM IE command
7416 SETCCKMIE<space><ie data>
7417
7418 \param - pValue Pointer to input data
7419 \param - pCckmIe Pointer to output cckm Ie
7420 \param - pCckmIeLen Pointer to output cckm ie length
7421
7422 \return - 0 for success non-zero for failure
7423
7424 --------------------------------------------------------------------------*/
7425VOS_STATUS hdd_parse_get_cckm_ie(tANI_U8 *pValue, tANI_U8 **pCckmIe,
7426 tANI_U8 *pCckmIeLen)
7427{
7428 tANI_U8 *inPtr = pValue;
7429 tANI_U8 *dataEnd;
7430 int j = 0;
7431 int i = 0;
7432 tANI_U8 tempByte = 0;
7433
7434 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
7435 /*no argument after the command*/
7436 if (NULL == inPtr)
7437 {
7438 return -EINVAL;
7439 }
7440
7441 /*no space after the command*/
7442 else if (SPACE_ASCII_VALUE != *inPtr)
7443 {
7444 return -EINVAL;
7445 }
7446
7447 /*removing empty spaces*/
7448 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
7449
7450 /*no argument followed by spaces*/
7451 if ('\0' == *inPtr)
7452 {
7453 return -EINVAL;
7454 }
7455
7456 /* find the length of data */
7457 dataEnd = inPtr;
7458 while(('\0' != *dataEnd) )
7459 {
7460 dataEnd++;
7461 ++(*pCckmIeLen);
7462 }
7463 if ( *pCckmIeLen <= 0) return -EINVAL;
7464
7465 /* Allocate the number of bytes based on the number of input characters
7466 whether it is even or odd.
7467 if the number of input characters are even, then we need N/2 byte.
7468 if the number of input characters are odd, then we need do (N+1)/2 to
7469 compensate rounding off.
7470 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
7471 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
7472 *pCckmIe = vos_mem_malloc((*pCckmIeLen + 1)/2);
7473 if (NULL == *pCckmIe)
7474 {
7475 hddLog(VOS_TRACE_LEVEL_FATAL,
7476 "%s: vos_mem_alloc failed ", __func__);
7477 return -EINVAL;
7478 }
7479 vos_mem_zero(*pCckmIe, (*pCckmIeLen + 1)/2);
7480 /* the buffer received from the upper layer is character buffer,
7481 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
7482 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
7483 and f0 in 3rd location */
7484 for (i = 0, j = 0; j < *pCckmIeLen; j += 2)
7485 {
7486 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
7487 (*pCckmIe)[i++] = tempByte;
7488 }
7489 *pCckmIeLen = i;
7490
7491 return VOS_STATUS_SUCCESS;
7492}
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08007493#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07007494
Jeff Johnson295189b2012-06-20 16:38:30 -07007495/**---------------------------------------------------------------------------
7496
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07007497 \brief hdd_is_valid_mac_address() - Validate MAC address
7498
7499 This function validates whether the given MAC address is valid or not
7500 Expected MAC address is of the format XX:XX:XX:XX:XX:XX
7501 where X is the hexa decimal digit character and separated by ':'
7502 This algorithm works even if MAC address is not separated by ':'
7503
7504 This code checks given input string mac contains exactly 12 hexadecimal digits.
7505 and a separator colon : appears in the input string only after
7506 an even number of hex digits.
7507
7508 \param - pMacAddr pointer to the input MAC address
7509 \return - 1 for valid and 0 for invalid
7510
7511 --------------------------------------------------------------------------*/
7512
7513v_BOOL_t hdd_is_valid_mac_address(const tANI_U8 *pMacAddr)
7514{
7515 int xdigit = 0;
7516 int separator = 0;
7517 while (*pMacAddr)
7518 {
7519 if (isxdigit(*pMacAddr))
7520 {
7521 xdigit++;
7522 }
7523 else if (':' == *pMacAddr)
7524 {
7525 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
7526 break;
7527
7528 ++separator;
7529 }
7530 else
7531 {
7532 separator = -1;
7533 /* Invalid MAC found */
7534 return 0;
7535 }
7536 ++pMacAddr;
7537 }
7538 return (xdigit == 12 && (separator == 5 || separator == 0));
7539}
7540
7541/**---------------------------------------------------------------------------
7542
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307543 \brief __hdd_open() - HDD Open function
Jeff Johnson295189b2012-06-20 16:38:30 -07007544
7545 \param - dev Pointer to net_device structure
7546
7547 \return - 0 for success non-zero for failure
7548
7549 --------------------------------------------------------------------------*/
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307550int __hdd_open(struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07007551{
7552 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7553 hdd_context_t *pHddCtx;
7554 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7555 VOS_STATUS status;
7556 v_BOOL_t in_standby = TRUE;
7557
7558 if (NULL == pAdapter)
7559 {
7560 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Agarwal Ashish971c2882013-10-30 20:11:12 +05307561 "%s: pAdapter is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007562 return -ENODEV;
7563 }
7564
7565 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05307566 MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_OPEN_REQUEST,
7567 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson295189b2012-06-20 16:38:30 -07007568 if (NULL == pHddCtx)
7569 {
7570 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007571 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007572 return -ENODEV;
7573 }
7574
7575 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7576 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
7577 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07007578 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
7579 {
7580 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307581 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07007582 in_standby = FALSE;
7583 break;
7584 }
7585 else
7586 {
7587 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7588 pAdapterNode = pNext;
7589 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007590 }
7591
7592 if (TRUE == in_standby)
7593 {
7594 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
7595 {
7596 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
7597 "wlan out of power save", __func__);
7598 return -EINVAL;
7599 }
7600 }
7601
Jeff Johnson6a81ca42013-04-05 10:37:08 -07007602 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07007603 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
7604 {
7605 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007606 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007607 /* Enable TX queues only when we are connected */
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05307608 hddLog(VOS_TRACE_LEVEL_INFO, FL("Enabling queues"));
Jeff Johnson295189b2012-06-20 16:38:30 -07007609 netif_tx_start_all_queues(dev);
7610 }
7611
7612 return 0;
7613}
7614
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307615/**---------------------------------------------------------------------------
7616
7617 \brief hdd_open() - Wrapper function for __hdd_open to protect it from SSR
7618
7619 This is called in response to ifconfig up
7620
7621 \param - dev Pointer to net_device structure
7622
7623 \return - 0 for success non-zero for failure
7624
7625 --------------------------------------------------------------------------*/
7626int hdd_open(struct net_device *dev)
7627{
7628 int ret;
7629
7630 vos_ssr_protect(__func__);
7631 ret = __hdd_open(dev);
7632 vos_ssr_unprotect(__func__);
7633
7634 return ret;
7635}
7636
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +05307637int __hdd_mon_open (struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07007638{
7639 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05307640 hdd_adapter_t *sta_adapter;
7641 hdd_context_t *hdd_ctx;
Jeff Johnson295189b2012-06-20 16:38:30 -07007642
7643 if(pAdapter == NULL) {
7644 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007645 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007646 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007647 }
7648
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05307649 if (vos_get_concurrency_mode() != VOS_STA_MON)
7650 return 0;
7651
7652 hdd_ctx = WLAN_HDD_GET_CTX(pAdapter);
7653 if (wlan_hdd_validate_context(hdd_ctx))
7654 return -EINVAL;
7655
7656 sta_adapter = hdd_get_adapter(hdd_ctx, WLAN_HDD_INFRA_STATION);
7657 if (!sta_adapter) {
7658 hddLog(LOGE, FL("No valid STA interface"));
7659 return -EINVAL;
7660 }
7661
7662 if (!test_bit(DEVICE_IFACE_OPENED, &sta_adapter->event_flags)) {
7663 hddLog(LOGE, FL("STA Interface is not OPENED"));
7664 return -EINVAL;
7665 }
7666
7667 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
7668
Jeff Johnson295189b2012-06-20 16:38:30 -07007669 return 0;
7670}
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +05307671
7672int hdd_mon_open (struct net_device *dev)
7673{
7674 int ret;
7675
7676 vos_ssr_protect(__func__);
7677 ret = __hdd_mon_open(dev);
7678 vos_ssr_unprotect(__func__);
7679
7680 return ret;
7681}
7682
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05307683int __hdd_mon_stop (struct net_device *dev)
7684{
7685 hdd_adapter_t *mon_adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7686 hdd_context_t *hdd_ctx;
7687
7688 if (vos_get_concurrency_mode() != VOS_STA_MON)
7689 return 0;
7690
7691 if(!mon_adapter) {
7692 hddLog(LOGE, FL("HDD adapter is Null"));
7693 return -EINVAL;
7694 }
7695
7696 hdd_ctx = WLAN_HDD_GET_CTX(mon_adapter);
7697 if (wlan_hdd_validate_context(hdd_ctx))
7698 return -EINVAL;
7699
7700 if (!test_bit(DEVICE_IFACE_OPENED, &mon_adapter->event_flags)) {
7701 hddLog(LOGE, FL("NETDEV Interface is not OPENED"));
7702 return -ENODEV;
7703 }
7704
7705 clear_bit(DEVICE_IFACE_OPENED, &mon_adapter->event_flags);
7706 hdd_stop_adapter(hdd_ctx, mon_adapter, VOS_FALSE);
7707
7708 return 0;
7709}
7710
Katya Nigame7b69a82015-04-28 15:24:06 +05307711int hdd_mon_stop(struct net_device *dev)
7712{
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05307713 int ret;
7714
7715 vos_ssr_protect(__func__);
7716 ret = __hdd_mon_stop(dev);
7717 vos_ssr_unprotect(__func__);
7718
7719 return ret;
Katya Nigame7b69a82015-04-28 15:24:06 +05307720}
7721
Jeff Johnson295189b2012-06-20 16:38:30 -07007722/**---------------------------------------------------------------------------
7723
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307724 \brief __hdd_stop() - HDD stop function
Jeff Johnson295189b2012-06-20 16:38:30 -07007725
7726 \param - dev Pointer to net_device structure
7727
7728 \return - 0 for success non-zero for failure
7729
7730 --------------------------------------------------------------------------*/
7731
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307732int __hdd_stop (struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07007733{
Vinay Krishna Eranna90f43532014-10-27 16:45:54 +05307734 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07007735 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7736 hdd_context_t *pHddCtx;
7737 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7738 VOS_STATUS status;
7739 v_BOOL_t enter_standby = TRUE;
7740
7741 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07007742 if (NULL == pAdapter)
7743 {
7744 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Agarwal Ashish971c2882013-10-30 20:11:12 +05307745 "%s: pAdapter is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007746 return -ENODEV;
7747 }
Sachin Ahuja9b4958f2015-01-15 21:37:00 +05307748 MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_STOP_REQUEST,
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05307749 pAdapter->sessionId, pAdapter->device_mode));
Vinay Krishna Eranna90f43532014-10-27 16:45:54 +05307750
7751 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7752 ret = wlan_hdd_validate_context(pHddCtx);
7753 if (ret)
Jeff Johnson295189b2012-06-20 16:38:30 -07007754 {
Vinay Krishna Eranna90f43532014-10-27 16:45:54 +05307755 return ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07007756 }
7757
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307758 /* Nothing to be done if the interface is not opened */
7759 if (VOS_FALSE == test_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags))
7760 {
7761 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7762 "%s: NETDEV Interface is not OPENED", __func__);
7763 return -ENODEV;
7764 }
7765
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05307766 if (pHddCtx->concurrency_mode == VOS_STA_MON) {
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05307767 /*
Rajeev Kumar Sirasanagandlaa74e1222018-01-09 17:38:55 +05307768 * In STA + Monitor mode concurrency, no point in running
7769 * capture on monitor interface, when STA interface is stopped
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05307770 */
Rajeev Kumar Sirasanagandlaa74e1222018-01-09 17:38:55 +05307771 wlan_hdd_stop_mon(pHddCtx, true);
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05307772 }
7773
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307774 /* Make sure the interface is marked as closed */
Jeff Johnson6a81ca42013-04-05 10:37:08 -07007775 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07007776 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307777
7778 /* Disable TX on the interface, after this hard_start_xmit() will not
7779 * be called on that interface
7780 */
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05307781 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
Jeff Johnson295189b2012-06-20 16:38:30 -07007782 netif_tx_disable(pAdapter->dev);
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307783
7784 /* Mark the interface status as "down" for outside world */
Jeff Johnson295189b2012-06-20 16:38:30 -07007785 netif_carrier_off(pAdapter->dev);
7786
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307787 /* The interface is marked as down for outside world (aka kernel)
7788 * But the driver is pretty much alive inside. The driver needs to
7789 * tear down the existing connection on the netdev (session)
7790 * cleanup the data pipes and wait until the control plane is stabilized
7791 * for this interface. The call also needs to wait until the above
7792 * mentioned actions are completed before returning to the caller.
7793 * Notice that the hdd_stop_adapter is requested not to close the session
7794 * That is intentional to be able to scan if it is a STA/P2P interface
7795 */
7796 hdd_stop_adapter(pHddCtx, pAdapter, VOS_FALSE);
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05307797#ifdef FEATURE_WLAN_TDLS
7798 mutex_lock(&pHddCtx->tdls_lock);
7799#endif
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307800 /* DeInit the adapter. This ensures datapath cleanup as well */
c_hpothu002231a2015-02-05 14:58:51 +05307801 hdd_deinit_adapter(pHddCtx, pAdapter, TRUE);
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05307802#ifdef FEATURE_WLAN_TDLS
7803 mutex_unlock(&pHddCtx->tdls_lock);
7804#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007805 /* SoftAP ifaces should never go in power save mode
7806 making sure same here. */
7807 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07007808 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07007809 )
7810 {
7811 /* SoftAP mode, so return from here */
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307812 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
7813 "%s: In SAP MODE", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007814 EXIT();
7815 return 0;
7816 }
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307817 /* Find if any iface is up. If any iface is up then can't put device to
7818 * sleep/power save mode
7819 */
Jeff Johnson295189b2012-06-20 16:38:30 -07007820 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7821 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
7822 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07007823 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
7824 {
7825 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307826 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07007827 enter_standby = FALSE;
7828 break;
7829 }
7830 else
7831 {
7832 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7833 pAdapterNode = pNext;
7834 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007835 }
7836
7837 if (TRUE == enter_standby)
7838 {
7839 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
7840 "entering standby", __func__);
7841 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
7842 {
7843 /*log and return success*/
7844 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
7845 "wlan in power save", __func__);
7846 }
7847 }
7848
7849 EXIT();
7850 return 0;
7851}
7852
7853/**---------------------------------------------------------------------------
7854
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307855 \brief hdd_stop() - wrapper_function for __hdd_stop to protect it from SSR
Jeff Johnson295189b2012-06-20 16:38:30 -07007856
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307857 This is called in response to ifconfig down
7858
7859 \param - dev Pointer to net_device structure
7860
7861 \return - 0 for success non-zero for failure
7862-----------------------------------------------------------------------------*/
7863int hdd_stop (struct net_device *dev)
7864{
7865 int ret;
7866
7867 vos_ssr_protect(__func__);
7868 ret = __hdd_stop(dev);
7869 vos_ssr_unprotect(__func__);
7870
7871 return ret;
7872}
7873
7874/**---------------------------------------------------------------------------
7875
7876 \brief __hdd_uninit() - HDD uninit function
Jeff Johnson295189b2012-06-20 16:38:30 -07007877
7878 \param - dev Pointer to net_device structure
7879
7880 \return - void
7881
7882 --------------------------------------------------------------------------*/
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307883static void __hdd_uninit (struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07007884{
7885 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05307886 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07007887 ENTER();
7888
7889 do
7890 {
7891 if (NULL == pAdapter)
7892 {
7893 hddLog(VOS_TRACE_LEVEL_FATAL,
7894 "%s: NULL pAdapter", __func__);
7895 break;
7896 }
7897
7898 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
7899 {
7900 hddLog(VOS_TRACE_LEVEL_FATAL,
7901 "%s: Invalid magic", __func__);
7902 break;
7903 }
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05307904 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7905 if (NULL == pHddCtx)
Jeff Johnson295189b2012-06-20 16:38:30 -07007906 {
7907 hddLog(VOS_TRACE_LEVEL_FATAL,
7908 "%s: NULL pHddCtx", __func__);
7909 break;
7910 }
7911
7912 if (dev != pAdapter->dev)
7913 {
7914 hddLog(VOS_TRACE_LEVEL_FATAL,
7915 "%s: Invalid device reference", __func__);
7916 /* we haven't validated all cases so let this go for now */
7917 }
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05307918#ifdef FEATURE_WLAN_TDLS
7919 mutex_lock(&pHddCtx->tdls_lock);
7920#endif
c_hpothu002231a2015-02-05 14:58:51 +05307921 hdd_deinit_adapter(pHddCtx, pAdapter, TRUE);
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05307922#ifdef FEATURE_WLAN_TDLS
7923 mutex_unlock(&pHddCtx->tdls_lock);
7924#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007925
7926 /* after uninit our adapter structure will no longer be valid */
7927 pAdapter->dev = NULL;
7928 pAdapter->magic = 0;
Manjeet Singh47ee8472016-04-11 11:57:18 +05307929 pAdapter->pHddCtx = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007930 } while (0);
7931
7932 EXIT();
7933}
7934
7935/**---------------------------------------------------------------------------
7936
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307937 \brief hdd_uninit() - Wrapper function to protect __hdd_uninit from SSR
7938
7939 This is called during the netdev unregister to uninitialize all data
7940associated with the device
7941
7942 \param - dev Pointer to net_device structure
7943
7944 \return - void
7945
7946 --------------------------------------------------------------------------*/
7947static void hdd_uninit (struct net_device *dev)
7948{
7949 vos_ssr_protect(__func__);
7950 __hdd_uninit(dev);
7951 vos_ssr_unprotect(__func__);
7952}
7953
7954/**---------------------------------------------------------------------------
7955
Jeff Johnson295189b2012-06-20 16:38:30 -07007956 \brief hdd_release_firmware() -
7957
7958 This function calls the release firmware API to free the firmware buffer.
7959
7960 \param - pFileName Pointer to the File Name.
7961 pCtx - Pointer to the adapter .
7962
7963
7964 \return - 0 for success, non zero for failure
7965
7966 --------------------------------------------------------------------------*/
7967
7968VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
7969{
7970 VOS_STATUS status = VOS_STATUS_SUCCESS;
7971 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
7972 ENTER();
7973
7974
7975 if (!strcmp(WLAN_FW_FILE, pFileName)) {
7976
7977 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
7978
7979 if(pHddCtx->fw) {
7980 release_firmware(pHddCtx->fw);
7981 pHddCtx->fw = NULL;
7982 }
7983 else
7984 status = VOS_STATUS_E_FAILURE;
7985 }
7986 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
7987 if(pHddCtx->nv) {
7988 release_firmware(pHddCtx->nv);
7989 pHddCtx->nv = NULL;
7990 }
7991 else
7992 status = VOS_STATUS_E_FAILURE;
7993
7994 }
7995
7996 EXIT();
7997 return status;
7998}
7999
8000/**---------------------------------------------------------------------------
8001
8002 \brief hdd_request_firmware() -
8003
8004 This function reads the firmware file using the request firmware
8005 API and returns the the firmware data and the firmware file size.
8006
8007 \param - pfileName - Pointer to the file name.
8008 - pCtx - Pointer to the adapter .
8009 - ppfw_data - Pointer to the pointer of the firmware data.
8010 - pSize - Pointer to the file size.
8011
8012 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
8013
8014 --------------------------------------------------------------------------*/
8015
8016
8017VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
8018{
8019 int status;
8020 VOS_STATUS retval = VOS_STATUS_SUCCESS;
8021 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
8022 ENTER();
8023
8024 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
8025
8026 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
8027
8028 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
8029 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
8030 __func__, pfileName);
8031 retval = VOS_STATUS_E_FAILURE;
8032 }
8033
8034 else {
8035 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
8036 *pSize = pHddCtx->fw->size;
8037 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
8038 __func__, *pSize);
8039 }
8040 }
8041 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
8042
8043 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
8044
8045 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
8046 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
8047 __func__, pfileName);
8048 retval = VOS_STATUS_E_FAILURE;
8049 }
8050
8051 else {
8052 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
8053 *pSize = pHddCtx->nv->size;
8054 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
8055 __func__, *pSize);
8056 }
8057 }
8058
8059 EXIT();
8060 return retval;
8061}
8062/**---------------------------------------------------------------------------
8063 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
8064
8065 This is the function invoked by SME to inform the result of a full power
8066 request issued by HDD
8067
8068 \param - callbackcontext - Pointer to cookie
8069 status - result of request
8070
8071 \return - None
8072
8073--------------------------------------------------------------------------*/
8074void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
8075{
8076 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
8077
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07008078 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07008079 if(&pHddCtx->full_pwr_comp_var)
8080 {
8081 complete(&pHddCtx->full_pwr_comp_var);
8082 }
8083}
8084
Abhishek Singh00b71972016-01-07 10:51:04 +05308085#ifdef WLAN_FEATURE_RMC
8086static void hdd_tx_fail_ind_callback(v_U8_t *MacAddr, v_U8_t seqNo)
8087{
8088 int payload_len;
8089 struct sk_buff *skb;
8090 struct nlmsghdr *nlh;
8091 v_U8_t *data;
8092
8093 payload_len = ETH_ALEN;
8094
8095 if (0 == cesium_pid)
8096 {
8097 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: cesium process not registered",
8098 __func__);
8099 return;
8100 }
8101
8102 if ((skb = nlmsg_new(payload_len,GFP_ATOMIC)) == NULL)
8103 {
8104 hddLog(VOS_TRACE_LEVEL_ERROR,
8105 "%s: nlmsg_new() failed for msg size[%d]",
8106 __func__, NLMSG_SPACE(payload_len));
8107 return;
8108 }
8109
8110 nlh = nlmsg_put(skb, cesium_pid, seqNo, 0, payload_len, NLM_F_REQUEST);
8111
8112 if (NULL == nlh)
8113 {
8114 hddLog(VOS_TRACE_LEVEL_ERROR,
8115 "%s: nlmsg_put() failed for msg size[%d]",
8116 __func__, NLMSG_SPACE(payload_len));
8117
8118 kfree_skb(skb);
8119 return;
8120 }
8121
8122 data = nlmsg_data(nlh);
8123 memcpy(data, MacAddr, ETH_ALEN);
8124
8125 if (nlmsg_unicast(cesium_nl_srv_sock, skb, cesium_pid) < 0)
8126 {
8127 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: nlmsg_unicast() failed for msg size[%d]",
8128 __func__, NLMSG_SPACE(payload_len));
8129 }
8130
8131 return;
8132}
8133
8134/**---------------------------------------------------------------------------
8135 \brief hdd_ParseuserParams - return a pointer to the next argument
8136
8137 \return - status
8138
8139--------------------------------------------------------------------------*/
8140static int hdd_ParseUserParams(tANI_U8 *pValue, tANI_U8 **ppArg)
8141{
8142 tANI_U8 *pVal;
8143
8144 pVal = strchr(pValue, ' ');
8145
8146 if (NULL == pVal)
8147 {
8148 /* no argument remains */
8149 return -EINVAL;
8150 }
8151 else if (SPACE_ASCII_VALUE != *pVal)
8152 {
8153 /* no space after the current argument */
8154 return -EINVAL;
8155 }
8156
8157 pVal++;
8158
8159 /* remove empty spaces */
8160 while ((SPACE_ASCII_VALUE == *pVal) && ('\0' != *pVal))
8161 {
8162 pVal++;
8163 }
8164
8165 /* no argument followed by spaces */
8166 if ('\0' == *pVal)
8167 {
8168 return -EINVAL;
8169 }
8170
8171 *ppArg = pVal;
8172
8173 return 0;
8174}
8175
8176/**----------------------------------------------------------------------------
8177 \brief hdd_ParseIBSSTXFailEventParams - Parse params for SETIBSSTXFAILEVENT
8178
8179 \return - status
8180
8181------------------------------------------------------------------------------*/
8182static int hdd_ParseIBSSTXFailEventParams(tANI_U8 *pValue,
8183 tANI_U8 *tx_fail_count,
8184 tANI_U16 *pid)
8185{
8186 tANI_U8 *param = NULL;
8187 int ret;
8188
8189 ret = hdd_ParseUserParams(pValue, &param);
8190
8191 if (0 == ret && NULL != param)
8192 {
8193 if (1 != sscanf(param, "%hhu", tx_fail_count))
8194 {
8195 ret = -EINVAL;
8196 goto done;
8197 }
8198 }
8199 else
8200 {
8201 goto done;
8202 }
8203
8204 if (0 == *tx_fail_count)
8205 {
8206 *pid = 0;
8207 goto done;
8208 }
8209
8210 pValue = param;
8211 pValue++;
8212
8213 ret = hdd_ParseUserParams(pValue, &param);
8214
8215 if (0 == ret)
8216 {
8217 if (1 != sscanf(param, "%hu", pid))
8218 {
8219 ret = -EINVAL;
8220 goto done;
8221 }
8222 }
8223 else
8224 {
8225 goto done;
8226 }
8227
8228done:
8229 return ret;
8230}
8231
8232static int hdd_open_cesium_nl_sock()
8233{
8234#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
8235 struct netlink_kernel_cfg cfg = {
8236 .groups = WLAN_NLINK_MCAST_GRP_ID,
8237 .input = NULL
8238 };
8239#endif
8240 int ret = 0;
8241
8242#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
8243 cesium_nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_CESIUM,
8244#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0))
8245 THIS_MODULE,
8246#endif
8247 &cfg);
8248#else
8249 cesium_nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_CESIUM,
8250 WLAN_NLINK_MCAST_GRP_ID, NULL, NULL, THIS_MODULE);
8251#endif
8252
8253 if (cesium_nl_srv_sock == NULL)
8254 {
8255 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8256 "NLINK: cesium netlink_kernel_create failed");
8257 ret = -ECONNREFUSED;
8258 }
8259
8260 return ret;
8261}
8262
8263static void hdd_close_cesium_nl_sock()
8264{
8265 if (NULL != cesium_nl_srv_sock)
8266 {
8267 netlink_kernel_release(cesium_nl_srv_sock);
8268 cesium_nl_srv_sock = NULL;
8269 }
8270}
8271#endif /* WLAN_FEATURE_RMC */
Jeff Johnson295189b2012-06-20 16:38:30 -07008272/**---------------------------------------------------------------------------
8273
8274 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
8275
8276 This is the function invoked by SME to inform the result of BMPS
8277 request issued by HDD
8278
8279 \param - callbackcontext - Pointer to cookie
8280 status - result of request
8281
8282 \return - None
8283
8284--------------------------------------------------------------------------*/
8285void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
8286{
8287
8288 struct completion *completion_var = (struct completion*) callbackContext;
8289
Arif Hussain6d2a3322013-11-17 19:50:10 -08008290 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07008291 if(completion_var != NULL)
8292 {
8293 complete(completion_var);
8294 }
8295}
8296
8297/**---------------------------------------------------------------------------
8298
8299 \brief hdd_get_cfg_file_size() -
8300
8301 This function reads the configuration file using the request firmware
8302 API and returns the configuration file size.
8303
8304 \param - pCtx - Pointer to the adapter .
8305 - pFileName - Pointer to the file name.
8306 - pBufSize - Pointer to the buffer size.
8307
8308 \return - 0 for success, non zero for failure
8309
8310 --------------------------------------------------------------------------*/
8311
8312VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
8313{
8314 int status;
8315 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
8316
8317 ENTER();
8318
8319 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
8320
8321 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
8322 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
8323 status = VOS_STATUS_E_FAILURE;
8324 }
8325 else {
8326 *pBufSize = pHddCtx->fw->size;
8327 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
8328 release_firmware(pHddCtx->fw);
8329 pHddCtx->fw = NULL;
8330 }
8331
8332 EXIT();
8333 return VOS_STATUS_SUCCESS;
8334}
8335
8336/**---------------------------------------------------------------------------
8337
8338 \brief hdd_read_cfg_file() -
8339
8340 This function reads the configuration file using the request firmware
8341 API and returns the cfg data and the buffer size of the configuration file.
8342
8343 \param - pCtx - Pointer to the adapter .
8344 - pFileName - Pointer to the file name.
8345 - pBuffer - Pointer to the data buffer.
8346 - pBufSize - Pointer to the buffer size.
8347
8348 \return - 0 for success, non zero for failure
8349
8350 --------------------------------------------------------------------------*/
8351
8352VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
8353 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
8354{
8355 int status;
8356 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
8357
8358 ENTER();
8359
8360 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
8361
8362 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
8363 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
8364 return VOS_STATUS_E_FAILURE;
8365 }
8366 else {
8367 if(*pBufSize != pHddCtx->fw->size) {
8368 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
8369 "file size", __func__);
8370 release_firmware(pHddCtx->fw);
8371 pHddCtx->fw = NULL;
8372 return VOS_STATUS_E_FAILURE;
8373 }
8374 else {
8375 if(pBuffer) {
8376 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
8377 }
8378 release_firmware(pHddCtx->fw);
8379 pHddCtx->fw = NULL;
8380 }
8381 }
8382
8383 EXIT();
8384
8385 return VOS_STATUS_SUCCESS;
8386}
8387
8388/**---------------------------------------------------------------------------
8389
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05308390 \brief __hdd_set_mac_address() -
Jeff Johnson295189b2012-06-20 16:38:30 -07008391
8392 This function sets the user specified mac address using
8393 the command ifconfig wlanX hw ether <mac adress>.
8394
8395 \param - dev - Pointer to the net device.
8396 - addr - Pointer to the sockaddr.
8397 \return - 0 for success, non zero for failure
8398
8399 --------------------------------------------------------------------------*/
8400
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05308401static int __hdd_set_mac_address(struct net_device *dev, void *addr)
Jeff Johnson295189b2012-06-20 16:38:30 -07008402{
Mahesh A Saptasagar74088392015-02-05 17:22:09 +05308403 hdd_adapter_t *pAdapter;
8404 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07008405 struct sockaddr *psta_mac_addr = addr;
8406 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
Mahesh A Saptasagar74088392015-02-05 17:22:09 +05308407 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07008408
8409 ENTER();
Mahesh A Saptasagar74088392015-02-05 17:22:09 +05308410 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
8411 if (NULL == pAdapter)
8412 {
8413 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8414 "%s: Adapter is NULL",__func__);
8415 return -EINVAL;
8416 }
8417 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
8418 ret = wlan_hdd_validate_context(pHddCtx);
8419 if (0 != ret)
8420 {
Mahesh A Saptasagar74088392015-02-05 17:22:09 +05308421 return ret;
8422 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008423
8424 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
Jeff Johnson295189b2012-06-20 16:38:30 -07008425 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
8426
8427 EXIT();
8428 return halStatus;
8429}
8430
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05308431/**---------------------------------------------------------------------------
8432
8433 \brief hdd_set_mac_address() -
8434
8435 Wrapper function to protect __hdd_set_mac_address() function from ssr
8436
8437 \param - dev - Pointer to the net device.
8438 - addr - Pointer to the sockaddr.
8439 \return - 0 for success, non zero for failure
8440
8441 --------------------------------------------------------------------------*/
8442static int hdd_set_mac_address(struct net_device *dev, void *addr)
8443{
8444 int ret;
8445
8446 vos_ssr_protect(__func__);
8447 ret = __hdd_set_mac_address(dev, addr);
8448 vos_ssr_unprotect(__func__);
8449
8450 return ret;
8451}
8452
Jeff Johnson295189b2012-06-20 16:38:30 -07008453tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
8454{
8455 int i;
8456 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
8457 {
Abhishek Singheb183782014-02-06 13:37:21 +05308458 if( 0 == ((pHddCtx->cfg_ini->intfAddrMask) & (1 << i)) )
Jeff Johnson295189b2012-06-20 16:38:30 -07008459 break;
8460 }
8461
8462 if( VOS_MAX_CONCURRENCY_PERSONA == i)
8463 return NULL;
8464
8465 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
8466 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
8467}
8468
8469void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
8470{
8471 int i;
8472 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
8473 {
8474 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
8475 {
8476 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
8477 break;
8478 }
8479 }
8480 return;
8481}
8482
8483#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
8484 static struct net_device_ops wlan_drv_ops = {
8485 .ndo_open = hdd_open,
8486 .ndo_stop = hdd_stop,
8487 .ndo_uninit = hdd_uninit,
8488 .ndo_start_xmit = hdd_hard_start_xmit,
8489 .ndo_tx_timeout = hdd_tx_timeout,
8490 .ndo_get_stats = hdd_stats,
8491 .ndo_do_ioctl = hdd_ioctl,
8492 .ndo_set_mac_address = hdd_set_mac_address,
8493 .ndo_select_queue = hdd_select_queue,
8494#ifdef WLAN_FEATURE_PACKET_FILTERING
8495#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
8496 .ndo_set_rx_mode = hdd_set_multicast_list,
8497#else
8498 .ndo_set_multicast_list = hdd_set_multicast_list,
8499#endif //LINUX_VERSION_CODE
8500#endif
8501 };
Jeff Johnson295189b2012-06-20 16:38:30 -07008502 static struct net_device_ops wlan_mon_drv_ops = {
8503 .ndo_open = hdd_mon_open,
Katya Nigame7b69a82015-04-28 15:24:06 +05308504 .ndo_stop = hdd_mon_stop,
Jeff Johnson295189b2012-06-20 16:38:30 -07008505 .ndo_uninit = hdd_uninit,
8506 .ndo_start_xmit = hdd_mon_hard_start_xmit,
8507 .ndo_tx_timeout = hdd_tx_timeout,
8508 .ndo_get_stats = hdd_stats,
Katya Nigame7b69a82015-04-28 15:24:06 +05308509 .ndo_do_ioctl = hdd_mon_ioctl,
Jeff Johnson295189b2012-06-20 16:38:30 -07008510 .ndo_set_mac_address = hdd_set_mac_address,
8511 };
Mahesh A Saptasagar305e2632015-03-04 12:57:33 +05308512
Jeff Johnson295189b2012-06-20 16:38:30 -07008513#endif
8514
8515void hdd_set_station_ops( struct net_device *pWlanDev )
8516{
8517#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
Jeff Johnson295189b2012-06-20 16:38:30 -07008518 pWlanDev->netdev_ops = &wlan_drv_ops;
8519#else
8520 pWlanDev->open = hdd_open;
8521 pWlanDev->stop = hdd_stop;
8522 pWlanDev->uninit = hdd_uninit;
8523 pWlanDev->hard_start_xmit = NULL;
8524 pWlanDev->tx_timeout = hdd_tx_timeout;
8525 pWlanDev->get_stats = hdd_stats;
8526 pWlanDev->do_ioctl = hdd_ioctl;
Jeff Johnson295189b2012-06-20 16:38:30 -07008527 pWlanDev->set_mac_address = hdd_set_mac_address;
8528#endif
8529}
8530
Katya Nigam1fd24402015-02-16 14:52:19 +05308531void hdd_set_ibss_ops( hdd_adapter_t *pAdapter )
8532{
8533 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
8534 wlan_drv_ops.ndo_start_xmit = hdd_ibss_hard_start_xmit;
8535 #else
8536 pAdapter->dev->hard_start_xmit = hdd_ibss_hard_start_xmit;
8537 #endif
8538}
8539
Jeff Johnsoneed415b2013-01-18 16:11:20 -08008540static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07008541{
8542 struct net_device *pWlanDev = NULL;
8543 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07008544 /*
8545 * cfg80211 initialization and registration....
8546 */
Anand N Sunkadc34abbd2015-07-29 09:52:59 +05308547 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name,
8548#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0))
8549 NET_NAME_UNKNOWN,
8550#endif
8551 ether_setup, NUM_TX_QUEUES);
Jeff Johnson295189b2012-06-20 16:38:30 -07008552 if(pWlanDev != NULL)
8553 {
8554
8555 //Save the pointer to the net_device in the HDD adapter
8556 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
8557
Jeff Johnson295189b2012-06-20 16:38:30 -07008558 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
8559
8560 pAdapter->dev = pWlanDev;
8561 pAdapter->pHddCtx = pHddCtx;
8562 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
Agarwal Ashish47d18112014-08-04 19:55:07 +05308563 spin_lock_init(&pAdapter->lock_for_active_session);
Jeff Johnson295189b2012-06-20 16:38:30 -07008564
Rajeev79dbe4c2013-10-05 11:03:42 +05308565#ifdef FEATURE_WLAN_BATCH_SCAN
Rajeev79dbe4c2013-10-05 11:03:42 +05308566 pAdapter->pBatchScanRsp = NULL;
8567 pAdapter->numScanList = 0;
Rajeev Kumar20140c12013-10-21 19:39:02 -07008568 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
Kiet Lamaa8e15a2014-02-11 23:30:06 -08008569 pAdapter->prev_batch_id = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05308570 mutex_init(&pAdapter->hdd_batch_scan_lock);
8571#endif
8572
Jeff Johnson295189b2012-06-20 16:38:30 -07008573 pAdapter->isLinkUpSvcNeeded = FALSE;
8574 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
8575 //Init the net_device structure
8576 strlcpy(pWlanDev->name, name, IFNAMSIZ);
8577
8578 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
8579 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
8580 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
8581 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
8582
8583 hdd_set_station_ops( pAdapter->dev );
8584
8585 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07008586 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
8587 pAdapter->wdev.wiphy = pHddCtx->wiphy;
8588 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07008589 /* set pWlanDev's parent to underlying device */
8590 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
Kumar Anand82c009f2014-05-29 00:29:42 -07008591
8592 hdd_wmm_init( pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07008593 }
8594
8595 return pAdapter;
8596}
8597
8598VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
8599{
8600 struct net_device *pWlanDev = pAdapter->dev;
8601 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
8602 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
8603 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
8604
8605 if( rtnl_lock_held )
8606 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08008607 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07008608 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
8609 {
8610 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
8611 return VOS_STATUS_E_FAILURE;
8612 }
8613 }
8614 if (register_netdevice(pWlanDev))
8615 {
8616 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
8617 return VOS_STATUS_E_FAILURE;
8618 }
8619 }
8620 else
8621 {
8622 if(register_netdev(pWlanDev))
8623 {
8624 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
8625 return VOS_STATUS_E_FAILURE;
8626 }
8627 }
8628 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
8629
8630 return VOS_STATUS_SUCCESS;
8631}
8632
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008633static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07008634{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008635 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07008636
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008637 if (NULL == pAdapter)
8638 {
8639 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
8640 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07008641 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008642
8643 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
8644 {
8645 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
8646 return eHAL_STATUS_NOT_INITIALIZED;
8647 }
8648
8649 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
8650
Sameer Thalappilbee426e2013-10-30 10:30:30 -07008651#ifndef WLAN_OPEN_SOURCE
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008652 /* need to make sure all of our scheduled work has completed.
8653 * This callback is called from MC thread context, so it is safe to
8654 * to call below flush workqueue API from here.
Sameer Thalappilbee426e2013-10-30 10:30:30 -07008655 *
8656 * Even though this is called from MC thread context, if there is a faulty
8657 * work item in the system, that can hang this call forever. So flushing
8658 * this global work queue is not safe; and now we make sure that
8659 * individual work queues are stopped correctly. But the cancel work queue
8660 * is a GPL only API, so the proprietary version of the driver would still
8661 * rely on the global work queue flush.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008662 */
8663 flush_scheduled_work();
Sameer Thalappilbee426e2013-10-30 10:30:30 -07008664#endif
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008665
8666 /* We can be blocked while waiting for scheduled work to be
8667 * flushed, and the adapter structure can potentially be freed, in
8668 * which case the magic will have been reset. So make sure the
8669 * magic is still good, and hence the adapter structure is still
8670 * valid, before signaling completion */
8671 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
8672 {
8673 complete(&pAdapter->session_close_comp_var);
8674 }
8675
Jeff Johnson295189b2012-06-20 16:38:30 -07008676 return eHAL_STATUS_SUCCESS;
8677}
Manjeet Singh47ee8472016-04-11 11:57:18 +05308678/**
8679 * hdd_close_tx_queues() - close tx queues
8680 * @hdd_ctx: hdd global context
8681 *
8682 * Return: None
8683 */
8684static void hdd_close_tx_queues(hdd_context_t *hdd_ctx)
8685{
8686 VOS_STATUS status;
8687 hdd_adapter_t *adapter;
8688 hdd_adapter_list_node_t *adapter_node = NULL, *next_adapter = NULL;
8689 /* Not validating hdd_ctx as it's already done by the caller */
8690 ENTER();
8691 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
8692 while (NULL != adapter_node && VOS_STATUS_SUCCESS == status) {
8693 adapter = adapter_node->pAdapter;
8694 if (adapter && adapter->dev) {
8695 netif_tx_disable (adapter->dev);
8696 netif_carrier_off(adapter->dev);
8697 }
8698 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
8699 &next_adapter);
8700 adapter_node = next_adapter;
8701 }
8702 EXIT();
8703}
Jeff Johnson295189b2012-06-20 16:38:30 -07008704
8705VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
8706{
8707 struct net_device *pWlanDev = pAdapter->dev;
8708 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
8709 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
8710 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
8711 VOS_STATUS status = VOS_STATUS_E_FAILURE;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308712 long rc = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07008713
Nirav Shah7e3c8132015-06-22 23:51:42 +05308714 spin_lock_init( &pAdapter->sta_hash_lock);
8715 pAdapter->is_sta_id_hash_initialized = VOS_FALSE;
8716
Jeff Johnson295189b2012-06-20 16:38:30 -07008717 INIT_COMPLETION(pAdapter->session_open_comp_var);
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07008718 sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07008719 //Open a SME session for future operation
8720 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07008721 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07008722 if ( !HAL_STATUS_SUCCESS( halStatus ) )
8723 {
8724 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07008725 "sme_OpenSession() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07008726 halStatus, halStatus );
8727 status = VOS_STATUS_E_FAILURE;
8728 goto error_sme_open;
8729 }
8730
8731 //Block on a completion variable. Can't wait forever though.
Vinay Krishna Eranna0fe2e7c2014-04-09 21:32:08 +05308732 rc = wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07008733 &pAdapter->session_open_comp_var,
8734 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308735 if (rc <= 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07008736 {
8737 hddLog(VOS_TRACE_LEVEL_FATAL,
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308738 "Session is not opened within timeout period code %ld", rc );
Jeff Johnson295189b2012-06-20 16:38:30 -07008739 status = VOS_STATUS_E_FAILURE;
8740 goto error_sme_open;
8741 }
8742
8743 // Register wireless extensions
8744 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
8745 {
8746 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07008747 "hdd_register_wext() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07008748 halStatus, halStatus );
8749 status = VOS_STATUS_E_FAILURE;
8750 goto error_register_wext;
8751 }
Katya Nigam1fd24402015-02-16 14:52:19 +05308752
Jeff Johnson295189b2012-06-20 16:38:30 -07008753 //Safe to register the hard_start_xmit function again
Katya Nigam1fd24402015-02-16 14:52:19 +05308754 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
8755 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
8756 #else
8757 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
8758 #endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008759
8760 //Set the Connection State to Not Connected
Abhishek Singhf4669da2014-05-26 15:07:49 +05308761 hddLog(VOS_TRACE_LEVEL_INFO,
8762 "%s: Set HDD connState to eConnectionState_NotConnected",
8763 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008764 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
8765
8766 //Set the default operation channel
8767 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
8768
8769 /* Make the default Auth Type as OPEN*/
8770 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
8771
8772 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
8773 {
8774 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07008775 "hdd_init_tx_rx() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07008776 status, status );
8777 goto error_init_txrx;
8778 }
8779
8780 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
8781
8782 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
8783 {
8784 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07008785 "hdd_wmm_adapter_init() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07008786 status, status );
8787 goto error_wmm_init;
8788 }
8789
8790 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
8791
8792 return VOS_STATUS_SUCCESS;
8793
8794error_wmm_init:
8795 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
8796 hdd_deinit_tx_rx(pAdapter);
8797error_init_txrx:
8798 hdd_UnregisterWext(pWlanDev);
8799error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008800 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07008801 {
8802 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008803 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Agrawal Ashish5a3522c2016-03-02 15:08:28 +05308804 pAdapter->sessionId, FALSE, VOS_TRUE,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008805 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07008806 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308807 unsigned long rc;
8808
Jeff Johnson295189b2012-06-20 16:38:30 -07008809 //Block on a completion variable. Can't wait forever though.
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308810 rc = wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07008811 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008812 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308813 if (rc <= 0)
8814 hddLog(VOS_TRACE_LEVEL_ERROR,
8815 FL("Session is not opened within timeout period code %ld"), rc);
Jeff Johnson295189b2012-06-20 16:38:30 -07008816 }
8817}
8818error_sme_open:
8819 return status;
8820}
8821
Jeff Johnson295189b2012-06-20 16:38:30 -07008822void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
8823{
8824 hdd_cfg80211_state_t *cfgState;
8825
8826 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
8827
8828 if( NULL != cfgState->buf )
8829 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308830 long rc;
Jeff Johnson295189b2012-06-20 16:38:30 -07008831 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
8832 rc = wait_for_completion_interruptible_timeout(
8833 &pAdapter->tx_action_cnf_event,
8834 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308835 if (rc <= 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07008836 {
Deepthi Gowri91b3e9c2015-08-25 13:14:58 +05308837 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8838 "%s ERROR: HDD Wait for Action Confirmation Failed!! %ld"
8839 , __func__, rc);
8840
8841 // Inform tx status as FAILURE to upper layer and free cfgState->buf
8842 hdd_sendActionCnf( pAdapter, FALSE );
Jeff Johnson295189b2012-06-20 16:38:30 -07008843 }
8844 }
8845 return;
8846}
Jeff Johnson295189b2012-06-20 16:38:30 -07008847
c_hpothu002231a2015-02-05 14:58:51 +05308848void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
Jeff Johnson295189b2012-06-20 16:38:30 -07008849{
8850 ENTER();
8851 switch ( pAdapter->device_mode )
8852 {
Katya Nigam1fd24402015-02-16 14:52:19 +05308853 case WLAN_HDD_IBSS:
8854 {
8855 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
8856 {
8857 hdd_ibss_deinit_tx_rx( pAdapter );
8858 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
8859 }
8860 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008861 case WLAN_HDD_INFRA_STATION:
8862 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07008863 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07008864 {
8865 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
8866 {
8867 hdd_deinit_tx_rx( pAdapter );
8868 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
8869 }
8870
8871 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
8872 {
8873 hdd_wmm_adapter_close( pAdapter );
8874 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
8875 }
8876
Jeff Johnson295189b2012-06-20 16:38:30 -07008877 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07008878 break;
8879 }
8880
8881 case WLAN_HDD_SOFTAP:
8882 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07008883 {
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05308884
8885 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
8886 {
8887 hdd_wmm_adapter_close( pAdapter );
8888 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
8889 }
8890
Jeff Johnson295189b2012-06-20 16:38:30 -07008891 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07008892
c_hpothu002231a2015-02-05 14:58:51 +05308893 hdd_unregister_hostapd(pAdapter, rtnl_held);
Agrawal Ashisha0584d42016-09-29 13:03:45 +05308894 /* set con_mode to STA only when no SAP concurrency mode */
8895 if (!(hdd_get_concurrency_mode() & (VOS_SAP | VOS_P2P_GO)))
8896 hdd_set_conparam(0);
Jeff Johnson295189b2012-06-20 16:38:30 -07008897 break;
8898 }
8899
8900 case WLAN_HDD_MONITOR:
8901 {
Jeff Johnson295189b2012-06-20 16:38:30 -07008902 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
8903 {
8904 hdd_deinit_tx_rx( pAdapter );
8905 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
8906 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008907 break;
8908 }
8909
8910
8911 default:
8912 break;
8913 }
8914
8915 EXIT();
8916}
8917
8918void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
8919{
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -08008920 struct net_device *pWlanDev = NULL;
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05308921
8922 ENTER();
8923 if (NULL == pAdapter)
8924 {
8925 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8926 "%s: HDD adapter is Null", __func__);
8927 return;
8928 }
8929
8930 pWlanDev = pAdapter->dev;
Jeff Johnson295189b2012-06-20 16:38:30 -07008931
Rajeev79dbe4c2013-10-05 11:03:42 +05308932#ifdef FEATURE_WLAN_BATCH_SCAN
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05308933 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
8934 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Rajeev Kumarf999e582014-01-09 17:33:29 -08008935 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05308936 || (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)
8937 )
8938 {
Rajeev Kumarf999e582014-01-09 17:33:29 -08008939 if (pAdapter)
Rajeev79dbe4c2013-10-05 11:03:42 +05308940 {
Rajeev Kumarf999e582014-01-09 17:33:29 -08008941 if (eHDD_BATCH_SCAN_STATE_STARTED == pAdapter->batchScanState)
8942 {
8943 hdd_deinit_batch_scan(pAdapter);
8944 }
Rajeev79dbe4c2013-10-05 11:03:42 +05308945 }
Rajeev Kumarf999e582014-01-09 17:33:29 -08008946 }
Rajeev79dbe4c2013-10-05 11:03:42 +05308947#endif
8948
Jeff Johnson295189b2012-06-20 16:38:30 -07008949 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
8950 if( rtnl_held )
8951 {
8952 unregister_netdevice(pWlanDev);
8953 }
8954 else
8955 {
8956 unregister_netdev(pWlanDev);
8957 }
8958 // note that the pAdapter is no longer valid at this point
8959 // since the memory has been reclaimed
8960 }
8961
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05308962 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07008963}
8964
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008965void hdd_set_pwrparams(hdd_context_t *pHddCtx)
8966{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308967 VOS_STATUS status;
8968 hdd_adapter_t *pAdapter = NULL;
8969 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008970
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308971 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008972
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308973 /*loop through all adapters.*/
8974 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008975 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308976 pAdapter = pAdapterNode->pAdapter;
8977 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
8978 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008979
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308980 { // we skip this registration for modes other than STA and P2P client modes.
8981 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
8982 pAdapterNode = pNext;
8983 continue;
8984 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008985
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308986 //Apply Dynamic DTIM For P2P
8987 //Only if ignoreDynamicDtimInP2pMode is not set in ini
8988 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
8989 pHddCtx->cfg_ini->enableModulatedDTIM) &&
8990 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
8991 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
8992 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
8993 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
8994 (eConnectionState_Associated ==
8995 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
8996 (pHddCtx->cfg_ini->fIsBmpsEnabled))
8997 {
8998 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008999
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05309000 powerRequest.uIgnoreDTIM = 1;
9001 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
9002
9003 if (pHddCtx->cfg_ini->enableModulatedDTIM)
9004 {
9005 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
9006 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
9007 }
9008 else
9009 {
9010 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
9011 }
9012
9013 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
9014 * specified during Enter/Exit BMPS when LCD off*/
9015 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
9016 NULL, eANI_BOOLEAN_FALSE);
9017 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
9018 NULL, eANI_BOOLEAN_FALSE);
9019
9020 /* switch to the DTIM specified in cfg.ini */
9021 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Abhishek Singh1e390cf2015-10-27 13:45:17 +05309022 "Switch to DTIM %d Listen interval %d",
9023 powerRequest.uDTIMPeriod,
9024 powerRequest.uListenInterval);
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05309025 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
9026 break;
9027
9028 }
9029
9030 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
9031 pAdapterNode = pNext;
9032 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08009033}
9034
9035void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
9036{
9037 /*Switch back to DTIM 1*/
9038 tSirSetPowerParamsReq powerRequest = { 0 };
9039
9040 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
9041 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07009042 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08009043
9044 /* Update ignoreDTIM and ListedInterval in CFG with default values */
9045 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
9046 NULL, eANI_BOOLEAN_FALSE);
9047 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
9048 NULL, eANI_BOOLEAN_FALSE);
9049
9050 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
9051 "Switch to DTIM%d",powerRequest.uListenInterval);
9052 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
9053
9054}
9055
Jeff Johnson295189b2012-06-20 16:38:30 -07009056VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
9057{
9058 VOS_STATUS status = VOS_STATUS_SUCCESS;
Sushant Kaushik4928e542014-12-29 15:25:54 +05309059 if (WLAN_HDD_IS_UNLOAD_IN_PROGRESS(pHddCtx))
9060 {
9061 hddLog( LOGE, FL("Wlan Unload in progress"));
9062 return VOS_STATUS_E_PERM;
9063 }
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05309064
9065 if (wlan_hdd_check_monitor_state(pHddCtx)) {
9066 hddLog(LOG1, FL("Monitor mode is started, cannot enable BMPS"));
9067 return VOS_STATUS_SUCCESS;
9068 }
9069
Jeff Johnson295189b2012-06-20 16:38:30 -07009070 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
9071 {
9072 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
9073 }
9074
9075 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
9076 {
9077 sme_StartAutoBmpsTimer(pHddCtx->hHal);
9078 }
9079
9080 if (pHddCtx->cfg_ini->fIsImpsEnabled)
9081 {
9082 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
9083 }
9084
9085 return status;
9086}
9087
9088VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
9089{
9090 hdd_adapter_t *pAdapter = NULL;
9091 eHalStatus halStatus;
9092 VOS_STATUS status = VOS_STATUS_E_INVAL;
9093 v_BOOL_t disableBmps = FALSE;
9094 v_BOOL_t disableImps = FALSE;
9095
9096 switch(session_type)
9097 {
9098 case WLAN_HDD_INFRA_STATION:
9099 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07009100 case WLAN_HDD_P2P_CLIENT:
9101 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07009102 //Exit BMPS -> Is Sta/P2P Client is already connected
9103 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
9104 if((NULL != pAdapter)&&
9105 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
9106 {
9107 disableBmps = TRUE;
9108 }
9109
9110 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
9111 if((NULL != pAdapter)&&
9112 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
9113 {
9114 disableBmps = TRUE;
9115 }
9116
9117 //Exit both Bmps and Imps incase of Go/SAP Mode
9118 if((WLAN_HDD_SOFTAP == session_type) ||
9119 (WLAN_HDD_P2P_GO == session_type))
9120 {
9121 disableBmps = TRUE;
9122 disableImps = TRUE;
9123 }
9124
9125 if(TRUE == disableImps)
9126 {
9127 if (pHddCtx->cfg_ini->fIsImpsEnabled)
9128 {
9129 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
9130 }
9131 }
9132
9133 if(TRUE == disableBmps)
9134 {
9135 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
9136 {
9137 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
9138
9139 if(eHAL_STATUS_SUCCESS != halStatus)
9140 {
9141 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08009142 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009143 VOS_ASSERT(0);
9144 return status;
9145 }
9146 }
9147
9148 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
9149 {
9150 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
9151
9152 if(eHAL_STATUS_SUCCESS != halStatus)
9153 {
9154 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08009155 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009156 VOS_ASSERT(0);
9157 return status;
9158 }
9159 }
9160 }
9161
9162 if((TRUE == disableBmps) ||
9163 (TRUE == disableImps))
9164 {
9165 /* Now, get the chip into Full Power now */
9166 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
9167 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
9168 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
9169
9170 if(halStatus != eHAL_STATUS_SUCCESS)
9171 {
9172 if(halStatus == eHAL_STATUS_PMC_PENDING)
9173 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309174 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07009175 //Block on a completion variable. Can't wait forever though
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309176 ret = wait_for_completion_interruptible_timeout(
9177 &pHddCtx->full_pwr_comp_var,
9178 msecs_to_jiffies(1000));
9179 if (ret <= 0)
9180 {
9181 hddLog(VOS_TRACE_LEVEL_ERROR,
9182 "%s: wait on full_pwr_comp_var failed %ld",
9183 __func__, ret);
9184 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009185 }
9186 else
9187 {
9188 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08009189 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009190 VOS_ASSERT(0);
9191 return status;
9192 }
9193 }
9194
9195 status = VOS_STATUS_SUCCESS;
9196 }
9197
9198 break;
9199 }
9200 return status;
9201}
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +05309202
9203void hdd_monPostMsgCb(tANI_U32 *magic, struct completion *cmpVar)
9204{
9205 if (magic == NULL || cmpVar == NULL) {
9206 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnsonc135a9a2017-09-19 08:37:24 -07009207 FL("invalid arguments %pK %pK"), magic, cmpVar);
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +05309208 return;
9209 }
9210 if (*magic != MON_MODE_MSG_MAGIC) {
9211 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9212 FL("maic: %x"), *magic);
9213 return;
9214 }
9215
9216 complete(cmpVar);
9217 return;
9218}
9219
Katya Nigame7b69a82015-04-28 15:24:06 +05309220void hdd_init_mon_mode (hdd_adapter_t *pAdapter)
9221 {
9222 hdd_mon_ctx_t *pMonCtx = NULL;
9223 pMonCtx = WLAN_HDD_GET_MONITOR_CTX_PTR(pAdapter);
9224
9225 pMonCtx->state = 0;
9226 pMonCtx->ChannelNo = 1;
9227 pMonCtx->ChannelBW = 20;
Katya Nigamd7d3a1f2015-06-11 14:04:24 +05309228 pMonCtx->crcCheckEnabled = 1;
9229 pMonCtx->typeSubtypeBitmap = 0xFFFF00000000;
9230 pMonCtx->is80211to803ConReq = 1;
Katya Nigame7b69a82015-04-28 15:24:06 +05309231 pMonCtx->numOfMacFilters = 0;
9232 }
9233
Jeff Johnson295189b2012-06-20 16:38:30 -07009234
9235hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08009236 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07009237 tANI_U8 rtnl_held )
9238{
9239 hdd_adapter_t *pAdapter = NULL;
9240 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
9241 VOS_STATUS status = VOS_STATUS_E_FAILURE;
9242 VOS_STATUS exitbmpsStatus;
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05309243 v_CONTEXT_t pVosContext = NULL;
9244
9245 /* No need to check for NULL, reaching this step
9246 * means vos context is initialized
9247 */
9248 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07009249
Arif Hussain6d2a3322013-11-17 19:50:10 -08009250 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d",__func__,iface_name,session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07009251
Nirav Shah436658f2014-02-28 17:05:45 +05309252 if(macAddr == NULL)
9253 {
9254 /* Not received valid macAddr */
9255 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9256 "%s:Unable to add virtual intf: Not able to get"
9257 "valid mac address",__func__);
9258 return NULL;
9259 }
9260
Jeff Johnson295189b2012-06-20 16:38:30 -07009261 //Disable BMPS incase of Concurrency
9262 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
9263
9264 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
9265 {
9266 //Fail to Exit BMPS
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309267 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Exit BMPS", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009268 VOS_ASSERT(0);
9269 return NULL;
9270 }
9271
9272 switch(session_type)
9273 {
9274 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07009275 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07009276 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07009277 {
9278 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
9279
9280 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309281 {
9282 hddLog(VOS_TRACE_LEVEL_FATAL,
9283 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07009284 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309285 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009286
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05309287#ifdef FEATURE_WLAN_TDLS
9288 /* A Mutex Lock is introduced while changing/initializing the mode to
9289 * protect the concurrent access for the Adapters by TDLS module.
9290 */
Rajesh Chauhana34c6e62014-03-25 16:37:58 +05309291 mutex_lock(&pHddCtx->tdls_lock);
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05309292#endif
9293
Jeff Johnsone7245742012-09-05 17:12:55 -07009294 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
9295 NL80211_IFTYPE_P2P_CLIENT:
9296 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07009297
Jeff Johnson295189b2012-06-20 16:38:30 -07009298 pAdapter->device_mode = session_type;
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05309299#ifdef FEATURE_WLAN_TDLS
9300 mutex_unlock(&pHddCtx->tdls_lock);
9301#endif
Sunil Dutt66485cb2013-12-19 19:05:03 +05309302
Mahesh A Saptasagar67ab9222015-10-21 15:38:41 +05309303 hdd_initialize_adapter_common(pAdapter);
Sunil Dutt66485cb2013-12-19 19:05:03 +05309304 status = hdd_init_station_mode( pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07009305 if( VOS_STATUS_SUCCESS != status )
9306 goto err_free_netdev;
9307
9308 status = hdd_register_interface( pAdapter, rtnl_held );
9309 if( VOS_STATUS_SUCCESS != status )
9310 {
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05309311#ifdef FEATURE_WLAN_TDLS
9312 mutex_lock(&pHddCtx->tdls_lock);
9313#endif
c_hpothu002231a2015-02-05 14:58:51 +05309314 hdd_deinit_adapter(pHddCtx, pAdapter, rtnl_held);
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05309315#ifdef FEATURE_WLAN_TDLS
9316 mutex_unlock(&pHddCtx->tdls_lock);
9317#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009318 goto err_free_netdev;
9319 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05309320
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05309321 // Workqueue which gets scheduled in IPv4 notification callback.
Anand N Sunkaddc63c792015-06-03 14:33:24 +05309322 vos_init_work(&pAdapter->ipv4NotifierWorkQueue, hdd_ipv4_notifier_work_queue);
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05309323
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05309324#ifdef WLAN_NS_OFFLOAD
9325 // Workqueue which gets scheduled in IPv6 notification callback.
Anand N Sunkaddc63c792015-06-03 14:33:24 +05309326 vos_init_work(&pAdapter->ipv6NotifierWorkQueue, hdd_ipv6_notifier_work_queue);
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05309327#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009328 //Stop the Interface TX queue.
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05309329 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
Jeff Johnson295189b2012-06-20 16:38:30 -07009330 netif_tx_disable(pAdapter->dev);
9331 //netif_tx_disable(pWlanDev);
9332 netif_carrier_off(pAdapter->dev);
9333
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +05309334 if (WLAN_HDD_P2P_CLIENT == session_type ||
9335 WLAN_HDD_P2P_DEVICE == session_type)
9336 {
9337 /* Initialize the work queue to defer the
9338 * back to back RoC request */
Anand N Sunkaddc63c792015-06-03 14:33:24 +05309339 vos_init_delayed_work(&pAdapter->roc_work,
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +05309340 hdd_p2p_roc_work_queue);
9341 }
9342
Jeff Johnson295189b2012-06-20 16:38:30 -07009343 break;
9344 }
9345
Jeff Johnson295189b2012-06-20 16:38:30 -07009346 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07009347 case WLAN_HDD_SOFTAP:
9348 {
9349 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
9350 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309351 {
9352 hddLog(VOS_TRACE_LEVEL_FATAL,
9353 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07009354 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309355 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009356
Jeff Johnson295189b2012-06-20 16:38:30 -07009357 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
9358 NL80211_IFTYPE_AP:
9359 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07009360 pAdapter->device_mode = session_type;
9361
Mahesh A Saptasagar67ab9222015-10-21 15:38:41 +05309362 hdd_initialize_adapter_common(pAdapter);
Hanumanth Reddy Pothula15bc0fa2017-02-03 17:24:17 +05309363 status = hdd_init_ap_mode(pAdapter, false);
Jeff Johnson295189b2012-06-20 16:38:30 -07009364 if( VOS_STATUS_SUCCESS != status )
9365 goto err_free_netdev;
9366
Nirav Shah7e3c8132015-06-22 23:51:42 +05309367 status = hdd_sta_id_hash_attach(pAdapter);
9368 if (VOS_STATUS_SUCCESS != status)
9369 {
9370 hddLog(VOS_TRACE_LEVEL_FATAL,
9371 FL("failed to attach hash for session %d"), session_type);
9372 hdd_deinit_adapter(pHddCtx, pAdapter, rtnl_held);
9373 goto err_free_netdev;
9374 }
9375
Jeff Johnson295189b2012-06-20 16:38:30 -07009376 status = hdd_register_hostapd( pAdapter, rtnl_held );
9377 if( VOS_STATUS_SUCCESS != status )
9378 {
c_hpothu002231a2015-02-05 14:58:51 +05309379 hdd_deinit_adapter(pHddCtx, pAdapter, rtnl_held);
Jeff Johnson295189b2012-06-20 16:38:30 -07009380 goto err_free_netdev;
9381 }
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05309382 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
Jeff Johnson295189b2012-06-20 16:38:30 -07009383 netif_tx_disable(pAdapter->dev);
9384 netif_carrier_off(pAdapter->dev);
9385
9386 hdd_set_conparam( 1 );
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +05309387
Hanumanth Reddy Pothulab4537b82018-03-02 12:20:38 +05309388 // Workqueue which gets scheduled in IPv4 notification callback.
9389 vos_init_work(&pAdapter->ipv4NotifierWorkQueue,
9390 hdd_ipv4_notifier_work_queue);
9391
9392#ifdef WLAN_NS_OFFLOAD
9393 // Workqueue which gets scheduled in IPv6 notification callback.
9394 vos_init_work(&pAdapter->ipv6NotifierWorkQueue,
9395 hdd_ipv6_notifier_work_queue);
9396#endif
9397
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +05309398 if (WLAN_HDD_P2P_GO == session_type)
9399 {
9400 /* Initialize the work queue to
9401 * defer the back to back RoC request */
9402 INIT_DELAYED_WORK(&pAdapter->roc_work,
9403 hdd_p2p_roc_work_queue);
9404 }
Bhargav Shahd0715912015-10-01 18:17:37 +05309405
Jeff Johnson295189b2012-06-20 16:38:30 -07009406 break;
9407 }
9408 case WLAN_HDD_MONITOR:
9409 {
Jeff Johnson295189b2012-06-20 16:38:30 -07009410 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
9411 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309412 {
9413 hddLog(VOS_TRACE_LEVEL_FATAL,
9414 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07009415 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309416 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009417
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05309418 pAdapter->device_mode = session_type;
9419 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
9420
Katya Nigame7b69a82015-04-28 15:24:06 +05309421 // Register wireless extensions
9422 if( VOS_STATUS_SUCCESS != (status = hdd_register_wext(pAdapter->dev)))
9423 {
9424 hddLog(VOS_TRACE_LEVEL_FATAL,
9425 "hdd_register_wext() failed with status code %08d [x%08x]",
9426 status, status );
9427 status = VOS_STATUS_E_FAILURE;
9428 }
9429
Jeff Johnson295189b2012-06-20 16:38:30 -07009430#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
9431 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
9432#else
9433 pAdapter->dev->open = hdd_mon_open;
9434 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
Katya Nigame7b69a82015-04-28 15:24:06 +05309435 pAdapter->dev->stop = hdd_mon_stop;
9436 pAdapter->dev->do_ioctl = hdd_mon_ioctl;
Jeff Johnson295189b2012-06-20 16:38:30 -07009437#endif
Katya Nigame7b69a82015-04-28 15:24:06 +05309438 hdd_init_mon_mode( pAdapter );
Mahesh A Saptasagar67ab9222015-10-21 15:38:41 +05309439 hdd_initialize_adapter_common(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07009440 hdd_init_tx_rx( pAdapter );
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05309441
9442 if (VOS_MONITOR_MODE != hdd_get_conparam())
9443 WLANTL_SetMonRxCbk( pVosContext, hdd_rx_packet_monitor_cbk );
9444
Jeff Johnson295189b2012-06-20 16:38:30 -07009445 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05309446 status = hdd_register_interface( pAdapter, rtnl_held );
Katya Nigame7b69a82015-04-28 15:24:06 +05309447 //Stop the Interface TX queue.
9448 netif_tx_disable(pAdapter->dev);
9449 netif_carrier_off(pAdapter->dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07009450 }
9451 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07009452 case WLAN_HDD_FTM:
9453 {
9454 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
9455
9456 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309457 {
9458 hddLog(VOS_TRACE_LEVEL_FATAL,
9459 FL("failed to allocate adapter for session %d"), session_type);
9460 return NULL;
9461 }
9462
Jeff Johnson295189b2012-06-20 16:38:30 -07009463 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
9464 * message while loading driver in FTM mode. */
9465 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
9466 pAdapter->device_mode = session_type;
9467 status = hdd_register_interface( pAdapter, rtnl_held );
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05309468
Mahesh A Saptasagar67ab9222015-10-21 15:38:41 +05309469 hdd_initialize_adapter_common(pAdapter);
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05309470 hdd_init_tx_rx( pAdapter );
9471
9472 //Stop the Interface TX queue.
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05309473 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05309474 netif_tx_disable(pAdapter->dev);
9475 netif_carrier_off(pAdapter->dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07009476 }
9477 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07009478 default:
9479 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309480 hddLog(VOS_TRACE_LEVEL_FATAL,"%s Invalid session type %d",
9481 __func__, session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07009482 VOS_ASSERT(0);
9483 return NULL;
9484 }
9485 }
9486
Jeff Johnson295189b2012-06-20 16:38:30 -07009487 if( VOS_STATUS_SUCCESS == status )
9488 {
Mahesh A Saptasagar67ab9222015-10-21 15:38:41 +05309489 //Add it to the hdd's session list.
Jeff Johnson295189b2012-06-20 16:38:30 -07009490 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
9491 if( NULL == pHddAdapterNode )
9492 {
9493 status = VOS_STATUS_E_NOMEM;
9494 }
9495 else
9496 {
9497 pHddAdapterNode->pAdapter = pAdapter;
9498 status = hdd_add_adapter_back ( pHddCtx,
9499 pHddAdapterNode );
9500 }
9501 }
9502
9503 if( VOS_STATUS_SUCCESS != status )
9504 {
9505 if( NULL != pAdapter )
9506 {
9507 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
9508 pAdapter = NULL;
9509 }
9510 if( NULL != pHddAdapterNode )
9511 {
9512 vos_mem_free( pHddAdapterNode );
9513 }
9514
9515 goto resume_bmps;
9516 }
9517
9518 if(VOS_STATUS_SUCCESS == status)
9519 {
9520 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07009521 //Initialize the WoWL service
9522 if(!hdd_init_wowl(pAdapter))
9523 {
9524 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
9525 goto err_free_netdev;
9526 }
Manjeet Singh3ed79242017-01-11 19:04:32 +05309527 //Initialize the TSF capture data
9528 wlan_hdd_tsf_init(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07009529 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009530 return pAdapter;
9531
9532err_free_netdev:
9533 free_netdev(pAdapter->dev);
9534 wlan_hdd_release_intf_addr( pHddCtx,
9535 pAdapter->macAddressCurrent.bytes );
9536
9537resume_bmps:
9538 //If bmps disabled enable it
9539 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
9540 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05309541 if (pHddCtx->hdd_wlan_suspended)
9542 {
9543 hdd_set_pwrparams(pHddCtx);
9544 }
9545 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07009546 }
9547 return NULL;
9548}
9549
9550VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
9551 tANI_U8 rtnl_held )
9552{
9553 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
9554 VOS_STATUS status;
9555
9556 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
9557 if( VOS_STATUS_SUCCESS != status )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309558 {
9559 hddLog(VOS_TRACE_LEVEL_WARN,"%s: adapter list empty %d",
9560 __func__, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07009561 return status;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309562 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009563
9564 while ( pCurrent->pAdapter != pAdapter )
9565 {
9566 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
9567 if( VOS_STATUS_SUCCESS != status )
9568 break;
9569
9570 pCurrent = pNext;
9571 }
9572 pAdapterNode = pCurrent;
9573 if( VOS_STATUS_SUCCESS == status )
9574 {
9575 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
9576 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05309577
9578#ifdef FEATURE_WLAN_TDLS
9579
9580 /* A Mutex Lock is introduced while changing/initializing the mode to
9581 * protect the concurrent access for the Adapters by TDLS module.
9582 */
Rajesh Chauhana34c6e62014-03-25 16:37:58 +05309583 mutex_lock(&pHddCtx->tdls_lock);
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05309584#endif
9585
Jeff Johnson295189b2012-06-20 16:38:30 -07009586 hdd_remove_adapter( pHddCtx, pAdapterNode );
9587 vos_mem_free( pAdapterNode );
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08009588 pAdapterNode = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07009589
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05309590#ifdef FEATURE_WLAN_TDLS
9591 mutex_unlock(&pHddCtx->tdls_lock);
9592#endif
9593
Jeff Johnson295189b2012-06-20 16:38:30 -07009594
9595 /* If there is a single session of STA/P2P client, re-enable BMPS */
Agarwal Ashish51325b52014-06-16 16:50:49 +05309596 if ((!vos_concurrent_open_sessions_running()) &&
9597 ((pHddCtx->no_of_open_sessions[VOS_STA_MODE] >= 1) ||
9598 (pHddCtx->no_of_open_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
Jeff Johnson295189b2012-06-20 16:38:30 -07009599 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05309600 if (pHddCtx->hdd_wlan_suspended)
9601 {
9602 hdd_set_pwrparams(pHddCtx);
9603 }
9604 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07009605 }
9606
9607 return VOS_STATUS_SUCCESS;
9608 }
9609
9610 return VOS_STATUS_E_FAILURE;
9611}
9612
9613VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
9614{
9615 hdd_adapter_list_node_t *pHddAdapterNode;
9616 VOS_STATUS status;
9617
9618 ENTER();
9619
9620 do
9621 {
9622 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
9623 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
9624 {
9625 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
9626 vos_mem_free( pHddAdapterNode );
9627 }
9628 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
9629
9630 EXIT();
9631
9632 return VOS_STATUS_SUCCESS;
9633}
9634
9635void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
9636{
9637 v_U8_t addIE[1] = {0};
9638
9639 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
9640 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
9641 eANI_BOOLEAN_FALSE) )
9642 {
9643 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08009644 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07009645 }
9646
9647 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
9648 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
9649 eANI_BOOLEAN_FALSE) )
9650 {
9651 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08009652 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07009653 }
9654
9655 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
9656 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
9657 eANI_BOOLEAN_FALSE) )
9658 {
9659 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08009660 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07009661 }
9662}
9663
Anurag Chouhan83026002016-12-13 22:46:21 +05309664VOS_STATUS hdd_cleanup_ap_events(hdd_adapter_t *adapter)
9665{
9666#ifdef DHCP_SERVER_OFFLOAD
9667 vos_event_destroy(&adapter->dhcp_status.vos_event);
9668#endif
Anurag Chouhan0b29de02016-12-16 13:18:40 +05309669#ifdef MDNS_OFFLOAD
9670 vos_event_destroy(&adapter->mdns_status.vos_event);
9671#endif
Anurag Chouhan83026002016-12-13 22:46:21 +05309672 return VOS_STATUS_SUCCESS;
9673}
9674
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05309675int wlan_hdd_stop_mon(hdd_context_t *hdd_ctx, bool wait)
9676{
9677 hdd_mon_ctx_t *mon_ctx;
9678 long ret;
9679 v_U32_t magic;
9680 struct completion cmp_var;
9681 void (*func_ptr)(tANI_U32 *magic, struct completion *cmpVar) = NULL;
9682 hdd_adapter_t *adapter;
9683
9684 adapter = hdd_get_adapter(hdd_ctx, WLAN_HDD_MONITOR);
9685 if (!adapter) {
9686 hddLog(LOGE, FL("Invalid STA + MON mode"));
9687 return -EINVAL;
9688 }
9689
9690 mon_ctx = WLAN_HDD_GET_MONITOR_CTX_PTR(adapter);
9691 if (!mon_ctx)
9692 return 0;
9693
9694 if (mon_ctx->state != MON_MODE_START)
9695 return 0;
9696
9697 mon_ctx->state = MON_MODE_STOP;
9698 if (wait) {
9699 func_ptr = hdd_monPostMsgCb;
9700 magic = MON_MODE_MSG_MAGIC;
9701 init_completion(&cmp_var);
9702 }
9703
9704 if (VOS_STATUS_SUCCESS != wlan_hdd_mon_postMsg(&magic, &cmp_var,
9705 mon_ctx,
9706 hdd_monPostMsgCb)) {
9707 hddLog(LOGE, FL("failed to stop MON MODE"));
9708 mon_ctx->state = MON_MODE_START;
9709 magic = 0;
9710 return -EINVAL;
9711 }
9712
9713 if (!wait)
9714 goto bmps_roaming;
9715
9716 ret = wait_for_completion_timeout(&cmp_var, MON_MODE_MSG_TIMEOUT);
9717 magic = 0;
9718 if (ret <= 0 ) {
9719 hddLog(LOGE,
9720 FL("timeout on stop monitor mode completion %ld"), ret);
9721 return -EINVAL;
9722 }
9723
9724bmps_roaming:
9725 hddLog(LOG1, FL("Enable BMPS"));
9726 hdd_enable_bmps_imps(hdd_ctx);
9727 hdd_restore_roaming(hdd_ctx);
9728
9729 return 0;
9730}
9731
9732bool wlan_hdd_check_monitor_state(hdd_context_t *hdd_ctx)
9733{
9734 hdd_adapter_t *mon_adapter;
9735 hdd_mon_ctx_t *mon_ctx;
9736
9737 if (hdd_ctx->concurrency_mode != VOS_STA_MON)
9738 return false;
9739
9740 mon_adapter = hdd_get_adapter(hdd_ctx, WLAN_HDD_MONITOR);
9741 if (!mon_adapter) {
9742 hddLog(LOGE, FL("Invalid concurrency mode"));
9743 return false;
9744 }
9745
9746 mon_ctx = WLAN_HDD_GET_MONITOR_CTX_PTR(mon_adapter);
9747 if (mon_ctx->state == MON_MODE_START)
9748 return true;
9749
9750 return false;
9751}
9752
9753int wlan_hdd_check_and_stop_mon(hdd_adapter_t *sta_adapter, bool wait)
9754{
9755 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(sta_adapter);
9756
9757 if ((sta_adapter->device_mode != WLAN_HDD_INFRA_STATION) ||
9758 !wlan_hdd_check_monitor_state(hdd_ctx))
9759 return 0;
9760
9761 if (wlan_hdd_stop_mon(hdd_ctx, wait))
9762 return -EINVAL;
9763
9764 return 0;
9765}
9766
9767void hdd_disable_roaming(hdd_context_t *hdd_ctx)
9768{
9769 if (!hdd_ctx)
9770 return;
9771
9772 if (!hdd_ctx->cfg_ini->isFastRoamIniFeatureEnabled) {
9773 hdd_ctx->roaming_ini_original = CFG_LFR_FEATURE_ENABLED_MIN;
9774 return;
9775 }
9776
9777 hddLog(LOG1, FL("Disable driver and firmware roaming"));
9778
9779 hdd_ctx->roaming_ini_original =
9780 hdd_ctx->cfg_ini->isFastRoamIniFeatureEnabled;
9781
9782 hdd_ctx->cfg_ini->isFastRoamIniFeatureEnabled =
9783 CFG_LFR_FEATURE_ENABLED_MIN;
9784
9785 sme_UpdateIsFastRoamIniFeatureEnabled(hdd_ctx->hHal,
9786 CFG_LFR_FEATURE_ENABLED_MIN);
9787}
9788
9789void hdd_restore_roaming(hdd_context_t *hdd_ctx)
9790{
9791 if (!hdd_ctx->roaming_ini_original)
9792 return;
9793
9794 hddLog(LOG1, FL("Enable driver and firmware roaming"));
9795
9796 hdd_ctx->cfg_ini->isFastRoamIniFeatureEnabled =
9797 CFG_LFR_FEATURE_ENABLED_MAX;
9798
9799 hdd_ctx->roaming_ini_original = CFG_LFR_FEATURE_ENABLED_MIN;
9800
9801 sme_UpdateIsFastRoamIniFeatureEnabled(hdd_ctx->hHal,
9802 CFG_LFR_FEATURE_ENABLED_MAX);
9803}
Anurag Chouhan83026002016-12-13 22:46:21 +05309804
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05309805VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
9806 const v_BOOL_t bCloseSession )
Jeff Johnson295189b2012-06-20 16:38:30 -07009807{
9808 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
9809 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
Kaushik, Sushant4975a572014-10-21 16:07:48 +05309810 hdd_scaninfo_t *pScanInfo = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07009811 union iwreq_data wrqu;
Kaushik, Sushant7005e372014-04-08 11:36:54 +05309812 v_U8_t retry = 0;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309813 long ret;
Nirav Shah7e3c8132015-06-22 23:51:42 +05309814 VOS_STATUS status;
Jeff Johnson295189b2012-06-20 16:38:30 -07009815
Anand N Sunkad26d71b92014-12-24 18:08:22 +05309816 if (pHddCtx->isLogpInProgress) {
9817 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
9818 "%s:LOGP in Progress. Ignore!!!",__func__);
9819 return VOS_STATUS_E_FAILURE;
9820 }
9821
Jeff Johnson295189b2012-06-20 16:38:30 -07009822 ENTER();
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +05309823
Kaushik, Sushant4975a572014-10-21 16:07:48 +05309824 pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07009825 switch(pAdapter->device_mode)
9826 {
Nirav Shah0cf4d892015-11-05 16:27:27 +05309827 case WLAN_HDD_IBSS:
9828 if ( VOS_TRUE == bCloseSession )
9829 {
9830 status = hdd_sta_id_hash_detach(pAdapter);
9831 if (status != VOS_STATUS_SUCCESS)
9832 hddLog(VOS_TRACE_LEVEL_ERROR,
9833 FL("sta id hash detach failed"));
9834 }
9835
Jeff Johnson295189b2012-06-20 16:38:30 -07009836 case WLAN_HDD_INFRA_STATION:
9837 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07009838 case WLAN_HDD_P2P_DEVICE:
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05309839 {
9840 hdd_station_ctx_t *pstation = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Mahesh A Saptasagare4d05d42015-07-02 16:17:20 +05309841#ifdef FEATURE_WLAN_TDLS
9842 mutex_lock(&pHddCtx->tdls_lock);
9843 wlan_hdd_tdls_exit(pAdapter, TRUE);
9844 mutex_unlock(&pHddCtx->tdls_lock);
9845#endif
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05309846 if( hdd_connIsConnected(pstation) ||
9847 (pstation->conn_info.connState == eConnectionState_Connecting) )
Jeff Johnson295189b2012-06-20 16:38:30 -07009848 {
Abhishek Singhe21a5212017-06-09 09:42:58 +05309849 /*
9850 * Indicate sme of disconnect so that in progress connection
9851 * or preauth can be aborted.
9852 */
9853 sme_abortConnection(WLAN_HDD_GET_HAL_CTX(pAdapter),
9854 pAdapter->sessionId);
Abhishek Singh99f17b82017-02-06 16:57:56 +05309855 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07009856 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
9857 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
9858 pAdapter->sessionId,
9859 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
9860 else
9861 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
9862 pAdapter->sessionId,
9863 eCSR_DISCONNECT_REASON_UNSPECIFIED);
Abhishek Singh7b52ed52016-02-11 17:45:54 +05309864 /* Success implies disconnect command got queued up successfully
9865 * Or cmd not queued as scan for SSID is in progress
9866 */
9867 if((eHAL_STATUS_SUCCESS == halStatus) ||
9868 (eHAL_STATUS_CMD_NOT_QUEUED == halStatus))
Jeff Johnson295189b2012-06-20 16:38:30 -07009869 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309870 ret = wait_for_completion_interruptible_timeout(
9871 &pAdapter->disconnect_comp_var,
9872 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Abhishek Singh7b52ed52016-02-11 17:45:54 +05309873 if (ret <= 0 &&
9874 (eHAL_STATUS_CMD_NOT_QUEUED != halStatus))
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309875 {
9876 hddLog(VOS_TRACE_LEVEL_ERROR,
9877 "%s: wait on disconnect_comp_var failed %ld",
9878 __func__, ret);
9879 }
9880 }
9881 else
9882 {
9883 hddLog(LOGE, "%s: failed to post disconnect event to SME",
9884 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009885 }
9886 memset(&wrqu, '\0', sizeof(wrqu));
9887 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
9888 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
9889 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
9890 }
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05309891 else if(pstation->conn_info.connState ==
9892 eConnectionState_Disconnecting)
9893 {
9894 ret = wait_for_completion_interruptible_timeout(
9895 &pAdapter->disconnect_comp_var,
9896 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
9897 if (ret <= 0)
9898 {
9899 hddLog(VOS_TRACE_LEVEL_ERROR,
9900 FL("wait on disconnect_comp_var failed %ld"), ret);
9901 }
9902 }
Sachin Ahuja27dd2402016-08-01 20:30:31 +05309903 if(pScanInfo != NULL && pHddCtx->scan_info.mScanPending)
Jeff Johnson295189b2012-06-20 16:38:30 -07009904 {
Mahesh A Saptasagar0b61dcc2016-02-15 14:23:38 +05309905 wlan_hdd_scan_abort(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07009906 }
Abhishek Singh3ac179b2015-09-21 10:01:34 +05309907 if ((pAdapter->device_mode != WLAN_HDD_INFRA_STATION) &&
9908 (pAdapter->device_mode != WLAN_HDD_IBSS))
Kaushik, Sushant7005e372014-04-08 11:36:54 +05309909 {
9910 while (pAdapter->is_roc_inprogress)
9911 {
9912 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9913 "%s: ROC in progress for session %d!!!",
9914 __func__, pAdapter->sessionId);
9915 // waiting for ROC to expire
9916 msleep(500);
9917 /* In GO present case , if retry exceeds 3,
9918 it means something went wrong. */
9919 if ( retry++ > MAX_WAIT_FOR_ROC_COMPLETION )
9920 {
9921 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9922 "%s: ROC completion is not received.!!!", __func__);
Deepthi Gowri70498252015-01-20 15:56:45 +05309923 if (eHAL_STATUS_SUCCESS !=
9924 sme_CancelRemainOnChannel( WLAN_HDD_GET_HAL_CTX( pAdapter),
9925 pAdapter->sessionId ))
9926 {
9927 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9928 FL("Failed to Cancel Remain on Channel"));
9929 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +05309930 wait_for_completion_interruptible_timeout(
9931 &pAdapter->cancel_rem_on_chan_var,
9932 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
9933 break;
9934 }
9935 }
Anand N Sunkaddc63c792015-06-03 14:33:24 +05309936 vos_flush_delayed_work(&pAdapter->roc_work);
Kaushik, Sushant7005e372014-04-08 11:36:54 +05309937 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05309938#ifdef WLAN_NS_OFFLOAD
Anand N Sunkaddc63c792015-06-03 14:33:24 +05309939 vos_flush_work(&pAdapter->ipv6NotifierWorkQueue);
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05309940#endif
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +05309941
Anand N Sunkaddc63c792015-06-03 14:33:24 +05309942 vos_flush_work(&pAdapter->ipv4NotifierWorkQueue);
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +05309943
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05309944 /* It is possible that the caller of this function does not
9945 * wish to close the session
9946 */
9947 if (VOS_TRUE == bCloseSession &&
9948 test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07009949 {
9950 INIT_COMPLETION(pAdapter->session_close_comp_var);
9951 if (eHAL_STATUS_SUCCESS ==
Agrawal Ashish5a3522c2016-03-02 15:08:28 +05309952 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId, FALSE,
9953 VOS_FALSE, hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07009954 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309955 unsigned long ret;
9956
Jeff Johnson295189b2012-06-20 16:38:30 -07009957 //Block on a completion variable. Can't wait forever though.
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309958 ret = wait_for_completion_timeout(
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05309959 &pAdapter->session_close_comp_var,
9960 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309961 if ( 0 >= ret)
9962 {
9963 hddLog(LOGE, "%s: failure waiting for session_close_comp_var %ld",
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05309964 __func__, ret);
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309965 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009966 }
9967 }
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05309968 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009969 break;
9970
9971 case WLAN_HDD_SOFTAP:
9972 case WLAN_HDD_P2P_GO:
Nirav Shah0cf4d892015-11-05 16:27:27 +05309973 if ( VOS_TRUE == bCloseSession )
9974 {
9975 status = hdd_sta_id_hash_detach(pAdapter);
9976 if (status != VOS_STATUS_SUCCESS)
9977 hddLog(VOS_TRACE_LEVEL_ERROR,
9978 FL("sta id hash detach failed"));
9979 }
9980
Jeff Johnson295189b2012-06-20 16:38:30 -07009981 //Any softap specific cleanup here...
Anurag Chouhan83026002016-12-13 22:46:21 +05309982 hdd_cleanup_ap_events(pAdapter);
Kaushik, Sushant7005e372014-04-08 11:36:54 +05309983 if (pAdapter->device_mode == WLAN_HDD_P2P_GO) {
9984 while (pAdapter->is_roc_inprogress) {
9985 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9986 "%s: ROC in progress for session %d!!!",
9987 __func__, pAdapter->sessionId);
9988 msleep(500);
9989 if ( retry++ > MAX_WAIT_FOR_ROC_COMPLETION ) {
9990 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9991 "%s: ROC completion is not received.!!!", __func__);
9992 WLANSAP_CancelRemainOnChannel(
9993 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
9994 wait_for_completion_interruptible_timeout(
9995 &pAdapter->cancel_rem_on_chan_var,
9996 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
9997 break;
9998 }
9999 }
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +053010000
Anand N Sunkaddc63c792015-06-03 14:33:24 +053010001 vos_flush_delayed_work(&pAdapter->roc_work);
Kaushik, Sushant7005e372014-04-08 11:36:54 +053010002 }
Agrawal Ashish17ef5082016-10-17 18:33:21 +053010003#ifdef SAP_AUTH_OFFLOAD
10004 if (pHddCtx->cfg_ini->enable_sap_auth_offload)
10005 hdd_set_sap_auth_offload(pAdapter, FALSE);
10006#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070010007 mutex_lock(&pHddCtx->sap_lock);
10008 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
10009 {
10010 VOS_STATUS status;
10011 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10012
10013 //Stop Bss.
10014 status = WLANSAP_StopBss(pHddCtx->pvosContext);
10015 if (VOS_IS_STATUS_SUCCESS(status))
10016 {
10017 hdd_hostapd_state_t *pHostapdState =
10018 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
10019
10020 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
10021
10022 if (!VOS_IS_STATUS_SUCCESS(status))
10023 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +053010024 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss %d",
10025 __func__, status);
Jeff Johnson295189b2012-06-20 16:38:30 -070010026 }
10027 }
10028 else
10029 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070010030 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -070010031 }
10032 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
Agarwal Ashish51325b52014-06-16 16:50:49 +053010033 wlan_hdd_decr_active_session(pHddCtx, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -070010034
10035 if (eHAL_STATUS_FAILURE ==
10036 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
10037 0, NULL, eANI_BOOLEAN_FALSE))
10038 {
10039 hddLog(LOGE,
10040 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070010041 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -070010042 }
10043
10044 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
10045 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
10046 eANI_BOOLEAN_FALSE) )
10047 {
10048 hddLog(LOGE,
10049 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
10050 }
10051
10052 // Reset WNI_CFG_PROBE_RSP Flags
10053 wlan_hdd_reset_prob_rspies(pAdapter);
10054 kfree(pAdapter->sessionCtx.ap.beacon);
10055 pAdapter->sessionCtx.ap.beacon = NULL;
10056 }
10057 mutex_unlock(&pHddCtx->sap_lock);
Hanumanth Reddy Pothulab4537b82018-03-02 12:20:38 +053010058
10059#ifdef WLAN_NS_OFFLOAD
10060 vos_flush_work(&pAdapter->ipv6NotifierWorkQueue);
10061#endif
10062 vos_flush_work(&pAdapter->ipv4NotifierWorkQueue);
10063
Jeff Johnson295189b2012-06-20 16:38:30 -070010064 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -070010065
Jeff Johnson295189b2012-06-20 16:38:30 -070010066 case WLAN_HDD_MONITOR:
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +053010067 if (VOS_MONITOR_MODE != hdd_get_conparam())
10068 wlan_hdd_stop_mon(pHddCtx, true);
10069 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -070010070
Jeff Johnson295189b2012-06-20 16:38:30 -070010071 default:
10072 break;
10073 }
10074
10075 EXIT();
10076 return VOS_STATUS_SUCCESS;
10077}
10078
Kapil Gupta137ef892016-12-13 19:38:00 +053010079/**
10080 * wlan_hdd_restart_sap() - to restart SAP in driver internally
10081 * @ap_adapter: - Pointer to SAP hdd_adapter_t structure
10082 *
10083 * wlan_hdd_restart_sap first delete SAP and do cleanup.
10084 * After that WLANSAP_StartBss start re-start process of SAP.
10085 *
10086 * Return: None
10087 */
10088static void wlan_hdd_restart_sap(hdd_adapter_t *ap_adapter)
10089{
10090 hdd_ap_ctx_t *pHddApCtx;
10091 hdd_hostapd_state_t *pHostapdState;
10092 VOS_STATUS vos_status;
10093 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(ap_adapter);
Rajeev Kumar Sirasanagandla5b21a9c2018-01-08 17:05:11 +053010094#ifdef USE_CFG80211_DEL_STA_V2
Kapil Gupta137ef892016-12-13 19:38:00 +053010095 struct station_del_parameters delStaParams;
10096#endif
10097 tsap_Config_t *pConfig;
10098
10099 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
10100 pConfig = &pHddApCtx->sapConfig;
10101
10102 mutex_lock(&pHddCtx->sap_lock);
10103 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags)) {
Rajeev Kumar Sirasanagandla5b21a9c2018-01-08 17:05:11 +053010104#ifdef USE_CFG80211_DEL_STA_V2
Kapil Gupta137ef892016-12-13 19:38:00 +053010105 delStaParams.mac = NULL;
10106 delStaParams.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
10107 delStaParams.reason_code = eCsrForcedDeauthSta;
10108 wlan_hdd_cfg80211_del_station(ap_adapter->wdev.wiphy, ap_adapter->dev,
10109 &delStaParams);
10110#else
10111 wlan_hdd_cfg80211_del_station(ap_adapter->wdev.wiphy, ap_adapter->dev,
10112 NULL);
10113#endif
10114 hdd_cleanup_actionframe(pHddCtx, ap_adapter);
10115
10116 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
10117 vos_event_reset(&pHostapdState->vosEvent);
10118
10119 if (VOS_STATUS_SUCCESS == WLANSAP_StopBss(pHddCtx->pvosContext)) {
10120 vos_status = vos_wait_single_event(&pHostapdState->vosEvent,
10121 10000);
10122 if (!VOS_IS_STATUS_SUCCESS(vos_status)) {
10123 hddLog(LOGE, FL("SAP Stop Failed"));
10124 goto end;
10125 }
10126 }
10127 clear_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
10128 wlan_hdd_decr_active_session(pHddCtx, ap_adapter->device_mode);
10129 hddLog(LOG1, FL("SAP Stop Success"));
10130
10131 if (0 != wlan_hdd_cfg80211_update_apies(ap_adapter)) {
10132 hddLog(LOGE, FL("SAP Not able to set AP IEs"));
10133 goto end;
10134 }
10135
10136 if (WLANSAP_StartBss(pHddCtx->pvosContext, hdd_hostapd_SAPEventCB,
10137 pConfig, (v_PVOID_t)ap_adapter->dev) != VOS_STATUS_SUCCESS) {
10138 hddLog(LOGE, FL("SAP Start Bss fail"));
10139 goto end;
10140 }
10141
10142 hddLog(LOG1, FL("Waiting for SAP to start"));
10143 vos_status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
10144 if (!VOS_IS_STATUS_SUCCESS(vos_status)) {
10145 hddLog(LOGE, FL("SAP Start failed"));
10146 goto end;
10147 }
10148 hddLog(LOG1, FL("SAP Start Success"));
10149 set_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
10150 wlan_hdd_incr_active_session(pHddCtx, ap_adapter->device_mode);
10151 pHostapdState->bCommit = TRUE;
Anurag Chouhanb2951ae2017-03-12 13:41:35 +053010152 if (!VOS_IS_STATUS_SUCCESS(hdd_dhcp_mdns_offload(ap_adapter))) {
10153 hddLog(VOS_TRACE_LEVEL_ERROR, FL("DHCP/MDNS offload Failed!!"));
10154 vos_event_reset(&pHostapdState->vosEvent);
10155 if (VOS_STATUS_SUCCESS == WLANSAP_StopBss(pHddCtx->pvosContext)) {
10156 vos_status = vos_wait_single_event(&pHostapdState->vosEvent,
10157 10000);
10158 if (!VOS_IS_STATUS_SUCCESS(vos_status)) {
10159 hddLog(LOGE, FL("SAP Stop Failed"));
10160 goto end;
10161 }
10162 }
10163 }
Kapil Gupta137ef892016-12-13 19:38:00 +053010164 }
10165end:
10166 mutex_unlock(&pHddCtx->sap_lock);
10167 return;
10168}
10169
10170/**
10171 * __hdd_sap_restart_handle() - to handle restarting of SAP
10172 * @work: name of the work
10173 *
10174 * Purpose of this function is to trigger sap start. this function
10175 * will be called from workqueue.
10176 *
10177 * Return: void.
10178 */
10179static void __hdd_sap_restart_handle(struct work_struct *work)
10180{
10181 hdd_adapter_t *sap_adapter;
10182 hdd_context_t *hdd_ctx = container_of(work,
10183 hdd_context_t,
10184 sap_start_work);
10185 if (0 != wlan_hdd_validate_context(hdd_ctx)) {
10186 vos_ssr_unprotect(__func__);
10187 return;
10188 }
10189 sap_adapter = hdd_get_adapter(hdd_ctx,
10190 WLAN_HDD_SOFTAP);
10191 if (sap_adapter == NULL) {
10192 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
10193 FL("sap_adapter is NULL"));
10194 vos_ssr_unprotect(__func__);
10195 return;
10196 }
10197
10198 if (hdd_ctx->is_ch_avoid_in_progress) {
10199 sap_adapter->sessionCtx.ap.sapConfig.channel = AUTO_CHANNEL_SELECT;
10200 wlan_hdd_restart_sap(sap_adapter);
10201 hdd_change_ch_avoidance_status(hdd_ctx, false);
10202 }
Agrawal Ashish574b3e62017-02-09 18:58:34 +053010203 if (hdd_ctx->cfg_ini->enable_sap_auth_offload)
10204 wlan_hdd_restart_sap(sap_adapter);
Kapil Gupta137ef892016-12-13 19:38:00 +053010205}
10206
10207/**
10208 * hdd_sap_restart_handle() - to handle restarting of SAP
10209 * @work: name of the work
10210 *
10211 * Purpose of this function is to trigger sap start. this function
10212 * will be called from workqueue.
10213 *
10214 * Return: void.
10215 */
10216static void hdd_sap_restart_handle(struct work_struct *work)
10217{
10218 vos_ssr_protect(__func__);
10219 __hdd_sap_restart_handle(work);
10220 vos_ssr_unprotect(__func__);
10221}
10222
10223
Abhishek Singh78c691f2017-11-30 13:48:44 +053010224/**
10225 * __hdd_force_scc_with_ecsa_handle() - to handle force scc using ecsa
10226 * @work: name of the work
10227 *
10228 * Purpose of this function is to force SCC using ECSA. This function
10229 * will be called from workqueue.
10230 *
10231 * Return: void.
10232 */
10233static void
10234__hdd_force_scc_with_ecsa_handle(struct work_struct *work)
10235{
10236 hdd_adapter_t *sap_adapter;
10237 hdd_station_ctx_t *sta_ctx;
10238 hdd_adapter_t *sta_adapter;
Ganesh Kondabattini3655a6d2018-01-08 20:25:39 +053010239 ptSapContext sap_ctx = NULL;
10240 v_CONTEXT_t vos_ctx;
10241 tANI_U8 target_channel;
10242 tsap_Config_t *sap_config;
10243 bool sta_sap_scc_on_dfs_chan;
10244 eNVChannelEnabledType chan_state;
Abhishek Singh78c691f2017-11-30 13:48:44 +053010245 hdd_context_t *hdd_ctx = container_of(to_delayed_work(work),
10246 hdd_context_t,
10247 ecsa_chan_change_work);
10248
10249 if (wlan_hdd_validate_context(hdd_ctx))
10250 return;
10251
10252 sap_adapter = hdd_get_adapter(hdd_ctx,
10253 WLAN_HDD_SOFTAP);
10254 if (!sap_adapter) {
10255 hddLog(LOGE, FL("sap_adapter is NULL"));
10256 return;
10257 }
10258
Ganesh Kondabattini3655a6d2018-01-08 20:25:39 +053010259 vos_ctx = hdd_ctx->pvosContext;
10260 if (!vos_ctx) {
10261 hddLog(LOGE, FL("vos_ctx is NULL"));
10262 return;
10263 }
10264
10265 sap_ctx = VOS_GET_SAP_CB(vos_ctx);
10266 if (!sap_ctx) {
10267 hddLog(LOGE, FL("sap_ctx is NULL"));
10268 return;
10269 }
10270
10271 sap_config = &sap_adapter->sessionCtx.ap.sapConfig;
10272
10273 sta_sap_scc_on_dfs_chan = hdd_is_sta_sap_scc_allowed_on_dfs_chan(hdd_ctx);
10274
Abhishek Singh78c691f2017-11-30 13:48:44 +053010275 sta_adapter = hdd_get_adapter(hdd_ctx,
10276 WLAN_HDD_INFRA_STATION);
10277 if (!sta_adapter) {
10278 hddLog(LOGE, FL("sta_adapter is NULL"));
10279 return;
10280 }
Abhishek Singh78c691f2017-11-30 13:48:44 +053010281
Abhishek Singh10e17cf2018-03-12 14:34:22 +053010282 if (wlansap_chk_n_set_chan_change_in_progress(sap_ctx))
Abhishek Singh78c691f2017-11-30 13:48:44 +053010283 return;
Abhishek Singh10e17cf2018-03-12 14:34:22 +053010284 INIT_COMPLETION(sap_ctx->ecsa_info.chan_switch_comp);
10285
10286 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(sta_adapter);
10287 if (sta_ctx->conn_info.connState != eConnectionState_Associated) {
10288 if (sta_ctx->conn_info.connState == eConnectionState_NotConnected) {
10289 chan_state = vos_nv_getChannelEnabledState(sap_ctx->channel);
10290 hddLog(LOG1, FL("sta not in connected state %d, sta_sap_scc_on_dfs_chan %d, chan_state %d"),
10291 sta_ctx->conn_info.connState, sta_sap_scc_on_dfs_chan,
10292 chan_state);
10293 if (sta_sap_scc_on_dfs_chan &&
10294 (chan_state == NV_CHANNEL_DFS)) {
10295 hddLog(LOGE, FL("Switch SAP to user configured channel"));
10296 target_channel = sap_config->user_config_channel;
10297 goto switch_channel;
10298 }
10299 }
10300 goto abort;
Abhishek Singh78c691f2017-11-30 13:48:44 +053010301 }
10302
Ganesh Kondabattini3655a6d2018-01-08 20:25:39 +053010303 target_channel = sta_ctx->conn_info.operationChannel;
10304switch_channel:
10305 hddLog(LOGE, FL("Switch SAP to %d channel"),
10306 target_channel);
Abhishek Singh10e17cf2018-03-12 14:34:22 +053010307 if (!wlansap_set_channel_change(vos_ctx, target_channel, true))
10308 return;
10309
10310abort:
10311 wlansap_reset_chan_change_in_progress(sap_ctx);
10312 complete(&sap_ctx->ecsa_info.chan_switch_comp);
Abhishek Singh78c691f2017-11-30 13:48:44 +053010313}
10314
10315/**
10316 * hdd_force_scc_with_ecsa_handle() - to handle force scc using ecsa
10317 * @work: name of the work
10318 *
10319 * Purpose of this function is to force SCC using ECSA. This function
10320 * will be called from workqueue.
10321 *
10322 * Return: void.
10323 */
10324static void
10325hdd_force_scc_with_ecsa_handle(struct work_struct *work)
10326{
10327 vos_ssr_protect(__func__);
10328 __hdd_force_scc_with_ecsa_handle(work);
10329 vos_ssr_unprotect(__func__);
10330}
10331
Abhishek Singh10e17cf2018-03-12 14:34:22 +053010332int hdd_wait_for_ecsa_complete(hdd_context_t *hdd_ctx)
10333{
10334 int ret;
10335 ptSapContext sap_ctx = NULL;
10336 v_CONTEXT_t vos_ctx;
10337
10338 vos_ctx = hdd_ctx->pvosContext;
10339 if (!vos_ctx) {
10340 hddLog(LOGE, FL("vos_ctx is NULL"));
10341 return 0;
10342 }
10343
10344 sap_ctx = VOS_GET_SAP_CB(vos_ctx);
10345 if (!sap_ctx) {
10346 hddLog(LOG1, FL("sap_ctx is NULL"));
10347 return 0;
10348 }
10349 if(!sap_ctx->isSapSessionOpen) {
10350 hddLog(LOG1, FL("sap session not opened, SAP in state %d"),
10351 sap_ctx->sapsMachine);
10352 return 0;
10353 }
10354
10355 if (!wlansap_get_change_in_progress(sap_ctx)) {
10356 hddLog(LOG1, FL("channel switch not in progress"));
10357 return 0;
10358 }
10359 ret = wait_for_completion_timeout(&sap_ctx->ecsa_info.chan_switch_comp,
10360 msecs_to_jiffies(HDD_SAP_CHAN_CNG_WAIT_TIME));
10361 if (!ret)
10362 {
10363 hddLog(LOGE, FL("Timeout waiting for SAP channel switch"));
10364 return ret;
10365 }
10366
10367 return 0;
10368}
10369
10370
Ganesh Kondabattini3655a6d2018-01-08 20:25:39 +053010371/**
10372 * hdd_is_sta_sap_scc_allowed_on_dfs_chan() - check if sta+sap scc allowed on
10373 * dfs chan
10374 * @hdd_ctx: pointer to hdd context
10375 *
10376 * This function used to check if sta+sap scc allowed on DFS channel.
10377 *
10378 * Return: None
10379 */
10380bool hdd_is_sta_sap_scc_allowed_on_dfs_chan(hdd_context_t *hdd_ctx)
10381{
10382 if (hdd_ctx->cfg_ini->force_scc_with_ecsa &&
10383 hdd_ctx->cfg_ini->sta_sap_scc_on_dfs_chan)
10384 return true;
10385 else
10386 return false;
10387}
10388
Jeff Johnson295189b2012-06-20 16:38:30 -070010389VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
10390{
10391 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
10392 VOS_STATUS status;
10393 hdd_adapter_t *pAdapter;
10394
10395 ENTER();
10396
10397 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10398
10399 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
10400 {
10401 pAdapter = pAdapterNode->pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -070010402
Agarwal Ashish3a38bd12014-06-12 15:16:52 +053010403 hdd_stop_adapter( pHddCtx, pAdapter, VOS_TRUE );
Jeff Johnson295189b2012-06-20 16:38:30 -070010404
10405 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10406 pAdapterNode = pNext;
10407 }
10408
10409 EXIT();
10410
10411 return VOS_STATUS_SUCCESS;
10412}
10413
Rajeev Kumarf999e582014-01-09 17:33:29 -080010414
10415#ifdef FEATURE_WLAN_BATCH_SCAN
10416/**---------------------------------------------------------------------------
10417
10418 \brief hdd_deinit_batch_scan () - This function cleans up batch scan data
10419 structures
10420
10421 \param - pAdapter Pointer to HDD adapter
10422
10423 \return - None
10424
10425 --------------------------------------------------------------------------*/
10426void hdd_deinit_batch_scan(hdd_adapter_t *pAdapter)
10427{
10428 tHddBatchScanRsp *pNode;
10429 tHddBatchScanRsp *pPrev;
10430
Siddharth Bhalb3e9b792014-02-24 15:14:16 +053010431 if (NULL == pAdapter)
Rajeev Kumarf999e582014-01-09 17:33:29 -080010432 {
Siddharth Bhalb3e9b792014-02-24 15:14:16 +053010433 hddLog(VOS_TRACE_LEVEL_ERROR,
10434 "%s: Adapter context is Null", __func__);
10435 return;
10436 }
10437
10438 pNode = pAdapter->pBatchScanRsp;
10439 while (pNode)
10440 {
10441 pPrev = pNode;
10442 pNode = pNode->pNext;
10443 vos_mem_free((v_VOID_t * )pPrev);
Rajeev Kumarf999e582014-01-09 17:33:29 -080010444 }
10445
10446 pAdapter->pBatchScanRsp = NULL;
10447 pAdapter->numScanList = 0;
10448 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
10449 pAdapter->prev_batch_id = 0;
10450
10451 return;
10452}
10453#endif
10454
10455
Jeff Johnson295189b2012-06-20 16:38:30 -070010456VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
10457{
10458 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
10459 VOS_STATUS status;
10460 hdd_adapter_t *pAdapter;
10461
10462 ENTER();
10463
10464 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10465
10466 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
10467 {
10468 pAdapter = pAdapterNode->pAdapter;
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +053010469 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
Jeff Johnson295189b2012-06-20 16:38:30 -070010470 netif_tx_disable(pAdapter->dev);
Hanumanth Reddy Pothulad864f312017-01-18 16:16:08 +053010471
10472 if (pHddCtx->cfg_ini->sap_internal_restart &&
10473 pAdapter->device_mode == WLAN_HDD_SOFTAP) {
10474 hddLog(LOG1, FL("driver supports sap restart"));
10475 vos_flush_work(&pHddCtx->sap_start_work);
10476 hdd_sap_indicate_disconnect_for_sta(pAdapter);
10477 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Hanumanth Reddy Pothula15bc0fa2017-02-03 17:24:17 +053010478 hdd_softap_deinit_tx_rx(pAdapter, true);
10479 hdd_sap_destroy_timers(pAdapter);
Hanumanth Reddy Pothulad864f312017-01-18 16:16:08 +053010480 } else {
10481 netif_carrier_off(pAdapter->dev);
10482 }
Jeff Johnson295189b2012-06-20 16:38:30 -070010483
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -070010484 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +053010485 pAdapter->sessionCtx.monitor.state = MON_MODE_STOP;
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -070010486
Jeff Johnson295189b2012-06-20 16:38:30 -070010487 hdd_deinit_tx_rx(pAdapter);
Agarwal Ashish6267caa2014-08-06 19:16:21 +053010488
Katya Nigam1fd24402015-02-16 14:52:19 +053010489 if(pAdapter->device_mode == WLAN_HDD_IBSS )
10490 hdd_ibss_deinit_tx_rx(pAdapter);
10491
Nirav Shah7e3c8132015-06-22 23:51:42 +053010492 status = hdd_sta_id_hash_detach(pAdapter);
10493 if (status != VOS_STATUS_SUCCESS)
10494 hddLog(VOS_TRACE_LEVEL_ERROR,
10495 FL("sta id hash detach failed for session id %d"),
10496 pAdapter->sessionId);
10497
Agarwal Ashish6267caa2014-08-06 19:16:21 +053010498 wlan_hdd_decr_active_session(pHddCtx, pAdapter->device_mode);
10499
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +053010500 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
10501 {
10502 hdd_wmm_adapter_close( pAdapter );
10503 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
10504 }
Jeff Johnson295189b2012-06-20 16:38:30 -070010505
Siddharth Bhal2db319d2014-12-03 12:37:18 +053010506 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
10507 {
10508 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
10509 }
10510
Rajeev Kumarf999e582014-01-09 17:33:29 -080010511#ifdef FEATURE_WLAN_BATCH_SCAN
10512 if (eHDD_BATCH_SCAN_STATE_STARTED == pAdapter->batchScanState)
10513 {
10514 hdd_deinit_batch_scan(pAdapter);
10515 }
10516#endif
10517
Mahesh A Saptasagarf5b8eff2015-01-31 01:07:07 +053010518#ifdef FEATURE_WLAN_TDLS
10519 mutex_lock(&pHddCtx->tdls_lock);
Pradeep Reddy POTTETI2d4d5c42015-03-03 14:34:19 +053010520 wlan_hdd_tdls_exit(pAdapter, TRUE);
Mahesh A Saptasagarf5b8eff2015-01-31 01:07:07 +053010521 mutex_unlock(&pHddCtx->tdls_lock);
10522#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070010523 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10524 pAdapterNode = pNext;
10525 }
10526
10527 EXIT();
10528
10529 return VOS_STATUS_SUCCESS;
10530}
10531
Abhishek Singhbbe0b2a2016-12-05 11:57:36 +053010532/**
Abhishek Singh5a597e62016-12-05 15:16:30 +053010533 * hdd_get_bss_entry() - Get the bss entry matching the chan, bssid and ssid
10534 * @wiphy: wiphy
10535 * @channel: channel of the BSS to find
10536 * @bssid: bssid of the BSS to find
10537 * @ssid: ssid of the BSS to find
10538 * @ssid_len: ssid len of of the BSS to find
10539 *
10540 * The API is a wrapper to get bss from kernel matching the chan,
10541 * bssid and ssid
10542 *
10543 * Return: Void
10544 */
10545#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) \
10546 && !defined(WITH_BACKPORTS) && !defined(IEEE80211_PRIVACY)
10547
10548struct cfg80211_bss* hdd_get_bss_entry(struct wiphy *wiphy,
10549 struct ieee80211_channel *channel,
10550 const u8 *bssid,
10551 const u8 *ssid, size_t ssid_len)
10552{
10553 return cfg80211_get_bss(wiphy, channel, bssid,
10554 ssid, ssid_len,
10555 WLAN_CAPABILITY_ESS,
10556 WLAN_CAPABILITY_ESS);
10557}
10558#else
10559struct cfg80211_bss* hdd_get_bss_entry(struct wiphy *wiphy,
10560 struct ieee80211_channel *channel,
10561 const u8 *bssid,
10562 const u8 *ssid, size_t ssid_len)
10563{
10564 return cfg80211_get_bss(wiphy, channel, bssid,
10565 ssid, ssid_len,
10566 IEEE80211_BSS_TYPE_ESS,
10567 IEEE80211_PRIVACY_ANY);
10568}
10569#endif
10570
Rajeev Kumar Sirasanagandla5b21a9c2018-01-08 17:05:11 +053010571#if defined(CFG80211_CONNECT_BSS) || \
10572 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
10573
10574#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) || \
10575 defined (CFG80211_CONNECT_TIMEOUT_REASON_CODE)
10576/**
10577 * hdd_connect_bss() - helper function to send connection status to supplicant
10578 * @dev: network device
10579 * @bssid: bssid to which we want to associate
10580 * @bss: information about connected bss
10581 * @req_ie: Request Information Element
10582 * @req_ie_len: len of the req IE
10583 * @resp_ie: Response IE
10584 * @resp_ie_len: len of ht response IE
10585 * @status: status
10586 * @gfp: Kernel Flag
10587 *
10588 * This is a helper function to send connection status to supplicant
10589 * and gets invoked from wrapper API
10590 *
10591 * Return: Void
10592 */
10593static void hdd_connect_bss(struct net_device *dev,
10594 const u8 *bssid,
10595 struct cfg80211_bss *bss,
10596 const u8 *req_ie,
10597 size_t req_ie_len,
10598 const u8 *resp_ie,
10599 size_t resp_ie_len,
10600 u16 status,
10601 gfp_t gfp)
10602{
10603 cfg80211_connect_bss(dev, bssid, bss, req_ie, req_ie_len,
10604 resp_ie, resp_ie_len, status, gfp, NL80211_TIMEOUT_UNSPECIFIED);
10605}
10606#else
10607/**
10608 * hdd_connect_bss() - helper function to send connection status to supplicant
10609 * @dev: network device
10610 * @bssid: bssid to which we want to associate
10611 * @bss: information about connected bss
10612 * @req_ie: Request Information Element
10613 * @req_ie_len: len of the req IE
10614 * @resp_ie: Response IE
10615 * @resp_ie_len: len of ht response IE
10616 * @status: status
10617 * @gfp: Kernel Flag
10618 *
10619 * This is a helper function to send connection status to supplicant
10620 * and gets invoked from wrapper API
10621 *
10622 * Return: Void
10623 */
10624static void hdd_connect_bss(struct net_device *dev,
10625 const u8 *bssid,
10626 struct cfg80211_bss *bss,
10627 const u8 *req_ie,
10628 size_t req_ie_len,
10629 const u8 *resp_ie,
10630 size_t resp_ie_len,
10631 u16 status,
10632 gfp_t gfp)
10633{
10634 cfg80211_connect_bss(dev, bssid, bss, req_ie, req_ie_len,
10635 resp_ie, resp_ie_len, status, gfp);
10636}
10637#endif
10638
Abhishek Singh5a597e62016-12-05 15:16:30 +053010639/**
Abhishek Singhbbe0b2a2016-12-05 11:57:36 +053010640 * hdd_connect_result() - API to send connection status to supplicant
10641 * @dev: network device
10642 * @bssid: bssid to which we want to associate
10643 * @roam_info: information about connected bss
10644 * @req_ie: Request Information Element
10645 * @req_ie_len: len of the req IE
10646 * @resp_ie: Response IE
10647 * @resp_ie_len: len of ht response IE
10648 * @status: status
10649 * @gfp: Kernel Flag
10650 *
10651 * The API is a wrapper to send connection status to supplicant
10652 *
10653 * Return: Void
10654 */
Abhishek Singhbbe0b2a2016-12-05 11:57:36 +053010655void hdd_connect_result(struct net_device *dev,
10656 const u8 *bssid,
10657 tCsrRoamInfo *roam_info,
10658 const u8 *req_ie,
10659 size_t req_ie_len,
10660 const u8 *resp_ie,
10661 size_t resp_ie_len,
10662 u16 status,
10663 gfp_t gfp)
10664{
10665 hdd_adapter_t *padapter = (hdd_adapter_t *) netdev_priv(dev);
10666 struct cfg80211_bss *bss = NULL;
10667
10668 if (WLAN_STATUS_SUCCESS == status) {
10669 struct ieee80211_channel *chan;
10670 int freq;
10671 int chan_no = roam_info->pBssDesc->channelId;;
10672
10673 if (chan_no <= 14)
10674 freq = ieee80211_channel_to_frequency(chan_no,
Rajeev Kumar Sirasanagandla5b21a9c2018-01-08 17:05:11 +053010675 HDD_NL80211_BAND_2GHZ);
Abhishek Singhbbe0b2a2016-12-05 11:57:36 +053010676 else
10677 freq = ieee80211_channel_to_frequency(chan_no,
Rajeev Kumar Sirasanagandla5b21a9c2018-01-08 17:05:11 +053010678 HDD_NL80211_BAND_5GHZ);
Abhishek Singhbbe0b2a2016-12-05 11:57:36 +053010679
10680 chan = ieee80211_get_channel(padapter->wdev.wiphy, freq);
Abhishek Singh5a597e62016-12-05 15:16:30 +053010681 bss = hdd_get_bss_entry(padapter->wdev.wiphy,
10682 chan, bssid,
10683 roam_info->u.pConnectedProfile->SSID.ssId,
10684 roam_info->u.pConnectedProfile->SSID.length);
Abhishek Singhbbe0b2a2016-12-05 11:57:36 +053010685 }
10686
Rajeev Kumar Sirasanagandla5b21a9c2018-01-08 17:05:11 +053010687 hdd_connect_bss(dev, bssid, bss, req_ie, req_ie_len, resp_ie, resp_ie_len,
10688 status, gfp);
Abhishek Singhbbe0b2a2016-12-05 11:57:36 +053010689}
10690#else
Rajeev Kumar Sirasanagandla5b21a9c2018-01-08 17:05:11 +053010691/**
10692 * hdd_connect_result() - API to send connection status to supplicant
10693 * @dev: network device
10694 * @bssid: bssid to which we want to associate
10695 * @roam_info: information about connected bss
10696 * @req_ie: Request Information Element
10697 * @req_ie_len: len of the req IE
10698 * @resp_ie: Response IE
10699 * @resp_ie_len: len of ht response IE
10700 * @status: status
10701 * @gfp: Kernel Flag
10702 *
10703 * The API is a wrapper to send connection status to supplicant
10704 *
10705 * Return: Void
10706 */
Abhishek Singhbbe0b2a2016-12-05 11:57:36 +053010707void hdd_connect_result(struct net_device *dev,
10708 const u8 *bssid,
10709 tCsrRoamInfo *roam_info,
10710 const u8 *req_ie,
10711 size_t req_ie_len,
10712 const u8 * resp_ie,
10713 size_t resp_ie_len,
10714 u16 status,
10715 gfp_t gfp)
10716{
10717 cfg80211_connect_result(dev, bssid, req_ie, req_ie_len,
10718 resp_ie, resp_ie_len, status, gfp);
10719}
10720#endif
10721
Jeff Johnson295189b2012-06-20 16:38:30 -070010722VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
10723{
10724 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
10725 VOS_STATUS status;
10726 hdd_adapter_t *pAdapter;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +053010727 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -070010728
10729 ENTER();
10730
10731 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10732
10733 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
10734 {
10735 pAdapter = pAdapterNode->pAdapter;
10736
Kumar Anand82c009f2014-05-29 00:29:42 -070010737 hdd_wmm_init( pAdapter );
10738
Jeff Johnson295189b2012-06-20 16:38:30 -070010739 switch(pAdapter->device_mode)
10740 {
10741 case WLAN_HDD_INFRA_STATION:
10742 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -070010743 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +053010744
10745 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
10746
Jeff Johnson295189b2012-06-20 16:38:30 -070010747 hdd_init_station_mode(pAdapter);
10748 /* Open the gates for HDD to receive Wext commands */
10749 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -070010750 pHddCtx->scan_info.mScanPending = FALSE;
10751 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -070010752
10753 //Trigger the initial scan
Mukul Sharmae74e42c2015-08-06 23:55:49 +053010754 if (!pHddCtx->isLogpInProgress)
10755 hdd_wlan_initial_scan(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -070010756
10757 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +053010758 if (eConnectionState_Associated == connState ||
10759 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -070010760 {
10761 union iwreq_data wrqu;
10762 memset(&wrqu, '\0', sizeof(wrqu));
10763 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
10764 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
10765 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -070010766 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -070010767
Jeff Johnson295189b2012-06-20 16:38:30 -070010768 /* indicate disconnected event to nl80211 */
Mahesh A Saptasagar9ff4bcc2016-06-01 17:17:50 +053010769 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, false,
Mahesh A Saptasagarb5a15142016-05-25 11:27:43 +053010770 WLAN_REASON_UNSPECIFIED);
Jeff Johnson295189b2012-06-20 16:38:30 -070010771 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +053010772 else if (eConnectionState_Connecting == connState)
10773 {
10774 /*
10775 * Indicate connect failure to supplicant if we were in the
10776 * process of connecting
10777 */
Abhishek Singhbbe0b2a2016-12-05 11:57:36 +053010778 hdd_connect_result(pAdapter->dev, NULL, NULL,
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +053010779 NULL, 0, NULL, 0,
10780 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
10781 GFP_KERNEL);
10782 }
Jeff Johnson295189b2012-06-20 16:38:30 -070010783 break;
10784
10785 case WLAN_HDD_SOFTAP:
Hanumanth Reddy Pothulad864f312017-01-18 16:16:08 +053010786 if (pHddCtx->cfg_ini->sap_internal_restart) {
Hanumanth Reddy Pothula15bc0fa2017-02-03 17:24:17 +053010787 hdd_init_ap_mode(pAdapter, true);
Hanumanth Reddy Pothulad864f312017-01-18 16:16:08 +053010788 status = hdd_sta_id_hash_attach(pAdapter);
10789 if (VOS_STATUS_SUCCESS != status)
10790 {
10791 hddLog(VOS_TRACE_LEVEL_FATAL,
10792 FL("failed to attach hash for"));
10793 }
10794 }
Jeff Johnson295189b2012-06-20 16:38:30 -070010795 break;
10796
10797 case WLAN_HDD_P2P_GO:
Sameer Thalappiledf0d792013-08-09 14:31:03 -070010798 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send stop ap to supplicant",
Jeff Johnson295189b2012-06-20 16:38:30 -070010799 __func__);
Sameer Thalappiledf0d792013-08-09 14:31:03 -070010800 cfg80211_ap_stopped(pAdapter->dev, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -070010801 break;
10802
10803 case WLAN_HDD_MONITOR:
10804 /* monitor interface start */
10805 break;
10806 default:
10807 break;
10808 }
10809
10810 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10811 pAdapterNode = pNext;
10812 }
10813
10814 EXIT();
10815
10816 return VOS_STATUS_SUCCESS;
10817}
10818
10819VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
10820{
10821 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
10822 hdd_adapter_t *pAdapter;
10823 VOS_STATUS status;
10824 v_U32_t roamId;
c_hpothu6ff1c3c2013-10-01 19:01:57 +053010825 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -070010826
10827 ENTER();
10828
10829 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10830
10831 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
10832 {
10833 pAdapter = pAdapterNode->pAdapter;
10834
10835 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
10836 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
10837 {
10838 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10839 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10840
Abhishek Singhf4669da2014-05-26 15:07:49 +053010841 hddLog(VOS_TRACE_LEVEL_INFO,
10842 "%s: Set HDD connState to eConnectionState_NotConnected",
10843 __func__);
Ganesh Kondabattini04338412015-09-14 15:39:09 +053010844 spin_lock_bh(&pAdapter->lock_for_active_session);
10845 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState)
10846 {
10847 wlan_hdd_decr_active_session(pHddCtx, pAdapter->device_mode);
10848 }
Jeff Johnson295189b2012-06-20 16:38:30 -070010849 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
Ganesh Kondabattini04338412015-09-14 15:39:09 +053010850 spin_unlock_bh(&pAdapter->lock_for_active_session);
Jeff Johnson295189b2012-06-20 16:38:30 -070010851 init_completion(&pAdapter->disconnect_comp_var);
10852 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
10853 eCSR_DISCONNECT_REASON_UNSPECIFIED);
10854
c_hpothu6ff1c3c2013-10-01 19:01:57 +053010855 ret = wait_for_completion_interruptible_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -070010856 &pAdapter->disconnect_comp_var,
10857 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +053010858 if (0 >= ret)
10859 hddLog(LOGE, "%s: failure waiting for disconnect_comp_var %ld",
10860 __func__, ret);
Jeff Johnson295189b2012-06-20 16:38:30 -070010861
10862 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
10863 pHddCtx->isAmpAllowed = VOS_FALSE;
10864 sme_RoamConnect(pHddCtx->hHal,
10865 pAdapter->sessionId, &(pWextState->roamProfile),
10866 &roamId);
10867 }
10868
10869 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10870 pAdapterNode = pNext;
10871 }
10872
10873 EXIT();
10874
10875 return VOS_STATUS_SUCCESS;
10876}
10877
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -070010878void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
10879{
10880 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
10881 VOS_STATUS status;
10882 hdd_adapter_t *pAdapter;
10883 hdd_station_ctx_t *pHddStaCtx;
10884 hdd_ap_ctx_t *pHddApCtx;
10885 hdd_hostapd_state_t * pHostapdState;
10886 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
10887 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
10888 const char *p2pMode = "DEV";
10889 const char *ccMode = "Standalone";
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -070010890
10891 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10892 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
10893 {
10894 pAdapter = pAdapterNode->pAdapter;
10895 switch (pAdapter->device_mode) {
10896 case WLAN_HDD_INFRA_STATION:
10897 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10898 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
10899 staChannel = pHddStaCtx->conn_info.operationChannel;
10900 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
10901 }
10902 break;
10903 case WLAN_HDD_P2P_CLIENT:
10904 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10905 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
10906 p2pChannel = pHddStaCtx->conn_info.operationChannel;
10907 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
10908 p2pMode = "CLI";
10909 }
10910 break;
10911 case WLAN_HDD_P2P_GO:
10912 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
10913 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
10914 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
10915 p2pChannel = pHddApCtx->operatingChannel;
10916 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
10917 }
10918 p2pMode = "GO";
10919 break;
10920 case WLAN_HDD_SOFTAP:
10921 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
10922 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
10923 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
10924 apChannel = pHddApCtx->operatingChannel;
10925 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
10926 }
10927 break;
10928 default:
10929 break;
10930 }
10931 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10932 pAdapterNode = pNext;
10933 }
10934 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
10935 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
10936 }
Yeshwanth Sriram Guntuka0004c0b2017-12-06 14:43:49 +053010937 hddLog(VOS_TRACE_LEVEL_ERROR, "wlan(%d) " MAC_ADDRESS_STR " %s",
10938 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -070010939 if (p2pChannel > 0) {
Sushant Kaushikdc3184b2015-10-09 12:00:21 +053010940 hddLog(VOS_TRACE_LEVEL_ERROR, "p2p-%s(%d) " MAC_ADDRESS_STR,
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -070010941 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
10942 }
10943 if (apChannel > 0) {
Sushant Kaushikdc3184b2015-10-09 12:00:21 +053010944 hddLog(VOS_TRACE_LEVEL_ERROR, "AP(%d) " MAC_ADDRESS_STR,
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -070010945 apChannel, MAC_ADDR_ARRAY(apBssid));
10946 }
10947
10948 if (p2pChannel > 0 && apChannel > 0) {
10949 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
10950 }
10951}
10952
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -070010953bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -070010954{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -070010955 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -070010956}
10957
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -070010958/* Once SSR is disabled then it cannot be set. */
10959void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -070010960{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -070010961 if (HDD_SSR_DISABLED == isSsrRequired)
10962 return;
10963
Jeff Johnson295189b2012-06-20 16:38:30 -070010964 isSsrRequired = value;
10965}
10966
Hema Aparna Medicharla6b4d4f32015-06-23 04:09:12 +053010967void hdd_set_pre_close( hdd_context_t *pHddCtx)
10968{
10969 sme_PreClose(pHddCtx->hHal);
10970}
10971
Jeff Johnson295189b2012-06-20 16:38:30 -070010972VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
10973 hdd_adapter_list_node_t** ppAdapterNode)
10974{
10975 VOS_STATUS status;
Mukul Sharmaae1266d2015-06-26 15:29:53 +053010976 spin_lock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010977 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
10978 (hdd_list_node_t**) ppAdapterNode );
Mukul Sharmaae1266d2015-06-26 15:29:53 +053010979 spin_unlock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010980 return status;
10981}
10982
10983VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
10984 hdd_adapter_list_node_t* pAdapterNode,
10985 hdd_adapter_list_node_t** pNextAdapterNode)
10986{
10987 VOS_STATUS status;
Mukul Sharmaae1266d2015-06-26 15:29:53 +053010988 spin_lock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010989 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
10990 (hdd_list_node_t*) pAdapterNode,
10991 (hdd_list_node_t**)pNextAdapterNode );
10992
Mukul Sharmaae1266d2015-06-26 15:29:53 +053010993 spin_unlock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010994 return status;
10995}
10996
10997VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
10998 hdd_adapter_list_node_t* pAdapterNode)
10999{
11000 VOS_STATUS status;
Mukul Sharmaae1266d2015-06-26 15:29:53 +053011001 spin_lock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070011002 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
11003 &pAdapterNode->node );
Mukul Sharmaae1266d2015-06-26 15:29:53 +053011004 spin_unlock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070011005 return status;
11006}
11007
11008VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
11009 hdd_adapter_list_node_t** ppAdapterNode)
11010{
11011 VOS_STATUS status;
Mukul Sharmaae1266d2015-06-26 15:29:53 +053011012 spin_lock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070011013 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
11014 (hdd_list_node_t**) ppAdapterNode );
Mukul Sharmaae1266d2015-06-26 15:29:53 +053011015 spin_unlock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070011016 return status;
11017}
11018
11019VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
11020 hdd_adapter_list_node_t* pAdapterNode)
11021{
11022 VOS_STATUS status;
Mukul Sharmaae1266d2015-06-26 15:29:53 +053011023 spin_lock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070011024 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
11025 (hdd_list_node_t*) pAdapterNode );
Mukul Sharmaae1266d2015-06-26 15:29:53 +053011026 spin_unlock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070011027 return status;
11028}
11029
11030VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
11031 hdd_adapter_list_node_t* pAdapterNode)
11032{
11033 VOS_STATUS status;
Mukul Sharmaae1266d2015-06-26 15:29:53 +053011034 spin_lock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070011035 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
11036 (hdd_list_node_t*) pAdapterNode );
Mukul Sharmaae1266d2015-06-26 15:29:53 +053011037 spin_unlock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070011038 return status;
11039}
11040
11041hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
11042 tSirMacAddr macAddr )
11043{
11044 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
11045 hdd_adapter_t *pAdapter;
11046 VOS_STATUS status;
11047
11048 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
11049
11050 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
11051 {
11052 pAdapter = pAdapterNode->pAdapter;
11053
11054 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
11055 macAddr, sizeof(tSirMacAddr) ) )
11056 {
11057 return pAdapter;
11058 }
11059 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
11060 pAdapterNode = pNext;
11061 }
11062
11063 return NULL;
11064
11065}
11066
11067hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
11068{
11069 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
11070 hdd_adapter_t *pAdapter;
11071 VOS_STATUS status;
11072
11073 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
11074
11075 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
11076 {
11077 pAdapter = pAdapterNode->pAdapter;
11078
11079 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
11080 IFNAMSIZ ) )
11081 {
11082 return pAdapter;
11083 }
11084 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
11085 pAdapterNode = pNext;
11086 }
11087
11088 return NULL;
11089
11090}
11091
Ganesh Kondabattinicbfdc392015-09-11 19:12:59 +053011092hdd_adapter_t *hdd_get_adapter_by_sme_session_id( hdd_context_t *pHddCtx,
11093 tANI_U32 sme_session_id )
11094{
11095 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
11096 hdd_adapter_t *pAdapter;
11097 VOS_STATUS vos_status;
11098
11099
11100 vos_status = hdd_get_front_adapter( pHddCtx, &pAdapterNode);
11101
11102 while ((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == vos_status))
11103 {
11104 pAdapter = pAdapterNode->pAdapter;
11105
11106 if (pAdapter->sessionId == sme_session_id)
11107 return pAdapter;
11108
11109 vos_status = hdd_get_next_adapter(pHddCtx, pAdapterNode, &pNext);
11110 pAdapterNode = pNext;
11111 }
11112
11113 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
11114 "%s: sme_session_id %d does not exist with host",
11115 __func__, sme_session_id);
11116
11117 return NULL;
11118}
11119
Jeff Johnson295189b2012-06-20 16:38:30 -070011120hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
11121{
11122 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
11123 hdd_adapter_t *pAdapter;
11124 VOS_STATUS status;
11125
11126 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
11127
11128 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
11129 {
11130 pAdapter = pAdapterNode->pAdapter;
11131
11132 if( pAdapter && (mode == pAdapter->device_mode) )
11133 {
11134 return pAdapter;
11135 }
11136 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
11137 pAdapterNode = pNext;
11138 }
11139
11140 return NULL;
11141
11142}
11143
11144//Remove this function later
11145hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
11146{
11147 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
11148 hdd_adapter_t *pAdapter;
11149 VOS_STATUS status;
11150
11151 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
11152
11153 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
11154 {
11155 pAdapter = pAdapterNode->pAdapter;
11156
11157 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
11158 {
11159 return pAdapter;
11160 }
11161
11162 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
11163 pAdapterNode = pNext;
11164 }
11165
11166 return NULL;
11167
11168}
11169
Jeff Johnson295189b2012-06-20 16:38:30 -070011170/**---------------------------------------------------------------------------
11171
Mahesh A Saptasgar64534612014-09-23 13:13:33 +053011172 \brief hdd_get_operating_channel() -
Jeff Johnson295189b2012-06-20 16:38:30 -070011173
11174 This API returns the operating channel of the requested device mode
11175
11176 \param - pHddCtx - Pointer to the HDD context.
11177 - mode - Device mode for which operating channel is required
11178 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
11179 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
11180 \return - channel number. "0" id the requested device is not found OR it is not connected.
11181 --------------------------------------------------------------------------*/
11182v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
11183{
11184 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
11185 VOS_STATUS status;
11186 hdd_adapter_t *pAdapter;
11187 v_U8_t operatingChannel = 0;
11188
11189 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
11190
11191 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
11192 {
11193 pAdapter = pAdapterNode->pAdapter;
11194
11195 if( mode == pAdapter->device_mode )
11196 {
11197 switch(pAdapter->device_mode)
11198 {
11199 case WLAN_HDD_INFRA_STATION:
11200 case WLAN_HDD_P2P_CLIENT:
11201 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
11202 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
11203 break;
11204 case WLAN_HDD_SOFTAP:
11205 case WLAN_HDD_P2P_GO:
11206 /*softap connection info */
11207 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
11208 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
11209 break;
11210 default:
11211 break;
11212 }
11213
11214 break; //Found the device of interest. break the loop
11215 }
11216
11217 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
11218 pAdapterNode = pNext;
11219 }
11220 return operatingChannel;
11221}
11222
11223#ifdef WLAN_FEATURE_PACKET_FILTERING
11224/**---------------------------------------------------------------------------
11225
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +053011226 \brief __hdd_set_multicast_list() -
Jeff Johnson295189b2012-06-20 16:38:30 -070011227
11228 This used to set the multicast address list.
11229
11230 \param - dev - Pointer to the WLAN device.
11231 - skb - Pointer to OS packet (sk_buff).
Mahesh A Saptasagar74088392015-02-05 17:22:09 +053011232 \return - success/fail
Jeff Johnson295189b2012-06-20 16:38:30 -070011233
11234 --------------------------------------------------------------------------*/
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +053011235static void __hdd_set_multicast_list(struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -070011236{
Mahesh A Saptasagar74088392015-02-05 17:22:09 +053011237 hdd_adapter_t *pAdapter;
11238 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -070011239 int mc_count;
Mahesh A Saptasagar74088392015-02-05 17:22:09 +053011240 int i = 0, ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -070011241 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +053011242
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +053011243 ENTER();
11244
Mahesh A Saptasagar74088392015-02-05 17:22:09 +053011245 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Gopichand Nakkala0f276812013-02-24 14:45:51 +053011246 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -070011247 {
11248 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +053011249 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -070011250 return;
11251 }
Mahesh A Saptasagar74088392015-02-05 17:22:09 +053011252 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11253 ret = wlan_hdd_validate_context(pHddCtx);
11254 if (0 != ret)
11255 {
Mahesh A Saptasagar74088392015-02-05 17:22:09 +053011256 return;
11257 }
Jeff Johnson295189b2012-06-20 16:38:30 -070011258 if (dev->flags & IFF_ALLMULTI)
11259 {
11260 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070011261 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +053011262 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -070011263 }
Mahesh A Saptasagar74088392015-02-05 17:22:09 +053011264 else
Jeff Johnson295189b2012-06-20 16:38:30 -070011265 {
11266 mc_count = netdev_mc_count(dev);
11267 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070011268 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -070011269 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
11270 {
11271 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070011272 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +053011273 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -070011274 return;
11275 }
11276
Gopichand Nakkala0f276812013-02-24 14:45:51 +053011277 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -070011278
11279 netdev_for_each_mc_addr(ha, dev) {
11280 if (i == mc_count)
11281 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +053011282 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
11283 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
Arif Hussain6d2a3322013-11-17 19:50:10 -080011284 hddLog(VOS_TRACE_LEVEL_INFO, "%s: mlist[%d] = "MAC_ADDRESS_STR,
Mahesh A Saptasagar74088392015-02-05 17:22:09 +053011285 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +053011286 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -070011287 i++;
11288 }
11289 }
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +053011290
Ganesh Kondabattinifb37e652015-10-09 15:46:47 +053011291 if (pHddCtx->hdd_wlan_suspended)
11292 {
11293 /*
11294 * Configure the Mcast address list to FW
11295 * If wlan is already in suspend mode
11296 */
11297 wlan_hdd_set_mc_addr_list(pAdapter, TRUE);
11298 }
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +053011299 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -070011300 return;
11301}
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +053011302
11303static void hdd_set_multicast_list(struct net_device *dev)
11304{
11305 vos_ssr_protect(__func__);
11306 __hdd_set_multicast_list(dev);
11307 vos_ssr_unprotect(__func__);
11308}
Jeff Johnson295189b2012-06-20 16:38:30 -070011309#endif
11310
11311/**---------------------------------------------------------------------------
11312
11313 \brief hdd_select_queue() -
11314
11315 This function is registered with the Linux OS for network
11316 core to decide which queue to use first.
11317
11318 \param - dev - Pointer to the WLAN device.
11319 - skb - Pointer to OS packet (sk_buff).
11320 \return - ac, Queue Index/access category corresponding to UP in IP header
11321
11322 --------------------------------------------------------------------------*/
11323v_U16_t hdd_select_queue(struct net_device *dev,
Anand N Sunkade9adb1b2015-07-29 09:56:45 +053011324 struct sk_buff *skb
11325#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0))
11326 , void *accel_priv
11327#endif
11328#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0))
11329 , select_queue_fallback_t fallback
11330#endif
11331)
Jeff Johnson295189b2012-06-20 16:38:30 -070011332{
11333 return hdd_wmm_select_queue(dev, skb);
11334}
11335
11336
11337/**---------------------------------------------------------------------------
11338
11339 \brief hdd_wlan_initial_scan() -
11340
11341 This function triggers the initial scan
11342
11343 \param - pAdapter - Pointer to the HDD adapter.
11344
11345 --------------------------------------------------------------------------*/
11346void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
11347{
11348 tCsrScanRequest scanReq;
11349 tCsrChannelInfo channelInfo;
11350 eHalStatus halStatus;
Jeff Johnson02797792013-10-26 19:17:13 -070011351 tANI_U32 scanId;
Jeff Johnson295189b2012-06-20 16:38:30 -070011352 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11353
11354 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
11355 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
11356 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
11357
11358 if(sme_Is11dSupported(pHddCtx->hHal))
11359 {
11360 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
11361 if ( HAL_STATUS_SUCCESS( halStatus ) )
11362 {
11363 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
11364 if( !scanReq.ChannelInfo.ChannelList )
11365 {
11366 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
11367 vos_mem_free(channelInfo.ChannelList);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -080011368 channelInfo.ChannelList = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -070011369 return;
11370 }
11371 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
11372 channelInfo.numOfChannels);
11373 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
11374 vos_mem_free(channelInfo.ChannelList);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -080011375 channelInfo.ChannelList = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -070011376 }
11377
11378 scanReq.scanType = eSIR_PASSIVE_SCAN;
11379 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
11380 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
11381 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
11382 }
11383 else
11384 {
11385 scanReq.scanType = eSIR_ACTIVE_SCAN;
11386 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
11387 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
11388 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
11389 }
11390
11391 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
11392 if ( !HAL_STATUS_SUCCESS( halStatus ) )
11393 {
11394 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
11395 __func__, halStatus );
11396 }
11397
11398 if(sme_Is11dSupported(pHddCtx->hHal))
11399 vos_mem_free(scanReq.ChannelInfo.ChannelList);
11400}
11401
Jeff Johnson295189b2012-06-20 16:38:30 -070011402/**---------------------------------------------------------------------------
11403
11404 \brief hdd_full_power_callback() - HDD full power callback function
11405
11406 This is the function invoked by SME to inform the result of a full power
11407 request issued by HDD
11408
11409 \param - callbackcontext - Pointer to cookie
11410 \param - status - result of request
11411
11412 \return - None
11413
11414 --------------------------------------------------------------------------*/
11415static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
11416{
Jeff Johnson72a40512013-12-19 10:14:15 -080011417 struct statsContext *pContext = callbackContext;
Jeff Johnson295189b2012-06-20 16:38:30 -070011418
11419 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnsonc135a9a2017-09-19 08:37:24 -070011420 "%s: context = %pK, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -070011421
11422 if (NULL == callbackContext)
11423 {
11424 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnsonc135a9a2017-09-19 08:37:24 -070011425 "%s: Bad param, context [%pK]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070011426 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -070011427 return;
11428 }
11429
Jeff Johnson72a40512013-12-19 10:14:15 -080011430 /* there is a race condition that exists between this callback
11431 function and the caller since the caller could time out either
11432 before or while this code is executing. we use a spinlock to
11433 serialize these actions */
11434 spin_lock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070011435
11436 if (POWER_CONTEXT_MAGIC != pContext->magic)
11437 {
11438 /* the caller presumably timed out so there is nothing we can do */
Jeff Johnson72a40512013-12-19 10:14:15 -080011439 spin_unlock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070011440 hddLog(VOS_TRACE_LEVEL_WARN,
11441 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070011442 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -070011443 return;
11444 }
11445
Jeff Johnson72a40512013-12-19 10:14:15 -080011446 /* context is valid so caller is still waiting */
11447
11448 /* paranoia: invalidate the magic */
11449 pContext->magic = 0;
11450
11451 /* notify the caller */
Jeff Johnson295189b2012-06-20 16:38:30 -070011452 complete(&pContext->completion);
Jeff Johnson72a40512013-12-19 10:14:15 -080011453
11454 /* serialization is complete */
11455 spin_unlock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070011456}
11457
Katya Nigamf0511f62015-05-05 16:40:57 +053011458void wlan_hdd_mon_set_typesubtype( hdd_mon_ctx_t *pMonCtx,int type)
11459{
11460 pMonCtx->typeSubtypeBitmap = 0;
11461 if( type%10 ) /* Management Packets */
11462 pMonCtx->typeSubtypeBitmap |= 0xFFFF;
11463 type/=10;
11464 if( type%10 ) /* Control Packets */
11465 pMonCtx->typeSubtypeBitmap |= 0xFFFF0000;
11466 type/=10;
11467 if( type%10 ) /* Data Packets */
11468 pMonCtx->typeSubtypeBitmap |= 0xFFFF00000000;
11469}
11470
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053011471VOS_STATUS wlan_hdd_mon_postMsg(tANI_U32 *magic, struct completion *cmpVar,
11472 hdd_mon_ctx_t *pMonCtx , void* callback)
Katya Nigamf0511f62015-05-05 16:40:57 +053011473{
11474 vos_msg_t monMsg;
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053011475 tSirMonModeReq *pMonModeReq;
Katya Nigamf0511f62015-05-05 16:40:57 +053011476
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053011477 if (MON_MODE_START == pMonCtx->state)
11478 monMsg.type = WDA_MON_START_REQ;
11479 else if (MON_MODE_STOP == pMonCtx->state)
11480 monMsg.type = WDA_MON_STOP_REQ;
11481 else {
11482 hddLog(VOS_TRACE_LEVEL_ERROR,
11483 FL("invalid monitor state %d"), pMonCtx->state);
Katya Nigamf0511f62015-05-05 16:40:57 +053011484 return VOS_STATUS_E_FAILURE;
11485 }
11486
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053011487 pMonModeReq = vos_mem_malloc(sizeof(tSirMonModeReq));
11488 if (pMonModeReq == NULL) {
11489 hddLog(VOS_TRACE_LEVEL_ERROR,
11490 FL("fail to allocate memory for monitor mode req"));
11491 return VOS_STATUS_E_FAILURE;
11492 }
Katya Nigamf0511f62015-05-05 16:40:57 +053011493
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053011494 pMonModeReq->magic = magic;
11495 pMonModeReq->cmpVar = cmpVar;
11496 pMonModeReq->data = pMonCtx;
11497 pMonModeReq->callback = callback;
Katya Nigamf0511f62015-05-05 16:40:57 +053011498
Katya Nigamf0511f62015-05-05 16:40:57 +053011499 monMsg.reserved = 0;
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053011500 monMsg.bodyptr = pMonModeReq;
Katya Nigamf0511f62015-05-05 16:40:57 +053011501 monMsg.bodyval = 0;
11502
11503 if (VOS_STATUS_SUCCESS != vos_mq_post_message(
11504 VOS_MODULE_ID_WDA,(vos_msg_t *)&monMsg)) {
11505 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: : Failed to post Msg to HAL",__func__);
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053011506 vos_mem_free(pMonModeReq);
Katya Nigamf0511f62015-05-05 16:40:57 +053011507 }
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053011508 return VOS_STATUS_SUCCESS;
Katya Nigamf0511f62015-05-05 16:40:57 +053011509}
11510
Katya Nigame7b69a82015-04-28 15:24:06 +053011511void wlan_hdd_mon_close(hdd_context_t *pHddCtx)
11512{
11513 VOS_STATUS vosStatus;
11514 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053011515 long ret;
11516 hdd_mon_ctx_t *pMonCtx = NULL;
11517 v_U32_t magic;
11518 struct completion cmpVar;
Hanumantha Reddy Pothulac99bc062015-09-08 14:59:26 +053011519
Katya Nigame7b69a82015-04-28 15:24:06 +053011520 hdd_adapter_t *pAdapter = hdd_get_adapter(pHddCtx,WLAN_HDD_MONITOR);
11521 if(pAdapter == NULL || pVosContext == NULL)
11522 {
11523 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:pAdapter is NULL",__func__);
11524 return ;
11525 }
Katya Nigamf0511f62015-05-05 16:40:57 +053011526
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053011527 pMonCtx = WLAN_HDD_GET_MONITOR_CTX_PTR(pAdapter);
11528 if (pMonCtx!= NULL && pMonCtx->state == MON_MODE_START) {
11529 pMonCtx->state = MON_MODE_STOP;
11530 magic = MON_MODE_MSG_MAGIC;
11531 init_completion(&cmpVar);
11532 if (VOS_STATUS_SUCCESS !=
11533 wlan_hdd_mon_postMsg(&magic, &cmpVar,
11534 pMonCtx, hdd_monPostMsgCb)) {
11535 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
11536 FL("failed to post MON MODE REQ"));
11537 pMonCtx->state = MON_MODE_START;
11538 magic = 0;
11539 return;
11540 }
11541 ret = wait_for_completion_timeout(&cmpVar, MON_MODE_MSG_TIMEOUT);
11542 magic = 0;
11543 if (ret <= 0 ) {
11544 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
11545 FL("timeout on monitor mode completion %ld"), ret);
11546 }
11547 }
11548
Katya Nigame7b69a82015-04-28 15:24:06 +053011549 hdd_UnregisterWext(pAdapter->dev);
11550
11551 vos_mon_stop( pVosContext );
11552
11553 vosStatus = vos_sched_close( pVosContext );
11554 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
11555 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
11556 "%s: Failed to close VOSS Scheduler",__func__);
11557 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
11558 }
11559
11560 vosStatus = vos_nv_close();
11561 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
11562 {
11563 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
11564 "%s: Failed to close NV", __func__);
11565 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
11566 }
11567
11568 vos_close(pVosContext);
11569
11570 #ifdef WLAN_KD_READY_NOTIFIER
11571 nl_srv_exit(pHddCtx->ptt_pid);
11572 #else
11573 nl_srv_exit();
11574 #endif
11575
Katya Nigame7b69a82015-04-28 15:24:06 +053011576 hdd_close_all_adapters( pHddCtx );
Katya Nigame7b69a82015-04-28 15:24:06 +053011577}
Agrawal Ashish33ec71e2015-11-26 20:20:58 +053011578/**
11579 * hdd_wlan_free_wiphy_channels - free Channel pointer for wiphy
11580 * @ wiphy: the wiphy to validate against
11581 *
11582 * Return: void
11583 */
11584void hdd_wlan_free_wiphy_channels(struct wiphy *wiphy)
11585{
11586 int i =0;
Rajeev Kumar Sirasanagandla5b21a9c2018-01-08 17:05:11 +053011587 for (i = 0; i < HDD_NUM_NL80211_BANDS; i++)
Agrawal Ashish33ec71e2015-11-26 20:20:58 +053011588 {
11589 if (NULL != wiphy->bands[i] &&
11590 (NULL != wiphy->bands[i]->channels))
11591 {
11592 vos_mem_free(wiphy->bands[i]->channels);
11593 wiphy->bands[i]->channels = NULL;
11594 }
11595 }
11596}
Jeff Johnson295189b2012-06-20 16:38:30 -070011597/**---------------------------------------------------------------------------
11598
11599 \brief hdd_wlan_exit() - HDD WLAN exit function
11600
11601 This is the driver exit point (invoked during rmmod)
11602
11603 \param - pHddCtx - Pointer to the HDD Context
11604
11605 \return - None
11606
11607 --------------------------------------------------------------------------*/
11608void hdd_wlan_exit(hdd_context_t *pHddCtx)
11609{
11610 eHalStatus halStatus;
11611 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
11612 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +053011613 struct wiphy *wiphy = pHddCtx->wiphy;
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -080011614 hdd_adapter_t* pAdapter = NULL;
Jeff Johnson72a40512013-12-19 10:14:15 -080011615 struct statsContext powerContext;
Jeff Johnson295189b2012-06-20 16:38:30 -070011616 long lrc;
c_hpothu5ab05e92014-06-13 17:34:05 +053011617 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -070011618
11619 ENTER();
11620
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053011621
Katya Nigame7b69a82015-04-28 15:24:06 +053011622 if (VOS_MONITOR_MODE == hdd_get_conparam())
11623 {
11624 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: MONITOR MODE",__func__);
11625 wlan_hdd_mon_close(pHddCtx);
Hanumantha Reddy Pothulac99bc062015-09-08 14:59:26 +053011626 goto free_hdd_ctx;
Katya Nigame7b69a82015-04-28 15:24:06 +053011627 }
11628 else if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -080011629 {
11630 // Unloading, restart logic is no more required.
11631 wlan_hdd_restart_deinit(pHddCtx);
Jeff Johnsone7245742012-09-05 17:12:55 -070011632
Agarwal Ashishb20e0ff2014-12-17 22:50:19 +053011633#ifdef FEATURE_WLAN_TDLS
11634 /* At the time of driver unloading; if tdls connection is present;
11635 * hdd_rx_packet_cbk calls wlan_hdd_tdls_find_peer.
11636 * wlan_hdd_tdls_find_peer always checks for valid context;
11637 * as load/unload in progress there can be a race condition.
11638 * hdd_rx_packet_cbk calls wlan_hdd_tdls_find_peer only
11639 * when tdls state is enabled.
11640 * As soon as driver set load/unload flag; tdls flag also needs
11641 * to be disabled so that hdd_rx_packet_cbk won't call
11642 * wlan_hdd_tdls_find_peer.
11643 */
Masti, Narayanraddi20494af2015-12-17 20:56:42 +053011644 wlan_hdd_tdls_set_mode(pHddCtx, eTDLS_SUPPORT_DISABLED, FALSE,
11645 HDD_SET_TDLS_MODE_SOURCE_USER);
Agarwal Ashishb20e0ff2014-12-17 22:50:19 +053011646#endif
11647
c_hpothu5ab05e92014-06-13 17:34:05 +053011648 vosStatus = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
11649 while (NULL != pAdapterNode && VOS_STATUS_E_EMPTY != vosStatus)
Jeff Johnson295189b2012-06-20 16:38:30 -070011650 {
c_hpothu5ab05e92014-06-13 17:34:05 +053011651 pAdapter = pAdapterNode->pAdapter;
11652 if (NULL != pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -070011653 {
Mahesh A Saptasagar305e2632015-03-04 12:57:33 +053011654 /* Disable TX on the interface, after this hard_start_xmit() will
11655 * not be called on that interface
11656 */
11657 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
11658 netif_tx_disable(pAdapter->dev);
11659
11660 /* Mark the interface status as "down" for outside world */
11661 netif_carrier_off(pAdapter->dev);
11662
Agarwal Ashish9ffa5b92014-11-18 21:07:02 +053011663 /* DeInit the adapter. This ensures that all data packets
11664 * are freed.
11665 */
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +053011666#ifdef FEATURE_WLAN_TDLS
11667 mutex_lock(&pHddCtx->tdls_lock);
11668#endif
c_hpothu002231a2015-02-05 14:58:51 +053011669 hdd_deinit_adapter(pHddCtx, pAdapter, FALSE);
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +053011670#ifdef FEATURE_WLAN_TDLS
11671 mutex_unlock(&pHddCtx->tdls_lock);
11672#endif
Masti, Narayanraddi26378462016-01-05 18:20:28 +053011673 vos_flush_delayed_work(&pHddCtx->scan_ctxt.scan_work);
11674
11675 wlan_hdd_init_deinit_defer_scan_context(&pHddCtx->scan_ctxt);
Agarwal Ashish9ffa5b92014-11-18 21:07:02 +053011676
c_hpothu5ab05e92014-06-13 17:34:05 +053011677 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode ||
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +053011678 WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ||
11679 WLAN_HDD_MONITOR == pAdapter->device_mode)
c_hpothu5ab05e92014-06-13 17:34:05 +053011680 {
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +053011681 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode ||
11682 WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)
11683 wlan_hdd_cfg80211_deregister_frames(pAdapter);
11684
c_hpothu5ab05e92014-06-13 17:34:05 +053011685 hdd_UnregisterWext(pAdapter->dev);
11686 }
Kaushik, Sushant4975a572014-10-21 16:07:48 +053011687
Jeff Johnson295189b2012-06-20 16:38:30 -070011688 }
c_hpothu5ab05e92014-06-13 17:34:05 +053011689 vosStatus = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
11690 pAdapterNode = pNext;
Jeff Johnson295189b2012-06-20 16:38:30 -070011691 }
mukul sharmabab477d2015-06-11 17:14:55 +053011692
Kaushik, Sushant4975a572014-10-21 16:07:48 +053011693 // Cancel any outstanding scan requests. We are about to close all
11694 // of our adapters, but an adapter structure is what SME passes back
11695 // to our callback function. Hence if there are any outstanding scan
11696 // requests then there is a race condition between when the adapter
11697 // is closed and when the callback is invoked.We try to resolve that
11698 // race condition here by canceling any outstanding scans before we
11699 // close the adapters.
11700 // Note that the scans may be cancelled in an asynchronous manner,
11701 // so ideally there needs to be some kind of synchronization. Rather
11702 // than introduce a new synchronization here, we will utilize the
11703 // fact that we are about to Request Full Power, and since that is
11704 // synchronized, the expectation is that by the time Request Full
11705 // Power has completed all scans will be cancelled.
11706 if (pHddCtx->scan_info.mScanPending)
11707 {
Hema Aparna Medicharlaf05f6cd2015-01-21 14:44:19 +053011708 if(NULL != pAdapter)
11709 {
11710 hddLog(VOS_TRACE_LEVEL_INFO,
11711 FL("abort scan mode: %d sessionId: %d"),
11712 pAdapter->device_mode,
11713 pAdapter->sessionId);
11714 }
11715 hdd_abort_mac_scan(pHddCtx,
11716 pHddCtx->scan_info.sessionId,
11717 eCSR_SCAN_ABORT_DEFAULT);
Kaushik, Sushant4975a572014-10-21 16:07:48 +053011718 }
Jeff Johnson295189b2012-06-20 16:38:30 -070011719 }
c_hpothu5ab05e92014-06-13 17:34:05 +053011720 else
Jeff Johnson88ba7742013-02-27 14:36:02 -080011721 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +053011722 hddLog(VOS_TRACE_LEVEL_INFO,"%s: FTM MODE",__func__);
Hanumantha Reddy Pothula45af96b2015-02-12 16:07:58 +053011723 if (pHddCtx->ftm.ftm_state == WLAN_FTM_STARTING)
11724 {
11725 INIT_COMPLETION(pHddCtx->ftm.startCmpVar);
11726 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
11727 "%s: in middle of FTM START", __func__);
11728 lrc = wait_for_completion_timeout(&pHddCtx->ftm.startCmpVar,
11729 msecs_to_jiffies(20000));
11730 if(!lrc)
11731 {
11732 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
11733 "%s: timedout on ftmStartCmpVar fatal error", __func__);
11734 }
11735 }
Jeff Johnson88ba7742013-02-27 14:36:02 -080011736 wlan_hdd_ftm_close(pHddCtx);
11737 goto free_hdd_ctx;
11738 }
c_hpothu6ff1c3c2013-10-01 19:01:57 +053011739
Jeff Johnson295189b2012-06-20 16:38:30 -070011740 /* DeRegister with platform driver as client for Suspend/Resume */
11741 vosStatus = hddDeregisterPmOps(pHddCtx);
11742 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
11743 {
11744 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
11745 VOS_ASSERT(0);
11746 }
11747
11748 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
11749 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
11750 {
11751 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
11752 }
Jeff Johnson295189b2012-06-20 16:38:30 -070011753
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -070011754 //Stop the traffic monitor timer
Mahesh A Saptasagard461e432016-07-20 15:01:40 +053011755 if ((pHddCtx->cfg_ini->dynSplitscan) && (VOS_TIMER_STATE_RUNNING ==
11756 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr)))
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -070011757 {
11758 vos_timer_stop(&pHddCtx->tx_rx_trafficTmr);
11759 }
11760
11761 // Destroy the traffic monitor timer
Mahesh A Saptasagard461e432016-07-20 15:01:40 +053011762 if ((pHddCtx->cfg_ini->dynSplitscan) &&
11763 (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
11764 &pHddCtx->tx_rx_trafficTmr))))
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -070011765 {
11766 hddLog(VOS_TRACE_LEVEL_ERROR,
11767 "%s: Cannot deallocate Traffic monitor timer", __func__);
11768 }
11769
Bhargav Shahd0715912015-10-01 18:17:37 +053011770 if (VOS_TIMER_STATE_RUNNING ==
11771 vos_timer_getCurrentState(&pHddCtx->delack_timer)) {
11772 vos_timer_stop(&pHddCtx->delack_timer);
11773 }
11774
11775 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
11776 &pHddCtx->delack_timer))) {
11777 hddLog(VOS_TRACE_LEVEL_ERROR,
11778 "%s: Cannot deallocate Bus bandwidth timer", __func__);
11779 }
11780
Masti, Narayanraddi44b0db02015-12-22 11:54:35 +053011781 if (VOS_TIMER_STATE_RUNNING ==
11782 vos_timer_getCurrentState(&pHddCtx->tdls_source_timer)) {
11783 vos_timer_stop(&pHddCtx->tdls_source_timer);
11784 }
11785
Abhishek Singh8a3e4dc2017-01-02 10:39:18 +053011786 vos_set_snoc_high_freq_voting(false);
11787
Masti, Narayanraddi44b0db02015-12-22 11:54:35 +053011788 vos_timer_destroy(&pHddCtx->tdls_source_timer);
11789
Jeff Johnson295189b2012-06-20 16:38:30 -070011790 //Disable IMPS/BMPS as we do not want the device to enter any power
11791 //save mode during shutdown
11792 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
11793 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
11794 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
11795
11796 //Ensure that device is in full power as we will touch H/W during vos_Stop
11797 init_completion(&powerContext.completion);
11798 powerContext.magic = POWER_CONTEXT_MAGIC;
11799
11800 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
11801 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
11802
11803 if (eHAL_STATUS_SUCCESS != halStatus)
11804 {
11805 if (eHAL_STATUS_PMC_PENDING == halStatus)
11806 {
11807 /* request was sent -- wait for the response */
11808 lrc = wait_for_completion_interruptible_timeout(
11809 &powerContext.completion,
11810 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
Jeff Johnson295189b2012-06-20 16:38:30 -070011811 if (lrc <= 0)
11812 {
11813 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070011814 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -070011815 }
11816 }
11817 else
11818 {
11819 hddLog(VOS_TRACE_LEVEL_ERROR,
11820 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070011821 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -070011822 /* continue -- need to clean up as much as possible */
11823 }
11824 }
Hanumantha Reddy Pothula81b42b22015-05-12 13:52:00 +053011825 if ((eHAL_STATUS_SUCCESS == halStatus) ||
11826 (eHAL_STATUS_PMC_PENDING == halStatus && lrc > 0))
11827 {
11828 /* This will issue a dump command which will clean up
11829 BTQM queues and unblock MC thread */
11830 vos_fwDumpReq(274, 0, 0, 0, 0, 1);
11831 }
Jeff Johnson295189b2012-06-20 16:38:30 -070011832
Jeff Johnson72a40512013-12-19 10:14:15 -080011833 /* either we never sent a request, we sent a request and received a
11834 response or we sent a request and timed out. if we never sent a
11835 request or if we sent a request and got a response, we want to
11836 clear the magic out of paranoia. if we timed out there is a
11837 race condition such that the callback function could be
11838 executing at the same time we are. of primary concern is if the
11839 callback function had already verified the "magic" but had not
11840 yet set the completion variable when a timeout occurred. we
11841 serialize these activities by invalidating the magic while
11842 holding a shared spinlock which will cause us to block if the
11843 callback is currently executing */
11844 spin_lock(&hdd_context_lock);
11845 powerContext.magic = 0;
11846 spin_unlock(&hdd_context_lock);
11847
Hema Aparna Medicharlaa6cf65e2015-06-01 16:23:28 +053011848 /* If Device is shutdown, no point for SME to wait for responses
11849 from device. Pre Close SME */
11850 if(wcnss_device_is_shutdown())
11851 {
11852 sme_PreClose(pHddCtx->hHal);
11853 }
Yue Ma0d4891e2013-08-06 17:01:45 -070011854 hdd_debugfs_exit(pHddCtx);
11855
Ratheesh S P35ed8b12015-04-27 14:01:07 +053011856#ifdef WLAN_NS_OFFLOAD
Ratheesh S P36dbc932015-08-07 14:28:57 +053011857 hddLog(LOG1, FL("Unregister IPv6 notifier"));
Ratheesh S P35ed8b12015-04-27 14:01:07 +053011858 unregister_inet6addr_notifier(&pHddCtx->ipv6_notifier);
11859#endif
Ratheesh S P36dbc932015-08-07 14:28:57 +053011860 hddLog(LOG1, FL("Unregister IPv4 notifier"));
Ratheesh S P35ed8b12015-04-27 14:01:07 +053011861 unregister_inetaddr_notifier(&pHddCtx->ipv4_notifier);
11862
Jeff Johnson295189b2012-06-20 16:38:30 -070011863 // Unregister the Net Device Notifier
11864 unregister_netdevice_notifier(&hdd_netdev_notifier);
11865
Jeff Johnson295189b2012-06-20 16:38:30 -070011866 hdd_stop_all_adapters( pHddCtx );
11867
Jeff Johnson295189b2012-06-20 16:38:30 -070011868#ifdef WLAN_BTAMP_FEATURE
11869 vosStatus = WLANBAP_Stop(pVosContext);
11870 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
11871 {
11872 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
11873 "%s: Failed to stop BAP",__func__);
11874 }
11875#endif //WLAN_BTAMP_FEATURE
11876
11877 //Stop all the modules
11878 vosStatus = vos_stop( pVosContext );
11879 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
11880 {
11881 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
11882 "%s: Failed to stop VOSS",__func__);
11883 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
Hanumantha Reddy Pothulabd9601a2016-02-12 13:22:27 +053011884 if (isSsrPanicOnFailure())
11885 VOS_BUG(0);
Jeff Johnson295189b2012-06-20 16:38:30 -070011886 }
11887
Jeff Johnson295189b2012-06-20 16:38:30 -070011888 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -070011889 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -070011890
11891 //Close the scheduler before calling vos_close to make sure no thread is
11892 // scheduled after the each module close is called i.e after all the data
11893 // structures are freed.
11894 vosStatus = vos_sched_close( pVosContext );
11895 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
11896 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
11897 "%s: Failed to close VOSS Scheduler",__func__);
11898 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
11899 }
Jeff Johnsone7245742012-09-05 17:12:55 -070011900#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
11901 /* Destroy the wake lock */
Sushant Kaushik83392fa2015-05-05 17:44:40 +053011902 vos_wake_lock_destroy(&pHddCtx->rx_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -070011903#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -080011904 /* Destroy the wake lock */
Sushant Kaushik83392fa2015-05-05 17:44:40 +053011905 vos_wake_lock_destroy(&pHddCtx->sap_wake_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070011906
Mihir Shete7a24b5f2013-12-21 12:18:31 +053011907#ifdef CONFIG_ENABLE_LINUX_REG
11908 vosStatus = vos_nv_close();
11909 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
11910 {
11911 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
11912 "%s: Failed to close NV", __func__);
11913 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
11914 }
11915#endif
11916
Jeff Johnson295189b2012-06-20 16:38:30 -070011917 //Close VOSS
11918 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
11919 vos_close(pVosContext);
11920
Jeff Johnson295189b2012-06-20 16:38:30 -070011921 //Close Watchdog
11922 if(pHddCtx->cfg_ini->fIsLogpEnabled)
11923 vos_watchdog_close(pVosContext);
11924
Gopichand Nakkalaa0358482013-06-12 17:05:47 +053011925 //Clean up HDD Nlink Service
11926 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Gopichand Nakkalaa0358482013-06-12 17:05:47 +053011927
Manjeet Singh47ee8472016-04-11 11:57:18 +053011928 hdd_close_tx_queues(pHddCtx);
c_manjeecfd1efb2015-09-25 19:32:34 +053011929 wlan_free_fwr_mem_dump_buffer();
11930 memdump_deinit();
11931
Vinay Krishna Erannad938c422014-03-10 17:14:21 +053011932#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +053011933 if (pHddCtx->cfg_ini->wlanLoggingEnable)
Vinay Krishna Erannad938c422014-03-10 17:14:21 +053011934 {
11935 wlan_logging_sock_deactivate_svc();
11936 }
11937#endif
11938
Vinay Krishna Erannaef30b522014-08-26 17:48:16 +053011939#ifdef WLAN_KD_READY_NOTIFIER
11940 nl_srv_exit(pHddCtx->ptt_pid);
11941#else
11942 nl_srv_exit();
11943#endif /* WLAN_KD_READY_NOTIFIER */
11944
Abhishek Singh00b71972016-01-07 10:51:04 +053011945#ifdef WLAN_FEATURE_RMC
11946 hdd_close_cesium_nl_sock();
11947#endif /* WLAN_FEATURE_RMC */
Vinay Krishna Erannaef30b522014-08-26 17:48:16 +053011948
Jeff Johnson295189b2012-06-20 16:38:30 -070011949 hdd_close_all_adapters( pHddCtx );
11950
Padma, Santhosh Kumar9cd38332015-11-17 12:18:10 +053011951 vos_flush_delayed_work(&pHddCtx->spoof_mac_addr_work);
Abhishek Singh78c691f2017-11-30 13:48:44 +053011952 vos_flush_delayed_work(&pHddCtx->ecsa_chan_change_work);
Kapil Gupta137ef892016-12-13 19:38:00 +053011953 vos_flush_work(&pHddCtx->sap_start_work);
Padma, Santhosh Kumar9cd38332015-11-17 12:18:10 +053011954
Hanumantha Reddy Pothula97f9bc92015-08-10 17:21:20 +053011955free_hdd_ctx:
Jeff Johnson295189b2012-06-20 16:38:30 -070011956 /* free the power on lock from platform driver */
11957 if (free_riva_power_on_lock("wlan"))
11958 {
11959 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
11960 __func__);
11961 }
11962
c_hpothu78c7b602014-05-17 17:35:49 +053011963 //Free up dynamically allocated members inside HDD Adapter
11964 if (pHddCtx->cfg_ini)
11965 {
11966 kfree(pHddCtx->cfg_ini);
11967 pHddCtx->cfg_ini= NULL;
11968 }
11969
Hanumantha Reddy Pothula6fe221c2016-01-28 15:01:09 +053011970 /* FTM/MONITOR mode, WIPHY did not registered
Leo Changf04ddad2013-09-18 13:46:38 -070011971 If un-register here, system crash will happen */
Hanumantha Reddy Pothula6fe221c2016-01-28 15:01:09 +053011972 if (!(VOS_FTM_MODE == hdd_get_conparam() ||
11973 VOS_MONITOR_MODE == hdd_get_conparam()))
Leo Changf04ddad2013-09-18 13:46:38 -070011974 {
11975 wiphy_unregister(wiphy) ;
Agrawal Ashish33ec71e2015-11-26 20:20:58 +053011976 hdd_wlan_free_wiphy_channels(wiphy);
Leo Changf04ddad2013-09-18 13:46:38 -070011977 }
Jeff Johnson295189b2012-06-20 16:38:30 -070011978 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -070011979 if (hdd_is_ssr_required())
11980 {
11981 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -070011982 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -070011983 msleep(5000);
11984 }
11985 hdd_set_ssr_required (VOS_FALSE);
11986}
11987
11988
11989/**---------------------------------------------------------------------------
11990
11991 \brief hdd_update_config_from_nv() - Function to update the contents of
11992 the running configuration with parameters taken from NV storage
11993
11994 \param - pHddCtx - Pointer to the HDD global context
11995
11996 \return - VOS_STATUS_SUCCESS if successful
11997
11998 --------------------------------------------------------------------------*/
11999static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
12000{
Jeff Johnson295189b2012-06-20 16:38:30 -070012001 v_BOOL_t itemIsValid = VOS_FALSE;
12002 VOS_STATUS status;
12003 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
12004 v_U8_t macLoop;
12005
12006 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
12007 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
12008 if(status != VOS_STATUS_SUCCESS)
12009 {
Arif Hussain6d2a3322013-11-17 19:50:10 -080012010 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed");
Jeff Johnson295189b2012-06-20 16:38:30 -070012011 return VOS_STATUS_E_FAILURE;
12012 }
12013
12014 if (itemIsValid == VOS_TRUE)
12015 {
Arif Hussain6d2a3322013-11-17 19:50:10 -080012016 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV");
Jeff Johnson295189b2012-06-20 16:38:30 -070012017 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
12018 VOS_MAX_CONCURRENCY_PERSONA);
12019 if(status != VOS_STATUS_SUCCESS)
12020 {
12021 /* Get MAC from NV fail, not update CFG info
12022 * INI MAC value will be used for MAC setting */
Arif Hussain6d2a3322013-11-17 19:50:10 -080012023 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed");
Jeff Johnson295189b2012-06-20 16:38:30 -070012024 return VOS_STATUS_E_FAILURE;
12025 }
12026
12027 /* If first MAC is not valid, treat all others are not valid
12028 * Then all MACs will be got from ini file */
12029 if(vos_is_macaddr_zero(&macFromNV[0]))
12030 {
12031 /* MAC address in NV file is not configured yet */
12032 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
12033 return VOS_STATUS_E_INVAL;
12034 }
12035
12036 /* Get MAC address from NV, update CFG info */
12037 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
12038 {
12039 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
12040 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +053012041 hddLog(VOS_TRACE_LEVEL_ERROR,"not valid MAC from NV for %d", macLoop);
Jeff Johnson295189b2012-06-20 16:38:30 -070012042 /* This MAC is not valid, skip it
12043 * This MAC will be got from ini file */
12044 }
12045 else
12046 {
12047 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
12048 (v_U8_t *)&macFromNV[macLoop].bytes[0],
12049 VOS_MAC_ADDR_SIZE);
12050 }
12051 }
12052 }
12053 else
12054 {
12055 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
12056 return VOS_STATUS_E_FAILURE;
12057 }
Jeff Johnson295189b2012-06-20 16:38:30 -070012058
Jeff Johnson295189b2012-06-20 16:38:30 -070012059
12060 return VOS_STATUS_SUCCESS;
12061}
12062
12063/**---------------------------------------------------------------------------
12064
12065 \brief hdd_post_voss_start_config() - HDD post voss start config helper
12066
12067 \param - pAdapter - Pointer to the HDD
12068
12069 \return - None
12070
12071 --------------------------------------------------------------------------*/
12072VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
12073{
12074 eHalStatus halStatus;
12075 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +053012076 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -070012077
Jeff Johnson295189b2012-06-20 16:38:30 -070012078
12079 // Send ready indication to the HDD. This will kick off the MAC
12080 // into a 'running' state and should kick off an initial scan.
12081 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
12082 if ( !HAL_STATUS_SUCCESS( halStatus ) )
12083 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +053012084 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -070012085 "code %08d [x%08x]",__func__, halStatus, halStatus );
12086 return VOS_STATUS_E_FAILURE;
12087 }
12088
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +053012089 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -070012090 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
12091 // And RIVA will crash
12092 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
12093 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +053012094 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
12095 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
12096
12097
Jeff Johnson295189b2012-06-20 16:38:30 -070012098 return VOS_STATUS_SUCCESS;
12099}
12100
Jeff Johnson295189b2012-06-20 16:38:30 -070012101/* wake lock APIs for HDD */
Sushant Kaushik83392fa2015-05-05 17:44:40 +053012102void hdd_prevent_suspend(uint32_t reason)
Jeff Johnson295189b2012-06-20 16:38:30 -070012103{
Sushant Kaushik83392fa2015-05-05 17:44:40 +053012104
12105 vos_wake_lock_acquire(&wlan_wake_lock, reason);
12106
Jeff Johnson295189b2012-06-20 16:38:30 -070012107}
12108
Sushant Kaushik83392fa2015-05-05 17:44:40 +053012109void hdd_allow_suspend(uint32_t reason)
Jeff Johnson295189b2012-06-20 16:38:30 -070012110{
Sushant Kaushik83392fa2015-05-05 17:44:40 +053012111
12112 vos_wake_lock_release(&wlan_wake_lock, reason);
12113
Jeff Johnson295189b2012-06-20 16:38:30 -070012114}
12115
Sushant Kaushik83392fa2015-05-05 17:44:40 +053012116void hdd_prevent_suspend_timeout(v_U32_t timeout, uint32_t reason)
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -070012117{
Sushant Kaushik83392fa2015-05-05 17:44:40 +053012118
12119 vos_wake_lock_timeout_release(&wlan_wake_lock, timeout,
12120 reason);
12121
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -070012122}
12123
Jeff Johnson295189b2012-06-20 16:38:30 -070012124/**---------------------------------------------------------------------------
12125
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070012126 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
12127 information between Host and Riva
12128
12129 This function gets reported version of FW
12130 It also finds the version of Riva headers used to compile the host
12131 It compares the above two and prints a warning if they are different
12132 It gets the SW and HW version string
12133 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
12134 indicating the features they support through a bitmap
12135
12136 \param - pHddCtx - Pointer to HDD context
12137
12138 \return - void
12139
12140 --------------------------------------------------------------------------*/
12141
12142void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
12143{
12144
12145 tSirVersionType versionCompiled;
12146 tSirVersionType versionReported;
12147 tSirVersionString versionString;
12148 tANI_U8 fwFeatCapsMsgSupported = 0;
12149 VOS_STATUS vstatus;
12150
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -080012151 memset(&versionCompiled, 0, sizeof(versionCompiled));
12152 memset(&versionReported, 0, sizeof(versionReported));
12153
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070012154 /* retrieve and display WCNSS version information */
12155 do {
12156
12157 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
12158 &versionCompiled);
12159 if (!VOS_IS_STATUS_SUCCESS(vstatus))
12160 {
12161 hddLog(VOS_TRACE_LEVEL_FATAL,
12162 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070012163 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070012164 break;
12165 }
12166
12167 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
12168 &versionReported);
12169 if (!VOS_IS_STATUS_SUCCESS(vstatus))
12170 {
12171 hddLog(VOS_TRACE_LEVEL_FATAL,
12172 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070012173 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070012174 break;
12175 }
12176
12177 if ((versionCompiled.major != versionReported.major) ||
12178 (versionCompiled.minor != versionReported.minor) ||
12179 (versionCompiled.version != versionReported.version) ||
12180 (versionCompiled.revision != versionReported.revision))
12181 {
12182 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
12183 "Host expected %u.%u.%u.%u\n",
12184 WLAN_MODULE_NAME,
12185 (int)versionReported.major,
12186 (int)versionReported.minor,
12187 (int)versionReported.version,
12188 (int)versionReported.revision,
12189 (int)versionCompiled.major,
12190 (int)versionCompiled.minor,
12191 (int)versionCompiled.version,
12192 (int)versionCompiled.revision);
12193 }
12194 else
12195 {
12196 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
12197 WLAN_MODULE_NAME,
12198 (int)versionReported.major,
12199 (int)versionReported.minor,
12200 (int)versionReported.version,
12201 (int)versionReported.revision);
12202 }
12203
12204 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
12205 versionString,
12206 sizeof(versionString));
12207 if (!VOS_IS_STATUS_SUCCESS(vstatus))
12208 {
12209 hddLog(VOS_TRACE_LEVEL_FATAL,
12210 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070012211 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070012212 break;
12213 }
12214
12215 pr_info("%s: WCNSS software version %s\n",
12216 WLAN_MODULE_NAME, versionString);
Sushant Kaushik084f6592015-09-10 13:11:56 +053012217 vos_mem_copy(pHddCtx->fw_Version, versionString, sizeof(versionString));
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070012218
12219 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
12220 versionString,
12221 sizeof(versionString));
12222 if (!VOS_IS_STATUS_SUCCESS(vstatus))
12223 {
12224 hddLog(VOS_TRACE_LEVEL_FATAL,
12225 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070012226 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070012227 break;
12228 }
12229
12230 pr_info("%s: WCNSS hardware version %s\n",
12231 WLAN_MODULE_NAME, versionString);
12232
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -070012233 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
12234 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070012235 send the message only if it the riva is 1.1
12236 minor numbers for different riva branches:
12237 0 -> (1.0)Mainline Build
12238 1 -> (1.1)Mainline Build
12239 2->(1.04) Stability Build
12240 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -070012241 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070012242 ((versionReported.minor>=1) && (versionReported.version>=1)))
12243 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
12244 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -070012245
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070012246 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -080012247 {
12248#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
12249 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
12250 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
12251#endif
Ravi Joshid2ca7c42013-07-23 08:37:49 -070012252 /* Indicate if IBSS heartbeat monitoring needs to be offloaded */
12253 if (!pHddCtx->cfg_ini->enableIbssHeartBeatOffload)
12254 {
12255 sme_disableFeatureCapablity(IBSS_HEARTBEAT_OFFLOAD);
12256 }
12257
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070012258 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -080012259 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070012260
12261 } while (0);
12262
12263}
Neelansh Mittaledafed22014-09-04 18:54:39 +053012264void wlan_hdd_send_svc_nlink_msg(int type, void *data, int len)
12265{
12266 struct sk_buff *skb;
12267 struct nlmsghdr *nlh;
12268 tAniMsgHdr *ani_hdr;
Hanumantha Reddy Pothulacf2c7ea2015-04-27 14:50:47 +053012269 int flags = GFP_KERNEL;
Bhargav shah23c94942015-10-13 12:48:35 +053012270 void *nl_data = NULL;
Neelansh Mittaledafed22014-09-04 18:54:39 +053012271
Hanumantha Reddy Pothulacf2c7ea2015-04-27 14:50:47 +053012272 if (in_interrupt() || irqs_disabled() || in_atomic())
12273 flags = GFP_ATOMIC;
12274
12275 skb = alloc_skb(NLMSG_SPACE(WLAN_NL_MAX_PAYLOAD), flags);
Neelansh Mittaledafed22014-09-04 18:54:39 +053012276
12277 if(skb == NULL) {
12278 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
12279 "%s: alloc_skb failed", __func__);
12280 return;
12281 }
12282
12283 nlh = (struct nlmsghdr *)skb->data;
12284 nlh->nlmsg_pid = 0; /* from kernel */
12285 nlh->nlmsg_flags = 0;
12286 nlh->nlmsg_seq = 0;
12287 nlh->nlmsg_type = WLAN_NL_MSG_SVC;
12288
12289 ani_hdr = NLMSG_DATA(nlh);
12290 ani_hdr->type = type;
12291
12292 switch(type) {
12293 case WLAN_SVC_SAP_RESTART_IND:
12294 ani_hdr->length = 0;
12295 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr)));
12296 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr)));
12297 break;
Bhargav Shahd0715912015-10-01 18:17:37 +053012298 case WLAN_SVC_WLAN_TP_IND:
12299 ani_hdr->length = len;
12300 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr)
12301 + len));
12302 nl_data = (char *)ani_hdr + sizeof(tAniMsgHdr);
12303 memcpy(nl_data, data, len);
12304 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + len));
12305 break;
Bhargav shah23c94942015-10-13 12:48:35 +053012306 case WLAN_MSG_RPS_ENABLE_IND:
12307 ani_hdr->length = len;
12308 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + len));
12309 nl_data = (char *)ani_hdr + sizeof(tAniMsgHdr);
12310 memcpy(nl_data, data, len);
12311 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + len));
12312 break;
Neelansh Mittaledafed22014-09-04 18:54:39 +053012313 default:
12314 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
12315 "Attempt to send unknown nlink message %d", type);
12316 kfree_skb(skb);
12317 return;
12318 }
12319
12320 nl_srv_bcast(skb);
12321
12322 return;
12323}
12324
Bhargav Shahd0715912015-10-01 18:17:37 +053012325/**
12326 * hdd_request_tcp_delack() - Find the Delack value based on RX packet
12327 * @pHddCtx: Valid Global HDD context pointer
12328 * @rx_packets: Number of RX packet in perticular time
12329 *
12330 * Based on the RX packet this function calculate next value of tcp delack.
12331 * This function compare rx packet value to high and low threshold limit.
12332 *
12333 * Return: void
12334 */
12335void hdd_request_tcp_delack(hdd_context_t *pHddCtx, uint64_t rx_packets)
12336{
12337 /* average of rx_packets and prev_rx is taken so that
12338 bus width doesnot fluctuate much */
12339 uint64_t temp_rx = (rx_packets + pHddCtx->prev_rx)/2;
12340 TP_IND_TYPE next_rx_level = pHddCtx->cur_rx_level;
Neelansh Mittaledafed22014-09-04 18:54:39 +053012341
Bhargav Shahd0715912015-10-01 18:17:37 +053012342 pHddCtx->prev_rx = rx_packets;
12343 if (temp_rx > pHddCtx->cfg_ini->tcpDelAckThresholdHigh)
12344 next_rx_level = TP_IND_HIGH;
12345 else if (temp_rx <= pHddCtx->cfg_ini->tcpDelAckThresholdLow)
12346 next_rx_level = TP_IND_LOW;
12347
12348 hdd_set_delack_value(pHddCtx, next_rx_level);
12349}
12350
12351#define HDD_BW_GET_DIFF(x, y) ((x) >= (y) ? (x) - (y) : (ULONG_MAX - (y) + (x)))
12352
12353/**
12354 * hdd_tcp_delack_compute_function() - get link status
12355 * @priv: Valid Global HDD context pointer
12356 *
12357 * This function find number of RX packet during timer life span.
12358 * It request tcp delack with number of RX packet and re-configure delack timer
12359 * for tcpDelAckComputeInterval timer interval.
12360 *
12361 * Return: void
12362 */
12363void hdd_tcp_delack_compute_function(void *priv)
12364{
12365 hdd_context_t *pHddCtx = (hdd_context_t *)priv;
12366 hdd_adapter_t *pAdapter = NULL;
12367 v_U32_t rx_packets = 0;
12368 hdd_adapter_list_node_t *pAdapterNode = NULL;
12369 VOS_STATUS status = 0;
12370
12371 for (status = hdd_get_front_adapter(pHddCtx, &pAdapterNode);
12372 NULL != pAdapterNode && VOS_STATUS_SUCCESS == status;
12373 status = hdd_get_next_adapter(pHddCtx, pAdapterNode, &pAdapterNode)) {
12374 if ((pAdapter = pAdapterNode->pAdapter) == NULL)
12375 continue;
12376
12377 rx_packets += HDD_BW_GET_DIFF(pAdapter->stats.rx_packets,
12378 pAdapter->prev_rx_packets);
12379 pAdapter->prev_rx_packets = pAdapter->stats.rx_packets;
12380 }
12381
12382 hdd_request_tcp_delack(pHddCtx, rx_packets);
12383
12384 vos_timer_start(&pHddCtx->delack_timer,
12385 pHddCtx->cfg_ini->tcpDelAckComputeInterval);
12386}
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070012387
12388/**---------------------------------------------------------------------------
12389
Gopichand Nakkalafce506f2013-07-03 23:55:16 +053012390 \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
12391
12392 \param - pHddCtx - Pointer to the hdd context
12393
12394 \return - true if hardware supports 5GHz
12395
12396 --------------------------------------------------------------------------*/
Vinay Krishna Erannafacf5e22014-02-24 13:16:25 +053012397boolean hdd_is_5g_supported(hdd_context_t * pHddCtx)
Gopichand Nakkalafce506f2013-07-03 23:55:16 +053012398{
12399 /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
12400 * then hardware support 5Ghz.
12401 */
12402 if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode())
12403 {
Ratheesh S P36dbc932015-08-07 14:28:57 +053012404 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware supports 5Ghz", __func__);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +053012405 return true;
12406 }
12407 else
12408 {
Ratheesh S P36dbc932015-08-07 14:28:57 +053012409 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware doesn't supports 5Ghz",
Gopichand Nakkalafce506f2013-07-03 23:55:16 +053012410 __func__);
12411 return false;
12412 }
12413}
12414
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053012415/**---------------------------------------------------------------------------
12416
12417 \brief hdd_generate_iface_mac_addr_auto() - HDD Mac Interface Auto
12418 generate function
12419
12420 This is generate the random mac address for WLAN interface
12421
12422 \param - pHddCtx - Pointer to HDD context
12423 idx - Start interface index to get auto
12424 generated mac addr.
12425 mac_addr - Mac address
12426
12427 \return - 0 for success, < 0 for failure
12428
12429 --------------------------------------------------------------------------*/
12430
12431static int hdd_generate_iface_mac_addr_auto(hdd_context_t *pHddCtx,
12432 int idx, v_MACADDR_t mac_addr)
12433{
12434 int i;
12435 unsigned int serialno;
12436 serialno = wcnss_get_serial_number();
12437
12438 if (0 != serialno)
12439 {
12440 /* MAC address has 3 bytes of OUI so we have a maximum of 3
12441 bytes of the serial number that can be used to generate
12442 the other 3 bytes of the MAC address. Mask off all but
12443 the lower 3 bytes (this will also make sure we don't
12444 overflow in the next step) */
12445 serialno &= 0x00FFFFFF;
12446
12447 /* we need a unique address for each session */
12448 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
12449
12450 /* autogen other Mac addresses */
12451 for (i = idx; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
12452 {
12453 /* start with the entire default address */
12454 pHddCtx->cfg_ini->intfMacAddr[i] = mac_addr;
12455 /* then replace the lower 3 bytes */
12456 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
12457 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
12458 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
12459
Nachiket Kukadede2e24f2017-09-25 16:24:27 +053012460 if (0 == memcmp(&pHddCtx->cfg_ini->intfMacAddr[i].bytes[0],
12461 &mac_addr.bytes[0], VOS_MAC_ADDR_SIZE))
12462 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] +=
12463 VOS_MAX_CONCURRENCY_PERSONA;
12464
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053012465 serialno++;
12466 hddLog(VOS_TRACE_LEVEL_ERROR,
12467 "%s: Derived Mac Addr: "
12468 MAC_ADDRESS_STR, __func__,
12469 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[i].bytes));
12470 }
12471
12472 }
12473 else
12474 {
12475 hddLog(LOGE, FL("Failed to Get Serial NO"));
12476 return -1;
12477 }
12478 return 0;
12479}
Gopichand Nakkalafce506f2013-07-03 23:55:16 +053012480
Katya Nigame7b69a82015-04-28 15:24:06 +053012481int wlan_hdd_mon_open(hdd_context_t *pHddCtx)
12482{
12483 VOS_STATUS status;
12484 v_CONTEXT_t pVosContext= NULL;
12485 hdd_adapter_t *pAdapter= NULL;
12486
12487 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
12488
12489 if (NULL == pVosContext)
12490 {
12491 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
12492 "%s: Trying to open VOSS without a PreOpen", __func__);
12493 VOS_ASSERT(0);
12494 return VOS_STATUS_E_FAILURE;
12495 }
12496
12497 status = vos_nv_open();
12498 if (!VOS_IS_STATUS_SUCCESS(status))
12499 {
12500 /* NV module cannot be initialized */
12501 hddLog( VOS_TRACE_LEVEL_FATAL,
12502 "%s: vos_nv_open failed", __func__);
12503 return VOS_STATUS_E_FAILURE;
12504 }
12505
12506 status = vos_init_wiphy_from_nv_bin();
12507 if (!VOS_IS_STATUS_SUCCESS(status))
12508 {
12509 /* NV module cannot be initialized */
12510 hddLog( VOS_TRACE_LEVEL_FATAL,
12511 "%s: vos_init_wiphy failed", __func__);
12512 goto err_vos_nv_close;
12513 }
12514
12515 status = vos_open( &pVosContext, pHddCtx->parent_dev);
12516 if ( !VOS_IS_STATUS_SUCCESS( status ))
12517 {
12518 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
12519 goto err_vos_nv_close;
12520 }
12521
12522 status = vos_mon_start( pVosContext );
12523 if ( !VOS_IS_STATUS_SUCCESS( status ) )
12524 {
12525 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
12526 goto err_vosclose;
12527 }
12528
12529 WLANTL_SetMonRxCbk( pVosContext, hdd_rx_packet_monitor_cbk );
12530 WDA_featureCapsExchange(pVosContext);
12531 wcnss_wlan_set_drvdata(pHddCtx->parent_dev, pHddCtx);
12532
12533 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_MONITOR, "wlan%d",
12534 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
12535 if( pAdapter == NULL )
12536 {
12537 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
12538 goto err_close_adapter;
12539 }
12540
12541 //Initialize the nlink service
12542 if(nl_srv_init() != 0)
12543 {
12544 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
12545 goto err_close_adapter;
12546 }
12547 return VOS_STATUS_SUCCESS;
12548
12549err_close_adapter:
12550 hdd_close_all_adapters( pHddCtx );
12551 vos_mon_stop( pVosContext );
12552err_vosclose:
12553 status = vos_sched_close( pVosContext );
12554 if (!VOS_IS_STATUS_SUCCESS(status)) {
12555 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
12556 "%s: Failed to close VOSS Scheduler", __func__);
12557 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
12558 }
12559 vos_close(pVosContext );
12560
12561err_vos_nv_close:
12562 vos_nv_close();
12563
12564return status;
12565}
Gopichand Nakkalafce506f2013-07-03 23:55:16 +053012566/**---------------------------------------------------------------------------
12567
Mihir Shetefc7ff5b2014-01-27 11:30:05 +053012568 \brief hdd_11d_scan_done - callback to be executed when 11d scan is
12569 completed to flush out the scan results
12570
12571 11d scan is done during driver load and is a passive scan on all
12572 channels supported by the device, 11d scans may find some APs on
12573 frequencies which are forbidden to be used in the regulatory domain
12574 the device is operating in. If these APs are notified to the supplicant
12575 it may try to connect to these APs, thus flush out all the scan results
12576 which are present in SME after 11d scan is done.
12577
12578 \return - eHalStatus
12579
12580 --------------------------------------------------------------------------*/
12581static eHalStatus hdd_11d_scan_done(tHalHandle halHandle, void *pContext,
12582 tANI_U32 scanId, eCsrScanStatus status)
12583{
12584 ENTER();
12585
12586 sme_ScanFlushResult(halHandle, 0);
12587
12588 EXIT();
12589
12590 return eHAL_STATUS_SUCCESS;
12591}
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012592/**---------------------------------------------------------------------------
12593
12594 \brief hdd_init_frame_logging_done - callback to be executed when mgmt frame
12595 logging is completed successfully.
12596
12597 \return - None
12598
12599 --------------------------------------------------------------------------*/
c_manjeecfd1efb2015-09-25 19:32:34 +053012600void hdd_init_frame_logging_done(void *fwlogInitCbContext, tAniLoggingInitRsp *pRsp)
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012601{
Siddharth Bhald1be97f2015-05-27 22:39:59 +053012602 hdd_context_t* pHddCtx = (hdd_context_t*)fwlogInitCbContext;
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012603
12604 if (NULL == pHddCtx)
12605 {
12606 hddLog(VOS_TRACE_LEVEL_ERROR,
12607 "%s: HDD context is NULL",__func__);
12608 return;
12609 }
12610
c_manjeecfd1efb2015-09-25 19:32:34 +053012611 if ((pRsp->status == VOS_STATUS_SUCCESS) &&
Mahesh A Saptasagarfabb1a02015-06-29 12:17:04 +053012612 (TRUE == pHddCtx->cfg_ini->enableMgmtLogging))
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012613 {
12614 hddLog(VOS_TRACE_LEVEL_INFO, FL("Mgmt Frame Logging init successful"));
12615 pHddCtx->mgmt_frame_logging = TRUE;
12616 }
12617 else
12618 {
12619 hddLog(VOS_TRACE_LEVEL_INFO, FL("Mgmt Frame Logging init not success"));
12620 pHddCtx->mgmt_frame_logging = FALSE;
c_manjeecfd1efb2015-09-25 19:32:34 +053012621 return;
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012622 }
12623
c_manjeecfd1efb2015-09-25 19:32:34 +053012624 /*Check feature supported by FW*/
12625 if(TRUE == sme_IsFeatureSupportedByFW(MEMORY_DUMP_SUPPORTED))
12626 {
12627 //Store fwr mem dump size given by firmware.
12628 wlan_store_fwr_mem_dump_size(pRsp->fw_mem_dump_max_size);
12629 }
12630 else
12631 {
12632 wlan_store_fwr_mem_dump_size(0);
12633 }
12634
12635
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012636}
12637/**---------------------------------------------------------------------------
12638
12639 \brief hdd_init_frame_logging - function to initialize frame logging.
12640 Currently only Mgmt Frames are logged in both TX
12641 and Rx direction and are sent to userspace
12642 application using logger thread when queried.
12643
12644 \return - None
12645
12646 --------------------------------------------------------------------------*/
Siddharth Bhald1be97f2015-05-27 22:39:59 +053012647void hdd_init_frame_logging(hdd_context_t* pHddCtx)
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012648{
12649 eHalStatus halStatus = eHAL_STATUS_FAILURE;
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053012650 tSirFWLoggingInitParam wlanFWLoggingInitParam = {0};
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012651
Siddharth Bhald1be97f2015-05-27 22:39:59 +053012652 if (TRUE != sme_IsFeatureSupportedByFW(MGMT_FRAME_LOGGING) &&
12653 TRUE != sme_IsFeatureSupportedByFW(LOGGING_ENHANCEMENT))
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012654 {
12655 hddLog(VOS_TRACE_LEVEL_INFO, FL("MGMT_FRAME_LOGGING not supp by FW"));
12656 return;
12657 }
12658
c_manjeecfd1efb2015-09-25 19:32:34 +053012659 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Configuring %s %s %s %s Logging",__func__,
Siddharth Bhald1be97f2015-05-27 22:39:59 +053012660 pHddCtx->cfg_ini->enableFWLogging?"FW Log,":"",
12661 pHddCtx->cfg_ini->enableContFWLogging ? "Cont FW log,":"",
c_manjeecfd1efb2015-09-25 19:32:34 +053012662 pHddCtx->cfg_ini->enableMgmtLogging ? "Mgmt Pkt Log":"",
12663 pHddCtx->cfg_ini->enableFwrMemDump ? "Fw Mem dump":"");
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012664
Siddharth Bhald1be97f2015-05-27 22:39:59 +053012665 if (pHddCtx->cfg_ini->enableFWLogging ||
12666 pHddCtx->cfg_ini->enableContFWLogging)
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012667 {
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053012668 wlanFWLoggingInitParam.enableFlag |= WLAN_QXDM_LOG_EN;
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012669 }
12670
Sushant Kaushik46804902015-07-08 14:46:03 +053012671 if (pHddCtx->cfg_ini->enableMgmtLogging)
12672 {
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053012673 wlanFWLoggingInitParam.enableFlag |= WLAN_FRAME_LOG_EN;
Sushant Kaushik46804902015-07-08 14:46:03 +053012674 }
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012675 if (pHddCtx->cfg_ini->enableBMUHWtracing)
12676 {
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053012677 wlanFWLoggingInitParam.enableFlag |= WLAN_BMUHW_TRACE_LOG_EN;
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012678 }
c_manjeecfd1efb2015-09-25 19:32:34 +053012679 if(pHddCtx->cfg_ini->enableFwrMemDump &&
12680 (TRUE == sme_IsFeatureSupportedByFW(MEMORY_DUMP_SUPPORTED)))
12681 {
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053012682 wlanFWLoggingInitParam.enableFlag |= WLAN_FW_MEM_DUMP_EN;
c_manjeecfd1efb2015-09-25 19:32:34 +053012683 }
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053012684 if( wlanFWLoggingInitParam.enableFlag == 0 )
c_manjeecfd1efb2015-09-25 19:32:34 +053012685 {
12686 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Logging not enabled", __func__);
12687 return;
12688 }
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053012689 wlanFWLoggingInitParam.frameType = WLAN_FRAME_LOGGING_FRAMETYPE_MGMT;
12690 wlanFWLoggingInitParam.frameSize = WLAN_MGMT_LOGGING_FRAMESIZE_128BYTES;
12691 wlanFWLoggingInitParam.bufferMode = WLAN_FRAME_LOGGING_BUFFERMODE_CIRCULAR;
12692 wlanFWLoggingInitParam.continuousFrameLogging =
Siddharth Bhald1be97f2015-05-27 22:39:59 +053012693 pHddCtx->cfg_ini->enableContFWLogging;
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012694
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053012695 wlanFWLoggingInitParam.enableFlag &= ~WLAN_DPU_TXP_LOG_EN;
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012696
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053012697 wlanFWLoggingInitParam.minLogBufferSize =
Siddharth Bhald1be97f2015-05-27 22:39:59 +053012698 pHddCtx->cfg_ini->minLoggingBufferSize;
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053012699 wlanFWLoggingInitParam.maxLogBufferSize =
Siddharth Bhald1be97f2015-05-27 22:39:59 +053012700 pHddCtx->cfg_ini->maxLoggingBufferSize;
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053012701 wlanFWLoggingInitParam.fwlogInitCallback = hdd_init_frame_logging_done;
12702 wlanFWLoggingInitParam.fwlogInitCbContext= pHddCtx;
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012703
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053012704 halStatus = sme_InitMgmtFrameLogging(pHddCtx->hHal, &wlanFWLoggingInitParam);
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012705
12706 if (eHAL_STATUS_SUCCESS != halStatus)
12707 {
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053012708 hddLog(LOGE, FL("sme_InitMgmtFrameLogging failed, returned %d"),
12709 halStatus);
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012710 }
12711
12712 return;
12713}
Mihir Shetefc7ff5b2014-01-27 11:30:05 +053012714
Bhargav shah23c94942015-10-13 12:48:35 +053012715static void hdd_dp_util_send_rps_ind(hdd_context_t *hdd_ctxt)
12716{
12717 hdd_adapter_t *adapter;
12718 hdd_adapter_list_node_t *adapter_node, *next;
12719 VOS_STATUS status = VOS_STATUS_SUCCESS;
12720 struct wlan_rps_data rps_data;
12721 int count;
12722
12723 if(!hdd_ctxt->cfg_ini->rps_mask)
12724 {
12725 return;
12726 }
12727
12728 for (count=0; count < WLAN_SVC_IFACE_NUM_QUEUES; count++)
12729 {
12730 rps_data.cpu_map[count] = hdd_ctxt->cfg_ini->rps_mask;
12731 }
12732
12733 rps_data.num_queues = WLAN_SVC_IFACE_NUM_QUEUES;
12734
12735 hddLog(LOG1, FL("0x%x 0x%x 0x%x 0x%x 0x%x 0x%x"),
12736 rps_data.cpu_map[0], rps_data.cpu_map[1],rps_data.cpu_map[2],
12737 rps_data.cpu_map[3], rps_data.cpu_map[4], rps_data.cpu_map[5]);
12738
12739 status = hdd_get_front_adapter (hdd_ctxt, &adapter_node);
12740
12741 while (NULL != adapter_node && VOS_STATUS_SUCCESS == status)
12742 {
12743 adapter = adapter_node->pAdapter;
12744 if (NULL != adapter) {
12745 strlcpy(rps_data.ifname, adapter->dev->name,
12746 sizeof(rps_data.ifname));
12747 wlan_hdd_send_svc_nlink_msg(WLAN_MSG_RPS_ENABLE_IND,
12748 (void *)&rps_data,sizeof(rps_data));
12749 }
12750 status = hdd_get_next_adapter (hdd_ctxt, adapter_node, &next);
12751 adapter_node = next;
12752 }
12753}
12754
Masti, Narayanraddi26378462016-01-05 18:20:28 +053012755void wlan_hdd_schedule_defer_scan(struct work_struct *work)
12756{
12757 scan_context_t *scan_ctx =
12758 container_of(work, scan_context_t, scan_work.work);
12759
12760 if (NULL == scan_ctx)
12761 {
12762 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
12763 FL("scan_ctx is NULL"));
12764 return;
12765 }
12766
12767 if (unlikely(TDLS_CTX_MAGIC != scan_ctx->magic))
12768 return;
12769
12770 scan_ctx->attempt++;
12771
12772 wlan_hdd_cfg80211_scan(scan_ctx->wiphy,
12773#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
12774 scan_ctx->dev,
12775#endif
12776 scan_ctx->scan_request);
12777}
12778
12779int wlan_hdd_copy_defer_scan_context(hdd_context_t *pHddCtx,
12780 struct wiphy *wiphy,
12781#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
12782 struct net_device *dev,
12783#endif
12784 struct cfg80211_scan_request *request)
12785{
12786 scan_context_t *scan_ctx;
12787
12788 ENTER();
12789 if (0 != (wlan_hdd_validate_context(pHddCtx)))
12790 {
12791 return -1;
12792 }
12793
12794 scan_ctx = &pHddCtx->scan_ctxt;
12795
12796 scan_ctx->wiphy = wiphy;
12797#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
12798 scan_ctx->dev = dev;
12799#endif
12800
12801 scan_ctx->scan_request = request;
12802
12803 EXIT();
12804 return 0;
12805}
12806
12807void wlan_hdd_defer_scan_init_work(hdd_context_t *pHddCtx,
12808 struct wiphy *wiphy,
12809#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
12810 struct net_device *dev,
12811#endif
12812 struct cfg80211_scan_request *request,
12813 unsigned long delay)
12814{
12815 if (TDLS_CTX_MAGIC != pHddCtx->scan_ctxt.magic)
12816 {
12817#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
12818 wlan_hdd_copy_defer_scan_context(pHddCtx, wiphy, dev, request);
12819#else
12820 wlan_hdd_copy_defer_scan_context(pHddCtx, wiphy, request);
12821#endif
12822 pHddCtx->scan_ctxt.attempt = 0;
12823 pHddCtx->scan_ctxt.magic = TDLS_CTX_MAGIC;
12824 }
12825 schedule_delayed_work(&pHddCtx->scan_ctxt.scan_work, delay);
12826}
12827
12828void wlan_hdd_init_deinit_defer_scan_context(scan_context_t *scan_ctx)
12829{
12830 scan_ctx->magic = 0;
12831 scan_ctx->attempt = 0;
12832 scan_ctx->reject = 0;
12833 scan_ctx->scan_request = NULL;
12834
12835 return;
12836}
12837
Mihir Shetefc7ff5b2014-01-27 11:30:05 +053012838/**---------------------------------------------------------------------------
12839
Jeff Johnson295189b2012-06-20 16:38:30 -070012840 \brief hdd_wlan_startup() - HDD init function
12841
12842 This is the driver startup code executed once a WLAN device has been detected
12843
12844 \param - dev - Pointer to the underlying device
12845
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -080012846 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -070012847
12848 --------------------------------------------------------------------------*/
12849
12850int hdd_wlan_startup(struct device *dev )
12851{
12852 VOS_STATUS status;
12853 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -070012854 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -070012855 hdd_context_t *pHddCtx = NULL;
12856 v_CONTEXT_t pVosContext= NULL;
12857#ifdef WLAN_BTAMP_FEATURE
12858 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
12859 WLANBAP_ConfigType btAmpConfig;
12860 hdd_config_t *pConfig;
12861#endif
12862 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -070012863 struct wiphy *wiphy;
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053012864 v_MACADDR_t mac_addr;
Jeff Johnson295189b2012-06-20 16:38:30 -070012865
12866 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -070012867 /*
12868 * cfg80211: wiphy allocation
12869 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +053012870 wiphy = wlan_hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t)) ;
Jeff Johnson295189b2012-06-20 16:38:30 -070012871
12872 if(wiphy == NULL)
12873 {
12874 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -080012875 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -070012876 }
Jeff Johnson295189b2012-06-20 16:38:30 -070012877 pHddCtx = wiphy_priv(wiphy);
12878
Jeff Johnson295189b2012-06-20 16:38:30 -070012879 //Initialize the adapter context to zeros.
12880 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
12881
Jeff Johnson295189b2012-06-20 16:38:30 -070012882 pHddCtx->wiphy = wiphy;
Sushant Kaushik83392fa2015-05-05 17:44:40 +053012883 hdd_prevent_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_INIT);
Mihir Shete18156292014-03-11 15:38:30 +053012884 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_LOAD_IN_PROGRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -070012885
12886 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
12887
Siddharth Bhalcd92b782015-06-29 12:25:40 +053012888 /* register for riva power on lock to platform driver
12889 * Locking power early to ensure FW doesn't reset by kernel while
12890 * host driver is busy initializing itself */
12891 if (req_riva_power_on_lock("wlan"))
12892 {
12893 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
12894 __func__);
12895 goto err_free_hdd_context;
12896 }
12897
Jeff Johnson295189b2012-06-20 16:38:30 -070012898 /*Get vos context here bcoz vos_open requires it*/
12899 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
12900
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -080012901 if(pVosContext == NULL)
12902 {
12903 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
12904 goto err_free_hdd_context;
12905 }
12906
Jeff Johnson295189b2012-06-20 16:38:30 -070012907 //Save the Global VOSS context in adapter context for future.
12908 pHddCtx->pvosContext = pVosContext;
12909
12910 //Save the adapter context in global context for future.
12911 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
12912
Jeff Johnson295189b2012-06-20 16:38:30 -070012913 pHddCtx->parent_dev = dev;
Sreelakshmi Konamkif0646d52016-12-09 12:35:31 +053012914 pHddCtx->last_scan_reject_session_id = 0xFF;
12915 pHddCtx->last_scan_reject_reason = 0;
Sreelakshmi Konamki20ebed92016-10-27 12:13:30 +053012916 pHddCtx->last_scan_reject_timestamp = 0;
Abhishek Singhe4b12562017-06-20 16:53:39 +053012917 pHddCtx->scan_reject_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -070012918
12919 init_completion(&pHddCtx->full_pwr_comp_var);
12920 init_completion(&pHddCtx->standby_comp_var);
12921 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -070012922 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -080012923 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Kiet Lam46b8e4e2013-11-06 21:49:53 +053012924 init_completion(&pHddCtx->wiphy_channel_update_event);
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +053012925 init_completion(&pHddCtx->ssr_comp_var);
Mahesh A Saptasagar67ab9222015-10-21 15:38:41 +053012926 init_completion(&pHddCtx->mc_sus_event_var);
12927 init_completion(&pHddCtx->tx_sus_event_var);
12928 init_completion(&pHddCtx->rx_sus_event_var);
12929
Amar Singhala49cbc52013-10-08 18:37:44 -070012930
mukul sharma4bd8d2e2015-08-13 20:33:25 +053012931 hdd_init_ll_stats_ctx(pHddCtx);
Anurag Chouhan6ee81542017-02-09 18:09:27 +053012932 hdd_init_nud_stats_ctx(pHddCtx);
mukul sharma4bd8d2e2015-08-13 20:33:25 +053012933
Amar Singhala49cbc52013-10-08 18:37:44 -070012934#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhalfddc28c2013-09-05 13:03:40 -070012935 init_completion(&pHddCtx->linux_reg_req);
Amar Singhala49cbc52013-10-08 18:37:44 -070012936#else
12937 init_completion(&pHddCtx->driver_crda_req);
12938#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070012939
Padma, Santhosh Kumara1aa4a32015-06-19 19:00:46 +053012940#ifdef WLAN_FEATURE_EXTSCAN
12941 init_completion(&pHddCtx->ext_scan_context.response_event);
12942#endif /* WLAN_FEATURE_EXTSCAN */
12943
Kamath Vinayak4000c9a2013-08-23 14:24:27 +053012944 spin_lock_init(&pHddCtx->schedScan_lock);
Kapil Gupta137ef892016-12-13 19:38:00 +053012945 vos_spin_lock_init(&pHddCtx->sap_update_info_lock);
Kamath Vinayak4000c9a2013-08-23 14:24:27 +053012946
Jeff Johnson295189b2012-06-20 16:38:30 -070012947 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
12948
Padma, Santhosh Kumar9cd38332015-11-17 12:18:10 +053012949 vos_init_delayed_work(&pHddCtx->spoof_mac_addr_work,
12950 hdd_processSpoofMacAddrRequest);
Kapil Gupta137ef892016-12-13 19:38:00 +053012951 vos_init_work(&pHddCtx->sap_start_work, hdd_sap_restart_handle);
Abhishek Singh78c691f2017-11-30 13:48:44 +053012952 vos_init_delayed_work(&pHddCtx->ecsa_chan_change_work,
12953 hdd_force_scc_with_ecsa_handle);
Padma, Santhosh Kumar9cd38332015-11-17 12:18:10 +053012954
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +053012955#ifdef FEATURE_WLAN_TDLS
12956 /* tdls_lock is initialized before an hdd_open_adapter ( which is
12957 * invoked by other instances also) to protect the concurrent
12958 * access for the Adapters by TDLS module.
12959 */
12960 mutex_init(&pHddCtx->tdls_lock);
12961#endif
Siddharth Bhal76972212014-10-15 16:22:51 +053012962 mutex_init(&pHddCtx->spoofMacAddr.macSpoofingLock);
Mukul Sharma1fd6efd2015-02-14 00:29:14 +053012963 mutex_init(&pHddCtx->wmmLock);
12964
Srinivas Girigowda8bf64cb2015-09-30 19:50:09 +053012965 hdd_init_offloaded_packets_ctx(pHddCtx);
Agarwal Ashish1f422872014-07-22 00:11:55 +053012966 /* By default Strict Regulatory For FCC should be false */
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +053012967
Agarwal Ashish1f422872014-07-22 00:11:55 +053012968 pHddCtx->nEnableStrictRegulatoryForFCC = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -070012969 // Load all config first as TL config is needed during vos_open
12970 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
12971 if(pHddCtx->cfg_ini == NULL)
12972 {
12973 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
12974 goto err_free_hdd_context;
12975 }
12976
12977 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
12978
12979 // Read and parse the qcom_cfg.ini file
12980 status = hdd_parse_config_ini( pHddCtx );
12981 if ( VOS_STATUS_SUCCESS != status )
12982 {
12983 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
12984 __func__, WLAN_INI_FILE);
12985 goto err_config;
12986 }
Arif Hussaind5218912013-12-05 01:10:55 -080012987#ifdef MEMORY_DEBUG
12988 if (pHddCtx->cfg_ini->IsMemoryDebugSupportEnabled)
12989 vos_mem_init();
12990
12991 hddLog(VOS_TRACE_LEVEL_INFO, "%s: gEnableMemoryDebug=%d",
12992 __func__, pHddCtx->cfg_ini->IsMemoryDebugSupportEnabled);
12993#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070012994
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +053012995 /* INI has been read, initialise the configuredMcastBcastFilter with
12996 * INI value as this will serve as the default value
12997 */
12998 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
12999 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
13000 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +053013001
13002 if (false == hdd_is_5g_supported(pHddCtx))
13003 {
13004 //5Ghz is not supported.
13005 if (1 != pHddCtx->cfg_ini->nBandCapability)
13006 {
13007 hddLog(VOS_TRACE_LEVEL_INFO,
13008 "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__);
13009 pHddCtx->cfg_ini->nBandCapability = 1;
13010 }
13011 }
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +053013012
13013 /* If SNR Monitoring is enabled, FW has to parse all beacons
13014 * for calcaluting and storing the average SNR, so set Nth beacon
13015 * filter to 1 to enable FW to parse all the beaocons
13016 */
13017 if (1 == pHddCtx->cfg_ini->fEnableSNRMonitoring)
13018 {
13019 /* The log level is deliberately set to WARN as overriding
13020 * nthBeaconFilter to 1 will increase power cosumption and this
13021 * might just prove helpful to detect the power issue.
13022 */
13023 hddLog(VOS_TRACE_LEVEL_WARN,
13024 "%s: Setting pHddCtx->cfg_ini->nthBeaconFilter = 1", __func__);
13025 pHddCtx->cfg_ini->nthBeaconFilter = 1;
13026 }
Jeff Johnson295189b2012-06-20 16:38:30 -070013027 /*
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +053013028 * cfg80211: Initialization ...
Jeff Johnson295189b2012-06-20 16:38:30 -070013029 */
Manjeet Singh61016fa2016-12-02 11:10:19 +053013030 if (0 < wlan_hdd_cfg80211_init(dev, wiphy, pHddCtx->cfg_ini))
Jeff Johnson295189b2012-06-20 16:38:30 -070013031 {
Manjeet Singh61016fa2016-12-02 11:10:19 +053013032 hddLog(VOS_TRACE_LEVEL_FATAL,
13033 "%s: wlan_hdd_cfg80211_init return failure", __func__);
13034 goto err_config;
Jeff Johnson295189b2012-06-20 16:38:30 -070013035 }
Jeff Johnson295189b2012-06-20 16:38:30 -070013036
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -080013037 // Update VOS trace levels based upon the cfg.ini
13038 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
13039 pHddCtx->cfg_ini->vosTraceEnableBAP);
13040 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
13041 pHddCtx->cfg_ini->vosTraceEnableTL);
13042 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
13043 pHddCtx->cfg_ini->vosTraceEnableWDI);
13044 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
13045 pHddCtx->cfg_ini->vosTraceEnableHDD);
13046 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
13047 pHddCtx->cfg_ini->vosTraceEnableSME);
13048 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
13049 pHddCtx->cfg_ini->vosTraceEnablePE);
Katya Nigam70d68332013-09-16 16:49:45 +053013050 hdd_vos_trace_enable(VOS_MODULE_ID_PMC,
13051 pHddCtx->cfg_ini->vosTraceEnablePMC);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -080013052 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
13053 pHddCtx->cfg_ini->vosTraceEnableWDA);
13054 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
13055 pHddCtx->cfg_ini->vosTraceEnableSYS);
13056 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
13057 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -080013058 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
13059 pHddCtx->cfg_ini->vosTraceEnableSAP);
13060 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
13061 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -080013062
Jeff Johnson295189b2012-06-20 16:38:30 -070013063 // Update WDI trace levels based upon the cfg.ini
13064 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
13065 pHddCtx->cfg_ini->wdiTraceEnableDAL);
13066 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
13067 pHddCtx->cfg_ini->wdiTraceEnableCTL);
13068 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
13069 pHddCtx->cfg_ini->wdiTraceEnableDAT);
13070 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
13071 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -070013072
Jeff Johnson88ba7742013-02-27 14:36:02 -080013073 if (VOS_FTM_MODE == hdd_get_conparam())
13074 {
Jeff Johnson295189b2012-06-20 16:38:30 -070013075 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
13076 {
13077 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
13078 goto err_free_hdd_context;
13079 }
13080 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
Sachin Ahuja38ef5e02015-03-13 17:31:16 +053013081 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_NO_LOAD_UNLOAD_IN_PROGRESS;
c_hpothu2de0ef62014-04-15 16:16:15 +053013082 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -070013083 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -080013084 }
Jeff Johnson295189b2012-06-20 16:38:30 -070013085
Katya Nigame7b69a82015-04-28 15:24:06 +053013086 if( VOS_MONITOR_MODE == hdd_get_conparam())
13087 {
13088 if ( VOS_STATUS_SUCCESS != wlan_hdd_mon_open(pHddCtx))
13089 {
13090 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_mon_open Failed",__func__);
13091 goto err_free_hdd_context;
13092 }
13093 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Driver loaded in Monitor Mode",__func__);
13094 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_NO_LOAD_UNLOAD_IN_PROGRESS;
13095 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
13096 return VOS_STATUS_SUCCESS;
13097 }
13098
Jeff Johnson88ba7742013-02-27 14:36:02 -080013099 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -070013100 if(pHddCtx->cfg_ini->fIsLogpEnabled)
13101 {
13102 status = vos_watchdog_open(pVosContext,
13103 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
13104
13105 if(!VOS_IS_STATUS_SUCCESS( status ))
13106 {
13107 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Ashish Kumar Dhanotiya532bdef2017-05-09 17:31:59 +053013108 goto err_config;
Jeff Johnson295189b2012-06-20 16:38:30 -070013109 }
13110 }
13111
13112 pHddCtx->isLogpInProgress = FALSE;
13113 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
13114
Amar Singhala49cbc52013-10-08 18:37:44 -070013115#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -070013116 /* initialize the NV module. This is required so that
13117 we can initialize the channel information in wiphy
13118 from the NV.bin data. The channel information in
13119 wiphy needs to be initialized before wiphy registration */
13120
13121 status = vos_nv_open();
13122 if (!VOS_IS_STATUS_SUCCESS(status))
13123 {
13124 /* NV module cannot be initialized */
13125 hddLog( VOS_TRACE_LEVEL_FATAL,
13126 "%s: vos_nv_open failed", __func__);
Vinay Krishna Eranna2025d892014-09-18 16:51:42 +053013127 goto err_wdclose;
Amar Singhal0a402232013-10-11 20:57:16 -070013128 }
13129
13130 status = vos_init_wiphy_from_nv_bin();
13131 if (!VOS_IS_STATUS_SUCCESS(status))
13132 {
13133 /* NV module cannot be initialized */
13134 hddLog( VOS_TRACE_LEVEL_FATAL,
13135 "%s: vos_init_wiphy failed", __func__);
13136 goto err_vos_nv_close;
13137 }
13138
Amar Singhala49cbc52013-10-08 18:37:44 -070013139#endif
Mahesh A Saptasagarc3ed0122016-01-19 16:45:11 +053013140 //Initialize the nlink service
13141 if(nl_srv_init() != 0)
13142 {
13143 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
13144 goto err_vos_nv_close;
13145 }
13146
13147#ifdef WLAN_KD_READY_NOTIFIER
13148 pHddCtx->kd_nl_init = 1;
13149#endif /* WLAN_KD_READY_NOTIFIER */
13150
Girish Gowlibf0e1ab2015-01-19 16:05:16 +053013151 vos_set_roam_delay_stats_enabled(pHddCtx->cfg_ini->gEnableRoamDelayStats);
Arun Kumar Khandavalliebb19482014-03-25 13:56:53 +053013152 status = vos_open( &pVosContext, pHddCtx->parent_dev);
Jeff Johnson295189b2012-06-20 16:38:30 -070013153 if ( !VOS_IS_STATUS_SUCCESS( status ))
13154 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -080013155 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
Mahesh A Saptasagarc3ed0122016-01-19 16:45:11 +053013156 goto err_nl_srv;
Jeff Johnson295189b2012-06-20 16:38:30 -070013157 }
13158
Jeff Johnson295189b2012-06-20 16:38:30 -070013159 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
13160
13161 if ( NULL == pHddCtx->hHal )
13162 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -080013163 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -070013164 goto err_vosclose;
13165 }
13166
Jeff Johnsonbc676b42013-02-14 16:04:08 -080013167 status = vos_preStart( pHddCtx->pvosContext );
13168 if ( !VOS_IS_STATUS_SUCCESS( status ) )
13169 {
13170 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053013171 goto err_vosclose;
Jeff Johnsonbc676b42013-02-14 16:04:08 -080013172 }
Jeff Johnsone7245742012-09-05 17:12:55 -070013173
Arif Hussaineaf68602013-12-30 23:10:44 -080013174 if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan)
13175 {
13176 pHddCtx->cfg_ini->enableDFSChnlScan = enable_dfs_chan_scan;
13177 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_dfs_chan_scan set to %d",
13178 __func__, enable_dfs_chan_scan);
13179 }
13180 if (0 == enable_11d || 1 == enable_11d)
13181 {
13182 pHddCtx->cfg_ini->Is11dSupportEnabled = enable_11d;
13183 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_11d set to %d",
13184 __func__, enable_11d);
13185 }
13186
Jeff Johnsonbc676b42013-02-14 16:04:08 -080013187 /* Note that the vos_preStart() sequence triggers the cfg download.
13188 The cfg download must occur before we update the SME config
13189 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -070013190 status = hdd_set_sme_config( pHddCtx );
13191
13192 if ( VOS_STATUS_SUCCESS != status )
13193 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -080013194 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053013195 goto err_vosclose;
Jeff Johnsonbc676b42013-02-14 16:04:08 -080013196 }
Jeff Johnson295189b2012-06-20 16:38:30 -070013197
Jeff Johnson295189b2012-06-20 16:38:30 -070013198 /* In the integrated architecture we update the configuration from
13199 the INI file and from NV before vOSS has been started so that
13200 the final contents are available to send down to the cCPU */
13201
13202 // Apply the cfg.ini to cfg.dat
13203 if (FALSE == hdd_update_config_dat(pHddCtx))
13204 {
13205 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053013206 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -070013207 }
13208
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053013209 // Get mac addr from platform driver
13210 ret = wcnss_get_wlan_mac_address((char*)&mac_addr.bytes);
13211
13212 if ((0 == ret) && (!vos_is_macaddr_zero(&mac_addr)))
Jeff Johnson295189b2012-06-20 16:38:30 -070013213 {
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053013214 /* Store the mac addr for first interface */
13215 pHddCtx->cfg_ini->intfMacAddr[0] = mac_addr;
13216
13217 hddLog(VOS_TRACE_LEVEL_ERROR,
13218 "%s: WLAN Mac Addr: "
13219 MAC_ADDRESS_STR, __func__,
13220 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
13221
13222 /* Here, passing Arg2 as 1 because we do not want to change the
13223 last 3 bytes (means non OUI bytes) of first interface mac
13224 addr.
13225 */
13226 if (0 != hdd_generate_iface_mac_addr_auto(pHddCtx, 1, mac_addr))
13227 {
13228 hddLog(VOS_TRACE_LEVEL_ERROR,
13229 "%s: Failed to generate wlan interface mac addr "
13230 "using MAC from ini file ", __func__);
13231 }
13232 }
13233 else if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
13234 {
13235 // Apply the NV to cfg.dat
13236 /* Prima Update MAC address only at here */
Jeff Johnson295189b2012-06-20 16:38:30 -070013237#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
13238 /* There was not a valid set of MAC Addresses in NV. See if the
13239 default addresses were modified by the cfg.ini settings. If so,
13240 we'll use them, but if not, we'll autogenerate a set of MAC
13241 addresses based upon the device serial number */
13242
13243 static const v_MACADDR_t default_address =
13244 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
Jeff Johnson295189b2012-06-20 16:38:30 -070013245
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053013246 if (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
13247 sizeof(default_address)))
Jeff Johnson295189b2012-06-20 16:38:30 -070013248 {
13249 /* cfg.ini has the default address, invoke autogen logic */
13250
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053013251 /* Here, passing Arg2 as 0 because we want to change the
13252 last 3 bytes (means non OUI bytes) of all the interfaces
13253 mac addr.
13254 */
13255 if (0 != hdd_generate_iface_mac_addr_auto(pHddCtx, 0,
13256 default_address))
Jeff Johnson295189b2012-06-20 16:38:30 -070013257 {
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053013258 hddLog(VOS_TRACE_LEVEL_ERROR,
13259 "%s: Failed to generate wlan interface mac addr "
13260 "using MAC from ini file " MAC_ADDRESS_STR, __func__,
13261 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
Jeff Johnson295189b2012-06-20 16:38:30 -070013262 }
Jeff Johnson295189b2012-06-20 16:38:30 -070013263 }
13264 else
13265#endif //WLAN_AUTOGEN_MACADDR_FEATURE
13266 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -080013267 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -070013268 "%s: Invalid MAC address in NV, using MAC from ini file "
13269 MAC_ADDRESS_STR, __func__,
13270 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
13271 }
13272 }
13273 {
13274 eHalStatus halStatus;
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053013275
13276 /* Set the MAC Address Currently this is used by HAL to
13277 * add self sta. Remove this once self sta is added as
13278 * part of session open.
13279 */
Jeff Johnson295189b2012-06-20 16:38:30 -070013280 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
13281 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
13282 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053013283
Jeff Johnson295189b2012-06-20 16:38:30 -070013284 if (!HAL_STATUS_SUCCESS( halStatus ))
13285 {
13286 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
13287 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053013288 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -070013289 }
13290 }
Jeff Johnson295189b2012-06-20 16:38:30 -070013291
13292 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
13293 Note: Firmware image will be read and downloaded inside vos_start API */
13294 status = vos_start( pHddCtx->pvosContext );
13295 if ( !VOS_IS_STATUS_SUCCESS( status ) )
13296 {
13297 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
Hanumantha Reddy Pothulabd9601a2016-02-12 13:22:27 +053013298 if (isSsrPanicOnFailure())
13299 VOS_BUG(0);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053013300 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -070013301 }
13302
Leo Chang6cec3e22014-01-21 15:33:49 -080013303#ifdef FEATURE_WLAN_CH_AVOID
13304 /* Plug in avoid channel notification callback
13305 * This should happen before ADD_SELF_STA
13306 * FW will send first IND with ADD_SELF_STA REQ from host */
Pradeep Reddy POTTETI5c2e16d2014-06-27 16:47:38 +053013307
13308 /* check the Channel Avoidance is enabled */
13309 if (TRUE == pHddCtx->cfg_ini->fenableCHAvoidance)
13310 {
13311 sme_AddChAvoidCallback(pHddCtx->hHal,
13312 hdd_hostapd_ch_avoid_cb);
13313 }
Leo Chang6cec3e22014-01-21 15:33:49 -080013314#endif /* FEATURE_WLAN_CH_AVOID */
13315
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070013316 /* Exchange capability info between Host and FW and also get versioning info from FW */
13317 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -070013318
Agarwal Ashishad9281b2014-06-10 14:57:30 +053013319#ifdef CONFIG_ENABLE_LINUX_REG
13320 status = wlan_hdd_init_channels(pHddCtx);
13321 if ( !VOS_IS_STATUS_SUCCESS( status ) )
13322 {
13323 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: wlan_hdd_init_channels failed",
13324 __func__);
13325 goto err_vosstop;
13326 }
13327#endif
13328
Jeff Johnson295189b2012-06-20 16:38:30 -070013329 status = hdd_post_voss_start_config( pHddCtx );
13330 if ( !VOS_IS_STATUS_SUCCESS( status ) )
13331 {
13332 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
13333 __func__);
13334 goto err_vosstop;
13335 }
Amar Singhala49cbc52013-10-08 18:37:44 -070013336
13337#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +053013338 wlan_hdd_cfg80211_update_reg_info( wiphy );
13339
13340 /* registration of wiphy dev with cfg80211 */
13341 if (0 > wlan_hdd_cfg80211_register(wiphy))
13342 {
13343 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
13344 goto err_vosstop;
13345 }
Amar Singhala49cbc52013-10-08 18:37:44 -070013346#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070013347
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053013348#ifdef CONFIG_ENABLE_LINUX_REG
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053013349 /* registration of wiphy dev with cfg80211 */
13350 if (0 > wlan_hdd_cfg80211_register(wiphy))
13351 {
13352 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
13353 goto err_vosstop;
13354 }
13355
Agarwal Ashish6db9d532014-09-30 18:19:10 +053013356 status = wlan_hdd_init_channels_for_cc(pHddCtx, INIT);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053013357 if ( !VOS_IS_STATUS_SUCCESS( status ) )
13358 {
13359 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: wlan_hdd_init_channels_for_cc failed",
13360 __func__);
13361 goto err_unregister_wiphy;
13362 }
13363#endif
13364
c_hpothu4a298be2014-12-22 21:12:51 +053013365 wcnss_wlan_set_drvdata(pHddCtx->parent_dev, pHddCtx);
13366
Jeff Johnson295189b2012-06-20 16:38:30 -070013367 if (VOS_STA_SAP_MODE == hdd_get_conparam())
13368 {
13369 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
13370 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
13371 }
13372 else
13373 {
Jeff Johnson295189b2012-06-20 16:38:30 -070013374 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
13375 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
13376 if (pAdapter != NULL)
13377 {
Katya Nigama7d81d72014-11-12 12:44:34 +053013378 if (pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated && !(pHddCtx->cfg_ini->intfMacAddr[0].bytes[0] & 0x02))
Jeff Johnson295189b2012-06-20 16:38:30 -070013379 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +053013380 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
13381 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
13382 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -070013383
Gopichand Nakkala49f96f62013-02-06 14:38:17 +053013384 /* Generate the P2P Device Address. This consists of the device's
13385 * primary MAC address with the locally administered bit set.
13386 */
13387 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -070013388 }
13389 else
13390 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +053013391 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
13392 if (p2p_dev_addr != NULL)
13393 {
13394 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
13395 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
13396 }
13397 else
13398 {
13399 hddLog(VOS_TRACE_LEVEL_FATAL,
13400 "%s: Failed to allocate mac_address for p2p_device",
13401 __func__);
13402 goto err_close_adapter;
13403 }
Jeff Johnson295189b2012-06-20 16:38:30 -070013404 }
Jeff Johnsone7245742012-09-05 17:12:55 -070013405
13406 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
13407 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
13408 if ( NULL == pP2pAdapter )
13409 {
13410 hddLog(VOS_TRACE_LEVEL_FATAL,
13411 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070013412 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -070013413 goto err_close_adapter;
13414 }
Jeff Johnsone7245742012-09-05 17:12:55 -070013415 }
Jeff Johnson295189b2012-06-20 16:38:30 -070013416 }
Jeff Johnson295189b2012-06-20 16:38:30 -070013417
13418 if( pAdapter == NULL )
13419 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -080013420 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
13421 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -070013422 }
Jeff Johnsone7245742012-09-05 17:12:55 -070013423
Arif Hussain66559122013-11-21 10:11:40 -080013424 if (country_code)
13425 {
13426 eHalStatus ret;
Arif Hussaincb607082013-12-20 11:57:42 -080013427 INIT_COMPLETION(pAdapter->change_country_code);
Arif Hussain66559122013-11-21 10:11:40 -080013428 hdd_checkandupdate_dfssetting(pAdapter, country_code);
13429#ifndef CONFIG_ENABLE_LINUX_REG
13430 hdd_checkandupdate_phymode(pAdapter, country_code);
13431#endif
Arif Hussaineaf68602013-12-30 23:10:44 -080013432 ret = sme_ChangeCountryCode(pHddCtx->hHal,
13433 (void *)(tSmeChangeCountryCallback)
13434 wlan_hdd_change_country_code_callback,
Arif Hussain66559122013-11-21 10:11:40 -080013435 country_code,
13436 pAdapter, pHddCtx->pvosContext,
Abhishek Singha306a442013-11-07 18:39:01 +053013437 eSIR_TRUE, eSIR_TRUE);
Arif Hussain66559122013-11-21 10:11:40 -080013438 if (eHAL_STATUS_SUCCESS == ret)
13439 {
Arif Hussaincb607082013-12-20 11:57:42 -080013440 ret = wait_for_completion_interruptible_timeout(
13441 &pAdapter->change_country_code,
13442 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
13443
13444 if (0 >= ret)
13445 {
13446 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
13447 "%s: SME while setting country code timed out", __func__);
13448 }
Arif Hussain66559122013-11-21 10:11:40 -080013449 }
13450 else
13451 {
Arif Hussaincb607082013-12-20 11:57:42 -080013452 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
13453 "%s: SME Change Country code from module param fail ret=%d",
13454 __func__, ret);
Arif Hussain66559122013-11-21 10:11:40 -080013455 }
13456 }
13457
Jeff Johnson295189b2012-06-20 16:38:30 -070013458#ifdef WLAN_BTAMP_FEATURE
13459 vStatus = WLANBAP_Open(pVosContext);
13460 if(!VOS_IS_STATUS_SUCCESS(vStatus))
13461 {
13462 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
13463 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -070013464 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -070013465 }
13466
13467 vStatus = BSL_Init(pVosContext);
13468 if(!VOS_IS_STATUS_SUCCESS(vStatus))
13469 {
13470 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
13471 "%s: Failed to Init BSL",__func__);
13472 goto err_bap_close;
13473 }
13474 vStatus = WLANBAP_Start(pVosContext);
13475 if (!VOS_IS_STATUS_SUCCESS(vStatus))
13476 {
13477 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
13478 "%s: Failed to start TL",__func__);
13479 goto err_bap_close;
13480 }
13481
13482 pConfig = pHddCtx->cfg_ini;
13483 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
13484 status = WLANBAP_SetConfig(&btAmpConfig);
13485
13486#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -070013487
Mihir Shete9c238772014-10-15 14:35:16 +053013488 /*
13489 * UapsdMask is 0xf if U-APSD is enbaled for all AC's...
13490 * The value of CFG_QOS_WMM_UAPSD_MASK_DEFAULT is 0xaa(Magic Value)
13491 * which is greater than 0xf. So the below check is safe to make
13492 * sure that there is no entry for UapsdMask in the ini
13493 */
13494 if (CFG_QOS_WMM_UAPSD_MASK_DEFAULT == pHddCtx->cfg_ini->UapsdMask)
13495 {
13496 if(IS_DYNAMIC_WMM_PS_ENABLED)
13497 {
13498 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: Enable UAPSD for VI & VO",
13499 __func__);
13500 pHddCtx->cfg_ini->UapsdMask =
13501 CFG_QOS_WMM_UAPSD_MASK_DYMANIC_WMM_PS_DEFAULT;
13502 }
13503 else
13504 {
13505 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: Do not enable UAPSD",
13506 __func__);
13507 pHddCtx->cfg_ini->UapsdMask =
13508 CFG_QOS_WMM_UAPSD_MASK_LEGACY_WMM_PS_DEFAULT;
13509 }
13510 }
13511
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -070013512#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
13513 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
13514 {
13515 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
13516 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
13517 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
13518 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
13519 }
13520#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070013521
Agarwal Ashish4b87f922014-06-18 03:03:21 +053013522 wlan_hdd_tdls_init(pHddCtx);
13523
Masti, Narayanraddi26378462016-01-05 18:20:28 +053013524 wlan_hdd_init_deinit_defer_scan_context(&pHddCtx->scan_ctxt);
13525
13526 vos_init_delayed_work(&pHddCtx->scan_ctxt.scan_work,
13527 wlan_hdd_schedule_defer_scan);
13528
Mihir Shetefc7ff5b2014-01-27 11:30:05 +053013529 sme_Register11dScanDoneCallback(pHddCtx->hHal, hdd_11d_scan_done);
13530
Jeff Johnson295189b2012-06-20 16:38:30 -070013531 /* Register with platform driver as client for Suspend/Resume */
13532 status = hddRegisterPmOps(pHddCtx);
13533 if ( !VOS_IS_STATUS_SUCCESS( status ) )
13534 {
13535 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
13536#ifdef WLAN_BTAMP_FEATURE
13537 goto err_bap_stop;
13538#else
Jeff Johnsone7245742012-09-05 17:12:55 -070013539 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -070013540#endif //WLAN_BTAMP_FEATURE
13541 }
13542
Yue Ma0d4891e2013-08-06 17:01:45 -070013543 /* Open debugfs interface */
13544 if (VOS_STATUS_SUCCESS != hdd_debugfs_init(pAdapter))
13545 {
13546 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
13547 "%s: hdd_debugfs_init failed!", __func__);
Yue Ma0d4891e2013-08-06 17:01:45 -070013548 }
13549
Jeff Johnson295189b2012-06-20 16:38:30 -070013550 /* Register TM level change handler function to the platform */
13551 status = hddDevTmRegisterNotifyCallback(pHddCtx);
13552 if ( !VOS_IS_STATUS_SUCCESS( status ) )
13553 {
13554 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
13555 goto err_unregister_pmops;
13556 }
Jeff Johnson295189b2012-06-20 16:38:30 -070013557
Jeff Johnson295189b2012-06-20 16:38:30 -070013558 // register net device notifier for device change notification
13559 ret = register_netdevice_notifier(&hdd_netdev_notifier);
13560
13561 if(ret < 0)
13562 {
13563 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
Siddharth Bhalcd92b782015-06-29 12:25:40 +053013564 goto err_unregister_pmops;
Jeff Johnson295189b2012-06-20 16:38:30 -070013565 }
13566
Jeff Johnson295189b2012-06-20 16:38:30 -070013567 //Initialize the BTC service
13568 if(btc_activate_service(pHddCtx) != 0)
13569 {
13570 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
Mahesh A Saptasagarc3ed0122016-01-19 16:45:11 +053013571 goto err_reg_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -070013572 }
13573
Padma, Santhosh Kumar2762e9d2015-10-20 15:02:57 +053013574#ifdef FEATURE_OEM_DATA_SUPPORT
13575 //Initialize the OEM service
13576 if (oem_activate_service(pHddCtx) != 0)
13577 {
13578 hddLog(VOS_TRACE_LEVEL_FATAL,
13579 "%s: oem_activate_service failed", __func__);
Hanumanth Reddy Pothula13789c42017-09-12 15:18:13 +053013580 goto err_btc_activate_service;
Padma, Santhosh Kumar2762e9d2015-10-20 15:02:57 +053013581 }
13582#endif
13583
Jeff Johnson295189b2012-06-20 16:38:30 -070013584#ifdef PTT_SOCK_SVC_ENABLE
13585 //Initialize the PTT service
13586 if(ptt_sock_activate_svc(pHddCtx) != 0)
13587 {
13588 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
Hanumanth Reddy Pothula13789c42017-09-12 15:18:13 +053013589 goto err_oem_activate_service;
Jeff Johnson295189b2012-06-20 16:38:30 -070013590 }
13591#endif
13592
Abhishek Singh00b71972016-01-07 10:51:04 +053013593#ifdef WLAN_FEATURE_RMC
13594 if (hdd_open_cesium_nl_sock() < 0)
13595 {
13596 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_open_cesium_nl_sock failed", __func__);
Hanumanth Reddy Pothula13789c42017-09-12 15:18:13 +053013597 goto err_ptt_sock_activate_svc;
Abhishek Singh00b71972016-01-07 10:51:04 +053013598 }
13599#endif
13600
Vinay Krishna Erannad938c422014-03-10 17:14:21 +053013601#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
13602 if(pHddCtx->cfg_ini && pHddCtx->cfg_ini->wlanLoggingEnable)
13603 {
Deepthi Gowri78083a32014-11-04 12:55:51 +053013604 if(wlan_logging_sock_activate_svc(
13605 pHddCtx->cfg_ini->wlanLoggingFEToConsole,
Sushant Kaushik33200572015-08-05 16:46:20 +053013606 pHddCtx->cfg_ini->wlanLoggingNumBuf,
13607 pHddCtx->cfg_ini->wlanPerPktStatsLogEnable,
13608 pHddCtx->cfg_ini->wlanPerPktStatsNumBuf))
Deepthi Gowri78083a32014-11-04 12:55:51 +053013609 {
13610 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wlan_logging_sock_activate_svc"
13611 " failed", __func__);
Hanumanth Reddy Pothula13789c42017-09-12 15:18:13 +053013612 goto err_open_cesium_nl_sock;
Deepthi Gowri78083a32014-11-04 12:55:51 +053013613 }
13614 //TODO: To Remove enableDhcpDebug and use gEnableDebugLog for
13615 //EAPOL and DHCP
Sachin Ahuja8c65f382014-12-12 15:34:21 +053013616 if (!pHddCtx->cfg_ini->gEnableDebugLog)
13617 pHddCtx->cfg_ini->gEnableDebugLog =
Sushant Kaushik6e4e2bc2015-10-05 17:23:07 +053013618 VOS_PKT_PROTO_TYPE_EAPOL | VOS_PKT_PROTO_TYPE_DHCP |
13619 VOS_PKT_PROTO_TYPE_ARP;
Vinay Krishna Erannad938c422014-03-10 17:14:21 +053013620 }
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053013621
Siddharth Bhald1be97f2015-05-27 22:39:59 +053013622 if (pHddCtx->cfg_ini->wlanLoggingEnable &&
13623 (pHddCtx->cfg_ini->enableFWLogging ||
Siddharth Bhaldb963232015-06-25 19:34:35 +053013624 pHddCtx->cfg_ini->enableMgmtLogging ||
c_manjeecfd1efb2015-09-25 19:32:34 +053013625 pHddCtx->cfg_ini->enableContFWLogging ||
13626 pHddCtx->cfg_ini->enableFwrMemDump )
13627 )
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053013628 {
Siddharth Bhald1be97f2015-05-27 22:39:59 +053013629 hdd_init_frame_logging(pHddCtx);
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053013630 }
13631 else
13632 {
Siddharth Bhald1be97f2015-05-27 22:39:59 +053013633 hddLog(VOS_TRACE_LEVEL_INFO, FL("Logging disabled in ini"));
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053013634 }
13635
Vinay Krishna Erannad938c422014-03-10 17:14:21 +053013636#endif
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053013637
Agrawal Ashish17ef5082016-10-17 18:33:21 +053013638#ifdef SAP_AUTH_OFFLOAD
13639 if (!sme_IsFeatureSupportedByFW(SAP_OFFLOADS))
13640 {
13641 hddLog(VOS_TRACE_LEVEL_INFO, FL(" SAP AUTH OFFLOAD not supp by FW"));
13642 pHddCtx->cfg_ini->enable_sap_auth_offload = 0;
13643 }
13644#endif
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053013645
Sushant Kaushik215778f2015-05-21 14:05:36 +053013646 if (vos_is_multicast_logging())
13647 wlan_logging_set_log_level();
13648
Jeff Johnson295189b2012-06-20 16:38:30 -070013649 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -070013650 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -070013651 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -070013652 /* Action frame registered in one adapter which will
13653 * applicable to all interfaces
13654 */
Agarwal Ashish8fa0e9a2014-05-23 00:40:12 +053013655 wlan_hdd_cfg80211_register_frames(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -070013656 }
Jeff Johnson295189b2012-06-20 16:38:30 -070013657
13658 mutex_init(&pHddCtx->sap_lock);
Mahesh A Saptasagar60627942014-10-13 13:55:14 +053013659 mutex_init(&pHddCtx->roc_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070013660
Jeff Johnsone7245742012-09-05 17:12:55 -070013661#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
13662 /* Initialize the wake lcok */
Sushant Kaushik83392fa2015-05-05 17:44:40 +053013663 vos_wake_lock_init(&pHddCtx->rx_wake_lock,
Jeff Johnsone7245742012-09-05 17:12:55 -070013664 "qcom_rx_wakelock");
Sushant Kaushik83392fa2015-05-05 17:44:40 +053013665
Jeff Johnsone7245742012-09-05 17:12:55 -070013666#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -080013667 /* Initialize the wake lcok */
Sushant Kaushik83392fa2015-05-05 17:44:40 +053013668 vos_wake_lock_init(&pHddCtx->sap_wake_lock,
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -080013669 "qcom_sap_wakelock");
Sushant Kaushik83392fa2015-05-05 17:44:40 +053013670
Jeff Johnsone7245742012-09-05 17:12:55 -070013671
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -070013672 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
13673 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -070013674
Katya Nigam5c306ea2014-06-19 15:39:54 +053013675 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_NO_LOAD_UNLOAD_IN_PROGRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -070013676 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
Sushant Kaushik83392fa2015-05-05 17:44:40 +053013677 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_INIT);
Katya Nigam5c306ea2014-06-19 15:39:54 +053013678
13679#ifdef FEATURE_WLAN_SCAN_PNO
13680 /*SME must send channel update configuration to RIVA*/
13681 sme_UpdateChannelConfig(pHddCtx->hHal);
13682#endif
Abhishek Singhf644b272014-08-21 02:59:39 +053013683 /* Send the update default channel list to the FW*/
13684 sme_UpdateChannelList(pHddCtx->hHal);
Mukul Sharma45063942015-04-01 20:07:59 +053013685
13686 /* Fwr capabilities received, Set the Dot11 mode */
Abhishek Singh41ebce12016-02-03 10:43:21 +053013687 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter),
13688 hdd_cfg_xlate_to_csr_phy_mode(pHddCtx->cfg_ini->dot11Mode));
Mukul Sharma45063942015-04-01 20:07:59 +053013689 sme_SetDefDot11Mode(pHddCtx->hHal);
13690
Abhishek Singha306a442013-11-07 18:39:01 +053013691#ifndef CONFIG_ENABLE_LINUX_REG
13692 /*updating wiphy so that regulatory user hints can be processed*/
13693 if (wiphy)
13694 {
13695 regulatory_hint(wiphy, "00");
13696 }
13697#endif
Jeff Johnsone7245742012-09-05 17:12:55 -070013698 // Initialize the restart logic
13699 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +053013700
Hanumanth Reddy Pothula146bca42016-11-08 12:01:07 +053013701 if (pHddCtx->cfg_ini->fIsLogpEnabled) {
13702 vos_wdthread_init_timer_work(vos_process_wd_timer);
13703 /* Initialize the timer to detect thread stuck issues */
13704 vos_thread_stuck_timer_init(
13705 &((VosContextType*)pVosContext)->vosWatchdog);
13706 }
13707
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -070013708 //Register the traffic monitor timer now
13709 if ( pHddCtx->cfg_ini->dynSplitscan)
13710 {
13711 vos_timer_init(&pHddCtx->tx_rx_trafficTmr,
13712 VOS_TIMER_TYPE_SW,
13713 hdd_tx_rx_pkt_cnt_stat_timer_handler,
13714 (void *)pHddCtx);
13715 }
Srinivas Dasari030bad32015-02-18 23:23:54 +053013716 wlan_hdd_cfg80211_nan_init(pHddCtx);
13717
Bhargav Shahd0715912015-10-01 18:17:37 +053013718 mutex_init(&pHddCtx->cur_rx_level_lock);
13719 vos_timer_init(&pHddCtx->delack_timer, VOS_TIMER_TYPE_SW,
13720 hdd_tcp_delack_compute_function,(void *)pHddCtx);
Masti, Narayanraddi44b0db02015-12-22 11:54:35 +053013721 vos_timer_init(&pHddCtx->tdls_source_timer, VOS_TIMER_TYPE_SW,
13722 wlan_hdd_change_tdls_mode, (void *)pHddCtx);
Bhargav Shahd0715912015-10-01 18:17:37 +053013723
Dino Mycle6fb96c12014-06-10 11:52:40 +053013724#ifdef WLAN_FEATURE_EXTSCAN
13725 sme_EXTScanRegisterCallback(pHddCtx->hHal,
13726 wlan_hdd_cfg80211_extscan_callback,
13727 pHddCtx);
13728#endif /* WLAN_FEATURE_EXTSCAN */
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053013729
Padma, Santhosh Kumar2ccac212015-10-20 17:27:27 +053013730#ifdef FEATURE_OEM_DATA_SUPPORT
13731 sme_OemDataRegisterCallback(pHddCtx->hHal,
13732 wlan_hdd_cfg80211_oemdata_callback,
13733 pHddCtx);
13734#endif /* FEATURE_OEM_DATA_SUPPORT */
13735
Gupta, Kapil7c34b322015-09-30 13:12:35 +053013736 sme_set_rssi_threshold_breached_cb(pHddCtx->hHal, hdd_rssi_threshold_breached_cb);
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053013737#ifdef WLAN_NS_OFFLOAD
13738 // Register IPv6 notifier to notify if any change in IP
13739 // So that we can reconfigure the offload parameters
13740 pHddCtx->ipv6_notifier.notifier_call = wlan_hdd_ipv6_changed;
13741 ret = register_inet6addr_notifier(&pHddCtx->ipv6_notifier);
13742 if (ret)
13743 {
Ratheesh S P36dbc932015-08-07 14:28:57 +053013744 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Failed to register IPv6 notifier"));
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053013745 }
13746 else
13747 {
Ratheesh S P36dbc932015-08-07 14:28:57 +053013748 hddLog(VOS_TRACE_LEVEL_INFO, FL("Registered IPv6 notifier"));
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053013749 }
13750#endif
13751
Sravan Kumar Kairamb0edc612016-10-26 13:55:24 +053013752 vos_mem_set((uint8_t *)&pHddCtx->bad_sta, HDD_MAX_STA_COUNT, 0);
13753
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053013754 // Register IPv4 notifier to notify if any change in IP
13755 // So that we can reconfigure the offload parameters
13756 pHddCtx->ipv4_notifier.notifier_call = wlan_hdd_ipv4_changed;
13757 ret = register_inetaddr_notifier(&pHddCtx->ipv4_notifier);
13758 if (ret)
13759 {
Ratheesh S P36dbc932015-08-07 14:28:57 +053013760 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Failed to register IPv4 notifier"));
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053013761 }
13762 else
13763 {
Ratheesh S P36dbc932015-08-07 14:28:57 +053013764 hddLog(VOS_TRACE_LEVEL_INFO, FL("Registered IPv4 notifier"));
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053013765 }
c_manjeecfd1efb2015-09-25 19:32:34 +053013766 /*Fw mem dump procfs initialization*/
13767 memdump_init();
Bhargav shah23c94942015-10-13 12:48:35 +053013768 hdd_dp_util_send_rps_ind(pHddCtx);
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053013769
Nishank Aggarwalc11826c2016-12-15 18:54:10 +053013770 pHddCtx->is_ap_mode_wow_supported =
13771 sme_IsFeatureSupportedByFW(SAP_MODE_WOW);
Sravan Kumar Kairam091e5b62017-01-23 14:14:20 +053013772
Hanumanth Reddy Pothulae92bcc12017-05-19 13:56:35 +053013773 pHddCtx->is_fatal_event_log_sup =
13774 sme_IsFeatureSupportedByFW(FATAL_EVENT_LOGGING);
13775 hddLog(VOS_TRACE_LEVEL_INFO, FL("FATAL_EVENT_LOGGING: %d"),
13776 pHddCtx->is_fatal_event_log_sup);
13777
Sravan Kumar Kairam091e5b62017-01-23 14:14:20 +053013778 hdd_assoc_registerFwdEapolCB(pVosContext);
13779
Ashish Kumar Dhanotiya32d092b2018-02-20 21:43:57 +053013780 mutex_init(&pHddCtx->cache_channel_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070013781 goto success;
13782
Hanumanth Reddy Pothula13789c42017-09-12 15:18:13 +053013783err_open_cesium_nl_sock:
13784#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
13785 hdd_close_cesium_nl_sock();
13786#endif
13787
13788err_ptt_sock_activate_svc:
13789#ifdef PTT_SOCK_SVC_ENABLE
13790 ptt_sock_deactivate_svc(pHddCtx);
13791#endif
13792
13793err_oem_activate_service:
13794#ifdef FEATURE_OEM_DATA_SUPPORT
13795 oem_deactivate_service();
13796#endif
13797
13798err_btc_activate_service:
13799 btc_deactivate_service();
13800
Jeff Johnson295189b2012-06-20 16:38:30 -070013801err_reg_netdev:
13802 unregister_netdevice_notifier(&hdd_netdev_notifier);
13803
Jeff Johnson295189b2012-06-20 16:38:30 -070013804err_unregister_pmops:
13805 hddDevTmUnregisterNotifyCallback(pHddCtx);
13806 hddDeregisterPmOps(pHddCtx);
13807
Yue Ma0d4891e2013-08-06 17:01:45 -070013808 hdd_debugfs_exit(pHddCtx);
13809
Jeff Johnson295189b2012-06-20 16:38:30 -070013810#ifdef WLAN_BTAMP_FEATURE
13811err_bap_stop:
13812 WLANBAP_Stop(pVosContext);
13813#endif
13814
13815#ifdef WLAN_BTAMP_FEATURE
13816err_bap_close:
13817 WLANBAP_Close(pVosContext);
13818#endif
13819
Jeff Johnson295189b2012-06-20 16:38:30 -070013820err_close_adapter:
13821 hdd_close_all_adapters( pHddCtx );
Mahesh A Saptasagar9ecefe42014-07-15 18:43:49 +053013822#ifdef CONFIG_ENABLE_LINUX_REG
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053013823err_unregister_wiphy:
Mahesh A Saptasagar9ecefe42014-07-15 18:43:49 +053013824#endif
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +053013825 wiphy_unregister(wiphy) ;
Agrawal Ashish33ec71e2015-11-26 20:20:58 +053013826 hdd_wlan_free_wiphy_channels(wiphy);
13827
Jeff Johnson295189b2012-06-20 16:38:30 -070013828err_vosstop:
13829 vos_stop(pVosContext);
13830
Amar Singhala49cbc52013-10-08 18:37:44 -070013831err_vosclose:
Jeff Johnson295189b2012-06-20 16:38:30 -070013832 status = vos_sched_close( pVosContext );
13833 if (!VOS_IS_STATUS_SUCCESS(status)) {
13834 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
13835 "%s: Failed to close VOSS Scheduler", __func__);
13836 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
13837 }
Amar Singhala49cbc52013-10-08 18:37:44 -070013838 vos_close(pVosContext );
13839
Mahesh A Saptasagarc3ed0122016-01-19 16:45:11 +053013840err_nl_srv:
13841#ifdef WLAN_KD_READY_NOTIFIER
13842 nl_srv_exit(pHddCtx->ptt_pid);
13843#else
13844 nl_srv_exit();
13845#endif /* WLAN_KD_READY_NOTIFIER */
Amar Singhal0a402232013-10-11 20:57:16 -070013846err_vos_nv_close:
13847
c_hpothue6a36282014-03-19 12:27:38 +053013848#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -070013849 vos_nv_close();
13850
c_hpothu70f8d812014-03-22 22:59:23 +053013851#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070013852
13853err_wdclose:
13854 if(pHddCtx->cfg_ini->fIsLogpEnabled)
13855 vos_watchdog_close(pVosContext);
13856
Jeff Johnson295189b2012-06-20 16:38:30 -070013857err_config:
13858 kfree(pHddCtx->cfg_ini);
13859 pHddCtx->cfg_ini= NULL;
13860
13861err_free_hdd_context:
Sushant Kaushik83392fa2015-05-05 17:44:40 +053013862 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_INIT);
Siddharth Bhalcd92b782015-06-29 12:25:40 +053013863 free_riva_power_on_lock("wlan");
Jeff Johnson295189b2012-06-20 16:38:30 -070013864 wiphy_free(wiphy) ;
13865 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -070013866 VOS_BUG(1);
13867
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -080013868 if (hdd_is_ssr_required())
13869 {
13870 /* WDI timeout had happened during load, so SSR is needed here */
13871 subsystem_restart("wcnss");
13872 msleep(5000);
13873 }
13874 hdd_set_ssr_required (VOS_FALSE);
13875
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -080013876 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -070013877
13878success:
13879 EXIT();
13880 return 0;
13881}
13882
13883/**---------------------------------------------------------------------------
13884
Jeff Johnson32d95a32012-09-10 13:15:23 -070013885 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -070013886
Jeff Johnson32d95a32012-09-10 13:15:23 -070013887 This is the driver entry point - called in different timeline depending
13888 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -070013889
13890 \param - None
13891
13892 \return - 0 for success, non zero for failure
13893
13894 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -070013895static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -070013896{
13897 VOS_STATUS status;
13898 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -070013899 struct device *dev = NULL;
13900 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -070013901#ifdef HAVE_WCNSS_CAL_DOWNLOAD
13902 int max_retries = 0;
13903#endif
Siddharth Bhalc7e79b62014-10-10 22:37:38 +053013904#ifdef HAVE_CBC_DONE
13905 int max_cbc_retries = 0;
13906#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070013907
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +053013908#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
13909 wlan_logging_sock_init_svc();
13910#endif
13911
Jeff Johnson295189b2012-06-20 16:38:30 -070013912 ENTER();
13913
Sushant Kaushik83392fa2015-05-05 17:44:40 +053013914 vos_wake_lock_init(&wlan_wake_lock, "wlan");
Jeff Johnson295189b2012-06-20 16:38:30 -070013915
13916 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
13917 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
13918
Jeff Johnson295189b2012-06-20 16:38:30 -070013919#ifdef ANI_BUS_TYPE_PCI
13920
13921 dev = wcnss_wlan_get_device();
13922
13923#endif // ANI_BUS_TYPE_PCI
13924
13925#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -070013926
13927#ifdef HAVE_WCNSS_CAL_DOWNLOAD
13928 /* wait until WCNSS driver downloads NV */
Ravi Kumar Bokka7a139e62016-11-17 21:32:55 +053013929 while (!wcnss_device_ready() && 10 >= ++max_retries) {
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -070013930 msleep(1000);
13931 }
Siddharth Bhalc7e79b62014-10-10 22:37:38 +053013932
Ravi Kumar Bokka7a139e62016-11-17 21:32:55 +053013933 if (max_retries >= 10) {
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -070013934 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
Sushant Kaushik83392fa2015-05-05 17:44:40 +053013935 vos_wake_lock_destroy(&wlan_wake_lock);
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +053013936#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
13937 wlan_logging_sock_deinit_svc();
13938#endif
13939
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -070013940 return -ENODEV;
13941 }
13942#endif
13943
Siddharth Bhalc7e79b62014-10-10 22:37:38 +053013944#ifdef HAVE_CBC_DONE
13945 while (!wcnss_cbc_complete() && 10 >= ++max_cbc_retries) {
13946 msleep(1000);
13947 }
13948 if (max_cbc_retries >= 10) {
13949 hddLog(VOS_TRACE_LEVEL_FATAL, "%s:CBC not completed", __func__);
13950 }
13951#endif
13952
Jeff Johnson295189b2012-06-20 16:38:30 -070013953 dev = wcnss_wlan_get_device();
13954#endif // ANI_BUS_TYPE_PLATFORM
13955
13956
13957 do {
13958 if (NULL == dev) {
13959 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
13960 ret_status = -1;
13961 break;
13962 }
13963
Jeff Johnson295189b2012-06-20 16:38:30 -070013964#ifdef TIMER_MANAGER
13965 vos_timer_manager_init();
13966#endif
13967
13968 /* Preopen VOSS so that it is ready to start at least SAL */
13969 status = vos_preOpen(&pVosContext);
13970
13971 if (!VOS_IS_STATUS_SUCCESS(status))
13972 {
13973 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
13974 ret_status = -1;
13975 break;
13976 }
13977
Sushant Kaushik02beb352015-06-04 15:15:01 +053013978 hddTraceInit();
Padma, Santhosh Kumar9093b202015-07-21 15:37:38 +053013979 hdd_register_debug_callback();
13980
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070013981#ifndef MODULE
13982 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
13983 */
13984 hdd_set_conparam((v_UINT_t)con_mode);
13985#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070013986
13987 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -080013988 if (hdd_wlan_startup(dev))
13989 {
Jeff Johnson295189b2012-06-20 16:38:30 -070013990 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -080013991 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -070013992 vos_preClose( &pVosContext );
13993 ret_status = -1;
13994 break;
13995 }
13996
Jeff Johnson295189b2012-06-20 16:38:30 -070013997 } while (0);
13998
13999 if (0 != ret_status)
14000 {
Jeff Johnson295189b2012-06-20 16:38:30 -070014001#ifdef TIMER_MANAGER
14002 vos_timer_exit();
14003#endif
14004#ifdef MEMORY_DEBUG
14005 vos_mem_exit();
14006#endif
Sushant Kaushik83392fa2015-05-05 17:44:40 +053014007 vos_wake_lock_destroy(&wlan_wake_lock);
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +053014008#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
14009 wlan_logging_sock_deinit_svc();
14010#endif
14011
Jeff Johnson295189b2012-06-20 16:38:30 -070014012 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
14013 }
14014 else
14015 {
14016 //Send WLAN UP indication to Nlink Service
14017 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
14018
14019 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Jeff Johnson295189b2012-06-20 16:38:30 -070014020 }
14021
14022 EXIT();
14023
14024 return ret_status;
14025}
14026
Jeff Johnson32d95a32012-09-10 13:15:23 -070014027/**---------------------------------------------------------------------------
14028
14029 \brief hdd_module_init() - Init Function
14030
14031 This is the driver entry point (invoked when module is loaded using insmod)
14032
14033 \param - None
14034
14035 \return - 0 for success, non zero for failure
14036
14037 --------------------------------------------------------------------------*/
14038#ifdef MODULE
14039static int __init hdd_module_init ( void)
14040{
14041 return hdd_driver_init();
14042}
Jeff Johnson32d95a32012-09-10 13:15:23 -070014043#else /* #ifdef MODULE */
14044static int __init hdd_module_init ( void)
14045{
14046 /* Driver initialization is delayed to fwpath_changed_handler */
14047 return 0;
14048}
Jeff Johnson32d95a32012-09-10 13:15:23 -070014049#endif /* #ifdef MODULE */
14050
Jeff Johnson295189b2012-06-20 16:38:30 -070014051
14052/**---------------------------------------------------------------------------
14053
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070014054 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -070014055
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070014056 This is the driver exit point (invoked when module is unloaded using rmmod
14057 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -070014058
14059 \param - None
14060
14061 \return - None
14062
14063 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070014064static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -070014065{
14066 hdd_context_t *pHddCtx = NULL;
14067 v_CONTEXT_t pVosContext = NULL;
Agarwal Ashish5e414792014-06-08 15:25:23 +053014068 v_REGDOMAIN_t regId;
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +053014069 unsigned long rc = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -070014070
14071 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
14072
14073 //Get the global vos context
14074 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
14075
14076 if(!pVosContext)
14077 {
14078 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
14079 goto done;
14080 }
14081
14082 //Get the HDD context.
14083 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
14084
14085 if(!pHddCtx)
14086 {
14087 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
14088 }
Katya Nigame7b69a82015-04-28 15:24:06 +053014089 else if (VOS_MONITOR_MODE == hdd_get_conparam())
14090 {
14091 hddLog(VOS_TRACE_LEVEL_INFO,"%s: MONITOR MODE",__func__);
14092 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_UNLOAD_IN_PROGRESS;
14093 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
14094 hdd_wlan_exit(pHddCtx);
14095 vos_preClose( &pVosContext );
14096 goto done;
14097 }
Jeff Johnson295189b2012-06-20 16:38:30 -070014098 else
14099 {
Siddharth Bhal2e5871b2015-03-24 16:20:51 +053014100 /* We wait for active entry threads to exit from driver
14101 * by waiting until rtnl_lock is available.
14102 */
14103 rtnl_lock();
14104 rtnl_unlock();
14105
Siddharth Bhal3c29dca2015-02-19 00:41:40 +053014106 INIT_COMPLETION(pHddCtx->ssr_comp_var);
14107 if ((pHddCtx->isLogpInProgress) && (FALSE ==
14108 vos_is_wlan_in_badState(VOS_MODULE_ID_HDD, NULL)))
14109 {
Siddharth Bhala204f572015-01-17 02:03:36 +053014110 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Siddharth Bhal3c29dca2015-02-19 00:41:40 +053014111 "%s:SSR in Progress; block rmmod !!!", __func__);
Siddharth Bhala204f572015-01-17 02:03:36 +053014112 rc = wait_for_completion_timeout(&pHddCtx->ssr_comp_var,
14113 msecs_to_jiffies(30000));
14114 if(!rc)
14115 {
14116 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
14117 "%s:SSR timedout, fatal error", __func__);
14118 VOS_BUG(0);
14119 }
14120 }
14121
Siddharth Bhal3c29dca2015-02-19 00:41:40 +053014122 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_UNLOAD_IN_PROGRESS;
14123 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
Jeff Johnson295189b2012-06-20 16:38:30 -070014124
c_hpothu8adb97b2014-12-08 19:38:20 +053014125 /* Driver Need to send country code 00 in below condition
14126 * 1) If gCountryCodePriority is set to 1; and last country
14127 * code set is through 11d. This needs to be done in case
14128 * when NV country code is 00.
14129 * This Needs to be done as when kernel store last country
14130 * code and if stored country code is not through 11d,
14131 * in sme_HandleChangeCountryCodeByUser we will disable 11d
14132 * in next load/unload as soon as we get any country through
14133 * 11d. In sme_HandleChangeCountryCodeByUser
14134 * pMsg->countryCode will be last countryCode and
14135 * pMac->scan.countryCode11d will be country through 11d so
14136 * due to mismatch driver will disable 11d.
14137 *
14138 */
Agarwal Ashish8db39882014-07-30 21:56:07 +053014139
c_hpothu8adb97b2014-12-08 19:38:20 +053014140 if ((eANI_BOOLEAN_TRUE == sme_Is11dCountrycode(pHddCtx->hHal) &&
Agarwal Ashish8dcd2862014-07-25 11:58:52 +053014141 pHddCtx->cfg_ini->fSupplicantCountryCodeHasPriority &&
Abhishek Singh2a705962014-10-30 14:47:28 +053014142 sme_Is11dSupported(pHddCtx->hHal)))
c_hpothu8adb97b2014-12-08 19:38:20 +053014143 {
14144 hddLog(VOS_TRACE_LEVEL_INFO,
Agarwal Ashish8dcd2862014-07-25 11:58:52 +053014145 FL("CountryCode 00 is being set while unloading driver"));
c_hpothu8adb97b2014-12-08 19:38:20 +053014146 vos_nv_getRegDomainFromCountryCode(&regId , "00", COUNTRY_USER);
14147 }
Agarwal Ashish5e414792014-06-08 15:25:23 +053014148
c_hpothu8adb97b2014-12-08 19:38:20 +053014149 //Do all the cleanup before deregistering the driver
14150 hdd_wlan_exit(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -070014151 }
14152
Jeff Johnson295189b2012-06-20 16:38:30 -070014153 vos_preClose( &pVosContext );
14154
14155#ifdef TIMER_MANAGER
14156 vos_timer_exit();
14157#endif
14158#ifdef MEMORY_DEBUG
14159 vos_mem_exit();
14160#endif
14161
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +053014162#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
14163 wlan_logging_sock_deinit_svc();
14164#endif
14165
Jeff Johnson295189b2012-06-20 16:38:30 -070014166done:
Sushant Kaushik83392fa2015-05-05 17:44:40 +053014167 vos_wake_lock_destroy(&wlan_wake_lock);
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +053014168
Jeff Johnson295189b2012-06-20 16:38:30 -070014169 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
14170}
14171
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070014172/**---------------------------------------------------------------------------
14173
14174 \brief hdd_module_exit() - Exit function
14175
14176 This is the driver exit point (invoked when module is unloaded using rmmod)
14177
14178 \param - None
14179
14180 \return - None
14181
14182 --------------------------------------------------------------------------*/
14183static void __exit hdd_module_exit(void)
14184{
14185 hdd_driver_exit();
14186}
14187
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070014188#ifdef MODULE
14189static int fwpath_changed_handler(const char *kmessage,
14190 struct kernel_param *kp)
14191{
Jeff Johnson76052702013-04-16 13:55:05 -070014192 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070014193}
14194
14195static int con_mode_handler(const char *kmessage,
14196 struct kernel_param *kp)
14197{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -070014198 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070014199}
14200#else /* #ifdef MODULE */
14201/**---------------------------------------------------------------------------
14202
Jeff Johnson76052702013-04-16 13:55:05 -070014203 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070014204
Jeff Johnson76052702013-04-16 13:55:05 -070014205 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070014206 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -070014207 - invoked when module parameter fwpath is modified from userspace to signal
14208 initializing the WLAN driver or when con_mode is modified from userspace
14209 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070014210
14211 \return - 0 for success, non zero for failure
14212
14213 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -070014214static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070014215{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -070014216 int ret_status;
14217
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070014218 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -070014219 ret_status = hdd_driver_init();
14220 wlan_hdd_inited = ret_status ? 0 : 1;
14221 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070014222 }
14223
14224 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -070014225
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070014226 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -070014227
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -070014228 ret_status = hdd_driver_init();
14229 wlan_hdd_inited = ret_status ? 0 : 1;
14230 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070014231}
14232
Jeff Johnson295189b2012-06-20 16:38:30 -070014233/**---------------------------------------------------------------------------
14234
Jeff Johnson76052702013-04-16 13:55:05 -070014235 \brief fwpath_changed_handler() - Handler Function
14236
14237 Handle changes to the fwpath parameter
14238
14239 \return - 0 for success, non zero for failure
14240
14241 --------------------------------------------------------------------------*/
14242static int fwpath_changed_handler(const char *kmessage,
14243 struct kernel_param *kp)
14244{
14245 int ret;
14246
14247 ret = param_set_copystring(kmessage, kp);
14248 if (0 == ret)
14249 ret = kickstart_driver();
14250 return ret;
14251}
14252
14253/**---------------------------------------------------------------------------
14254
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070014255 \brief con_mode_handler() -
14256
14257 Handler function for module param con_mode when it is changed by userspace
14258 Dynamically linked - do nothing
14259 Statically linked - exit and init driver, as in rmmod and insmod
14260
Jeff Johnson76052702013-04-16 13:55:05 -070014261 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070014262
Jeff Johnson76052702013-04-16 13:55:05 -070014263 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070014264
14265 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -070014266static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070014267{
Jeff Johnson76052702013-04-16 13:55:05 -070014268 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070014269
Jeff Johnson76052702013-04-16 13:55:05 -070014270 ret = param_set_int(kmessage, kp);
14271 if (0 == ret)
14272 ret = kickstart_driver();
14273 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070014274}
14275#endif /* #ifdef MODULE */
14276
14277/**---------------------------------------------------------------------------
14278
Jeff Johnson295189b2012-06-20 16:38:30 -070014279 \brief hdd_get_conparam() -
14280
14281 This is the driver exit point (invoked when module is unloaded using rmmod)
14282
14283 \param - None
14284
14285 \return - tVOS_CON_MODE
14286
14287 --------------------------------------------------------------------------*/
14288tVOS_CON_MODE hdd_get_conparam ( void )
14289{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070014290#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -070014291 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070014292#else
14293 return (tVOS_CON_MODE)curr_con_mode;
14294#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070014295}
14296void hdd_set_conparam ( v_UINT_t newParam )
14297{
14298 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070014299#ifndef MODULE
14300 curr_con_mode = con_mode;
14301#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070014302}
14303/**---------------------------------------------------------------------------
14304
14305 \brief hdd_softap_sta_deauth() - function
14306
14307 This to take counter measure to handle deauth req from HDD
14308
14309 \param - pAdapter - Pointer to the HDD
14310
14311 \param - enable - boolean value
14312
14313 \return - None
14314
14315 --------------------------------------------------------------------------*/
14316
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +053014317VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter,
14318 struct tagCsrDelStaParams *pDelStaParams)
Jeff Johnson295189b2012-06-20 16:38:30 -070014319{
Jeff Johnson295189b2012-06-20 16:38:30 -070014320 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -080014321 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Hanumanth Reddy Pothula57323632017-12-06 17:55:09 +053014322 struct hdd_cache_sta_info *cache_sta_info;
14323 ptSapContext pSapCtx = VOS_GET_SAP_CB(pVosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -070014324
14325 ENTER();
14326
Jeff Johnsonc135a9a2017-09-19 08:37:24 -070014327 hddLog(LOG1, "hdd_softap_sta_deauth:(%pK, false)",
Rajesh Chauhan18488fc2013-08-22 10:15:03 -070014328 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -070014329
Hanumanth Reddy Pothula57323632017-12-06 17:55:09 +053014330 if (!pSapCtx) {
14331 hddLog(LOGE, "sap context is NULL");
14332 return vosStatus;
14333 }
14334
14335 cache_sta_info = hdd_get_cache_stainfo(pSapCtx->cache_sta_info,
14336 pDelStaParams->peerMacAddr);
14337 if (cache_sta_info) {
14338 cache_sta_info->reason_code = pDelStaParams->reason_code;
14339 cache_sta_info->rx_rate =
14340 wlan_tl_get_sta_rx_rate(pVosContext, cache_sta_info->ucSTAId);
14341 WLANTL_GetSAPStaRSSi(pVosContext, cache_sta_info->ucSTAId,
14342 &cache_sta_info->rssi);
14343 }
14344
Jeff Johnson295189b2012-06-20 16:38:30 -070014345 //Ignore request to deauth bcmc station
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +053014346 if (pDelStaParams->peerMacAddr[0] & 0x1)
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -080014347 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -070014348
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +053014349 vosStatus = WLANSAP_DeauthSta(pVosContext, pDelStaParams);
Jeff Johnson295189b2012-06-20 16:38:30 -070014350
14351 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -080014352 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -070014353}
14354
14355/**---------------------------------------------------------------------------
14356
Rashmi Ramanna1f0948d2014-08-28 15:33:48 +053014357 \brief hdd_del_all_sta() - function
14358
14359 This function removes all the stations associated on stopping AP/P2P GO.
14360
14361 \param - pAdapter - Pointer to the HDD
14362
14363 \return - None
14364
14365 --------------------------------------------------------------------------*/
14366
14367int hdd_del_all_sta(hdd_adapter_t *pAdapter)
14368{
14369 v_U16_t i;
14370 VOS_STATUS vos_status;
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +053014371 v_CONTEXT_t pVosContext = ( WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
14372 ptSapContext pSapCtx = NULL;
14373 pSapCtx = VOS_GET_SAP_CB(pVosContext);
14374 if(pSapCtx == NULL){
14375 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
14376 FL("psapCtx is NULL"));
14377 return 1;
14378 }
Rashmi Ramanna1f0948d2014-08-28 15:33:48 +053014379 ENTER();
14380
14381 hddLog(VOS_TRACE_LEVEL_INFO,
14382 "%s: Delete all STAs associated.",__func__);
14383 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
14384 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
14385 )
14386 {
14387 for(i = 0; i < WLAN_MAX_STA_COUNT; i++)
14388 {
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +053014389 if ((pSapCtx->aStaInfo[i].isUsed) &&
14390 (!pSapCtx->aStaInfo[i].isDeauthInProgress))
Rashmi Ramanna1f0948d2014-08-28 15:33:48 +053014391 {
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +053014392 struct tagCsrDelStaParams delStaParams;
14393
14394 WLANSAP_PopulateDelStaParams(
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +053014395 pSapCtx->aStaInfo[i].macAddrSTA.bytes,
Sushant Kaushik4cd28f62014-12-26 14:23:50 +053014396 eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
14397 SIR_MAC_MGMT_DEAUTH >> 4,
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +053014398 &delStaParams);
14399 vos_status = hdd_softap_sta_deauth(pAdapter, &delStaParams);
Rashmi Ramanna1f0948d2014-08-28 15:33:48 +053014400 if (VOS_IS_STATUS_SUCCESS(vos_status))
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +053014401 pSapCtx->aStaInfo[i].isDeauthInProgress = TRUE;
Rashmi Ramanna1f0948d2014-08-28 15:33:48 +053014402 }
14403 }
14404 }
14405
14406 EXIT();
14407 return 0;
14408}
14409
14410/**---------------------------------------------------------------------------
14411
Jeff Johnson295189b2012-06-20 16:38:30 -070014412 \brief hdd_softap_sta_disassoc() - function
14413
14414 This to take counter measure to handle deauth req from HDD
14415
14416 \param - pAdapter - Pointer to the HDD
14417
14418 \param - enable - boolean value
14419
14420 \return - None
14421
14422 --------------------------------------------------------------------------*/
14423
14424void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
14425{
Hanumanth Reddy Pothula57323632017-12-06 17:55:09 +053014426 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
14427 struct hdd_cache_sta_info *cache_sta_info;
14428 ptSapContext pSapCtx = VOS_GET_SAP_CB(pVosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -070014429
14430 ENTER();
14431
Jeff Johnsonc135a9a2017-09-19 08:37:24 -070014432 hddLog( LOGE, "hdd_softap_sta_disassoc:(%pK, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -070014433
Hanumanth Reddy Pothula57323632017-12-06 17:55:09 +053014434 if (!pSapCtx) {
14435 hddLog(LOGE, "sap context is NULL");
14436 return ;
14437 }
14438
Jeff Johnson295189b2012-06-20 16:38:30 -070014439 //Ignore request to disassoc bcmc station
14440 if( pDestMacAddress[0] & 0x1 )
14441 return;
14442
Hanumanth Reddy Pothula57323632017-12-06 17:55:09 +053014443 cache_sta_info = hdd_get_cache_stainfo(pSapCtx->cache_sta_info,
14444 pDestMacAddress);
14445 if (cache_sta_info) {
14446 cache_sta_info->reason_code = eSIR_MAC_DEAUTH_LEAVING_BSS_REASON;
14447 cache_sta_info->rx_rate =
14448 wlan_tl_get_sta_rx_rate(pVosContext, cache_sta_info->ucSTAId);
14449 WLANTL_GetSAPStaRSSi(pVosContext, cache_sta_info->ucSTAId,
14450 &cache_sta_info->rssi);
14451 }
14452
Jeff Johnson295189b2012-06-20 16:38:30 -070014453 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
14454}
14455
14456void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
14457{
14458 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
14459
14460 ENTER();
14461
Jeff Johnsonc135a9a2017-09-19 08:37:24 -070014462 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%pK, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -070014463
14464 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
14465}
14466
Jeff Johnson295189b2012-06-20 16:38:30 -070014467/**---------------------------------------------------------------------------
14468 *
14469 * \brief hdd_get__concurrency_mode() -
14470 *
14471 *
14472 * \param - None
14473 *
14474 * \return - CONCURRENCY MODE
14475 *
14476 * --------------------------------------------------------------------------*/
14477tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
14478{
14479 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
14480 hdd_context_t *pHddCtx;
14481
14482 if (NULL != pVosContext)
14483 {
14484 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
14485 if (NULL != pHddCtx)
14486 {
14487 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
14488 }
14489 }
14490
14491 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070014492 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -070014493 return VOS_STA;
14494}
Sushant Kaushikabb7ee62014-07-18 16:20:12 +053014495v_BOOL_t
14496wlan_hdd_is_GO_power_collapse_allowed (hdd_context_t* pHddCtx)
14497{
14498 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -070014499
Sushant Kaushikabb7ee62014-07-18 16:20:12 +053014500 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_GO);
14501 if (pAdapter == NULL)
14502 {
14503 hddLog(VOS_TRACE_LEVEL_INFO,
14504 FL("GO doesn't exist"));
14505 return TRUE;
14506 }
14507 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
14508 {
14509 hddLog(VOS_TRACE_LEVEL_INFO,
14510 FL("GO started"));
14511 return TRUE;
14512 }
14513 else
14514 /* wait till GO changes its interface to p2p device */
14515 hddLog(VOS_TRACE_LEVEL_INFO,
14516 FL("Del_bss called, avoid apps suspend"));
14517 return FALSE;
14518
14519}
Jeff Johnson295189b2012-06-20 16:38:30 -070014520/* Decide whether to allow/not the apps power collapse.
14521 * Allow apps power collapse if we are in connected state.
14522 * if not, allow only if we are in IMPS */
14523v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
14524{
14525 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -080014526 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -080014527 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -070014528 hdd_config_t *pConfig = pHddCtx->cfg_ini;
14529 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
14530 hdd_adapter_t *pAdapter = NULL;
14531 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -080014532 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -070014533
Jeff Johnson295189b2012-06-20 16:38:30 -070014534 if (VOS_STA_SAP_MODE == hdd_get_conparam())
14535 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -070014536
Yathish9f22e662012-12-10 14:21:35 -080014537 concurrent_state = hdd_get_concurrency_mode();
14538
Sushant Kaushikabb7ee62014-07-18 16:20:12 +053014539 if ((concurrent_state == (VOS_STA | VOS_P2P_GO)) &&
14540 !(wlan_hdd_is_GO_power_collapse_allowed(pHddCtx)))
14541 return FALSE;
Yathish9f22e662012-12-10 14:21:35 -080014542#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
Sushant Kaushikabb7ee62014-07-18 16:20:12 +053014543
Yathish9f22e662012-12-10 14:21:35 -080014544 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
Sushant Kaushikabb7ee62014-07-18 16:20:12 +053014545 (concurrent_state == (VOS_STA | VOS_P2P_GO)))&&
Yathish9f22e662012-12-10 14:21:35 -080014546 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
14547 return TRUE;
14548#endif
14549
Jeff Johnson295189b2012-06-20 16:38:30 -070014550 /*loop through all adapters. TBD fix for Concurrency */
14551 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
14552 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
14553 {
14554 pAdapter = pAdapterNode->pAdapter;
14555 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
14556 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
14557 {
Srikant Kuppafef66a72013-01-30 17:32:44 -080014558 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
c_hpothu4e8faac2014-05-16 17:38:44 +053014559 && (pmcState != IMPS && pmcState != BMPS && pmcState != UAPSD
c_hpothu1c6957d2015-01-06 18:19:47 +053014560 && pmcState != STOPPED && pmcState != STANDBY &&
14561 pmcState != WOWL)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -080014562 (eANI_BOOLEAN_TRUE == scanRspPending) ||
14563 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -070014564 {
Mukul Sharma4be88422015-03-09 20:29:07 +053014565 if(pmcState == FULL_POWER &&
14566 sme_IsCoexScoIndicationSet(pHddCtx->hHal))
14567 {
14568 /*
14569 * When SCO indication comes from Coex module , host will
14570 * enter in to full power mode, but this should not prevent
14571 * apps processor power collapse.
14572 */
14573 hddLog(LOG1,
14574 FL("Allow apps power collapse"
14575 "even when sco indication is set"));
14576 return TRUE;
14577 }
Srikant Kuppafef66a72013-01-30 17:32:44 -080014578 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Deepthi Gowri03a979f2016-11-03 15:20:19 +053014579 "pmcState = %d scanRspPending = %d "
14580 "inMiddleOfRoaming = %d connected = %d",
14581 __func__, pmcState, scanRspPending,
14582 inMiddleOfRoaming, hdd_connIsConnected(
14583 WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )));
14584 wlan_hdd_get_tdls_stats(pAdapter);
14585 return FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -070014586 }
14587 }
14588 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
14589 pAdapterNode = pNext;
14590 }
14591 return TRUE;
14592}
14593
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -080014594/* Decides whether to send suspend notification to Riva
14595 * if any adapter is in BMPS; then it is required */
14596v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
14597{
14598 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
14599 hdd_config_t *pConfig = pHddCtx->cfg_ini;
14600
14601 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
14602 {
14603 return TRUE;
14604 }
14605 return FALSE;
14606}
14607
Jeff Johnson295189b2012-06-20 16:38:30 -070014608void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
14609{
14610 switch(mode)
14611 {
Chilam Ngc4244af2013-04-01 15:37:32 -070014612 case VOS_STA_MODE:
14613 case VOS_P2P_CLIENT_MODE:
14614 case VOS_P2P_GO_MODE:
14615 case VOS_STA_SAP_MODE:
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +053014616 case VOS_MONITOR_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -070014617 pHddCtx->concurrency_mode |= (1 << mode);
Agarwal Ashish51325b52014-06-16 16:50:49 +053014618 pHddCtx->no_of_open_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -070014619 break;
14620 default:
14621 break;
Jeff Johnson295189b2012-06-20 16:38:30 -070014622 }
Agarwal Ashish51325b52014-06-16 16:50:49 +053014623 hddLog(VOS_TRACE_LEVEL_INFO, FL("concurrency_mode = 0x%x "
14624 "Number of open sessions for mode %d = %d"),
14625 pHddCtx->concurrency_mode, mode,
14626 pHddCtx->no_of_open_sessions[mode]);
Jeff Johnson295189b2012-06-20 16:38:30 -070014627}
14628
14629
14630void wlan_hdd_clear_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:
Agarwal Ashish51325b52014-06-16 16:50:49 +053014639 pHddCtx->no_of_open_sessions[mode]--;
14640 if (!(pHddCtx->no_of_open_sessions[mode]))
14641 pHddCtx->concurrency_mode &= (~(1 << mode));
Jeff Johnson295189b2012-06-20 16:38:30 -070014642 break;
14643 default:
14644 break;
14645 }
Agarwal Ashish51325b52014-06-16 16:50:49 +053014646 hddLog(VOS_TRACE_LEVEL_INFO, FL("concurrency_mode = 0x%x "
14647 "Number of open sessions for mode %d = %d"),
14648 pHddCtx->concurrency_mode, mode, pHddCtx->no_of_open_sessions[mode]);
14649
14650}
14651/**---------------------------------------------------------------------------
14652 *
14653 * \brief wlan_hdd_incr_active_session()
14654 *
14655 * This function increments the number of active sessions
14656 * maintained per device mode
14657 * Incase of STA/P2P CLI/IBSS upon connection indication it is incremented
14658 * Incase of SAP/P2P GO upon bss start it is incremented
14659 *
14660 * \param pHddCtx - HDD Context
14661 * \param mode - device mode
14662 *
14663 * \return - None
14664 *
14665 * --------------------------------------------------------------------------*/
14666void wlan_hdd_incr_active_session(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
14667{
14668 switch (mode) {
14669 case VOS_STA_MODE:
14670 case VOS_P2P_CLIENT_MODE:
14671 case VOS_P2P_GO_MODE:
14672 case VOS_STA_SAP_MODE:
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +053014673 case VOS_MONITOR_MODE:
Agarwal Ashish51325b52014-06-16 16:50:49 +053014674 pHddCtx->no_of_active_sessions[mode]++;
14675 break;
14676 default:
14677 hddLog(VOS_TRACE_LEVEL_INFO, FL("Not Expected Mode %d"), mode);
14678 break;
14679 }
14680 hddLog(VOS_TRACE_LEVEL_INFO, FL("No.# of active sessions for mode %d = %d"),
14681 mode,
14682 pHddCtx->no_of_active_sessions[mode]);
14683}
14684
14685/**---------------------------------------------------------------------------
14686 *
14687 * \brief wlan_hdd_decr_active_session()
14688 *
14689 * This function decrements the number of active sessions
14690 * maintained per device mode
14691 * Incase of STA/P2P CLI/IBSS upon disconnection it is decremented
14692 * Incase of SAP/P2P GO upon bss stop it is decremented
14693 *
14694 * \param pHddCtx - HDD Context
14695 * \param mode - device mode
14696 *
14697 * \return - None
14698 *
14699 * --------------------------------------------------------------------------*/
14700void wlan_hdd_decr_active_session(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
14701{
Bhargav Shahd0715912015-10-01 18:17:37 +053014702
Agarwal Ashish51325b52014-06-16 16:50:49 +053014703 switch (mode) {
14704 case VOS_STA_MODE:
14705 case VOS_P2P_CLIENT_MODE:
14706 case VOS_P2P_GO_MODE:
14707 case VOS_STA_SAP_MODE:
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +053014708 case VOS_MONITOR_MODE:
Agarwal Ashish5325f522014-08-06 00:58:44 +053014709 if (pHddCtx->no_of_active_sessions[mode] > 0)
14710 pHddCtx->no_of_active_sessions[mode]--;
14711 else
14712 hddLog(VOS_TRACE_LEVEL_INFO, FL(" No.# of Active sessions"
14713 "is already Zero"));
Agarwal Ashish51325b52014-06-16 16:50:49 +053014714 break;
14715 default:
14716 hddLog(VOS_TRACE_LEVEL_INFO, FL("Not Expected Mode %d"), mode);
14717 break;
14718 }
14719 hddLog(VOS_TRACE_LEVEL_INFO, FL("No.# of active sessions for mode %d = %d"),
14720 mode,
14721 pHddCtx->no_of_active_sessions[mode]);
Jeff Johnson295189b2012-06-20 16:38:30 -070014722}
14723
Jeff Johnsone7245742012-09-05 17:12:55 -070014724/**---------------------------------------------------------------------------
14725 *
14726 * \brief wlan_hdd_restart_init
14727 *
14728 * This function initalizes restart timer/flag. An internal function.
14729 *
14730 * \param - pHddCtx
14731 *
14732 * \return - None
14733 *
14734 * --------------------------------------------------------------------------*/
14735
14736static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
14737{
14738 /* Initialize */
14739 pHddCtx->hdd_restart_retries = 0;
14740 atomic_set(&pHddCtx->isRestartInProgress, 0);
14741 vos_timer_init(&pHddCtx->hdd_restart_timer,
14742 VOS_TIMER_TYPE_SW,
14743 wlan_hdd_restart_timer_cb,
14744 pHddCtx);
14745}
14746/**---------------------------------------------------------------------------
14747 *
14748 * \brief wlan_hdd_restart_deinit
14749 *
14750 * This function cleans up the resources used. An internal function.
14751 *
14752 * \param - pHddCtx
14753 *
14754 * \return - None
14755 *
14756 * --------------------------------------------------------------------------*/
14757
14758static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
14759{
14760
14761 VOS_STATUS vos_status;
14762 /* Block any further calls */
14763 atomic_set(&pHddCtx->isRestartInProgress, 1);
14764 /* Cleanup */
14765 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
14766 if (!VOS_IS_STATUS_SUCCESS(vos_status))
c_hpothu6ff1c3c2013-10-01 19:01:57 +053014767 hddLog(LOGE, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -070014768 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
14769 if (!VOS_IS_STATUS_SUCCESS(vos_status))
c_hpothu6ff1c3c2013-10-01 19:01:57 +053014770 hddLog(LOGE, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -070014771
14772}
14773
14774/**---------------------------------------------------------------------------
14775 *
14776 * \brief wlan_hdd_framework_restart
14777 *
14778 * This function uses a cfg80211 API to start a framework initiated WLAN
14779 * driver module unload/load.
14780 *
14781 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
14782 *
14783 *
14784 * \param - pHddCtx
14785 *
14786 * \return - VOS_STATUS_SUCCESS: Success
14787 * VOS_STATUS_E_EMPTY: Adapter is Empty
14788 * VOS_STATUS_E_NOMEM: No memory
14789
14790 * --------------------------------------------------------------------------*/
14791
14792static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
14793{
14794 VOS_STATUS status = VOS_STATUS_SUCCESS;
14795 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -070014796 int len = (sizeof (struct ieee80211_mgmt));
14797 struct ieee80211_mgmt *mgmt = NULL;
14798
14799 /* Prepare the DEAUTH managment frame with reason code */
14800 mgmt = kzalloc(len, GFP_KERNEL);
14801 if(mgmt == NULL)
14802 {
14803 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
14804 "%s: memory allocation failed (%d bytes)", __func__, len);
14805 return VOS_STATUS_E_NOMEM;
14806 }
14807 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -070014808
14809 /* Iterate over all adapters/devices */
14810 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Hanumantha Reddy Pothulada0fe362015-02-27 18:37:03 +053014811 if ((NULL == pAdapterNode) || (VOS_STATUS_SUCCESS != status))
14812 {
14813 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnsonc135a9a2017-09-19 08:37:24 -070014814 FL("fail to get adapter: %pK %d"), pAdapterNode, status);
Hanumantha Reddy Pothulada0fe362015-02-27 18:37:03 +053014815 goto end;
14816 }
14817
Jeff Johnsone7245742012-09-05 17:12:55 -070014818 do
14819 {
Hanumantha Reddy Pothulada0fe362015-02-27 18:37:03 +053014820 if(pAdapterNode->pAdapter &&
14821 WLAN_HDD_ADAPTER_MAGIC == pAdapterNode->pAdapter->magic)
Jeff Johnsone7245742012-09-05 17:12:55 -070014822 {
14823 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
14824 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
14825 pAdapterNode->pAdapter->dev->name,
14826 pAdapterNode->pAdapter->device_mode,
14827 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -070014828 /*
14829 * CFG80211 event to restart the driver
14830 *
14831 * 'cfg80211_send_unprot_deauth' sends a
14832 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
14833 * of SME(Linux Kernel) state machine.
14834 *
14835 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
14836 * the driver.
14837 *
14838 */
Abhishek Singh00b71972016-01-07 10:51:04 +053014839
Anand N Sunkade9adb1b2015-07-29 09:56:45 +053014840#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
14841 cfg80211_rx_unprot_mlme_mgmt(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len);
14842#else
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -070014843 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Anand N Sunkade9adb1b2015-07-29 09:56:45 +053014844#endif
Jeff Johnsone7245742012-09-05 17:12:55 -070014845 }
14846 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
14847 pAdapterNode = pNext;
14848 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
14849
Hanumantha Reddy Pothulada0fe362015-02-27 18:37:03 +053014850 end:
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -070014851 /* Free the allocated management frame */
14852 kfree(mgmt);
14853
Jeff Johnsone7245742012-09-05 17:12:55 -070014854 /* Retry until we unload or reach max count */
14855 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
14856 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
14857
14858 return status;
14859
14860}
14861/**---------------------------------------------------------------------------
14862 *
14863 * \brief wlan_hdd_restart_timer_cb
14864 *
14865 * Restart timer callback. An internal function.
14866 *
14867 * \param - User data:
14868 *
14869 * \return - None
14870 *
14871 * --------------------------------------------------------------------------*/
14872
14873void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
14874{
14875 hdd_context_t *pHddCtx = usrDataForCallback;
14876 wlan_hdd_framework_restart(pHddCtx);
14877 return;
14878
14879}
14880
14881
14882/**---------------------------------------------------------------------------
14883 *
14884 * \brief wlan_hdd_restart_driver
14885 *
14886 * This function sends an event to supplicant to restart the WLAN driver.
14887 *
14888 * This function is called from vos_wlanRestart.
14889 *
14890 * \param - pHddCtx
14891 *
14892 * \return - VOS_STATUS_SUCCESS: Success
14893 * VOS_STATUS_E_EMPTY: Adapter is Empty
14894 * VOS_STATUS_E_ALREADY: Request already in progress
14895
14896 * --------------------------------------------------------------------------*/
14897VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
14898{
14899 VOS_STATUS status = VOS_STATUS_SUCCESS;
14900
14901 /* A tight check to make sure reentrancy */
14902 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
14903 {
Mihir Shetefd528652014-06-23 19:07:50 +053014904 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnsone7245742012-09-05 17:12:55 -070014905 "%s: WLAN restart is already in progress", __func__);
14906
14907 return VOS_STATUS_E_ALREADY;
14908 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -070014909 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -080014910#ifdef HAVE_WCNSS_RESET_INTR
Siddharth Bhal864e7e82015-04-07 20:07:24 +053014911 wcnss_reset_fiq(TRUE);
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -070014912#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -070014913
Jeff Johnsone7245742012-09-05 17:12:55 -070014914 return status;
14915}
14916
Bhargav Shahd0715912015-10-01 18:17:37 +053014917/**
14918 * hdd_get_total_sessions() - provide total number of active sessions
14919 * @pHddCtx: Valid Global HDD context pointer
14920 *
14921 * This function iterates through pAdaptors and find the number of all active
14922 * sessions. This active sessions includes connected sta, p2p client and number
14923 * of client connected to sap/p2p go.
14924 *
14925 * Return: Total number of active sessions.
14926 */
14927v_U8_t hdd_get_total_sessions(hdd_context_t *pHddCtx)
14928{
14929 v_U8_t active_session = 0;
14930 hdd_station_ctx_t *pHddStaCtx;
14931 hdd_adapter_list_node_t *pAdapterNode, *pNext;
14932 hdd_adapter_t *pAdapter;
14933 VOS_STATUS status;
14934
14935 status = hdd_get_front_adapter(pHddCtx, &pAdapterNode);
14936 while (NULL != pAdapterNode && VOS_STATUS_SUCCESS == status) {
14937 pAdapter = pAdapterNode->pAdapter;
14938 switch (pAdapter->device_mode) {
14939 case VOS_STA_MODE:
14940 case VOS_P2P_CLIENT_MODE:
14941 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14942 if(eConnectionState_Associated == pHddStaCtx->conn_info.connState)
14943 active_session += 1;
14944 break;
14945 case VOS_STA_SAP_MODE:
14946 case VOS_P2P_GO_MODE:
14947 active_session += hdd_softap_get_connected_sta(pAdapter);
14948 break;
14949 default:
14950 break;
14951 }
14952
14953 status = hdd_get_next_adapter(pHddCtx, pAdapterNode, &pNext);
14954 pAdapterNode = pNext;
14955 }
14956
14957 return active_session;
14958}
14959
14960/**
14961 * hdd_set_delack_value() - Set delack value
14962 * @pHddCtx: Valid Global HDD context pointer
14963 * @next_rx_level: Value to set for delack
14964 *
14965 * This function compare present value and next value of delack. If the both
14966 * are diffrent then it sets next value .
14967 *
14968 * Return: void.
14969 */
14970void hdd_set_delack_value(hdd_context_t *pHddCtx, v_U32_t next_rx_level)
14971{
14972 if (pHddCtx->cur_rx_level != next_rx_level) {
14973 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_DEBUG,
14974 "%s: TCP DELACK trigger level %d",
14975 __func__, next_rx_level);
14976 mutex_lock(&pHddCtx->cur_rx_level_lock);
14977 pHddCtx->cur_rx_level = next_rx_level;
14978 mutex_unlock(&pHddCtx->cur_rx_level_lock);
14979 wlan_hdd_send_svc_nlink_msg(WLAN_SVC_WLAN_TP_IND, &next_rx_level,
14980 sizeof(next_rx_level));
14981 }
14982}
14983
14984/**
14985 * hdd_set_default_stop_delack_timer() - Start delack timer
14986 * @pHddCtx: Valid Global HDD context pointer
14987 *
14988 * This function stop delack timer and set delack value to default..
14989 *
14990 * Return: void.
14991 */
14992
14993void hdd_set_default_stop_delack_timer(hdd_context_t *pHddCtx)
14994{
14995 if (VOS_TIMER_STATE_RUNNING !=
14996 vos_timer_getCurrentState(&pHddCtx->delack_timer)) {
14997 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_DEBUG,
14998 "%s: Can not stop timer", __func__);
14999 return;
15000 }
15001
15002 vos_timer_stop(&pHddCtx->delack_timer);
15003 hdd_set_delack_value(pHddCtx, TP_IND_LOW);
15004}
15005
15006/**
15007 * hdd_start_delack_timer() - Start delack timer
15008 * @pHddCtx: Valid Global HDD context pointer
15009 *
15010 * This function starts the delack timer for tcpDelAckComputeInterval time
15011 * interval.The default timer value is 2 second.
15012 *
15013 * Return: void.
15014 */
15015void hdd_start_delack_timer(hdd_context_t *pHddCtx)
15016{
15017 if (VOS_TIMER_STATE_RUNNING ==
15018 vos_timer_getCurrentState(&pHddCtx->delack_timer)) {
15019 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_DEBUG,
15020 "%s: Timer is already running", __func__);
15021 return;
15022 }
15023
15024 vos_timer_start(&pHddCtx->delack_timer,
15025 pHddCtx->cfg_ini->tcpDelAckComputeInterval);
15026}
15027
15028/**
15029 * hdd_update_prev_rx_packet_count() - Update previous rx packet count
15030 * @pHddCtx: Valid Global HDD context pointer
15031 *
15032 * This function updates the prev_rx_packets count from the corresponding
15033 * pAdapter states. This prev_rx_packets will diffed with the packet count
15034 * at the end of delack timer. That can give number of RX packet is spacific
15035 * time.
15036 *
15037 * Return: void.
15038 */
15039void hdd_update_prev_rx_packet_count(hdd_context_t *pHddCtx)
15040{
15041 hdd_adapter_list_node_t *pAdapterNode, *pNext;
15042 hdd_adapter_t *pAdapter;
15043 VOS_STATUS status;
15044
15045 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
15046 while (NULL != pAdapterNode && VOS_STATUS_SUCCESS == status) {
15047 pAdapter = pAdapterNode->pAdapter;
15048 pAdapter->prev_rx_packets = pAdapter->stats.rx_packets;
15049 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
15050 pAdapterNode = pNext;
15051 }
15052}
15053
15054/**
15055 * hdd_manage_delack_timer() - start\stop delack timer
15056 * @pHddCtx: Valid Global HDD context pointer
15057 *
15058 * This function check the number of concerent session present, it starts the
15059 * delack timer if only one session is present.
15060 * In the case of BT_COEX and TDLS mode it blindly stop delack functionality.
15061 *
15062 * Return: void.
15063 */
15064void hdd_manage_delack_timer(hdd_context_t *pHddCtx)
15065{
15066 uint8_t sessions;
15067
15068 if (!pHddCtx->cfg_ini->enable_delack) {
15069 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_DEBUG,
15070 "%s: TCP DELACK is not enabled", __func__);
15071 return;
15072 }
15073
15074 /* Blindly stop timer of BTCOEX and TDLS Session is up */
15075 if (pHddCtx->mode != 0) {
15076 hdd_set_default_stop_delack_timer(pHddCtx);
15077 return;
15078 }
15079
15080 sessions = hdd_get_total_sessions(pHddCtx);
15081 if (sessions == 1) {
15082 hdd_update_prev_rx_packet_count(pHddCtx);
15083 hdd_start_delack_timer(pHddCtx);
15084 } else {
15085 hdd_set_default_stop_delack_timer(pHddCtx);
15086 }
15087}
15088
Mihir Shetee1093ba2014-01-21 20:13:32 +053015089/**---------------------------------------------------------------------------
15090 *
15091 * \brief wlan_hdd_init_channels
15092 *
15093 * This function is used to initialize the channel list in CSR
15094 *
15095 * This function is called from hdd_wlan_startup
15096 *
15097 * \param - pHddCtx: HDD context
15098 *
15099 * \return - VOS_STATUS_SUCCESS: Success
15100 * VOS_STATUS_E_FAULT: Failure reported by SME
15101
15102 * --------------------------------------------------------------------------*/
15103static VOS_STATUS wlan_hdd_init_channels(hdd_context_t *pHddCtx)
15104{
15105 eHalStatus status;
15106
15107 status = sme_InitChannels(pHddCtx->hHal);
15108 if (HAL_STATUS_SUCCESS(status))
15109 {
15110 return VOS_STATUS_SUCCESS;
15111 }
15112 else
15113 {
15114 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Channel initialization failed(%d)",
15115 __func__, status);
15116 return VOS_STATUS_E_FAULT;
15117 }
15118}
15119
Mihir Shete04206452014-11-20 17:50:58 +053015120#ifdef CONFIG_ENABLE_LINUX_REG
Agarwal Ashish6db9d532014-09-30 18:19:10 +053015121VOS_STATUS wlan_hdd_init_channels_for_cc(hdd_context_t *pHddCtx, driver_load_type init )
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053015122{
15123 eHalStatus status;
15124
Agarwal Ashish6db9d532014-09-30 18:19:10 +053015125 status = sme_InitChannelsForCC(pHddCtx->hHal, init);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053015126 if (HAL_STATUS_SUCCESS(status))
15127 {
15128 return VOS_STATUS_SUCCESS;
15129 }
15130 else
15131 {
15132 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Issue reg hint failed(%d)",
15133 __func__, status);
15134 return VOS_STATUS_E_FAULT;
15135 }
15136}
Mihir Shete04206452014-11-20 17:50:58 +053015137#endif
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -070015138/*
15139 * API to find if there is any STA or P2P-Client is connected
15140 */
15141VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
15142{
15143 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
15144}
Jeff Johnsone7245742012-09-05 17:12:55 -070015145
Mihir Shetee2ae82a2015-03-16 14:08:49 +053015146
15147/*
15148 * API to find if the firmware will send logs using DXE channel
15149 */
15150v_U8_t hdd_is_fw_logging_enabled(void)
15151{
15152 hdd_context_t *pHddCtx;
15153
15154 pHddCtx = vos_get_context(VOS_MODULE_ID_HDD,
15155 vos_get_global_context(VOS_MODULE_ID_HDD, NULL));
15156
Sachin Ahuja084313e2015-05-21 17:57:10 +053015157 return (pHddCtx && pHddCtx->cfg_ini->enableMgmtLogging);
Mihir Shetee2ae82a2015-03-16 14:08:49 +053015158}
15159
Agarwal Ashish57e84372014-12-05 18:26:53 +053015160/*
Mihir Shetebe94ebb2015-05-26 12:07:14 +053015161 * API to find if the firmware will send trace logs using DXE channel
15162 */
15163v_U8_t hdd_is_fw_ev_logging_enabled(void)
15164{
15165 hdd_context_t *pHddCtx;
15166
15167 pHddCtx = vos_get_context(VOS_MODULE_ID_HDD,
15168 vos_get_global_context(VOS_MODULE_ID_HDD, NULL));
15169
15170 return (pHddCtx && pHddCtx->cfg_ini->enableFWLogging);
15171}
15172/*
Agarwal Ashish57e84372014-12-05 18:26:53 +053015173 * API to find if there is any session connected
15174 */
15175VOS_STATUS hdd_is_any_session_connected(hdd_context_t *pHddCtx)
15176{
15177 return sme_is_any_session_connected(pHddCtx->hHal);
15178}
15179
15180
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053015181int wlan_hdd_scan_abort(hdd_adapter_t *pAdapter)
15182{
15183 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15184 hdd_scaninfo_t *pScanInfo = NULL;
Girish Gowli4bf7a632014-06-12 13:42:11 +053015185 long status = 0;
c_hpothua3d45d52015-01-05 14:11:17 +053015186 tSirAbortScanStatus abortScanStatus;
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053015187
15188 pScanInfo = &pHddCtx->scan_info;
Ratnam Rachuric7681132015-06-30 10:35:13 +053015189 INIT_COMPLETION(pScanInfo->abortscan_event_var);
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053015190 if (pScanInfo->mScanPending)
15191 {
c_hpothua3d45d52015-01-05 14:11:17 +053015192 abortScanStatus = hdd_abort_mac_scan(pHddCtx, pScanInfo->sessionId,
15193 eCSR_SCAN_ABORT_DEFAULT);
15194 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
15195 FL("abortScanStatus: %d"), abortScanStatus);
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053015196
c_hpothua3d45d52015-01-05 14:11:17 +053015197 /* If there is active scan command lets wait for the completion else
15198 * there is no need to wait as scan command might be in the SME pending
15199 * command list.
15200 */
15201 if (abortScanStatus == eSIR_ABORT_ACTIVE_SCAN_LIST_NOT_EMPTY)
15202 {
Mukul Sharmab392b642017-08-17 17:45:29 +053015203 status = wait_for_completion_timeout(
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053015204 &pScanInfo->abortscan_event_var,
15205 msecs_to_jiffies(5000));
c_hpothua3d45d52015-01-05 14:11:17 +053015206 if (0 >= status)
15207 {
15208 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Girish Gowli4bf7a632014-06-12 13:42:11 +053015209 "%s: Timeout or Interrupt occurred while waiting for abort"
15210 "scan, status- %ld", __func__, status);
c_hpothua3d45d52015-01-05 14:11:17 +053015211 return -ETIMEDOUT;
15212 }
15213 }
15214 else if (abortScanStatus == eSIR_ABORT_SCAN_FAILURE)
15215 {
15216 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
15217 FL("hdd_abort_mac_scan failed"));
15218 return -VOS_STATUS_E_FAILURE;
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053015219 }
15220 }
Girish Gowli4bf7a632014-06-12 13:42:11 +053015221 return 0;
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053015222}
15223
Abhishek Singh7d624e12015-11-30 14:29:27 +053015224/**
15225 * hdd_indicate_mgmt_frame() - Wrapper to indicate management frame to
15226 * user space
15227 * @frame_ind: Management frame data to be informed.
15228 *
15229 * This function is used to indicate management frame to
15230 * user space
15231 *
15232 * Return: None
15233 *
15234 */
15235void hdd_indicate_mgmt_frame(tSirSmeMgmtFrameInd *frame_ind)
15236{
15237 hdd_context_t *hdd_ctx = NULL;
15238 hdd_adapter_t *adapter = NULL;
15239 v_CONTEXT_t vos_context = NULL;
15240
15241 /* Get the global VOSS context.*/
15242 vos_context = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
15243 if (!vos_context) {
15244 hddLog(LOGE, FL("Global VOS context is Null"));
15245 return;
15246 }
15247 /* Get the HDD context.*/
15248 hdd_ctx =
15249 (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, vos_context );
15250
15251 if (0 != wlan_hdd_validate_context(hdd_ctx))
15252 {
15253 return;
15254 }
15255 adapter = hdd_get_adapter_by_sme_session_id(hdd_ctx,
15256 frame_ind->sessionId);
15257
15258 if ((NULL != adapter) &&
15259 (WLAN_HDD_ADAPTER_MAGIC == adapter->magic))
15260 __hdd_indicate_mgmt_frame(adapter,
15261 frame_ind->frameLen,
15262 frame_ind->frameBuf,
15263 frame_ind->frameType,
15264 frame_ind->rxChan,
15265 frame_ind->rxRssi);
15266 return;
15267
15268}
15269
c_hpothu225aa7c2014-10-22 17:45:13 +053015270VOS_STATUS wlan_hdd_cancel_remain_on_channel(hdd_context_t *pHddCtx)
15271{
15272 hdd_adapter_t *pAdapter;
15273 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
15274 VOS_STATUS vosStatus;
15275
15276 vosStatus = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
15277 while (NULL != pAdapterNode && VOS_STATUS_E_EMPTY != vosStatus)
15278 {
15279 pAdapter = pAdapterNode->pAdapter;
15280 if (NULL != pAdapter)
15281 {
15282 if (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode ||
15283 WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ||
15284 WLAN_HDD_P2P_GO == pAdapter->device_mode)
15285 {
15286 hddLog(LOG1, FL("abort ROC deviceMode: %d"),
15287 pAdapter->device_mode);
15288 if (VOS_STATUS_SUCCESS !=
15289 wlan_hdd_cancel_existing_remain_on_channel(pAdapter))
15290 {
15291 hddLog(LOGE, FL("failed to abort ROC"));
15292 return VOS_STATUS_E_FAILURE;
15293 }
15294 }
15295 }
15296 vosStatus = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
15297 pAdapterNode = pNext;
15298 }
15299 return VOS_STATUS_SUCCESS;
15300}
Mahesh A Saptasagard477b092015-02-06 15:12:16 +053015301
Mihir Shete0be28772015-02-17 18:42:14 +053015302hdd_remain_on_chan_ctx_t *hdd_get_remain_on_channel_ctx(hdd_context_t *pHddCtx)
15303{
15304 hdd_adapter_t *pAdapter;
15305 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
15306 hdd_cfg80211_state_t *cfgState;
15307 hdd_remain_on_chan_ctx_t *pRemainChanCtx = NULL;
15308 VOS_STATUS vosStatus;
15309
15310 vosStatus = hdd_get_front_adapter (pHddCtx, &pAdapterNode);
15311 while (NULL != pAdapterNode && VOS_STATUS_E_EMPTY != vosStatus)
15312 {
15313 pAdapter = pAdapterNode->pAdapter;
15314 if (NULL != pAdapter)
15315 {
15316 cfgState = WLAN_HDD_GET_CFG_STATE_PTR(pAdapter);
15317 pRemainChanCtx = cfgState->remain_on_chan_ctx;
15318 if (pRemainChanCtx)
15319 break;
15320 }
15321 vosStatus = hdd_get_next_adapter (pHddCtx, pAdapterNode, &pNext);
15322 pAdapterNode = pNext;
15323 }
15324 return pRemainChanCtx;
15325}
15326
Padma, Santhosh Kumar778d8382015-03-04 17:41:22 +053015327/**
15328 * wlan_hdd_handle_dfs_chan_scan () - handles disable/enable DFS channels
15329 *
15330 * @pHddCtx: HDD context within host driver
15331 * @dfsScanMode: dfsScanMode passed from ioctl
15332 *
15333 */
15334
15335VOS_STATUS wlan_hdd_handle_dfs_chan_scan(hdd_context_t *pHddCtx,
15336 tANI_U8 dfsScanMode)
15337{
15338 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
15339 hdd_adapter_t *pAdapter;
15340 VOS_STATUS vosStatus;
15341 hdd_station_ctx_t *pHddStaCtx;
15342 eHalStatus status = eHAL_STATUS_SUCCESS;
15343
15344 if(!pHddCtx)
15345 {
15346 hddLog(LOGE, FL("HDD context is Null"));
15347 return eHAL_STATUS_FAILURE;
15348 }
15349
15350 if (pHddCtx->scan_info.mScanPending)
15351 {
15352 hddLog(LOG1, FL("Aborting scan for sessionId: %d"),
15353 pHddCtx->scan_info.sessionId);
15354 hdd_abort_mac_scan(pHddCtx,
15355 pHddCtx->scan_info.sessionId,
15356 eCSR_SCAN_ABORT_DEFAULT);
15357 }
15358
15359 if (!dfsScanMode)
15360 {
15361 vosStatus = hdd_get_front_adapter( pHddCtx, &pAdapterNode);
15362 while ((NULL != pAdapterNode) &&
15363 (VOS_STATUS_SUCCESS == vosStatus))
15364 {
15365 pAdapter = pAdapterNode->pAdapter;
15366
15367 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
15368 {
15369 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
15370
15371 if(!pHddStaCtx)
15372 {
15373 hddLog(LOGE, FL("HDD STA context is Null"));
15374 return eHAL_STATUS_FAILURE;
15375 }
15376
15377 /* if STA is already connected on DFS channel,
15378 disconnect immediately*/
15379 if (hdd_connIsConnected(pHddStaCtx) &&
15380 (NV_CHANNEL_DFS ==
15381 vos_nv_getChannelEnabledState(
15382 pHddStaCtx->conn_info.operationChannel)))
15383 {
15384 status = sme_RoamDisconnect(pHddCtx->hHal,
15385 pAdapter->sessionId,
15386 eCSR_DISCONNECT_REASON_UNSPECIFIED);
15387 hddLog(LOG1, FL("Client connected on DFS channel %d,"
15388 "sme_RoamDisconnect returned with status: %d"
15389 "for sessionid: %d"), pHddStaCtx->conn_info.
15390 operationChannel, status, pAdapter->sessionId);
15391 }
15392 }
15393
15394 vosStatus = hdd_get_next_adapter(pHddCtx, pAdapterNode,
15395 &pNext);
15396 pAdapterNode = pNext;
15397 }
15398 }
15399
15400 sme_UpdateDFSScanMode(pHddCtx->hHal, dfsScanMode);
15401 sme_UpdateDFSRoamMode(pHddCtx->hHal,
15402 (dfsScanMode != DFS_CHNL_SCAN_DISABLED));
15403
15404 status = sme_HandleDFSChanScan(pHddCtx->hHal);
15405 if (!HAL_STATUS_SUCCESS(status))
15406 {
15407 hddLog(LOGE,
15408 FL("Failed in sme_HandleDFSChanScan (err=%d)"), status);
15409 return status;
15410 }
15411
15412 return status;
15413}
15414
Nirav Shah7e3c8132015-06-22 23:51:42 +053015415static int hdd_log2_ceil(unsigned value)
15416{
15417 /* need to switch to unsigned math so that negative values
15418 * will right-shift towards 0 instead of -1
15419 */
15420 unsigned tmp = value;
15421 int log2 = -1;
15422
15423 if (value == 0)
15424 return 0;
15425
15426 while (tmp) {
15427 log2++;
15428 tmp >>= 1;
15429 }
15430 if (1U << log2 != value)
15431 log2++;
15432
15433 return log2;
15434}
15435
15436/**
15437 * hdd_sta_id_hash_attach() - initialize sta id to macaddr hash
15438 * @pAdapter: adapter handle
15439 *
15440 * Return: vos status
15441 */
15442VOS_STATUS hdd_sta_id_hash_attach(hdd_adapter_t *pAdapter)
15443{
15444 int hash_elem, log2, i;
15445
15446 spin_lock_bh( &pAdapter->sta_hash_lock);
15447 if (pAdapter->is_sta_id_hash_initialized == VOS_TRUE) {
15448 spin_unlock_bh( &pAdapter->sta_hash_lock);
15449 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
15450 "%s: hash already attached for session id %d",
15451 __func__, pAdapter->sessionId);
15452 return VOS_STATUS_SUCCESS;
15453 }
15454 spin_unlock_bh( &pAdapter->sta_hash_lock);
15455
15456 hash_elem = WLAN_MAX_STA_COUNT;
15457 hash_elem *= HDD_STA_ID_HASH_MULTIPLIER;
15458 log2 = hdd_log2_ceil(hash_elem);
15459 hash_elem = 1 << log2;
15460
15461 pAdapter->sta_id_hash.mask = hash_elem - 1;
15462 pAdapter->sta_id_hash.idx_bits = log2;
15463 pAdapter->sta_id_hash.bins =
15464 vos_mem_malloc(hash_elem *sizeof(hdd_list_t));
15465 if (!pAdapter->sta_id_hash.bins) {
15466 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
15467 "%s: malloc failed for session %d",
15468 __func__, pAdapter->sessionId);
15469 return VOS_STATUS_E_NOMEM;
15470 }
15471
15472 for (i = 0; i < hash_elem; i++)
15473 hdd_list_init(&pAdapter->sta_id_hash.bins[i], WLAN_MAX_STA_COUNT);
15474
15475 spin_lock_bh( &pAdapter->sta_hash_lock);
15476 pAdapter->is_sta_id_hash_initialized = VOS_TRUE;
15477 spin_unlock_bh( &pAdapter->sta_hash_lock);
15478 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
15479 "%s: Station ID Hash attached for session id %d",
15480 __func__, pAdapter->sessionId);
15481
15482 return VOS_STATUS_SUCCESS;
15483}
15484
15485/**
15486 * hdd_sta_id_hash_detach() - deinit sta_id to macaddr hash
15487 * @pAdapter: adapter handle
15488 *
15489 * Return: vos status
15490 */
15491VOS_STATUS hdd_sta_id_hash_detach(hdd_adapter_t *pAdapter)
15492{
15493 int hash_elem, i;
15494 v_SIZE_t size;
15495
15496 spin_lock_bh( &pAdapter->sta_hash_lock);
15497 if (pAdapter->is_sta_id_hash_initialized != VOS_TRUE) {
15498 spin_unlock_bh( &pAdapter->sta_hash_lock);
15499 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
15500 "%s: hash not initialized for session id %d",
15501 __func__, pAdapter->sessionId);
15502 return VOS_STATUS_SUCCESS;
15503 }
15504
15505 pAdapter->is_sta_id_hash_initialized = VOS_FALSE;
15506 spin_unlock_bh( &pAdapter->sta_hash_lock);
15507
15508 hash_elem = 1 << pAdapter->sta_id_hash.idx_bits;
15509
15510 /* free all station info*/
15511 for (i = 0; i < hash_elem; i++) {
15512 hdd_list_size(&pAdapter->sta_id_hash.bins[i], &size);
15513 if (size != 0) {
15514 VOS_STATUS status;
15515 hdd_staid_hash_node_t *sta_info_node = NULL;
15516 hdd_staid_hash_node_t *next_node = NULL;
15517 status = hdd_list_peek_front ( &pAdapter->sta_id_hash.bins[i],
15518 (hdd_list_node_t**) &sta_info_node );
15519
15520 while ( NULL != sta_info_node && VOS_STATUS_SUCCESS == status )
15521 {
15522 status = hdd_list_remove_node( &pAdapter->sta_id_hash.bins[i],
15523 &sta_info_node->node);
15524 vos_mem_free(sta_info_node);
15525
15526 status = hdd_list_peek_next (&pAdapter->sta_id_hash.bins[i],
15527 (hdd_list_node_t*)sta_info_node,
15528 (hdd_list_node_t**)&next_node);
15529 sta_info_node = next_node;
15530 }
15531 }
15532 }
15533
15534 vos_mem_free(pAdapter->sta_id_hash.bins);
15535 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
15536 "%s: Station ID Hash detached for session id %d",
15537 __func__, pAdapter->sessionId);
15538 return VOS_STATUS_SUCCESS;
15539}
15540
15541/**
15542 * hdd_sta_id_hash_calculate_index() - derive index from macaddr
15543 * @pAdapter: adapter handle
15544 * @mac_addr_in: input mac address
15545 *
15546 * Return: index derived from mac address
15547 */
15548int hdd_sta_id_hash_calculate_index(hdd_adapter_t *pAdapter,
15549 v_MACADDR_t *mac_addr_in)
15550{
15551 uint16 index;
15552 struct hdd_align_mac_addr_t * mac_addr =
15553 (struct hdd_align_mac_addr_t *)mac_addr_in;
15554
15555 index = mac_addr->bytes_ab ^
15556 mac_addr->bytes_cd ^ mac_addr->bytes_ef;
15557 index ^= index >> pAdapter->sta_id_hash.idx_bits;
15558 index &= pAdapter->sta_id_hash.mask;
15559 return index;
15560}
15561
15562/**
15563 * hdd_sta_id_hash_add_entry() - add entry in hash
15564 * @pAdapter: adapter handle
15565 * @sta_id: station id
15566 * @mac_addr: mac address
15567 *
15568 * Return: vos status
15569 */
15570VOS_STATUS hdd_sta_id_hash_add_entry(hdd_adapter_t *pAdapter,
15571 v_U8_t sta_id, v_MACADDR_t *mac_addr)
15572{
15573 uint16 index;
15574 hdd_staid_hash_node_t *sta_info_node = NULL;
15575
Nirav Shah7e3c8132015-06-22 23:51:42 +053015576 index = hdd_sta_id_hash_calculate_index(pAdapter, mac_addr);
15577 sta_info_node = vos_mem_malloc(sizeof(hdd_staid_hash_node_t));
15578 if (!sta_info_node) {
Nirav Shah7e3c8132015-06-22 23:51:42 +053015579 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
15580 "%s: malloc failed", __func__);
15581 return VOS_STATUS_E_NOMEM;
15582 }
15583
15584 sta_info_node->sta_id = sta_id;
15585 vos_mem_copy(&sta_info_node->mac_addr, mac_addr, sizeof(v_MACADDR_t));
15586
Nirav Shah303ed5c2015-08-24 10:29:25 +053015587 spin_lock_bh( &pAdapter->sta_hash_lock);
15588 if (pAdapter->is_sta_id_hash_initialized != VOS_TRUE) {
15589 spin_unlock_bh( &pAdapter->sta_hash_lock);
15590 vos_mem_free(sta_info_node);
15591 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
15592 "%s: hash is not initialized for session id %d",
15593 __func__, pAdapter->sessionId);
15594 return VOS_STATUS_E_FAILURE;
15595 }
15596
Nirav Shah7e3c8132015-06-22 23:51:42 +053015597 hdd_list_insert_back ( &pAdapter->sta_id_hash.bins[index],
15598 (hdd_list_node_t*) sta_info_node );
15599 spin_unlock_bh( &pAdapter->sta_hash_lock);
15600 return VOS_STATUS_SUCCESS;
15601}
15602
15603/**
15604 * hdd_sta_id_hash_remove_entry() - remove entry from hash
15605 * @pAdapter: adapter handle
15606 * @sta_id: station id
15607 * @mac_addr: mac address
15608 *
15609 * Return: vos status
15610 */
15611VOS_STATUS hdd_sta_id_hash_remove_entry(hdd_adapter_t *pAdapter,
15612 v_U8_t sta_id, v_MACADDR_t *mac_addr)
15613{
15614 uint16 index;
15615 VOS_STATUS status;
15616 hdd_staid_hash_node_t *sta_info_node = NULL;
15617 hdd_staid_hash_node_t *next_node = NULL;
15618
15619 spin_lock_bh( &pAdapter->sta_hash_lock);
15620 if (pAdapter->is_sta_id_hash_initialized != VOS_TRUE) {
15621 spin_unlock_bh( &pAdapter->sta_hash_lock);
15622 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
15623 "%s: hash is not initialized for session id %d",
15624 __func__, pAdapter->sessionId);
15625 return VOS_STATUS_E_FAILURE;
15626 }
15627
15628 index = hdd_sta_id_hash_calculate_index(pAdapter, mac_addr);
15629 status = hdd_list_peek_front ( &pAdapter->sta_id_hash.bins[index],
15630 (hdd_list_node_t**) &sta_info_node );
15631
15632 while ( NULL != sta_info_node && VOS_STATUS_SUCCESS == status )
15633 {
15634 if (sta_info_node->sta_id == sta_id) {
15635 status = hdd_list_remove_node( &pAdapter->sta_id_hash.bins[index],
15636 &sta_info_node->node);
15637 vos_mem_free(sta_info_node);
15638 break;
15639 }
15640 status = hdd_list_peek_next (&pAdapter->sta_id_hash.bins[index],
15641 (hdd_list_node_t*)sta_info_node, (hdd_list_node_t**)&next_node);
15642 sta_info_node = next_node;
15643 }
15644 spin_unlock_bh( &pAdapter->sta_hash_lock);
15645 return status;
15646}
15647
15648/**
15649 * hdd_sta_id_find_from_mac_addr() - find sta id from mac address
15650 * @pAdapter: adapter handle
15651 * @mac_addr_in: mac address
15652 *
15653 * Return: station id
15654 */
15655int hdd_sta_id_find_from_mac_addr(hdd_adapter_t *pAdapter,
15656 v_MACADDR_t *mac_addr_in)
15657{
15658 uint8 is_found = 0;
15659 uint8 sta_id = HDD_WLAN_INVALID_STA_ID;
15660 uint16 index;
15661 VOS_STATUS status;
15662 hdd_staid_hash_node_t *sta_info_node = NULL;
15663 hdd_staid_hash_node_t *next_node = NULL;
15664
15665 spin_lock_bh( &pAdapter->sta_hash_lock);
15666 if (pAdapter->is_sta_id_hash_initialized != VOS_TRUE) {
15667 spin_unlock_bh( &pAdapter->sta_hash_lock);
Bhargav Shahce3b32c2015-08-10 12:29:24 +053015668 hddLog(VOS_TRACE_LEVEL_INFO,
Nirav Shah7e3c8132015-06-22 23:51:42 +053015669 FL("hash is not initialized for session id %d"),
15670 pAdapter->sessionId);
15671 return HDD_WLAN_INVALID_STA_ID;
15672 }
15673
15674 index = hdd_sta_id_hash_calculate_index(pAdapter, mac_addr_in);
15675 status = hdd_list_peek_front ( &pAdapter->sta_id_hash.bins[index],
15676 (hdd_list_node_t**) &sta_info_node );
15677
15678 while ( NULL != sta_info_node && VOS_STATUS_SUCCESS == status )
15679 {
15680 if (vos_mem_compare(&sta_info_node->mac_addr,
15681 mac_addr_in, sizeof(v_MACADDR_t))) {
15682 is_found = 1;
15683 sta_id = sta_info_node->sta_id;
15684 break;
15685 }
15686 status = hdd_list_peek_next (&pAdapter->sta_id_hash.bins[index],
15687 (hdd_list_node_t*)sta_info_node,
15688 (hdd_list_node_t**)&next_node);
15689 sta_info_node = next_node;
15690 }
15691 spin_unlock_bh( &pAdapter->sta_hash_lock);
15692 return sta_id;
15693}
15694
c_manjeecfd1efb2015-09-25 19:32:34 +053015695/*FW memory dump feature*/
15696/**
15697 * This structure hold information about the /proc file
15698 *
15699 */
15700static struct proc_dir_entry *proc_file, *proc_dir;
15701
15702/**
15703 * memdump_read() - perform read operation in memory dump proc file
15704 *
15705 * @file - handle for the proc file.
15706 * @buf - pointer to user space buffer.
15707 * @count - number of bytes to be read.
15708 * @pos - offset in the from buffer.
15709 *
15710 * This function performs read operation for the memory dump proc file.
15711 *
15712 * Return: number of bytes read on success, error code otherwise.
15713 */
15714static ssize_t memdump_read(struct file *file, char __user *buf,
15715 size_t count, loff_t *pos)
15716{
15717 int status;
15718 hdd_context_t *hdd_ctx = (hdd_context_t *)PDE_DATA(file_inode(file));
15719 size_t ret_count;
c_manjeef1495642015-10-13 18:35:01 +053015720 loff_t bytes_left;
c_manjeecfd1efb2015-09-25 19:32:34 +053015721 ENTER();
15722
15723 hddLog(LOG1, FL("Read req for size:%zu pos:%llu"), count, *pos);
15724 status = wlan_hdd_validate_context(hdd_ctx);
15725 if (0 != status) {
15726 return -EINVAL;
15727 }
15728
15729 if (!wlan_fwr_mem_dump_test_and_set_read_allowed_bit()) {
15730 hddLog(LOGE, FL("Current mem dump request timed out/failed"));
15731 return -EINVAL;
15732 }
15733
15734 /* run fs_read_handler in an atomic context*/
15735 vos_ssr_protect(__func__);
c_manjeef1495642015-10-13 18:35:01 +053015736 ret_count = wlan_fwr_mem_dump_fsread_handler( buf, count, pos, &bytes_left);
15737 if(bytes_left == 0)
c_manjeecfd1efb2015-09-25 19:32:34 +053015738 {
15739 /*Free the fwr mem dump buffer */
15740 wlan_free_fwr_mem_dump_buffer();
15741 wlan_set_fwr_mem_dump_state(FW_MEM_DUMP_IDLE);
c_manjeef1495642015-10-13 18:35:01 +053015742 ret_count=0;
c_manjeecfd1efb2015-09-25 19:32:34 +053015743 }
15744 /*if SSR/unload code is waiting for memdump_read to finish,signal it*/
15745 vos_ssr_unprotect(__func__);
15746 EXIT();
15747 return ret_count;
15748}
15749
15750/**
15751 * struct memdump_fops - file operations for memory dump feature
15752 * @read - read function for memory dump operation.
15753 *
15754 * This structure initialize the file operation handle for memory
15755 * dump feature
15756 */
15757static const struct file_operations memdump_fops = {
15758 read: memdump_read
15759};
15760
15761/*
15762* wlan_hdd_fw_mem_dump_cb : callback for Fw mem dump request
15763* To be passed by HDD to WDA and called upon receiving of response
15764* from firmware
15765* @fwMemDumpReqContext : memory dump request context
15766* @dump_rsp : dump response from HAL
15767* Returns none
15768*/
15769void wlan_hdd_fw_mem_dump_cb(void *fwMemDumpReqContext,
15770 tAniFwrDumpRsp *dump_rsp)
15771{
c_manjeef1495642015-10-13 18:35:01 +053015772 struct hdd_fw_mem_dump_req_ctx *pHddFwMemDumpCtx = (struct hdd_fw_mem_dump_req_ctx *)fwMemDumpReqContext;
c_manjeecfd1efb2015-09-25 19:32:34 +053015773
c_manjeef1495642015-10-13 18:35:01 +053015774 ENTER();
15775 spin_lock(&hdd_context_lock);
15776 if(!pHddFwMemDumpCtx || (FW_MEM_DUMP_MAGIC != pHddFwMemDumpCtx->magic)) {
15777 spin_unlock(&hdd_context_lock);
15778 return;
15779 }
15780 /* report the status to requesting function and free mem.*/
c_manjeecfd1efb2015-09-25 19:32:34 +053015781 if (dump_rsp->dump_status != eHAL_STATUS_SUCCESS) {
c_manjeef1495642015-10-13 18:35:01 +053015782 hddLog(LOGE, FL("fw dump request declined by fwr"));
15783 //set the request completion variable
15784 complete(&(pHddFwMemDumpCtx->req_completion));
c_manjeecfd1efb2015-09-25 19:32:34 +053015785 //Free the allocated fwr dump
15786 wlan_free_fwr_mem_dump_buffer();
15787 wlan_set_fwr_mem_dump_state(FW_MEM_DUMP_IDLE);
c_manjeecfd1efb2015-09-25 19:32:34 +053015788 }
c_manjeef1495642015-10-13 18:35:01 +053015789 else {
15790 hddLog(LOG1, FL("fw dump request accepted by fwr"));
15791 /* register the HDD callback which will be called by SVC */
15792 wlan_set_svc_fw_mem_dump_req_cb((void*)wlan_hdd_fw_mem_dump_req_cb,(void*)pHddFwMemDumpCtx);
15793 }
15794 spin_unlock(&hdd_context_lock);
c_manjeecfd1efb2015-09-25 19:32:34 +053015795 EXIT();
15796
15797}
15798
15799/**
15800 * memdump_procfs_remove() - Remove file/dir under procfs for memory dump
15801 *
15802 * This function removes file/dir under proc file system that was
15803 * processing firmware memory dump
15804 *
15805 * Return: None
15806 */
15807static void memdump_procfs_remove(void)
15808{
15809 remove_proc_entry(PROCFS_MEMDUMP_NAME, proc_dir);
15810 hddLog(LOG1 , FL("/proc/%s/%s removed\n"),
15811 PROCFS_MEMDUMP_DIR, PROCFS_MEMDUMP_NAME);
15812 remove_proc_entry(PROCFS_MEMDUMP_DIR, NULL);
15813 hddLog(LOG1 , FL("/proc/%s removed\n"), PROCFS_MEMDUMP_DIR);
15814}
15815
15816/**
15817 * memdump_procfs_init() - Initialize procfs for memory dump
15818 *
15819 * @vos_ctx - Global vos context.
15820 *
15821 * This function create file under proc file system to be used later for
15822 * processing firmware memory dump
15823 *
15824 * Return: 0 on success, error code otherwise.
15825 */
15826static int memdump_procfs_init(void *vos_ctx)
15827{
15828 hdd_context_t *hdd_ctx;
15829
15830 hdd_ctx = vos_get_context(VOS_MODULE_ID_HDD, vos_ctx);
15831 if (!hdd_ctx) {
15832 hddLog(LOGE , FL("Invalid HDD context"));
15833 return -EINVAL;
15834 }
15835
15836 proc_dir = proc_mkdir(PROCFS_MEMDUMP_DIR, NULL);
15837 if (proc_dir == NULL) {
15838 remove_proc_entry(PROCFS_MEMDUMP_DIR, NULL);
15839 hddLog(LOGE , FL("Error: Could not initialize /proc/%s"),
15840 PROCFS_MEMDUMP_DIR);
15841 return -ENOMEM;
15842 }
15843
15844 proc_file = proc_create_data(PROCFS_MEMDUMP_NAME,
15845 S_IRUSR | S_IWUSR, proc_dir,
15846 &memdump_fops, hdd_ctx);
15847 if (proc_file == NULL) {
15848 remove_proc_entry(PROCFS_MEMDUMP_NAME, proc_dir);
15849 hddLog(LOGE , FL("Error: Could not initialize /proc/%s"),
15850 PROCFS_MEMDUMP_NAME);
15851 return -ENOMEM;
15852 }
15853
15854 hddLog(LOG1 , FL("/proc/%s/%s created"),
15855 PROCFS_MEMDUMP_DIR, PROCFS_MEMDUMP_NAME);
15856
15857 return 0;
15858}
15859
15860/**
15861 * memdump_init() - Initialization function for memory dump feature
15862 *
15863 * This function creates proc file for memdump feature and registers
15864 * HDD callback function with SME.
15865 *
15866 * Return - 0 on success, error otherwise
15867 */
15868int memdump_init(void)
15869{
15870 hdd_context_t *hdd_ctx;
15871 void *vos_ctx;
15872 int status = 0;
15873
15874 vos_ctx = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
15875 if (!vos_ctx) {
15876 hddLog(LOGE, FL("Invalid VOS context"));
15877 return -EINVAL;
15878 }
15879
15880 hdd_ctx = vos_get_context(VOS_MODULE_ID_HDD, vos_ctx);
15881 if (!hdd_ctx) {
15882 hddLog(LOGE , FL("Invalid HDD context"));
15883 return -EINVAL;
15884 }
15885
15886 status = memdump_procfs_init(vos_ctx);
15887 if (status) {
15888 hddLog(LOGE , FL("Failed to create proc file"));
15889 return status;
15890 }
15891
15892 return 0;
15893}
15894
15895/**
15896 * memdump_deinit() - De initialize memdump feature
15897 *
15898 * This function removes proc file created for memdump feature.
15899 *
15900 * Return: None
15901 */
15902int memdump_deinit(void)
15903{
15904 hdd_context_t *hdd_ctx;
15905 void *vos_ctx;
15906
15907 vos_ctx = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
15908 if (!vos_ctx) {
15909 hddLog(LOGE, FL("Invalid VOS context"));
15910 return -EINVAL;
15911 }
15912
15913 hdd_ctx = vos_get_context(VOS_MODULE_ID_HDD, vos_ctx);
15914 if(!hdd_ctx) {
15915 hddLog(LOGE , FL("Invalid HDD context"));
15916 return -EINVAL;
15917 }
15918
15919 memdump_procfs_remove();
15920 return 0;
15921}
15922
15923/**
15924 * wlan_hdd_fw_mem_dump_req(pHddCtx) - common API(cfg80211/ioctl) for requesting fw mem dump to SME
15925 * Return: HAL status
15926 */
15927
15928int wlan_hdd_fw_mem_dump_req(hdd_context_t * pHddCtx)
15929{
15930 tAniFwrDumpReq fw_mem_dump_req={0};
c_manjeef1495642015-10-13 18:35:01 +053015931 struct hdd_fw_mem_dump_req_ctx fw_mem_dump_ctx;
c_manjeecfd1efb2015-09-25 19:32:34 +053015932 eHalStatus status = eHAL_STATUS_FAILURE;
Abhishek Singh4eca9822015-12-09 18:07:34 +053015933 int ret=0, result;
c_manjeecfd1efb2015-09-25 19:32:34 +053015934 ENTER();
c_manjeef1495642015-10-13 18:35:01 +053015935
c_manjeecfd1efb2015-09-25 19:32:34 +053015936 /*Check whether a dump request is already going on
15937 *Caution this function will free previously held memory if new dump request is allowed*/
15938 if (!wlan_fwr_mem_dump_test_and_set_write_allowed_bit()) {
15939 hddLog(LOGE, FL("Fw memdump already in progress"));
15940 return -EBUSY;
15941 }
15942 //Allocate memory for fw mem dump buffer
15943 ret = wlan_fwr_mem_dump_buffer_allocation();
15944 if(ret == -EFAULT)
15945 {
15946 hddLog(LOGE, FL("Fwr mem dump not supported by FW"));
15947 return ret;
15948 }
15949 if (0 != ret) {
15950 hddLog(LOGE, FL("Fwr mem Allocation failed"));
15951 return -ENOMEM;
15952 }
c_manjeef1495642015-10-13 18:35:01 +053015953 init_completion(&fw_mem_dump_ctx.req_completion);
15954 fw_mem_dump_ctx.magic = FW_MEM_DUMP_MAGIC;
15955 fw_mem_dump_ctx.status = false;
15956
c_manjeecfd1efb2015-09-25 19:32:34 +053015957 fw_mem_dump_req.fwMemDumpReqCallback = wlan_hdd_fw_mem_dump_cb;
c_manjeef1495642015-10-13 18:35:01 +053015958 fw_mem_dump_req.fwMemDumpReqContext = &fw_mem_dump_ctx;
c_manjeecfd1efb2015-09-25 19:32:34 +053015959 status = sme_FwMemDumpReq(pHddCtx->hHal, &fw_mem_dump_req);
15960 if(eHAL_STATUS_SUCCESS != status)
15961 {
15962 hddLog(VOS_TRACE_LEVEL_ERROR,
15963 "%s: fw_mem_dump_req failed ", __func__);
15964 wlan_free_fwr_mem_dump_buffer();
c_manjeef1495642015-10-13 18:35:01 +053015965 ret = -EFAULT;
15966 goto cleanup;
c_manjeecfd1efb2015-09-25 19:32:34 +053015967 }
c_manjeef1495642015-10-13 18:35:01 +053015968 /*wait for fw mem dump completion to send event to userspace*/
Abhishek Singh4eca9822015-12-09 18:07:34 +053015969 result =
15970 wait_for_completion_timeout(&fw_mem_dump_ctx.req_completion,
15971 msecs_to_jiffies(FW_MEM_DUMP_TIMEOUT_MS));
15972 if (0 >= result )
c_manjeef1495642015-10-13 18:35:01 +053015973 {
15974 hddLog(VOS_TRACE_LEVEL_ERROR,
Abhishek Singh4eca9822015-12-09 18:07:34 +053015975 "%s: fw_mem_dump_req timeout %d ", __func__,result);
15976 ret = -ETIMEDOUT;
c_manjeef1495642015-10-13 18:35:01 +053015977 }
15978cleanup:
15979 spin_lock(&hdd_context_lock);
15980 fw_mem_dump_ctx.magic = 0;
Abhishek Singh4eca9822015-12-09 18:07:34 +053015981 if(!ret && !fw_mem_dump_ctx.status)
15982 ret = -EFAULT;
c_manjeef1495642015-10-13 18:35:01 +053015983 spin_unlock(&hdd_context_lock);
c_manjeecfd1efb2015-09-25 19:32:34 +053015984
c_manjeef1495642015-10-13 18:35:01 +053015985 EXIT();
Abhishek Singh4eca9822015-12-09 18:07:34 +053015986 return ret;
c_manjeef1495642015-10-13 18:35:01 +053015987}
15988
15989/**
15990 * HDD callback which will be called by SVC to indicate mem dump completion.
15991 */
15992void wlan_hdd_fw_mem_dump_req_cb(struct hdd_fw_mem_dump_req_ctx* pHddFwMemDumpCtx)
15993{
15994 if (!pHddFwMemDumpCtx) {
15995 hddLog(VOS_TRACE_LEVEL_ERROR,
15996 "%s: HDD context not valid ", __func__);
15997 return;
15998 }
15999 spin_lock(&hdd_context_lock);
16000 /* check the req magic and set status */
16001 if (pHddFwMemDumpCtx->magic == FW_MEM_DUMP_MAGIC)
16002 {
16003 pHddFwMemDumpCtx->status = true;
16004 //signal the completion
16005 complete(&(pHddFwMemDumpCtx->req_completion));
16006 }
16007 else
16008 {
16009 hddLog(VOS_TRACE_LEVEL_ERROR,
16010 "%s: fw mem dump request possible timeout ", __func__);
16011 }
16012 spin_unlock(&hdd_context_lock);
c_manjeecfd1efb2015-09-25 19:32:34 +053016013}
16014
Mahesh A Saptasagar67ab9222015-10-21 15:38:41 +053016015void hdd_initialize_adapter_common(hdd_adapter_t *pAdapter)
16016{
16017 if (NULL == pAdapter)
16018 {
16019 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: pAdapter is NULL ", __func__);
16020 return;
16021 }
16022 init_completion(&pAdapter->session_open_comp_var);
16023 init_completion(&pAdapter->session_close_comp_var);
16024 init_completion(&pAdapter->disconnect_comp_var);
16025 init_completion(&pAdapter->linkup_event_var);
16026 init_completion(&pAdapter->cancel_rem_on_chan_var);
16027 init_completion(&pAdapter->rem_on_chan_ready_event);
16028 init_completion(&pAdapter->pno_comp_var);
16029#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
16030 init_completion(&pAdapter->offchannel_tx_event);
16031#endif
16032 init_completion(&pAdapter->tx_action_cnf_event);
16033#ifdef FEATURE_WLAN_TDLS
16034 init_completion(&pAdapter->tdls_add_station_comp);
16035 init_completion(&pAdapter->tdls_del_station_comp);
16036 init_completion(&pAdapter->tdls_mgmt_comp);
16037 init_completion(&pAdapter->tdls_link_establish_req_comp);
16038#endif
16039
16040#ifdef WLAN_FEATURE_RMC
16041 init_completion(&pAdapter->ibss_peer_info_comp);
16042#endif /* WLAN_FEATURE_RMC */
16043 init_completion(&pAdapter->ula_complete);
16044 init_completion(&pAdapter->change_country_code);
16045
16046#ifdef FEATURE_WLAN_BATCH_SCAN
16047 init_completion(&pAdapter->hdd_set_batch_scan_req_var);
16048 init_completion(&pAdapter->hdd_get_batch_scan_req_var);
16049#endif
Kapil Gupta2b44acb2016-12-30 16:49:51 +053016050 init_completion(&pAdapter->wlan_suspend_comp_var);
Mahesh A Saptasagar67ab9222015-10-21 15:38:41 +053016051
16052 return;
16053}
c_manjeecfd1efb2015-09-25 19:32:34 +053016054
Anurag Chouhan0b29de02016-12-16 13:18:40 +053016055#ifdef MDNS_OFFLOAD
16056
16057/**
16058 * hdd_mdns_enable_offload_done() - mdns enable offload response api
16059 * @padapter: holds adapter
16060 * @status: response status
16061 *
16062 * Return - None
16063 */
16064void hdd_mdns_enable_offload_done(void *padapter, VOS_STATUS status)
16065{
16066 hdd_adapter_t* adapter = (hdd_adapter_t*) padapter;
16067
16068 ENTER();
16069
16070 if (NULL == adapter)
16071 {
16072 hddLog(VOS_TRACE_LEVEL_ERROR,
16073 "%s: adapter is NULL",__func__);
16074 return;
16075 }
16076
16077 adapter->mdns_status.mdns_enable_status = status;
16078 vos_event_set(&adapter->mdns_status.vos_event);
16079 return;
16080}
16081
16082/**
16083 * hdd_mdns_fqdn_offload_done() - mdns fqdn offload response api
16084 * @padapter: holds adapter
16085 * @status: responce status
16086 *
16087 * Return - None
16088 */
16089void hdd_mdns_fqdn_offload_done(void *padapter, VOS_STATUS status)
16090{
16091 hdd_adapter_t* adapter = (hdd_adapter_t*) padapter;
16092
16093 ENTER();
16094
16095 if (NULL == adapter)
16096 {
16097 hddLog(VOS_TRACE_LEVEL_ERROR,
16098 "%s: adapter is NULL",__func__);
16099 return;
16100 }
16101
16102 adapter->mdns_status.mdns_fqdn_status = status;
16103 return;
16104}
16105
16106/**
16107 * hdd_mdns_resp_offload_done() - mdns resp offload response api
16108 * @padapter: holds adapter
16109 * @status: responce status
16110 *
16111 * Return - None
16112 */
16113void hdd_mdns_resp_offload_done(void *padapter, VOS_STATUS status)
16114{
16115 hdd_adapter_t* adapter = (hdd_adapter_t*) padapter;
16116
16117 ENTER();
16118
16119 if (NULL == adapter)
16120 {
16121 hddLog(VOS_TRACE_LEVEL_ERROR,
16122 "%s: adapter is NULL",__func__);
16123 return;
16124 }
16125
16126 adapter->mdns_status.mdns_resp_status = status;
16127 return;
16128}
16129
16130/**
16131 * wlan_hdd_mdns_process_response_dname() - Process mDNS domain name
16132 * @response: Pointer to a struct hdd_mdns_resp_info
16133 * @resp_info: Pointer to a struct tSirMDNSResponseInfo
16134 *
16135 * This function will pack the whole domain name without compression. It will
16136 * add the leading len for each field and add zero length octet to terminate
16137 * the domain name.
16138 *
16139 * Return: Return boolean. TRUE for success, FALSE for fail.
16140 */
16141static bool
16142wlan_hdd_mdns_process_response_dname(struct hdd_mdns_resp_info *response,
16143 sir_mdns_resp_info resp_info)
16144{
16145 uint8_t num;
16146 uint16_t idx;
16147 uint8_t len = 0;
16148
16149 if ((response == NULL) || (response->data == NULL) ||
16150 (response->offset == NULL)) {
16151 hddLog(LOGE, FL("Either data or offset in response is NULL!"));
16152 return FALSE;
16153 }
16154
16155 if ((resp_info == NULL) ||
16156 (resp_info->resp_len >= MAX_MDNS_RESP_LEN)) {
16157 hddLog(LOGE, FL("resp_len exceeds %d!"), MAX_MDNS_RESP_LEN);
16158 return FALSE;
16159 }
16160
16161 for (num = 0; num < response->num_entries; num++) {
16162 response->offset[num] =
16163 resp_info->resp_len + MDNS_HEADER_LEN;
16164 idx = num * MAX_LEN_DOMAINNAME_FIELD;
16165 len = strlen((char *)&response->data[idx]);
16166 if ((resp_info->resp_len + len + 1) >= MAX_MDNS_RESP_LEN) {
16167 hddLog(LOGE, FL("resp_len exceeds %d!"),
16168 MAX_MDNS_RESP_LEN);
16169 return FALSE;
16170 }
16171 resp_info->resp_data[resp_info->resp_len] = len;
16172 resp_info->resp_len++;
16173 vos_mem_copy(&resp_info->resp_data[resp_info->resp_len],
16174 &response->data[idx], len);
16175 resp_info->resp_len += len;
16176 }
16177
16178 /* The domain name terminates with the zero length octet */
16179 if (num == response->num_entries) {
16180 if (resp_info->resp_len >= MAX_MDNS_RESP_LEN) {
16181 hddLog(LOGE, FL("resp_len exceeds %d!"),
16182 MAX_MDNS_RESP_LEN);
16183 return FALSE;
16184 }
16185 resp_info->resp_data[resp_info->resp_len] = 0;
16186 resp_info->resp_len++;
16187 }
16188
16189 return TRUE;
16190}
16191
16192/**
16193 * wlan_hdd_mdns_format_response_u16() - Form uint16_t response data
16194 * @value: The uint16_t value is formed to the struct tSirMDNSResponseInfo
16195 * @resp_info: Pointer to a struct tSirMDNSResponseInfo
16196 *
16197 * Return: None
16198 */
16199static void wlan_hdd_mdns_format_response_u16(uint16_t value,
16200 sir_mdns_resp_info resp_info)
16201{
16202 uint8_t val_u8;
16203
16204 if ((resp_info == NULL) || (resp_info->resp_data == NULL))
16205 return;
16206 val_u8 = (value & 0xff00) >> 8;
16207 resp_info->resp_data[resp_info->resp_len++] = val_u8;
16208 val_u8 = value & 0xff;
16209 resp_info->resp_data[resp_info->resp_len++] = val_u8;
16210}
16211
16212/**
16213 * wlan_hdd_mdns_format_response_u32() - Form uint32_t response data
16214 * @value: The uint32_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_u32(uint32_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 & 0xff000000) >> 24;
16227 resp_info->resp_data[resp_info->resp_len++] = val_u8;
16228 val_u8 = (value & 0xff0000) >> 16;
16229 resp_info->resp_data[resp_info->resp_len++] = val_u8;
16230 val_u8 = (value & 0xff00) >> 8;
16231 resp_info->resp_data[resp_info->resp_len++] = val_u8;
16232 val_u8 = value & 0xff;
16233 resp_info->resp_data[resp_info->resp_len++] = val_u8;
16234}
16235
16236/**
16237 * wlan_hdd_mdns_process_response_misc() - Process misc info in mDNS response
16238 * @resp_type: Response type for mDNS
16239 * @resp_info: Pointer to a struct tSirMDNSResponseInfo
16240 *
16241 * This function will pack the response type, class and TTL (Time To Live).
16242 *
16243 * Return: Return boolean. TRUE for success, FALSE for fail.
16244 */
16245static bool wlan_hdd_mdns_process_response_misc(uint16_t resp_type,
16246 sir_mdns_resp_info resp_info)
16247{
16248 uint16_t len;
16249
16250 if (resp_info == NULL) {
16251 hddLog(LOGE, FL("resp_info is NULL!"));
16252 return FALSE;
16253 }
16254
16255 len = resp_info->resp_len + (2 * sizeof(uint16_t) + sizeof(uint32_t));
16256 if (len >= MAX_MDNS_RESP_LEN) {
16257 hddLog(LOGE, FL("resp_len exceeds %d!"), MAX_MDNS_RESP_LEN);
16258 return FALSE;
16259 }
16260
16261 /* Fill Type, Class, TTL */
16262 wlan_hdd_mdns_format_response_u16(resp_type, resp_info);
16263 wlan_hdd_mdns_format_response_u16(MDNS_CLASS, resp_info);
16264 wlan_hdd_mdns_format_response_u32(MDNS_TTL, resp_info);
16265
16266 return TRUE;
16267}
16268
16269/**
16270 * wlan_hdd_mdns_compress_data() - Compress the domain name in mDNS response
16271 * @resp_info: Pointer to a struct tSirMDNSResponseInfo
16272 * @response_dst: The response which domain name is compressed.
16273 * @response_src: The response which domain name is matched with response_dst.
16274 * Its offset is used for data compression.
16275 * @num_matched: The number of matched entries between response_dst and
16276 * response_src
16277 *
16278 * This function will form the different fields of domain name in response_dst
16279 * if any. Then use the offset of the matched domain name in response_src to
16280 * compress the matched domain name.
16281 *
16282 * Return: Return boolean. TRUE for success, FALSE for fail.
16283 */
16284static bool
16285wlan_hdd_mdns_compress_data(sir_mdns_resp_info resp_info,
16286 struct hdd_mdns_resp_info *response_dst,
16287 struct hdd_mdns_resp_info *response_src,
16288 uint8_t num_matched)
16289{
16290 uint8_t num, num_diff;
16291 uint16_t value, idx;
16292 uint8_t len = 0;
16293
16294 if ((response_src == NULL) || (response_dst == NULL) ||
16295 (resp_info == NULL)) {
16296 hddLog(LOGE, FL("response info is NULL!"));
16297 return FALSE;
16298 }
16299
16300 if (response_dst->num_entries < num_matched) {
16301 hddLog(LOGE, FL("num_entries is less than num_matched!"));
16302 return FALSE;
16303 }
16304
16305 if (resp_info->resp_len >= MAX_MDNS_RESP_LEN) {
16306 hddLog(LOGE, FL("resp_len exceeds %d!"), MAX_MDNS_RESP_LEN);
16307 return FALSE;
16308 }
16309
16310 num_diff = response_dst->num_entries - num_matched;
16311 if ((num_diff > 0) && (response_dst->data == NULL)) {
16312 hddLog(LOGE, FL("response_dst->data is NULL!"));
16313 return FALSE;
16314 }
16315
16316 /*
16317 * Handle the unmatched string at the beginning
16318 * Store the length of octets and the octets
16319 */
16320 for (num = 0; num < num_diff; num++) {
16321 response_dst->offset[num] =
16322 resp_info->resp_len + MDNS_HEADER_LEN;
16323 idx = num * MAX_LEN_DOMAINNAME_FIELD;
16324 len = strlen((char *)&response_dst->data[idx]);
16325 if ((resp_info->resp_len + len + 1) >= MAX_MDNS_RESP_LEN) {
16326 hddLog(LOGE, FL("resp_len exceeds %d!"),
16327 MAX_MDNS_RESP_LEN);
16328 return FALSE;
16329 }
16330 resp_info->resp_data[resp_info->resp_len] = len;
16331 resp_info->resp_len++;
16332 vos_mem_copy(&resp_info->resp_data[resp_info->resp_len],
16333 &response_dst->data[idx], len);
16334 resp_info->resp_len += len;
16335 }
16336 /*
16337 * Handle the matched string from the end
16338 * Just keep the offset and mask the leading two bit
16339 */
16340 if (response_src->num_entries >= num_matched) {
16341 num_diff = response_src->num_entries - num_matched;
16342 value = response_src->offset[num_diff];
16343 if (value > 0) {
16344 value |= 0xc000;
16345 if ((resp_info->resp_len + sizeof(uint16_t)) >=
16346 MAX_MDNS_RESP_LEN) {
16347 hddLog(LOGE, FL("resp_len exceeds %d!"),
16348 MAX_MDNS_RESP_LEN);
16349 return FALSE;
16350 }
16351 wlan_hdd_mdns_format_response_u16(value, resp_info);
16352 return TRUE;
16353 }
16354 }
16355 return FALSE;
16356}
16357
16358/**
16359 * wlan_hdd_mdns_reset_response() - Reset the response info
16360 * @response: The response which info is reset.
16361 *
16362 * Return: None
16363 */
16364static void wlan_hdd_mdns_reset_response(struct hdd_mdns_resp_info *response)
16365{
16366 if (response == NULL)
16367 return;
16368 response->num_entries = 0;
16369 response->data = NULL;
16370 response->offset = NULL;
16371}
16372
16373/**
16374 * wlan_hdd_mdns_init_response() - Initialize the response info
16375 * @response: The response which info is initiatized.
16376 * @resp_dname: The domain name string which might be tokenized.
16377 *
16378 * This function will allocate the memory for both response->data and
16379 * response->offset. Besides, it will also tokenize the domain name to some
16380 * entries and fill response->num_entries with the num of entries.
16381 *
16382 * Return: Return boolean. TRUE for success, FALSE for fail.
16383 */
16384static bool wlan_hdd_mdns_init_response(struct hdd_mdns_resp_info *response,
16385 uint8_t *resp_dname, char separator)
16386{
16387 uint16_t size;
16388
16389 if ((resp_dname == NULL) || (response == NULL)) {
16390 hddLog(LOGE, FL("resp_dname or response is NULL!"));
16391 return FALSE;
16392 }
16393
16394 size = MAX_NUM_FIELD_DOMAINNAME * MAX_LEN_DOMAINNAME_FIELD;
16395 response->data = vos_mem_malloc(size);
16396 if (response->data) {
16397 vos_mem_zero(response->data, size);
16398 if (VOS_STATUS_SUCCESS !=
16399 hdd_string_to_string_array((char *)resp_dname,
16400 response->data,
16401 separator,
16402 &response->num_entries,
16403 MAX_NUM_FIELD_DOMAINNAME,
16404 MAX_LEN_DOMAINNAME_FIELD)) {
16405 hddLog(LOGE, FL("hdd_string_to_string_array fail!"));
16406 goto err_init_resp;
16407 }
16408
16409 if ((response->num_entries > 0) &&
16410 (strlen((char *)&response->data[0]) > 0)) {
16411 size = sizeof(uint16_t) * response->num_entries;
16412 response->offset = vos_mem_malloc(size);
16413 if (response->offset) {
16414 vos_mem_zero(response->offset, size);
16415 return TRUE;
16416 }
16417 }
16418 }
16419
16420err_init_resp:
16421 if (response->data)
16422 vos_mem_free(response->data);
16423 wlan_hdd_mdns_reset_response(response);
16424 return FALSE;
16425}
16426
16427/**
16428 * wlan_hdd_mdns_find_entries_from_end() - Find the matched entries
16429 * @response1: The response info is used to be compared.
16430 * @response2: The response info is used to be compared.
16431 *
16432 * This function will find the matched entries from the end.
16433 *
16434 * Return: Return the number of the matched entries.
16435 */
16436static uint8_t
16437wlan_hdd_mdns_find_entries_from_end(struct hdd_mdns_resp_info *response1,
16438 struct hdd_mdns_resp_info *response2)
16439{
16440 uint8_t min, len1, i;
16441 uint16_t num1, num2;
16442 uint8_t num_matched = 0;
16443
16444 min = VOS_MIN(response1->num_entries, response2->num_entries);
16445
16446 for (i = 1; i <= min; i++) {
16447 num1 = (response1->num_entries - i);
16448 num1 *= MAX_LEN_DOMAINNAME_FIELD;
16449 num2 = (response2->num_entries - i);
16450 num2 *= MAX_LEN_DOMAINNAME_FIELD;
16451 len1 = strlen((char *)&response1->data[num1]);
16452
16453 if ((len1 == 0) ||
16454 (len1 != strlen((char *)&response2->data[num2])))
16455 break;
16456 if (memcmp(&response1->data[num1],
16457 &response2->data[num2], len1))
16458 break;
16459 else
16460 num_matched++;
16461 }
16462
16463 return num_matched;
16464}
16465
16466/**
16467 * wlan_hdd_mdns_find_max() - Find the maximum number of the matched entries
16468 * @matchedlist: Pointer to the array of struct hdd_mdns_resp_matched
16469 * @numlist: The number of the elements in the array matchedlist.
16470 *
16471 * Find the max number of the matched entries among the array matchedlist.
16472 *
16473 * Return: None
16474 */
16475static void wlan_hdd_mdns_find_max(struct hdd_mdns_resp_matched *matchedlist,
16476 uint8_t numlist)
16477{
16478 int j;
16479 struct hdd_mdns_resp_matched tmp;
16480
16481 /* At least two values are used for sorting */
16482 if ((numlist < 2) || (matchedlist == NULL)) {
16483 hddLog(LOGE, FL("At least two values are used for sorting!"));
16484 return;
16485 }
16486
16487 for (j = 0; j < numlist-1; j++) {
16488 if (matchedlist[j].num_matched >
16489 matchedlist[j+1].num_matched) {
16490 vos_mem_copy(&tmp, &matchedlist[j],
16491 sizeof(struct hdd_mdns_resp_matched));
16492 vos_mem_copy(&matchedlist[j], &matchedlist[j+1],
16493 sizeof(struct hdd_mdns_resp_matched));
16494 vos_mem_copy(&matchedlist[j+1], &tmp,
16495 sizeof(struct hdd_mdns_resp_matched));
16496 }
16497 }
16498}
16499
16500/**
16501 * wlan_hdd_mdns_pack_response_type_a() - Pack Type A response
16502 * @ini_config: Pointer to the struct hdd_config_t
16503 * @resp_info: Pointer to the struct tSirMDNSResponseInfo
16504 * @resptype_a: Pointer to the struct hdd_mdns_resp_info of Type A
16505 *
16506 * Type A response include QName, response type, class, TTL and Ipv4.
16507 *
16508 * Return: Return boolean. TRUE for success, FALSE for fail.
16509 */
16510static bool
16511wlan_hdd_mdns_pack_response_type_a(hdd_config_t *ini_config,
16512 sir_mdns_resp_info resp_info,
16513 struct hdd_mdns_resp_info *resptype_a)
16514{
16515 uint16_t value;
16516 uint32_t len;
16517
16518 ENTER();
16519 if ((ini_config == NULL) || (resp_info == NULL) ||
16520 (resptype_a == NULL)) {
16521 hddLog(LOGE, FL("ini_config or response info is NULL!"));
16522 return FALSE;
16523 }
16524
16525 /* No Type A response */
16526 if (strlen((char *)ini_config->mdns_resp_type_a) <= 0)
16527 return TRUE;
16528
16529 /* Wrong response is assigned, just ignore this response */
16530 if (!wlan_hdd_mdns_init_response(resptype_a,
16531 ini_config->mdns_resp_type_a, '.'))
16532 return TRUE;
16533
16534 /* Process response domain name */
16535 if (!wlan_hdd_mdns_process_response_dname(resptype_a, resp_info)) {
16536 hddLog(LOGE, FL("Fail to process mDNS response (%d)!"),
16537 MDNS_TYPE_A);
16538 return FALSE;
16539 }
16540
16541 /* Process response Type, Class, TTL */
16542 if (!wlan_hdd_mdns_process_response_misc(MDNS_TYPE_A, resp_info)) {
16543 hddLog(LOGE, FL("Fail to process mDNS misc response (%d)!"),
16544 MDNS_TYPE_A);
16545 return FALSE;
16546 }
16547
16548 /* Process response RDLength, RData */
16549 len = sizeof(uint16_t) + sizeof(uint32_t);
16550 len += resp_info->resp_len;
16551 if (len >= MAX_MDNS_RESP_LEN) {
16552 hddLog(LOGE, FL("resp_len exceeds %d!"), MAX_MDNS_RESP_LEN);
16553 return FALSE;
16554 }
16555 value = sizeof(uint32_t);
16556 wlan_hdd_mdns_format_response_u16(value, resp_info);
16557 wlan_hdd_mdns_format_response_u32(ini_config->mdns_resp_type_a_ipv4,
16558 resp_info);
16559
16560 EXIT();
16561 return TRUE;
16562}
16563
16564/**
16565 * wlan_hdd_mdns_pack_response_type_txt() - Pack Type Txt response
16566 * @ini_config: Pointer to the struct hdd_config_t
16567 * @resp_info: Pointer to the struct tSirMDNSResponseInfo
16568 * @resptype_txt: Pointer to the struct hdd_mdns_resp_info of Type txt
16569 * @resptype_a: Pointer to the struct hdd_mdns_resp_info of Type A
16570 *
16571 * Type Txt response include QName, response type, class, TTL and text content.
16572 * Also, it will find the matched QName from resptype_A and compress the data.
16573 *
16574 * Return: Return boolean. TRUE for success, FALSE for fail.
16575 */
16576static bool
16577wlan_hdd_mdns_pack_response_type_txt(hdd_config_t *ini_config,
16578 sir_mdns_resp_info resp_info,
16579 struct hdd_mdns_resp_info *resptype_txt,
16580 struct hdd_mdns_resp_info *resptype_a)
16581{
16582 uint8_t num_matched;
16583 uint8_t num;
16584 uint16_t idx;
16585 uint16_t value = 0;
16586 uint32_t len;
16587 uint32_t total_len;
16588 bool status;
16589 struct hdd_mdns_resp_info resptype_content;
16590
16591 ENTER();
16592
16593 if ((ini_config == NULL) || (resp_info == NULL) ||
16594 (resptype_txt == NULL)) {
16595 hddLog(LOGE, FL("ini_config or response info is NULL!"));
16596 return FALSE;
16597 }
16598
16599 /* No Type Txt response */
16600 if (strlen((char *)ini_config->mdns_resp_type_txt) <= 0)
16601 return TRUE;
16602
16603 /* Wrong response is assigned, just ignore this response */
16604 if (!wlan_hdd_mdns_init_response(resptype_txt,
16605 ini_config->mdns_resp_type_txt, '.'))
16606 return TRUE;
16607
16608 /*
16609 * For data compression
16610 * Check if any strings are matched with Type A response
16611 */
16612 if (resptype_a && (resptype_a->num_entries > 0)) {
16613 num_matched = wlan_hdd_mdns_find_entries_from_end(resptype_txt,
16614 resptype_a);
16615 if (num_matched > 0) {
16616 if (!wlan_hdd_mdns_compress_data(resp_info,
16617 resptype_txt, resptype_a, num_matched)) {
16618 hddLog(LOGE, FL("Fail to compress mDNS "
16619 "response (%d)!"), MDNS_TYPE_TXT);
16620 return FALSE;
16621 }
16622 } else {
16623 /*
16624 * num_matched is zero. Error!
16625 * At least ".local" is needed.
16626 */
16627 hddLog(LOGE, FL("No matched string! Fail to pack mDNS "
16628 "response (%d)!"), MDNS_TYPE_TXT);
16629 return FALSE;
16630 }
16631 } else {
16632 /* no TypeA response, so show the whole data */
16633 if (!wlan_hdd_mdns_process_response_dname(resptype_txt,
16634 resp_info)) {
16635 hddLog(LOGE, FL("Fail to process mDNS response (%d)!"),
16636 MDNS_TYPE_TXT);
16637 return FALSE;
16638 }
16639 }
16640
16641 /* Process response Type, Class, TTL */
16642 if (!wlan_hdd_mdns_process_response_misc(MDNS_TYPE_TXT, resp_info)) {
16643 hddLog(LOGE, FL("Fail to process mDNS misc response (%d)!"),
16644 MDNS_TYPE_TXT);
16645 return FALSE;
16646 }
16647
16648 /*
16649 * Process response RDLength, RData.
16650 * TypeTxt RData include len.
16651 */
16652 status = wlan_hdd_mdns_init_response(&resptype_content,
16653 ini_config->mdns_resp_type_txt_content,
16654 '/');
16655 if (status == FALSE) {
16656 hddLog(LOGE, FL("wlan_hdd_mdns_init_response FAIL"));
16657 return FALSE;
16658 }
16659
16660 for (num = 0; num < resptype_content.num_entries; num++) {
16661 idx = num * MAX_LEN_DOMAINNAME_FIELD;
16662 value += strlen((char *)&resptype_content.data[idx]);
16663 }
16664
16665 /* content len is uint16_t */
16666 total_len = sizeof(uint16_t);
16667 total_len += resp_info->resp_len + value +
16668 resptype_content.num_entries;
16669
16670 if (total_len >= MAX_MDNS_RESP_LEN) {
16671 hddLog(LOGE, FL("resp_len exceeds %d!"), MAX_MDNS_RESP_LEN);
16672 return FALSE;
16673 }
16674 wlan_hdd_mdns_format_response_u16(value + resptype_content.num_entries,
16675 resp_info);
16676
16677 for (num = 0; num < resptype_content.num_entries; num++) {
16678 idx = num * MAX_LEN_DOMAINNAME_FIELD;
16679 len = strlen((char *)&resptype_content.data[idx]);
16680 resp_info->resp_data[resp_info->resp_len] = len;
16681 resp_info->resp_len++;
16682
16683 vos_mem_copy(&resp_info->resp_data[resp_info->resp_len],
16684 &resptype_content.data[idx], len);
16685
16686 resp_info->resp_len += len;
16687 hddLog(LOG1, FL("index = %d, len = %d, str = %s"),
16688 num, len, &resptype_content.data[idx]);
16689 }
16690
16691 EXIT();
16692 return TRUE;
16693}
16694
16695/**
16696 * wlan_hdd_mdns_pack_response_type_ptr_dname() - Pack Type PTR domain name
16697 * @ini_config: Pointer to the struct hdd_config_t
16698 * @resp_info: Pointer to the struct tSirMDNSResponseInfo
16699 * @resptype_ptr_dn: Pointer to the struct hdd_mdns_resp_info of Type Ptr
16700 * domain name
16701 * @resptype_ptr: Pointer to the struct hdd_mdns_resp_info of Type Ptr
16702 * @resptype_txt: Pointer to the struct hdd_mdns_resp_info of Type Txt
16703 * @resptype_a: Pointer to the struct hdd_mdns_resp_info of Type A
16704 *
16705 * The Type Ptr response include Type PTR domain name in its data field.
16706 * Also, it will find the matched QName from the existing resptype_ptr,
16707 * resptype_txt, resptype_a and then compress the data.
16708 *
16709 * Return: Return boolean. TRUE for success, FALSE for fail.
16710 */
16711static bool
16712wlan_hdd_mdns_pack_response_type_ptr_dname(hdd_config_t *ini_config,
16713 sir_mdns_resp_info resp_info,
16714 struct hdd_mdns_resp_info *resptype_ptr_dn,
16715 struct hdd_mdns_resp_info *resptype_ptr,
16716 struct hdd_mdns_resp_info *resptype_txt,
16717 struct hdd_mdns_resp_info *resptype_a)
16718{
16719 uint8_t num_matched, numlist, size;
16720 struct hdd_mdns_resp_matched matchedlist[MAX_MDNS_RESP_TYPE-1];
16721 struct hdd_mdns_resp_info *resp;
16722
16723 if ((ini_config == NULL) || (resp_info == NULL) ||
16724 (resptype_ptr == NULL) || (resptype_ptr_dn == NULL)) {
16725 hddLog(LOGE, FL("ini_config or response info is NULL!"));
16726 return FALSE;
16727 }
16728
16729 /* No Type Ptr domain name response */
16730 if (strlen((char *)ini_config->mdns_resp_type_ptr_dname) <= 0)
16731 return TRUE;
16732
16733 /* Wrong response is assigned, just ignore this response */
16734 if (!wlan_hdd_mdns_init_response(resptype_ptr_dn,
16735 ini_config->mdns_resp_type_ptr_dname, '.'))
16736 return TRUE;
16737
16738 /*
16739 * For data compression
16740 * Check if any strings are matched with previous
16741 * response.
16742 */
16743 numlist = 0;
16744 size = (MAX_MDNS_RESP_TYPE-1);
16745 size *= sizeof(struct hdd_mdns_resp_matched);
16746 vos_mem_zero(matchedlist, size);
16747 num_matched = wlan_hdd_mdns_find_entries_from_end(resptype_ptr_dn,
16748 resptype_ptr);
16749 if (num_matched > 0) {
16750 matchedlist[numlist].num_matched = num_matched;
16751 matchedlist[numlist].type = MDNS_TYPE_PTR;
16752 numlist++;
16753 }
16754 if (resptype_txt && (resptype_txt->num_entries > 0)) {
16755 num_matched = wlan_hdd_mdns_find_entries_from_end(
16756 resptype_ptr_dn, resptype_txt);
16757 if (num_matched > 0) {
16758 matchedlist[numlist].num_matched = num_matched;
16759 matchedlist[numlist].type = MDNS_TYPE_TXT;
16760 numlist++;
16761 }
16762 }
16763 if (resptype_a && (resptype_a->num_entries > 0)) {
16764 num_matched = wlan_hdd_mdns_find_entries_from_end(
16765 resptype_ptr_dn,resptype_a);
16766 if (num_matched > 0) {
16767 matchedlist[numlist].num_matched = num_matched;
16768 matchedlist[numlist].type = MDNS_TYPE_A;
16769 numlist++;
16770 }
16771 }
16772 if (numlist > 0) {
16773 if (numlist > 1)
16774 wlan_hdd_mdns_find_max(matchedlist, numlist);
16775 resp = NULL;
16776 switch (matchedlist[numlist-1].type) {
16777 case MDNS_TYPE_A:
16778 resp = resptype_a;
16779 break;
16780 case MDNS_TYPE_TXT:
16781 resp = resptype_txt;
16782 break;
16783 case MDNS_TYPE_PTR:
16784 resp = resptype_ptr;
16785 break;
16786 default:
16787 hddLog(LOGE, FL("Fail to compress mDNS response "
16788 "(%d)!"), MDNS_TYPE_PTR_DNAME);
16789 return FALSE;
16790 }
16791 num_matched = matchedlist[numlist-1].num_matched;
16792 if (!wlan_hdd_mdns_compress_data(resp_info, resptype_ptr_dn,
16793 resp, num_matched)) {
16794 hddLog(LOGE, FL("Fail to compress mDNS response "
16795 "(%d)!"), MDNS_TYPE_PTR_DNAME);
16796 return FALSE;
16797 }
16798 } else {
16799 /* num = 0 -> no matched string */
16800 if (!wlan_hdd_mdns_process_response_dname(resptype_ptr_dn,
16801 resp_info)) {
16802 hddLog(LOGE, FL("Fail to process mDNS response (%d)!"),
16803 MDNS_TYPE_PTR_DNAME);
16804 return FALSE;
16805 }
16806 }
16807
16808 return TRUE;
16809}
16810
16811/**
16812 * wlan_hdd_mdns_pack_response_type_ptr() - Pack Type PTR response
16813 * @ini_config: Pointer to the struct hdd_config_t
16814 * @resp_info: Pointer to the struct tSirMDNSResponseInfo
16815 * @resptype_ptr: Pointer to the struct hdd_mdns_resp_info of Type Ptr
16816 * @resptype_ptr_dn: Pointer to the struct hdd_mdns_resp_info of Type Ptr
16817 * domain name
16818 * @resptype_txt: Pointer to the struct hdd_mdns_resp_info of Type Txt
16819 * @resptype_a: Pointer to the struct hdd_mdns_resp_info of Type A
16820 *
16821 * The Type Ptr response include QName, response type, class, TTL and
16822 * Type PTR domain name. Also, it will find the matched QName from the
16823 * existing resptype_txt, resptype_a and then compress the data.
16824 *
16825 * Return: Return boolean. TRUE for success, FALSE for fail.
16826 */
16827static bool
16828wlan_hdd_mdns_pack_response_type_ptr(hdd_config_t *ini_config,
16829 sir_mdns_resp_info resp_info,
16830 struct hdd_mdns_resp_info *resptype_ptr,
16831 struct hdd_mdns_resp_info *resptype_ptr_dn,
16832 struct hdd_mdns_resp_info *resptype_txt,
16833 struct hdd_mdns_resp_info *resptype_a)
16834{
16835 uint8_t num_matched, num_matched1;
16836 uint16_t value;
16837 uint8_t val_u8;
16838 uint32_t offset_data_len, len;
16839
16840 ENTER();
16841 if ((ini_config == NULL) || (resp_info == NULL) ||
16842 (resptype_ptr == NULL) || (resptype_ptr_dn == NULL)) {
16843 hddLog(LOGE, FL("ini_config or response info is NULL!"));
16844 return FALSE;
16845 }
16846
16847 /* No Type Ptr response */
16848 if (strlen((char *)ini_config->mdns_resp_type_ptr) <= 0)
16849 return TRUE;
16850
16851 /* Wrong response is assigned, just ignore this response */
16852 if (!wlan_hdd_mdns_init_response(resptype_ptr,
16853 ini_config->mdns_resp_type_ptr, '.'))
16854 return TRUE;
16855
16856 /*
16857 * For data compression
16858 * Check if any strings are matched with Type A response
16859 */
16860 num_matched = 0;
16861 num_matched1 = 0;
16862 if (resptype_a && (resptype_a->num_entries > 0)) {
16863 num_matched = wlan_hdd_mdns_find_entries_from_end(resptype_ptr,
16864 resptype_a);
16865 }
16866 if (resptype_txt && (resptype_txt->num_entries > 0)) {
16867 num_matched1 = wlan_hdd_mdns_find_entries_from_end(
16868 resptype_ptr, resptype_txt);
16869 }
16870 if ((num_matched != num_matched1) ||
16871 ((num_matched > 0) && (num_matched1 > 0))) {
16872 if (num_matched >= num_matched1) {
16873 if (!wlan_hdd_mdns_compress_data(resp_info,
16874 resptype_ptr, resptype_a, num_matched)) {
16875 hddLog(LOGE, FL("Fail to compress mDNS "
16876 "response (%d)!"), MDNS_TYPE_PTR);
16877 return FALSE;
16878 }
16879 } else {
16880 /* num_matched is less than num_matched1 */
16881 if (!wlan_hdd_mdns_compress_data(resp_info,
16882 resptype_ptr, resptype_txt, num_matched1)) {
16883 hddLog(LOGE, FL("Fail to compress mDNS "
16884 "response (%d)!"), MDNS_TYPE_PTR);
16885 return FALSE;
16886 }
16887 }
16888 } else {
16889 /*
16890 * Both num_matched and num_matched1 are zero.
16891 * no TypeA & TypeTxt
16892 */
16893 if (!wlan_hdd_mdns_process_response_dname(resptype_ptr,
16894 resp_info)) {
16895 hddLog(LOGE, FL("Fail to process mDNS response (%d)!"),
16896 MDNS_TYPE_PTR);
16897 return FALSE;
16898 }
16899 }
16900
16901 /* Process response Type, Class, TTL */
16902 if (!wlan_hdd_mdns_process_response_misc(MDNS_TYPE_PTR, resp_info)) {
16903 hddLog(LOGE, FL("Fail to process mDNS misc response (%d)!"),
16904 MDNS_TYPE_PTR);
16905 return FALSE;
16906 }
16907
16908 /*
16909 * Process response RDLength, RData (Ptr domain name)
16910 * Save the offset of RData length
16911 */
16912 offset_data_len = resp_info->resp_len;
16913 resp_info->resp_len += sizeof(uint16_t);
16914
16915 if (!wlan_hdd_mdns_pack_response_type_ptr_dname(ini_config, resp_info,
16916 resptype_ptr_dn, resptype_ptr,
16917 resptype_txt, resptype_a)) {
16918 return FALSE;
16919 }
16920 /* Set the RData length */
16921 len = offset_data_len + sizeof(uint16_t);
16922 if ((resptype_ptr_dn->num_entries > 0) &&
16923 (resp_info->resp_len > len)) {
16924 value = resp_info->resp_len - len;
16925 val_u8 = (value & 0xff00) >> 8;
16926 resp_info->resp_data[offset_data_len] = val_u8;
16927 val_u8 = value & 0xff;
16928 resp_info->resp_data[offset_data_len+1] = val_u8;
16929 } else {
16930 hddLog(LOGE, FL("Fail to process mDNS response (%d)!"),
16931 MDNS_TYPE_PTR);
16932 return FALSE;
16933 }
16934
16935 EXIT();
16936 return TRUE;
16937}
16938
16939/**
16940 * wlan_hdd_mdns_pack_response_type_srv_target()- Pack Type Service Target
16941 * @ini_config: Pointer to the struct hdd_config_t
16942 * @resp_info: Pointer to the struct tSirMDNSResponseInfo
16943 * @resptype_srv_tgt: Pointer to the struct hdd_mdns_resp_info of Type Srv
16944 * target
16945 * @resptype_srv: Pointer to the struct hdd_mdns_resp_info of Type Srv
16946 * @resptype_ptr: Pointer to the struct hdd_mdns_resp_info of Type Ptr
16947 * @resptype_ptr_dn: Pointer to the struct hdd_mdns_resp_info of Type Ptr
16948 * domain name
16949 * @resptype_txt: Pointer to the struct hdd_mdns_resp_info of Type Txt
16950 * @resptype_a: Pointer to the struct hdd_mdns_resp_info of Type A
16951 *
16952 * The Type service target is one of the data field in the Type SRV response.
16953 * Also, it will find the matched QName from the existing resptype_srv,
16954 * resptype_ptr, resptype_ptr_dn, resptype_txt, resptype_a and then compress
16955 * the data.
16956 *
16957 * Return: Return boolean. TRUE for success, FALSE for fail.
16958 */
16959static bool
16960wlan_hdd_mdns_pack_response_type_srv_target(hdd_config_t *ini_config,
16961 sir_mdns_resp_info resp_info,
16962 struct hdd_mdns_resp_info *resptype_srv_tgt,
16963 struct hdd_mdns_resp_info *resptype_srv,
16964 struct hdd_mdns_resp_info *resptype_ptr,
16965 struct hdd_mdns_resp_info *resptype_ptr_dn,
16966 struct hdd_mdns_resp_info *resptype_txt,
16967 struct hdd_mdns_resp_info *resptype_a)
16968{
16969 uint8_t num_matched, num, size;
16970 struct hdd_mdns_resp_matched matchedlist[MAX_MDNS_RESP_TYPE-1];
16971 struct hdd_mdns_resp_info *resp;
16972
16973 if ((ini_config == NULL) || (resp_info == NULL) ||
16974 (resptype_srv == NULL) || (resptype_srv_tgt == NULL)) {
16975 hddLog(LOGE, FL("ini_config or response info is NULL!"));
16976 return FALSE;
16977 }
16978
16979 /* No Type Srv Target response */
16980 if (strlen((char *)ini_config->mdns_resp_type_srv_target) <= 0)
16981 return TRUE;
16982
16983 /* Wrong response is assigned, just ignore this response */
16984 if (!wlan_hdd_mdns_init_response(resptype_srv_tgt,
16985 ini_config->mdns_resp_type_srv_target, '.'))
16986 return TRUE;
16987
16988 /*
16989 * For data compression
16990 * Check if any strings are matched with previous response.
16991 */
16992 num = 0;
16993 size = (MAX_MDNS_RESP_TYPE-1);
16994 size *= sizeof(struct hdd_mdns_resp_matched);
16995 vos_mem_zero(matchedlist, size);
16996 num_matched = wlan_hdd_mdns_find_entries_from_end(resptype_srv_tgt,
16997 resptype_srv);
16998 if (num_matched > 0) {
16999 matchedlist[num].num_matched = num_matched;
17000 matchedlist[num].type = MDNS_TYPE_SRV;
17001 num++;
17002 }
17003 if (resptype_ptr && (resptype_ptr->num_entries > 0)) {
17004 if (resptype_ptr_dn && (resptype_ptr_dn->num_entries > 0)) {
17005 num_matched = wlan_hdd_mdns_find_entries_from_end(
17006 resptype_srv_tgt, resptype_ptr_dn);
17007 if (num_matched > 0) {
17008 matchedlist[num].num_matched = num_matched;
17009 matchedlist[num].type = MDNS_TYPE_PTR_DNAME;
17010 num++;
17011 }
17012 }
17013 num_matched = wlan_hdd_mdns_find_entries_from_end(
17014 resptype_srv_tgt, resptype_ptr);
17015 if (num_matched > 0) {
17016 matchedlist[num].num_matched = num_matched;
17017 matchedlist[num].type = MDNS_TYPE_PTR;
17018 num++;
17019 }
17020 }
17021 if (resptype_txt && (resptype_txt->num_entries > 0)) {
17022 num_matched = wlan_hdd_mdns_find_entries_from_end(
17023 resptype_srv_tgt, resptype_txt);
17024 if (num_matched > 0) {
17025 matchedlist[num].num_matched = num_matched;
17026 matchedlist[num].type = MDNS_TYPE_TXT;
17027 num++;
17028 }
17029 }
17030 if (resptype_a && (resptype_a->num_entries > 0)) {
17031 num_matched = wlan_hdd_mdns_find_entries_from_end(
17032 resptype_srv_tgt, resptype_a);
17033 if (num_matched > 0) {
17034 matchedlist[num].num_matched = num_matched;
17035 matchedlist[num].type = MDNS_TYPE_A;
17036 num++;
17037 }
17038 }
17039 if (num > 0) {
17040 if (num > 1)
17041 wlan_hdd_mdns_find_max(matchedlist, num);
17042 resp = NULL;
17043 switch (matchedlist[num-1].type) {
17044 case MDNS_TYPE_A:
17045 resp = resptype_a;
17046 break;
17047 case MDNS_TYPE_TXT:
17048 resp = resptype_txt;
17049 break;
17050 case MDNS_TYPE_PTR:
17051 resp = resptype_ptr;
17052 break;
17053 case MDNS_TYPE_PTR_DNAME:
17054 resp = resptype_ptr_dn;
17055 break;
17056 case MDNS_TYPE_SRV:
17057 resp = resptype_srv;
17058 break;
17059 default:
17060 hddLog(LOGE, FL("Fail to compress mDNS response "
17061 "(%d)!"), MDNS_TYPE_SRV_TARGET);
17062 return FALSE;
17063 }
17064 num_matched = matchedlist[num-1].num_matched;
17065 if (!wlan_hdd_mdns_compress_data(resp_info, resptype_srv_tgt,
17066 resp, num_matched)) {
17067 hddLog(LOGE, FL("Fail to compress mDNS response "
17068 "(%d)!"), MDNS_TYPE_SRV_TARGET);
17069 return FALSE;
17070 }
17071 } else {
17072 /* num = 0 -> no matched string */
17073 if (!wlan_hdd_mdns_process_response_dname(resptype_srv_tgt,
17074 resp_info)) {
17075 hddLog(LOGE, FL("Fail to process mDNS response (%d)!"),
17076 MDNS_TYPE_SRV_TARGET);
17077 return FALSE;
17078 }
17079 }
17080
17081 return TRUE;
17082}
17083
17084/**
17085 * wlan_hdd_mdns_pack_response_type_srv()- Pack Type Service response
17086 * @ini_config: Pointer to the struct hdd_config_t
17087 * @resp_info: Pointer to the struct tSirMDNSResponseInfo
17088 * @resptype_srv: Pointer to the struct hdd_mdns_resp_info of Type Srv
17089 * @resptype_srv_tgt: Pointer to the struct hdd_mdns_resp_info of Type Srv
17090 * target
17091 * @resptype_ptr: Pointer to the struct hdd_mdns_resp_info of Type Ptr
17092 * @resptype_ptr_dn: Pointer to the struct hdd_mdns_resp_info of Type Ptr
17093 * domain name
17094 * @resptype_txt: Pointer to the struct hdd_mdns_resp_info of Type Txt
17095 * @resptype_a: Pointer to the struct hdd_mdns_resp_info of Type A
17096 *
17097 * The Type SRV (Service) response include QName, response type, class, TTL
17098 * and four kinds of data fields. Also, it will find the matched QName from
17099 * the existing resptype_ptr, resptype_ptr_dn, resptype_txt, resptype_a and
17100 * then compress the data.
17101 *
17102 * Return: Return boolean. TRUE for success, FALSE for fail.
17103 */
17104static bool
17105wlan_hdd_mdns_pack_response_type_srv(hdd_config_t *ini_config,
17106 sir_mdns_resp_info resp_info,
17107 struct hdd_mdns_resp_info *resptype_srv,
17108 struct hdd_mdns_resp_info *resptype_srv_tgt,
17109 struct hdd_mdns_resp_info *resptype_ptr,
17110 struct hdd_mdns_resp_info *resptype_ptr_dn,
17111 struct hdd_mdns_resp_info *resptype_txt,
17112 struct hdd_mdns_resp_info *resptype_a)
17113{
17114 uint8_t num_matched, num, size;
17115 uint16_t value;
17116 uint8_t val_u8;
17117 uint32_t offset_data_len, len;
17118 struct hdd_mdns_resp_info *resp;
17119 struct hdd_mdns_resp_matched matchedlist[MAX_MDNS_RESP_TYPE-1];
17120
17121 ENTER();
17122
17123 if ((ini_config == NULL) || (resp_info == NULL) ||
17124 (resptype_srv == NULL) || (resptype_srv_tgt == NULL)) {
17125 hddLog(LOGE, FL("ini_config or response info is NULL!"));
17126 return FALSE;
17127 }
17128
17129 /* No Type Srv response */
17130 if (strlen((char *)ini_config->mdns_resp_type_srv) <= 0)
17131 return TRUE;
17132
17133 /* Wrong response is assigned, just ignore this response */
17134 if (!wlan_hdd_mdns_init_response(resptype_srv,
17135 ini_config->mdns_resp_type_srv, '.'))
17136 return TRUE;
17137
17138 /*
17139 * For data compression
17140 * Check if any strings are matched with Type A response
17141 */
17142 num = 0;
17143 size = (MAX_MDNS_RESP_TYPE-1);
17144 size *= sizeof(struct hdd_mdns_resp_matched);
17145 vos_mem_zero(matchedlist, size);
17146 if (resptype_ptr && (resptype_ptr->num_entries > 0)) {
17147 if (resptype_ptr_dn && (resptype_ptr_dn->num_entries > 0)) {
17148 num_matched = wlan_hdd_mdns_find_entries_from_end(
17149 resptype_srv,
17150 resptype_ptr_dn);
17151 if (num_matched > 0) {
17152 matchedlist[num].num_matched = num_matched;
17153 matchedlist[num].type = MDNS_TYPE_PTR_DNAME;
17154 num++;
17155 }
17156 }
17157 num_matched = wlan_hdd_mdns_find_entries_from_end(resptype_srv,
17158 resptype_ptr);
17159 if (num_matched > 0) {
17160 matchedlist[num].num_matched = num_matched;
17161 matchedlist[num].type = MDNS_TYPE_PTR;
17162 num++;
17163 }
17164 }
17165 if (resptype_txt && (resptype_txt->num_entries > 0)) {
17166 num_matched = wlan_hdd_mdns_find_entries_from_end(resptype_srv,
17167 resptype_txt);
17168 if (num_matched > 0) {
17169 matchedlist[num].num_matched =num_matched;
17170 matchedlist[num].type = MDNS_TYPE_TXT;
17171 num++;
17172 }
17173 }
17174 if (resptype_a && (resptype_a->num_entries > 0)) {
17175 num_matched = wlan_hdd_mdns_find_entries_from_end(resptype_srv,
17176 resptype_a);
17177 if (num_matched > 0) {
17178 matchedlist[num].num_matched = num_matched;
17179 matchedlist[num].type = MDNS_TYPE_A;
17180 num++;
17181 }
17182 }
17183 if (num > 0) {
17184 if (num > 1)
17185 wlan_hdd_mdns_find_max(matchedlist, num);
17186 resp = NULL;
17187 switch (matchedlist[num-1].type) {
17188 case MDNS_TYPE_A:
17189 resp = resptype_a;
17190 break;
17191 case MDNS_TYPE_TXT:
17192 resp = resptype_txt;
17193 break;
17194 case MDNS_TYPE_PTR:
17195 resp = resptype_ptr;
17196 break;
17197 case MDNS_TYPE_PTR_DNAME:
17198 resp = resptype_ptr_dn;
17199 break;
17200 default:
17201 hddLog(LOGE, FL("Fail to compress mDNS response "
17202 "(%d)!"), MDNS_TYPE_SRV);
17203 return FALSE;
17204 }
17205 num_matched = matchedlist[num-1].num_matched;
17206 if (!wlan_hdd_mdns_compress_data(resp_info, resptype_srv,
17207 resp, num_matched)) {
17208 hddLog(LOGE, FL("Fail to compress mDNS response "
17209 "(%d)!"), MDNS_TYPE_SRV);
17210 return FALSE;
17211 }
17212 } else {
17213 /* num = 0 -> no matched string */
17214 if (!wlan_hdd_mdns_process_response_dname(resptype_srv,
17215 resp_info)) {
17216 hddLog(LOGE, FL("Fail to process mDNS response (%d)!"),
17217 MDNS_TYPE_SRV);
17218 return FALSE;
17219 }
17220 }
17221
17222 /* Process response Type, Class, TTL */
17223 if (!wlan_hdd_mdns_process_response_misc(MDNS_TYPE_SRV, resp_info)) {
17224 hddLog(LOGE, FL("Fail to process mDNS misc response (%d)!"),
17225 MDNS_TYPE_SRV);
17226 return FALSE;
17227 }
17228
17229 /*
17230 * Process response RDLength, RData (Srv target name)
17231 * Save the offset of RData length
17232 */
17233 offset_data_len = resp_info->resp_len;
17234 resp_info->resp_len += sizeof(uint16_t);
17235
17236 len = resp_info->resp_len + (3 * sizeof(uint16_t));
17237 if (len >= MAX_MDNS_RESP_LEN) {
17238 hddLog(LOGE, FL("resp_len exceeds %d!"), MAX_MDNS_RESP_LEN);
17239 return FALSE;
17240 }
17241
17242 /* set Srv Priority */
17243 value = ini_config->mdns_resp_type_srv_priority;
17244 wlan_hdd_mdns_format_response_u16(value, resp_info);
17245 /* set Srv Weight */
17246 value = ini_config->mdns_resp_type_srv_weight;
17247 wlan_hdd_mdns_format_response_u16(value, resp_info);
17248 /* set Srv Port */
17249 value = ini_config->mdns_resp_type_srv_port;
17250 wlan_hdd_mdns_format_response_u16(value, resp_info);
17251
17252 if (!wlan_hdd_mdns_pack_response_type_srv_target(ini_config, resp_info,
17253 resptype_srv_tgt, resptype_srv,
17254 resptype_ptr, resptype_ptr_dn,
17255 resptype_txt, resptype_a)) {
17256 return FALSE;
17257 }
17258 /* Set the RData length */
17259 len = offset_data_len + sizeof(uint16_t);
17260 if ((resptype_srv_tgt->num_entries > 0) &&
17261 (resp_info->resp_len > len)) {
17262 value = resp_info->resp_len - len;
17263 val_u8 = (value & 0xff00) >> 8;
17264 resp_info->resp_data[offset_data_len] = val_u8;
17265 val_u8 = value & 0xff;
17266 resp_info->resp_data[offset_data_len+1] = val_u8;
17267 } else {
17268 hddLog(LOGE, FL("Fail to process mDNS response (%d)!"),
17269 MDNS_TYPE_SRV);
17270 return FALSE;
17271 }
17272
17273 EXIT();
17274 return TRUE;
17275}
17276
17277/**
17278 * wlan_hdd_mdns_free_mem() - Free the allocated memory
17279 * @response: Pointer to the struct hdd_mdns_resp_info
17280 *
17281 * Return: None
17282 */
17283static void wlan_hdd_mdns_free_mem(struct hdd_mdns_resp_info *response)
17284{
17285 if (response && response->data)
17286 vos_mem_free(response->data);
17287 if (response && response->offset)
17288 vos_mem_free(response->offset);
17289}
17290
17291/**
17292 * wlan_hdd_mdns_pack_response() - Pack mDNS response
17293 * @ini_config: Pointer to the struct hdd_config_t
17294 * @resp_info: Pointer to the struct tSirMDNSResponseInfo
17295 *
17296 * This function will pack four types of responses (Type A, Type Txt, Type Ptr
17297 * and Type Service). Each response contains QName, response type, class, TTL
17298 * and data fields.
17299 *
17300 * Return: Return boolean. TRUE for success, FALSE for fail.
17301 */
17302static bool wlan_hdd_mdns_pack_response(hdd_config_t *ini_config,
17303 sir_mdns_resp_info resp_info)
17304{
17305 struct hdd_mdns_resp_info resptype_a, resptype_txt;
17306 struct hdd_mdns_resp_info resptype_ptr, resptype_ptr_dn;
17307 struct hdd_mdns_resp_info resptype_srv, resptype_srv_tgt;
17308 uint32_t num_res_records = 0;
17309 bool status = FALSE;
17310
17311 ENTER();
17312
17313 wlan_hdd_mdns_reset_response(&resptype_a);
17314 wlan_hdd_mdns_reset_response(&resptype_txt);
17315 wlan_hdd_mdns_reset_response(&resptype_ptr);
17316 wlan_hdd_mdns_reset_response(&resptype_ptr_dn);
17317 wlan_hdd_mdns_reset_response(&resptype_srv);
17318 wlan_hdd_mdns_reset_response(&resptype_srv_tgt);
17319
17320 resp_info->resp_len = 0;
17321
17322 /* Process Type A response */
17323 if (!wlan_hdd_mdns_pack_response_type_a(ini_config, resp_info,
17324 &resptype_a))
17325 goto err_resptype_a;
17326
17327 if ((resptype_a.num_entries > 0) &&
17328 (strlen((char *)&resptype_a.data[0]) > 0))
17329 num_res_records++;
17330
17331 /* Process Type TXT response */
17332 if (!wlan_hdd_mdns_pack_response_type_txt(ini_config, resp_info,
17333 &resptype_txt, &resptype_a))
17334 goto err_resptype_txt;
17335
17336 if ((resptype_txt.num_entries > 0) &&
17337 (strlen((char *)&resptype_txt.data[0]) > 0))
17338 num_res_records++;
17339
17340 /* Process Type PTR response */
17341 if (!wlan_hdd_mdns_pack_response_type_ptr(ini_config, resp_info,
17342 &resptype_ptr, &resptype_ptr_dn,
17343 &resptype_txt, &resptype_a))
17344 goto err_resptype_ptr;
17345
17346 if ((resptype_ptr.num_entries > 0) &&
17347 (strlen((char *)&resptype_ptr.data[0]) > 0))
17348 num_res_records++;
17349
17350 /* Process Type SRV response */
17351 if (!wlan_hdd_mdns_pack_response_type_srv(ini_config, resp_info,
17352 &resptype_srv, &resptype_srv_tgt,
17353 &resptype_ptr, &resptype_ptr_dn,
17354 &resptype_txt, &resptype_a))
17355 goto err_resptype_srv;
17356
17357 if ((resptype_srv.num_entries > 0) &&
17358 (strlen((char *)&resptype_srv.data[0]) > 0))
17359 num_res_records++;
17360
17361 resp_info->resourceRecord_count = num_res_records;
17362 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
17363 "%s: Pack mDNS response data successfully!", __func__);
17364 status = TRUE;
17365
17366err_resptype_srv:
17367 wlan_hdd_mdns_free_mem(&resptype_srv);
17368 wlan_hdd_mdns_free_mem(&resptype_srv_tgt);
17369
17370err_resptype_ptr:
17371 wlan_hdd_mdns_free_mem(&resptype_ptr);
17372 wlan_hdd_mdns_free_mem(&resptype_ptr_dn);
17373
17374err_resptype_txt:
17375 wlan_hdd_mdns_free_mem(&resptype_txt);
17376
17377err_resptype_a:
17378 wlan_hdd_mdns_free_mem(&resptype_a);
17379
17380 EXIT();
17381 return status;
17382}
17383
17384/**
17385 * wlan_hdd_set_mdns_offload() - Enable mDNS offload
17386 * @hostapd_adapter: Pointer to the struct hdd_adapter_t
17387 *
17388 * This function will set FQDN/unique FQDN (full qualified domain name)
17389 * and the mDNS response. Then send them to SME.
17390 *
17391 * Return: Return boolean. TRUE for success, FALSE for fail.
17392 */
17393bool wlan_hdd_set_mdns_offload(hdd_adapter_t *hostapd_adapter)
17394{
17395 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(hostapd_adapter);
17396 sir_mdns_offload_info mdns_offload_info;
17397 sir_mdns_fqdn_info mdns_fqdn_info;
17398 sir_mdns_resp_info mdns_resp_info;
17399 uint32_t fqdn_len, ufqdn_len;
17400
17401 ENTER();
17402
17403 /* 1. Prepare the MDNS fqdn request to send to SME */
17404 fqdn_len = strlen(hdd_ctx->cfg_ini->mdns_fqdn);
17405 ufqdn_len = strlen(hdd_ctx->cfg_ini->mdns_uniquefqdn);
17406 if ((fqdn_len == 0) && (ufqdn_len == 0)) {
17407 hddLog(LOGE, FL("No mDNS FQDN or UFQDN is assigned fqdn_len %d,"
17408 "ufqdn_len %d!"), fqdn_len, ufqdn_len);
17409 return FALSE;
17410 }
17411
17412 mdns_fqdn_info = vos_mem_malloc(sizeof(*mdns_fqdn_info));
17413 if (NULL == mdns_fqdn_info) {
17414 hddLog(LOGE, FL("could not allocate tSirMDNSFqdnInfo!"));
17415 return FALSE;
17416 }
17417 /* MDNS fqdn request */
17418 if (fqdn_len > 0) {
17419 vos_mem_zero(mdns_fqdn_info, sizeof(*mdns_fqdn_info));
17420 mdns_fqdn_info->bss_idx = hostapd_adapter->sessionId;
17421 mdns_fqdn_info->fqdn_type = MDNS_FQDN_TYPE_GENERAL;
17422 mdns_fqdn_info->fqdn_len = fqdn_len;
17423 mdns_fqdn_info->mdns_fqdn_callback = hdd_mdns_fqdn_offload_done;
17424 mdns_fqdn_info->mdns_fqdn_cb_context = hostapd_adapter;
17425 vos_mem_copy(mdns_fqdn_info->fqdn_data,
17426 hdd_ctx->cfg_ini->mdns_fqdn,
17427 mdns_fqdn_info->fqdn_len);
17428
17429 if (eHAL_STATUS_SUCCESS !=
17430 sme_set_mdns_fqdn(hdd_ctx->hHal, mdns_fqdn_info)) {
17431 hddLog(LOGE, FL("sme_set_mdns_fqdn fail!"));
17432 vos_mem_free(mdns_fqdn_info);
17433 return FALSE;
17434 }
17435 }
17436 /* MDNS unique fqdn request */
17437 if (ufqdn_len > 0) {
17438 vos_mem_zero(mdns_fqdn_info, sizeof(*mdns_fqdn_info));
17439 mdns_fqdn_info->bss_idx = hostapd_adapter->sessionId;
17440 mdns_fqdn_info->fqdn_type = MDNS_FQDN_TYPE_UNIQUE;
17441 mdns_fqdn_info->fqdn_len = ufqdn_len;
17442 mdns_fqdn_info->mdns_fqdn_callback = hdd_mdns_fqdn_offload_done;
17443 mdns_fqdn_info->mdns_fqdn_cb_context = hostapd_adapter;
17444 vos_mem_copy(mdns_fqdn_info->fqdn_data,
17445 hdd_ctx->cfg_ini->mdns_uniquefqdn,
17446 mdns_fqdn_info->fqdn_len);
17447 if (eHAL_STATUS_SUCCESS !=
17448 sme_set_mdns_fqdn(hdd_ctx->hHal, mdns_fqdn_info)) {
17449 hddLog(LOGE, FL("sme_set_mdns_fqdn fail!"));
17450 vos_mem_free(mdns_fqdn_info);
17451 return FALSE;
17452 }
17453 }
17454 vos_mem_free(mdns_fqdn_info);
17455
17456 /* 2. Prepare the MDNS response request to send to SME */
17457 mdns_resp_info = vos_mem_malloc(sizeof(*mdns_resp_info));
17458 if (NULL == mdns_resp_info) {
17459 hddLog(LOGE, FL("could not allocate tSirMDNSResponseInfo!"));
17460 return FALSE;
17461 }
17462
17463 vos_mem_zero(mdns_resp_info, sizeof(*mdns_resp_info));
17464 mdns_resp_info->bss_idx = hostapd_adapter->sessionId;
17465 mdns_resp_info->mdns_resp_callback = hdd_mdns_resp_offload_done;
17466 mdns_resp_info->mdns_resp_cb_context = hostapd_adapter;
17467 if (!wlan_hdd_mdns_pack_response(hdd_ctx->cfg_ini, mdns_resp_info)) {
17468 hddLog(LOGE, FL("wlan_hdd_pack_mdns_response fail!"));
17469 vos_mem_free(mdns_resp_info);
17470 return FALSE;
17471 }
17472 if (eHAL_STATUS_SUCCESS !=
17473 sme_set_mdns_resp(hdd_ctx->hHal, mdns_resp_info)) {
17474 hddLog(LOGE, FL("sme_set_mdns_resp fail!"));
17475 vos_mem_free(mdns_resp_info);
17476 return FALSE;
17477 }
17478 vos_mem_free(mdns_resp_info);
17479
17480 /* 3. Prepare the MDNS Enable request to send to SME */
17481 mdns_offload_info = vos_mem_malloc(sizeof(*mdns_offload_info));
17482 if (NULL == mdns_offload_info) {
17483 hddLog(LOGE, FL("could not allocate tSirMDNSOffloadInfo!"));
17484 return FALSE;
17485 }
17486
17487 vos_mem_zero(mdns_offload_info, sizeof(*mdns_offload_info));
17488
17489 mdns_offload_info->bss_idx = hostapd_adapter->sessionId;
17490 mdns_offload_info->enable = hdd_ctx->cfg_ini->enable_mdns_offload;
17491 mdns_offload_info->mdns_enable_callback = hdd_mdns_enable_offload_done;
17492 mdns_offload_info->mdns_enable_cb_context = hostapd_adapter;
17493 if (eHAL_STATUS_SUCCESS !=
17494 sme_set_mdns_offload(hdd_ctx->hHal, mdns_offload_info)) {
17495 hddLog(LOGE, FL("sme_set_mdns_offload fail!"));
17496 vos_mem_free(mdns_offload_info);
17497 return FALSE;
17498 }
17499
17500 vos_mem_free(mdns_offload_info);
17501 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
17502 "%s: enable mDNS offload successfully!", __func__);
17503 return TRUE;
17504}
Manjeet Singh3ed79242017-01-11 19:04:32 +053017505
17506
Anurag Chouhan0b29de02016-12-16 13:18:40 +053017507#endif /* MDNS_OFFLOAD */
c_manjeecfd1efb2015-09-25 19:32:34 +053017508
Hanumanth Reddy Pothulad864f312017-01-18 16:16:08 +053017509/**
17510 * wlan_hdd_start_sap() - This function starts bss of SAP.
17511 * @ap_adapter: SAP adapter
17512 *
17513 * This function will process the starting of sap adapter.
17514 *
17515 * Return: void.
17516 */
17517void wlan_hdd_start_sap(hdd_adapter_t *ap_adapter)
17518{
17519 hdd_ap_ctx_t *hdd_ap_ctx;
17520 hdd_hostapd_state_t *hostapd_state;
17521 VOS_STATUS vos_status;
17522 hdd_context_t *hdd_ctx;
17523 tsap_Config_t *pConfig;
17524
17525 if (NULL == ap_adapter) {
17526 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
17527 FL("ap_adapter is NULL here"));
17528 return;
17529 }
17530
17531 hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter);
17532 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
17533 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
17534 pConfig = &ap_adapter->sessionCtx.ap.sapConfig;
17535
17536 mutex_lock(&hdd_ctx->sap_lock);
17537 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags))
17538 goto end;
17539
17540 if (0 != wlan_hdd_cfg80211_update_apies(ap_adapter)) {
17541 hddLog(LOGE, FL("SAP Not able to set AP IEs"));
17542 goto end;
17543 }
17544
17545 vos_event_reset(&hostapd_state->vosEvent);
17546 if (WLANSAP_StartBss(hdd_ctx->pvosContext, hdd_hostapd_SAPEventCB,
17547 &hdd_ap_ctx->sapConfig, (v_PVOID_t)ap_adapter->dev)
17548 != VOS_STATUS_SUCCESS) {
17549 goto end;
17550 }
17551
17552 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
17553 FL("Waiting for SAP to start"));
17554 vos_status = vos_wait_single_event(&hostapd_state->vosEvent, 10000);
17555 if (!VOS_IS_STATUS_SUCCESS(vos_status)) {
17556 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
17557 FL("SAP Start failed"));
17558 goto end;
17559 }
17560 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
17561 FL("SAP Start Success"));
17562 set_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
17563
17564 wlan_hdd_incr_active_session(hdd_ctx, ap_adapter->device_mode);
17565 hostapd_state->bCommit = TRUE;
17566
17567end:
17568 mutex_unlock(&hdd_ctx->sap_lock);
17569 return;
17570}
17571
Manjeet Singh3ed79242017-01-11 19:04:32 +053017572#ifdef WLAN_FEATURE_TSF
17573
17574/**
17575 * hdd_tsf_cb() - handle tsf request callback
17576 *
17577 * @pcb_cxt: pointer to the hdd_contex
17578 * @ptsf: pointer to struct stsf
17579 *
17580 * Based on the request sent .
17581 *
17582 * Return: Describe the execute result of this routine
17583 */
17584static int hdd_tsf_cb(void *pcb_ctx, struct stsf *ptsf)
17585{
17586 hdd_context_t *hddctx;
17587 int status;
17588 hdd_adapter_t* adapter = (hdd_adapter_t*)pcb_ctx;
17589
17590 if (pcb_ctx == NULL || ptsf == NULL) {
17591 hddLog(VOS_TRACE_LEVEL_ERROR,
17592 FL("HDD context is not valid"));
17593 return -EINVAL;
17594 }
17595
17596 hddctx = (hdd_context_t *)pcb_ctx;
17597 status = wlan_hdd_validate_context(hddctx);
17598 if (0 != status)
17599 return -EINVAL;
17600
17601 if (NULL == adapter) {
17602 hddLog(VOS_TRACE_LEVEL_ERROR,
17603 FL("failed to find adapter"));
17604 return -EINVAL;
17605 }
17606
17607 hddLog(VOS_TRACE_LEVEL_INFO,
17608 FL("tsf cb handle event, device_mode is %d"),
17609 adapter->device_mode);
17610
17611 /* copy the return value to hdd_tsf_ctx in adapter*/
17612 if (ptsf->tsf_req_status) {
17613
17614 vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
17615 adapter->tsf_cap_ctx.tsf_get_state = TSF_NOT_RETURNED_BY_FW;
17616 adapter->tsf_cap_ctx.tsf_capture_state = TSF_IDLE;
17617 vos_event_set (&adapter->tsf_cap_ctx.tsf_capture_done_event);
17618 vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
17619
17620 hddLog(VOS_TRACE_LEVEL_ERROR, FL("tsf req failure :%d"),
17621 ptsf->tsf_req_status);
17622 return ptsf->tsf_req_status;
17623 }
17624 /* If this is a get request.Store the tsf values in adapter. */
17625 if (!ptsf->set_tsf_req) {
17626 vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
17627 adapter->tsf_cap_ctx.tsf_low = ptsf->tsf_low;
17628 adapter->tsf_cap_ctx.tsf_high = ptsf->tsf_high;
17629 adapter->tsf_cap_ctx.tsf_get_state = TSF_RETURN;
17630 adapter->tsf_cap_ctx.tsf_capture_state = TSF_IDLE;
17631 vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
17632
17633 hddLog(VOS_TRACE_LEVEL_INFO,
17634 FL("hdd_get_tsf_cb sta=%u, tsf_low=%u, tsf_high=%u"),
17635 adapter->sessionId, ptsf->tsf_low, ptsf->tsf_high);
17636 }
17637 else {
17638 vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
17639 adapter->tsf_cap_ctx.tsf_capture_state = TSF_CAP_STATE;
17640 adapter->tsf_cap_ctx.tsf_get_state = TSF_CURRENT_IN_CAP_STATE;
17641 vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
17642 }
17643 vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
17644 vos_event_set (&adapter->tsf_cap_ctx.tsf_capture_done_event);
17645 vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
17646
17647 /* free allocated mem */
17648 vos_mem_free(ptsf);
17649
17650 return 0;
17651}
17652
17653/**
17654 * hdd_capture_tsf() - capture tsf
17655 *
17656 * @adapter: pointer to adapter
17657 * @buf: pointer to upper layer buf
17658 * @len : the length of buf
17659 *
17660 * This function returns tsf value to uplayer.
17661 *
17662 * Return: Describe the execute result of this routine
17663 */
17664int hdd_capture_tsf(hdd_adapter_t *adapter, uint32_t *buf, int len)
17665{
17666 int ret = 0;
17667 hdd_station_ctx_t *hdd_sta_ctx;
17668 hdd_context_t *hdd_ctx;
17669 tSirCapTsfParams cap_tsf_params;
17670 VOS_STATUS status;
17671
17672 if (adapter == NULL || buf == NULL) {
17673 hddLog(VOS_TRACE_LEVEL_ERROR,
17674 FL("invalid pointer"));
17675 return -EINVAL;
17676 }
17677 if (len != 1)
17678 return -EINVAL;
17679
17680 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
17681
17682 if (wlan_hdd_validate_context(hdd_ctx)) {
17683 hddLog(VOS_TRACE_LEVEL_ERROR,
17684 FL("invalid hdd ctx"));
17685 return -EINVAL;
17686 }
17687 if (adapter->device_mode == WLAN_HDD_INFRA_STATION ||
17688 adapter->device_mode == WLAN_HDD_P2P_CLIENT) {
17689 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
17690 if (hdd_sta_ctx->conn_info.connState !=
17691 eConnectionState_Associated) {
17692
17693 hddLog(VOS_TRACE_LEVEL_INFO,
17694 FL("failed to cap tsf, not connect with ap"));
17695 buf[0] = TSF_STA_NOT_CONNECTED_NO_TSF;
17696 return ret;
17697 }
17698 }
17699 if ((adapter->device_mode == WLAN_HDD_SOFTAP ||
17700 adapter->device_mode == WLAN_HDD_P2P_GO) &&
17701 !(test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags))) {
17702 hddLog(VOS_TRACE_LEVEL_INFO,
17703 FL("Soft AP / P2p GO not beaconing"));
17704 buf[0] = TSF_SAP_NOT_STARTED_NO_TSF;
17705 return ret;
17706 }
17707 if (adapter->tsf_cap_ctx.tsf_capture_state == TSF_CAP_STATE) {
17708 hddLog(VOS_TRACE_LEVEL_INFO,
17709 FL("current in capture state, pls reset"));
17710 buf[0] = TSF_CURRENT_IN_CAP_STATE;
17711 } else {
17712 hddLog(VOS_TRACE_LEVEL_INFO, FL("ioctl issue cap tsf cmd"));
17713 buf[0] = TSF_RETURN;
17714 cap_tsf_params.session_id = adapter->sessionId;
17715 cap_tsf_params.tsf_rsp_cb_func = hdd_tsf_cb;
17716 cap_tsf_params.tsf_rsp_cb_ctx = adapter;
17717
17718 vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
17719 adapter->tsf_cap_ctx.tsf_capture_state = TSF_CAP_STATE;
17720 adapter->tsf_cap_ctx.tsf_get_state = TSF_CURRENT_IN_CAP_STATE;
17721 vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
17722
17723 ret = sme_capture_tsf_req(hdd_ctx->hHal, cap_tsf_params);
17724
17725 if (ret != VOS_STATUS_SUCCESS) {
17726 hddLog(VOS_TRACE_LEVEL_ERROR, FL("capture fail"));
17727 buf[0] = TSF_CAPTURE_FAIL;
17728 vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
17729 adapter->tsf_cap_ctx.tsf_capture_state = TSF_IDLE;
17730 vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
17731 return -EINVAL;
17732 }
17733 /* wait till we get a response from fw */
17734 status = vos_wait_single_event(&adapter->tsf_cap_ctx.
17735 tsf_capture_done_event,
17736 HDD_TSF_CAP_REQ_TIMEOUT);
17737
17738 if (!VOS_IS_STATUS_SUCCESS(status)) {
17739 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
17740 ("capture tsf vos wait for single_event failed!! %d"),
17741 adapter->tsf_cap_ctx.tsf_get_state);
17742
17743 vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
17744 adapter->tsf_cap_ctx.tsf_capture_state = TSF_IDLE;
17745 vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
17746
17747 return -EINVAL;
17748 }
17749 }
17750 buf[0] = TSF_RETURN;
17751 hddLog(VOS_TRACE_LEVEL_INFO,
17752 FL("ioctl return cap tsf cmd, ret = %d"), ret);
17753 return ret;
17754}
17755
17756/**
17757 * hdd_indicate_tsf() - return tsf to uplayer
17758 *
17759 * @adapter: pointer to adapter
17760 * @buf: pointer to uplayer buf
17761 * @len : the length of buf
17762 *
17763 * This function returns tsf value to uplayer.
17764 *
17765 * Return: Describe the execute result of this routine
17766 */
17767int hdd_indicate_tsf(hdd_adapter_t *adapter, uint32_t *buf, int len)
17768{
17769 int ret = 0;
17770 hdd_station_ctx_t *hdd_sta_ctx;
17771 hdd_context_t *hdd_ctx;
17772 tSirCapTsfParams cap_tsf_params;
17773 VOS_STATUS status;
17774
17775 if (adapter == NULL || buf == NULL) {
17776 hddLog(VOS_TRACE_LEVEL_ERROR,
17777 FL("invalid pointer"));
17778 return -EINVAL;
17779 }
17780 if (len != 3)
17781 return -EINVAL;
17782
17783 buf [1] = 0;
17784 buf [2] = 0;
17785 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
17786
17787 if (wlan_hdd_validate_context(hdd_ctx)) {
17788 hddLog(VOS_TRACE_LEVEL_ERROR,
17789 FL("invalid hdd ctx"));
17790 return -EINVAL;
17791 }
17792 if (adapter->device_mode == WLAN_HDD_INFRA_STATION ||
17793 adapter->device_mode == WLAN_HDD_P2P_CLIENT) {
17794 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
17795 if (hdd_sta_ctx->conn_info.connState !=
17796 eConnectionState_Associated) {
17797
17798 hddLog(VOS_TRACE_LEVEL_INFO,
17799 FL("failed to cap tsf, not connect with ap"));
17800 buf[0] = TSF_STA_NOT_CONNECTED_NO_TSF;
17801 return ret;
17802 }
17803 }
17804 if ((adapter->device_mode == WLAN_HDD_SOFTAP ||
17805 adapter->device_mode == WLAN_HDD_P2P_GO) &&
17806 !(test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags))) {
17807 hddLog(VOS_TRACE_LEVEL_INFO,
17808 FL("Soft AP / P2p GO not beaconing"));
17809 buf[0] = TSF_SAP_NOT_STARTED_NO_TSF;
17810 return ret;
17811 }
17812
17813 if (adapter->tsf_cap_ctx.tsf_capture_state != TSF_CAP_STATE ||
17814 adapter->tsf_cap_ctx.tsf_get_state != TSF_CURRENT_IN_CAP_STATE ) {
17815 hddLog(VOS_TRACE_LEVEL_INFO,
17816 FL("Not in capture state,Enter capture state first"));
17817 buf[0] = TSF_GET_FAIL;
17818 } else {
17819 hddLog(VOS_TRACE_LEVEL_INFO, FL("ioctl issue cap tsf cmd"));
17820 cap_tsf_params.session_id = adapter->sessionId;
17821 cap_tsf_params.tsf_rsp_cb_func = hdd_tsf_cb;
17822 cap_tsf_params.tsf_rsp_cb_ctx = adapter;
17823
17824 ret = sme_get_tsf_req(hdd_ctx->hHal, cap_tsf_params);
17825
17826 if (ret != VOS_STATUS_SUCCESS) {
17827 hddLog(VOS_TRACE_LEVEL_ERROR, FL("capture fail"));
17828 buf[0] = TSF_CAPTURE_FAIL;
17829 vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
17830 adapter->tsf_cap_ctx.tsf_capture_state = TSF_IDLE;
17831 vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
17832 return -EINVAL;
17833 }
17834 /* wait till we get a response from fw */
17835 status = vos_wait_single_event(&adapter->tsf_cap_ctx.
17836 tsf_capture_done_event,
17837 HDD_TSF_GET_REQ_TIMEOUT);
17838
17839 if (!VOS_IS_STATUS_SUCCESS(status)) {
17840 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
17841 ("capture tsf vos wait for single_event failed!! %d"),
17842 status);
17843
17844 vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
17845 adapter->tsf_cap_ctx.tsf_capture_state = TSF_IDLE;
17846 vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
17847 return status;
17848 }
17849 buf[1] = adapter->tsf_cap_ctx.tsf_low;
17850 buf[2] = adapter->tsf_cap_ctx.tsf_high;
17851
17852 hddLog(VOS_TRACE_LEVEL_INFO,
17853 FL("get tsf cmd,status=%u, tsf_low=%u, tsf_high=%u"),
17854 buf[0], buf[1], buf[2]);
17855 }
17856 hddLog(VOS_TRACE_LEVEL_INFO,
17857 FL("ioctl return cap tsf cmd, ret = %d"), ret);
17858 return ret;
17859}
17860
17861void wlan_hdd_tsf_init(hdd_adapter_t *adapter)
17862{
17863
17864 if (adapter == NULL) {
17865 hddLog(VOS_TRACE_LEVEL_ERROR,
17866 FL("TSF init on a null adapter!"));
17867 return;
17868 }
17869
17870 adapter->tsf_cap_ctx.tsf_get_state = TSF_RETURN;
17871 adapter->tsf_cap_ctx.tsf_capture_state = TSF_IDLE;
17872 vos_event_init(&adapter->tsf_cap_ctx.tsf_capture_done_event);
17873 vos_spin_lock_init(&adapter->tsf_cap_ctx.tsf_lock);
17874 adapter->tsf_cap_ctx.tsf_high = 0;
17875 adapter->tsf_cap_ctx.tsf_low = 0;
17876}
17877
17878#endif
17879
Jeff Johnson295189b2012-06-20 16:38:30 -070017880//Register the module init/exit functions
17881module_init(hdd_module_init);
17882module_exit(hdd_module_exit);
17883
17884MODULE_LICENSE("Dual BSD/GPL");
17885MODULE_AUTHOR("Qualcomm Atheros, Inc.");
17886MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
17887
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070017888module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
17889 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -070017890
Jeff Johnson76052702013-04-16 13:55:05 -070017891module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -070017892 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Arif Hussain66559122013-11-21 10:11:40 -080017893
17894module_param(enable_dfs_chan_scan, int,
17895 S_IRUSR | S_IRGRP | S_IROTH);
17896
17897module_param(enable_11d, int,
17898 S_IRUSR | S_IRGRP | S_IROTH);
17899
17900module_param(country_code, charp,
17901 S_IRUSR | S_IRGRP | S_IROTH);