blob: fee2bc2413ee1f90067f4c6c749aab0468159b7e [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
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003439static int hdd_driver_command(hdd_adapter_t *pAdapter,
3440 hdd_priv_data_t *ppriv_data)
Jeff Johnson295189b2012-06-20 16:38:30 -07003441{
Jeff Johnson295189b2012-06-20 16:38:30 -07003442 hdd_priv_data_t priv_data;
3443 tANI_U8 *command = NULL;
Kaushik, Sushant96122442014-10-21 16:40:18 +05303444 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3445 hdd_scaninfo_t *pScanInfo = NULL;
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003446 int ret = 0;
Kaushik, Sushant96122442014-10-21 16:40:18 +05303447 int status;
Anand N Sunkade9adb1b2015-07-29 09:56:45 +05303448#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0))
3449 struct cfg80211_mgmt_tx_params params;
3450#endif
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05303451
3452 ENTER();
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003453 /*
3454 * Note that valid pointers are provided by caller
3455 */
Jeff Johnson295189b2012-06-20 16:38:30 -07003456
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003457 /* copy to local struct to avoid numerous changes to legacy code */
3458 priv_data = *ppriv_data;
Jeff Johnson295189b2012-06-20 16:38:30 -07003459
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003460 if (priv_data.total_len <= 0 ||
3461 priv_data.total_len > WLAN_PRIV_DATA_MAX_LEN)
Sameer Thalappil8ef3a0e2013-04-05 14:36:04 -07003462 {
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003463 hddLog(VOS_TRACE_LEVEL_WARN,
3464 "%s:invalid priv_data.total_len(%d)!!!", __func__,
3465 priv_data.total_len);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003466 ret = -EINVAL;
3467 goto exit;
3468 }
Kaushik, Sushant96122442014-10-21 16:40:18 +05303469 status = wlan_hdd_validate_context(pHddCtx);
3470 if (0 != status)
3471 {
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05303472 ret = -EINVAL;
3473 goto exit;
Kaushik, Sushant96122442014-10-21 16:40:18 +05303474 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003475 /* Allocate +1 for '\0' */
3476 command = kmalloc(priv_data.total_len + 1, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07003477 if (!command)
3478 {
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003479 hddLog(VOS_TRACE_LEVEL_ERROR,
3480 "%s: failed to allocate memory", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003481 ret = -ENOMEM;
3482 goto exit;
3483 }
3484
3485 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
3486 {
3487 ret = -EFAULT;
3488 goto exit;
3489 }
3490
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003491 /* Make sure the command is NUL-terminated */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003492 command[priv_data.total_len] = '\0';
3493
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003494 /* at one time the following block of code was conditional. braces
3495 * have been retained to avoid re-indenting the legacy code
3496 */
Jeff Johnson295189b2012-06-20 16:38:30 -07003497 {
3498 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
3499
3500 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07003501 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -07003502
3503 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
3504 {
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303505 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3506 TRACE_CODE_HDD_P2P_DEV_ADDR_IOCTL,
3507 pAdapter->sessionId, (unsigned)
3508 (*(pHddCtx->p2pDeviceAddress.bytes+2)<<24 |
3509 *(pHddCtx->p2pDeviceAddress.bytes+3)<<16 |
3510 *(pHddCtx->p2pDeviceAddress.bytes+4)<<8 |
3511 *(pHddCtx->p2pDeviceAddress.bytes+5))));
Jeff Johnson295189b2012-06-20 16:38:30 -07003512 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
3513 sizeof(tSirMacAddr)))
3514 {
3515 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Arif Hussain6d2a3322013-11-17 19:50:10 -08003516 "%s: failed to copy data to user buffer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003517 ret = -EFAULT;
3518 }
3519 }
Amar Singhal0974e402013-02-12 14:27:46 -08003520 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07003521 {
Amar Singhal0974e402013-02-12 14:27:46 -08003522 tANI_U8 *ptr = command ;
Srinivas Girigowdade697412013-02-14 16:31:48 -08003523
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05303524 ret = hdd_drv_cmd_validate(command, 7);
3525 if (ret)
3526 goto exit;
3527
Jeff Johnson295189b2012-06-20 16:38:30 -07003528 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -08003529
3530 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -07003531 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07003532 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -08003533 "%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 +05303534 if(VOS_FTM_MODE != hdd_get_conparam())
3535 {
3536 /* Change band request received */
3537 ret = hdd_setBand_helper(pAdapter->dev, ptr);
3538 if(ret < 0)
3539 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
3540 "%s: failed to set band ret=%d", __func__, ret);
3541 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08003542 }
Kiet Lamf040f472013-11-20 21:15:23 +05303543 else if(strncmp(command, "SETWMMPS", 8) == 0)
3544 {
3545 tANI_U8 *ptr = command;
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05303546
3547 ret = hdd_drv_cmd_validate(command, 8);
3548 if (ret)
3549 goto exit;
3550
Kiet Lamf040f472013-11-20 21:15:23 +05303551 ret = hdd_wmmps_helper(pAdapter, ptr);
3552 }
Agarwal Ashishef54a182014-12-16 15:07:31 +05303553
3554 else if(strncmp(command, "TDLSSCAN", 8) == 0)
3555 {
3556 tANI_U8 *ptr = command;
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05303557
3558 ret = hdd_drv_cmd_validate(command, 8);
3559 if (ret)
3560 goto exit;
3561
Agarwal Ashishef54a182014-12-16 15:07:31 +05303562 ret = hdd_set_tdls_scan_type(pAdapter, ptr);
3563 }
3564
Jeff Johnson32d95a32012-09-10 13:15:23 -07003565 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
3566 {
3567 char *country_code;
3568
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05303569 ret = hdd_drv_cmd_validate(command, 7);
3570 if (ret)
3571 goto exit;
3572
Jeff Johnson32d95a32012-09-10 13:15:23 -07003573 country_code = command + 8;
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07003574
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07003575 INIT_COMPLETION(pAdapter->change_country_code);
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07003576 hdd_checkandupdate_dfssetting(pAdapter, country_code);
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -07003577#ifndef CONFIG_ENABLE_LINUX_REG
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +05303578 hdd_checkandupdate_phymode(pAdapter, country_code);
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -07003579#endif
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07003580 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal,
3581 (void *)(tSmeChangeCountryCallback)
3582 wlan_hdd_change_country_code_callback,
Abhishek Singha306a442013-11-07 18:39:01 +05303583 country_code, pAdapter, pHddCtx->pvosContext, eSIR_TRUE, eSIR_TRUE);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07003584 if (eHAL_STATUS_SUCCESS == ret)
3585 {
3586 ret = wait_for_completion_interruptible_timeout(
3587 &pAdapter->change_country_code,
3588 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
3589 if (0 >= ret)
3590 {
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003591 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: SME while setting country code timed out %d",
c_hpothu6ff1c3c2013-10-01 19:01:57 +05303592 __func__, ret);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07003593 }
3594 }
3595 else
Jeff Johnson32d95a32012-09-10 13:15:23 -07003596 {
3597 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003598 "%s: SME Change Country code fail ret=%d", __func__, ret);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07003599 ret = -EINVAL;
Jeff Johnson32d95a32012-09-10 13:15:23 -07003600 }
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07003601
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07003602 }
3603 /*
3604 command should be a string having format
3605 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
3606 */
Amar Singhal0974e402013-02-12 14:27:46 -08003607 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07003608 {
Amar Singhal0974e402013-02-12 14:27:46 -08003609 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07003610
3611 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003612 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07003613
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -08003614 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -07003615 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -08003616 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
3617 {
3618 int suspend = 0;
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05303619 tANI_U8 *ptr;
3620
3621 ret = hdd_drv_cmd_validate(command, 14);
3622 if (ret)
3623 goto exit;
3624
3625 ptr = (tANI_U8*)command + 15;
Sameer Thalappil45931fb2013-02-01 11:18:05 -08003626
3627 suspend = *ptr - '0';
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303628 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3629 TRACE_CODE_HDD_SETSUSPENDMODE_IOCTL,
3630 pAdapter->sessionId, suspend));
Sameer Thalappil45931fb2013-02-01 11:18:05 -08003631 hdd_set_wlan_suspend_mode(suspend);
3632 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08003633#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
3634 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
3635 {
3636 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003637 tANI_S8 rssi = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08003638 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
3639 eHalStatus status = eHAL_STATUS_SUCCESS;
3640
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05303641 ret = hdd_drv_cmd_validate(command, 14);
3642 if (ret)
3643 goto exit;
3644
Srinivas Girigowdade697412013-02-14 16:31:48 -08003645 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
3646 value = value + 15;
3647
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003648 /* Convert the value from ascii to integer */
3649 ret = kstrtos8(value, 10, &rssi);
3650 if (ret < 0)
3651 {
3652 /* If the input value is greater than max value of datatype, then also
3653 kstrtou8 fails */
3654 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3655 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdafa7157d2013-10-31 10:14:22 -07003656 __func__,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003657 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
3658 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
3659 ret = -EINVAL;
3660 goto exit;
3661 }
3662
Srinivas Girigowdade697412013-02-14 16:31:48 -08003663 lookUpThreshold = abs(rssi);
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003664
Srinivas Girigowdade697412013-02-14 16:31:48 -08003665 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
3666 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
3667 {
3668 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3669 "Neighbor lookup threshold value %d is out of range"
3670 " (Min: %d Max: %d)", lookUpThreshold,
3671 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
3672 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
3673 ret = -EINVAL;
3674 goto exit;
3675 }
3676
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303677 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3678 TRACE_CODE_HDD_SETROAMTRIGGER_IOCTL,
3679 pAdapter->sessionId, lookUpThreshold));
Srinivas Girigowdade697412013-02-14 16:31:48 -08003680 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3681 "%s: Received Command to Set Roam trigger"
3682 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
3683
3684 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
3685 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
3686 if (eHAL_STATUS_SUCCESS != status)
3687 {
3688 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3689 "%s: Failed to set roam trigger, try again", __func__);
3690 ret = -EPERM;
3691 goto exit;
3692 }
3693
3694 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
mukul sharmad6e1fdd2014-06-23 19:19:09 +05303695 pHddCtx->cfg_ini->nNeighborReassocRssiThreshold = lookUpThreshold + 5;
Srinivas Girigowdade697412013-02-14 16:31:48 -08003696 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
3697 }
3698 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
3699 {
3700 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
3701 int rssi = (-1) * lookUpThreshold;
3702 char extra[32];
3703 tANI_U8 len = 0;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303704 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3705 TRACE_CODE_HDD_GETROAMTRIGGER_IOCTL,
3706 pAdapter->sessionId, lookUpThreshold));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003707 len = scnprintf(extra, sizeof(extra), "%s %d", command, rssi);
Srinivas Girigowda91719232015-07-13 15:10:10 +05303708 len = VOS_MIN(priv_data.total_len, len + 1);
3709 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdade697412013-02-14 16:31:48 -08003710 {
3711 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3712 "%s: failed to copy data to user buffer", __func__);
3713 ret = -EFAULT;
3714 goto exit;
3715 }
3716 }
3717 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
3718 {
3719 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003720 tANI_U8 roamScanPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003721 tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003722
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05303723 ret = hdd_drv_cmd_validate(command, 17);
3724 if (ret)
3725 goto exit;
3726
Srinivas Girigowdade697412013-02-14 16:31:48 -08003727 /* input refresh period is in terms of seconds */
3728 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
3729 value = value + 18;
3730 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003731 ret = kstrtou8(value, 10, &roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08003732 if (ret < 0)
3733 {
3734 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003735 kstrtou8 fails */
Srinivas Girigowdade697412013-02-14 16:31:48 -08003736 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003737 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdade697412013-02-14 16:31:48 -08003738 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07003739 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
3740 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08003741 ret = -EINVAL;
3742 goto exit;
3743 }
3744
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003745 if ((roamScanPeriod < (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000)) ||
3746 (roamScanPeriod > (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000)))
Srinivas Girigowdade697412013-02-14 16:31:48 -08003747 {
3748 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003749 "Roam scan period value %d is out of range"
3750 " (Min: %d Max: %d)", roamScanPeriod,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07003751 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
3752 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08003753 ret = -EINVAL;
3754 goto exit;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303755 }
3756 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3757 TRACE_CODE_HDD_SETROAMSCANPERIOD_IOCTL,
3758 pAdapter->sessionId, roamScanPeriod));
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003759 neighborEmptyScanRefreshPeriod = roamScanPeriod * 1000;
Srinivas Girigowdade697412013-02-14 16:31:48 -08003760
3761 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3762 "%s: Received Command to Set roam scan period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003763 " (Empty Scan refresh period) = %d", __func__, roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08003764
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003765 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod;
3766 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08003767 }
3768 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
3769 {
3770 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
3771 char extra[32];
3772 tANI_U8 len = 0;
3773
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303774 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3775 TRACE_CODE_HDD_GETROAMSCANPERIOD_IOCTL,
3776 pAdapter->sessionId, nEmptyScanRefreshPeriod));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003777 len = scnprintf(extra, sizeof(extra), "%s %d",
3778 "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08003779 /* Returned value is in units of seconds */
Ratnam Rachuria72ba112015-07-17 13:27:03 +05303780 len = VOS_MIN(priv_data.total_len, len + 1);
3781 if (copy_to_user(priv_data.buf, &extra, len)) {
Srinivas Girigowdade697412013-02-14 16:31:48 -08003782 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3783 "%s: failed to copy data to user buffer", __func__);
3784 ret = -EFAULT;
3785 goto exit;
3786 }
3787 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003788 else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0)
3789 {
3790 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003791 tANI_U8 roamScanRefreshPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003792 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003793
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05303794 ret = hdd_drv_cmd_validate(command, 24);
3795 if (ret)
3796 goto exit;
3797
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003798 /* input refresh period is in terms of seconds */
3799 /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */
3800 value = value + 25;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003801
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003802 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003803 ret = kstrtou8(value, 10, &roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003804 if (ret < 0)
3805 {
3806 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003807 kstrtou8 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003808 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003809 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003810 __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003811 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
3812 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
3813 ret = -EINVAL;
3814 goto exit;
3815 }
3816
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003817 if ((roamScanRefreshPeriod < (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000)) ||
3818 (roamScanRefreshPeriod > (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000)))
3819 {
3820 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3821 "Neighbor scan results refresh period value %d is out of range"
3822 " (Min: %d Max: %d)", roamScanRefreshPeriod,
3823 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
3824 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
3825 ret = -EINVAL;
3826 goto exit;
3827 }
3828 neighborScanRefreshPeriod = roamScanRefreshPeriod * 1000;
3829
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003830 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3831 "%s: Received Command to Set roam scan refresh period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003832 " (Scan refresh period) = %d", __func__, roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003833
3834 pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod;
3835 sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
3836 }
3837 else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0)
3838 {
3839 tANI_U16 value = sme_getNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
3840 char extra[32];
3841 tANI_U8 len = 0;
3842
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003843 len = scnprintf(extra, sizeof(extra), "%s %d",
3844 "GETROAMSCANREFRESHPERIOD", (value/1000));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003845 /* Returned value is in units of seconds */
Ratnam Rachuri2c9d6702015-07-17 13:25:16 +05303846 len = VOS_MIN(priv_data.total_len, len + 1);
3847 if (copy_to_user(priv_data.buf, &extra, len)) {
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003848 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3849 "%s: failed to copy data to user buffer", __func__);
3850 ret = -EFAULT;
3851 goto exit;
3852 }
3853 }
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07003854#ifdef FEATURE_WLAN_LFR
3855 /* SETROAMMODE */
3856 else if (strncmp(command, "SETROAMMODE", SIZE_OF_SETROAMMODE) == 0)
3857 {
3858 tANI_U8 *value = command;
3859 tANI_BOOLEAN roamMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
3860
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05303861 if (pHddCtx->concurrency_mode == VOS_STA_MON) {
3862 hddLog(LOGE,
3863 FL("Roaming is always disabled in STA + MON concurrency"));
3864 ret = -EINVAL;
3865 goto exit;
3866 }
3867
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05303868 ret = hdd_drv_cmd_validate(command, SIZE_OF_SETROAMMODE);
3869 if (ret)
3870 goto exit;
3871
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07003872 /* Move pointer to ahead of SETROAMMODE<delimiter> */
3873 value = value + SIZE_OF_SETROAMMODE + 1;
3874
3875 /* Convert the value from ascii to integer */
3876 ret = kstrtou8(value, SIZE_OF_SETROAMMODE, &roamMode);
3877 if (ret < 0)
3878 {
3879 /* If the input value is greater than max value of datatype, then also
3880 kstrtou8 fails */
3881 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3882 "%s: kstrtou8 failed range [%d - %d]", __func__,
3883 CFG_LFR_FEATURE_ENABLED_MIN,
3884 CFG_LFR_FEATURE_ENABLED_MAX);
3885 ret = -EINVAL;
3886 goto exit;
3887 }
3888 if ((roamMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
3889 (roamMode > CFG_LFR_FEATURE_ENABLED_MAX))
3890 {
3891 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3892 "Roam Mode value %d is out of range"
3893 " (Min: %d Max: %d)", roamMode,
3894 CFG_LFR_FEATURE_ENABLED_MIN,
3895 CFG_LFR_FEATURE_ENABLED_MAX);
3896 ret = -EINVAL;
3897 goto exit;
3898 }
3899
3900 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3901 "%s: Received Command to Set Roam Mode = %d", __func__, roamMode);
3902 /*
3903 * Note that
3904 * SETROAMMODE 0 is to enable LFR while
3905 * SETROAMMODE 1 is to disable LFR, but
3906 * NotifyIsFastRoamIniFeatureEnabled 0/1 is to enable/disable.
3907 * So, we have to invert the value to call sme_UpdateIsFastRoamIniFeatureEnabled.
3908 */
3909 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
3910 roamMode = CFG_LFR_FEATURE_ENABLED_MAX; /* Roam enable */
3911 else
3912 roamMode = CFG_LFR_FEATURE_ENABLED_MIN; /* Roam disable */
3913
3914 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = roamMode;
3915 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), roamMode);
3916 }
3917 /* GETROAMMODE */
Mahesh A Saptasagarec7d1092015-04-02 13:41:34 +05303918 else if (strncmp(command, "GETROAMMODE", SIZE_OF_GETROAMMODE) == 0)
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07003919 {
3920 tANI_BOOLEAN roamMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
3921 char extra[32];
3922 tANI_U8 len = 0;
3923
3924 /*
3925 * roamMode value shall be inverted because the sementics is different.
3926 */
3927 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
3928 roamMode = CFG_LFR_FEATURE_ENABLED_MAX;
3929 else
3930 roamMode = CFG_LFR_FEATURE_ENABLED_MIN;
3931
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003932 len = scnprintf(extra, sizeof(extra), "%s %d", command, roamMode);
Ratnam Rachuri28693eb2015-07-17 13:23:42 +05303933 len = VOS_MIN(priv_data.total_len, len + 1);
3934 if (copy_to_user(priv_data.buf, &extra, len)) {
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07003935 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3936 "%s: failed to copy data to user buffer", __func__);
3937 ret = -EFAULT;
3938 goto exit;
3939 }
3940 }
3941#endif
Srinivas Girigowdade697412013-02-14 16:31:48 -08003942#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003943#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -08003944 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
3945 {
3946 tANI_U8 *value = command;
3947 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
3948
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05303949 ret = hdd_drv_cmd_validate(command, 12);
3950 if (ret)
3951 goto exit;
3952
Srinivas Girigowdade697412013-02-14 16:31:48 -08003953 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
3954 value = value + 13;
3955 /* Convert the value from ascii to integer */
3956 ret = kstrtou8(value, 10, &roamRssiDiff);
3957 if (ret < 0)
3958 {
3959 /* If the input value is greater than max value of datatype, then also
3960 kstrtou8 fails */
3961 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3962 "%s: kstrtou8 failed range [%d - %d]", __func__,
3963 CFG_ROAM_RSSI_DIFF_MIN,
3964 CFG_ROAM_RSSI_DIFF_MAX);
3965 ret = -EINVAL;
3966 goto exit;
3967 }
3968
3969 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
3970 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
3971 {
3972 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3973 "Roam rssi diff value %d is out of range"
3974 " (Min: %d Max: %d)", roamRssiDiff,
3975 CFG_ROAM_RSSI_DIFF_MIN,
3976 CFG_ROAM_RSSI_DIFF_MAX);
3977 ret = -EINVAL;
3978 goto exit;
3979 }
3980
3981 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3982 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
3983
3984 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
3985 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
3986 }
Mahesh A Saptasagarec7d1092015-04-02 13:41:34 +05303987 else if (strncmp(command, "GETROAMDELTA", 12) == 0)
Srinivas Girigowdade697412013-02-14 16:31:48 -08003988 {
3989 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
3990 char extra[32];
3991 tANI_U8 len = 0;
3992
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303993 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3994 TRACE_CODE_HDD_GETROAMDELTA_IOCTL,
3995 pAdapter->sessionId, roamRssiDiff));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003996 len = scnprintf(extra, sizeof(extra), "%s %d",
3997 command, roamRssiDiff);
Ratnam Rachuri22a3b402015-07-17 13:21:49 +05303998 len = VOS_MIN(priv_data.total_len, len + 1);
3999 if (copy_to_user(priv_data.buf, &extra, len)) {
Srinivas Girigowdade697412013-02-14 16:31:48 -08004000 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4001 "%s: failed to copy data to user buffer", __func__);
4002 ret = -EFAULT;
4003 goto exit;
4004 }
4005 }
4006#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004007#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -08004008 else if (strncmp(command, "GETBAND", 7) == 0)
4009 {
4010 int band = -1;
4011 char extra[32];
4012 tANI_U8 len = 0;
4013 hdd_getBand_helper(pHddCtx, &band);
4014
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05304015 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
4016 TRACE_CODE_HDD_GETBAND_IOCTL,
4017 pAdapter->sessionId, band));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004018 len = scnprintf(extra, sizeof(extra), "%s %d", command, band);
Ratnam Rachuri52139592015-07-17 13:17:29 +05304019 len = VOS_MIN(priv_data.total_len, len + 1);
4020 if (copy_to_user(priv_data.buf, &extra, len)) {
Srinivas Girigowdade697412013-02-14 16:31:48 -08004021 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4022 "%s: failed to copy data to user buffer", __func__);
4023 ret = -EFAULT;
4024 goto exit;
4025 }
4026 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004027 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
4028 {
4029 tANI_U8 *value = command;
4030 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
4031 tANI_U8 numChannels = 0;
4032 eHalStatus status = eHAL_STATUS_SUCCESS;
4033
4034 status = hdd_parse_channellist(value, ChannelList, &numChannels);
4035 if (eHAL_STATUS_SUCCESS != status)
4036 {
4037 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4038 "%s: Failed to parse channel list information", __func__);
4039 ret = -EINVAL;
4040 goto exit;
4041 }
4042
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05304043 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
4044 TRACE_CODE_HDD_SETROAMSCANCHANNELS_IOCTL,
4045 pAdapter->sessionId, numChannels));
Srinivas Girigowdade697412013-02-14 16:31:48 -08004046 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
4047 {
4048 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4049 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
4050 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
4051 ret = -EINVAL;
4052 goto exit;
4053 }
4054 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
4055 numChannels);
4056 if (eHAL_STATUS_SUCCESS != status)
4057 {
4058 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4059 "%s: Failed to update channel list information", __func__);
4060 ret = -EINVAL;
4061 goto exit;
4062 }
4063 }
4064 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
4065 {
4066 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
4067 tANI_U8 numChannels = 0;
Jeff Johnson51b67782013-04-05 12:35:41 -07004068 tANI_U8 j = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08004069 char extra[128] = {0};
Jeff Johnson51b67782013-04-05 12:35:41 -07004070 int len;
Srinivas Girigowdade697412013-02-14 16:31:48 -08004071
4072 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
4073 ChannelList, &numChannels ))
4074 {
4075 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4076 "%s: failed to get roam scan channel list", __func__);
4077 ret = -EFAULT;
4078 goto exit;
4079 }
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05304080 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
4081 TRACE_CODE_HDD_GETROAMSCANCHANNELS_IOCTL,
4082 pAdapter->sessionId, numChannels));
Srinivas Girigowdade697412013-02-14 16:31:48 -08004083 /* output channel list is of the format
4084 [Number of roam scan channels][Channel1][Channel2]... */
4085 /* copy the number of channels in the 0th index */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004086 len = scnprintf(extra, sizeof(extra), "%s %d", command, numChannels);
Sushant Kaushika08ca192015-09-16 15:52:04 +05304087 for (j = 0; (j < numChannels) && len <= sizeof(extra); j++)
Srinivas Girigowdade697412013-02-14 16:31:48 -08004088 {
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004089 len += scnprintf(extra + len, sizeof(extra) - len, " %d",
4090 ChannelList[j]);
Srinivas Girigowdade697412013-02-14 16:31:48 -08004091 }
4092
Sushant Kaushikc9b8be52015-07-15 16:41:27 +05304093 len = VOS_MIN(priv_data.total_len, len + 1);
4094 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdade697412013-02-14 16:31:48 -08004095 {
4096 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4097 "%s: failed to copy data to user buffer", __func__);
4098 ret = -EFAULT;
4099 goto exit;
4100 }
4101 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004102 else if (strncmp(command, "GETCCXMODE", 10) == 0)
4103 {
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004104 tANI_BOOLEAN eseMode = sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004105 char extra[32];
4106 tANI_U8 len = 0;
4107
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004108 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07004109 then this operation is not permitted (return FAILURE) */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004110 if (eseMode &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07004111 hdd_is_okc_mode_enabled(pHddCtx) &&
4112 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
4113 {
4114 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004115 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07004116 " hence this operation is not permitted!", __func__);
4117 ret = -EPERM;
4118 goto exit;
4119 }
4120
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004121 len = scnprintf(extra, sizeof(extra), "%s %d",
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004122 "GETCCXMODE", eseMode);
Sushant Kaushikf8abd352015-07-15 16:37:49 +05304123 len = VOS_MIN(priv_data.total_len, len + 1);
4124 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004125 {
4126 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4127 "%s: failed to copy data to user buffer", __func__);
4128 ret = -EFAULT;
4129 goto exit;
4130 }
4131 }
4132 else if (strncmp(command, "GETOKCMODE", 10) == 0)
4133 {
4134 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
4135 char extra[32];
4136 tANI_U8 len = 0;
4137
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004138 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07004139 then this operation is not permitted (return FAILURE) */
4140 if (okcMode &&
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004141 sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07004142 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
4143 {
4144 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004145 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07004146 " hence this operation is not permitted!", __func__);
4147 ret = -EPERM;
4148 goto exit;
4149 }
4150
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004151 len = scnprintf(extra, sizeof(extra), "%s %d",
4152 "GETOKCMODE", okcMode);
Sushant Kaushikbc2fb5c2015-07-15 16:43:16 +05304153 len = VOS_MIN(priv_data.total_len, len + 1);
4154 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004155 {
4156 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4157 "%s: failed to copy data to user buffer", __func__);
4158 ret = -EFAULT;
4159 goto exit;
4160 }
4161 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07004162 else if (strncmp(command, "GETFASTROAM", 11) == 0)
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004163 {
4164 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
4165 char extra[32];
4166 tANI_U8 len = 0;
4167
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004168 len = scnprintf(extra, sizeof(extra), "%s %d",
4169 "GETFASTROAM", lfrMode);
Sushant Kaushik4da7ec92015-07-15 16:39:32 +05304170 len = VOS_MIN(priv_data.total_len, len + 1);
4171 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004172 {
4173 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4174 "%s: failed to copy data to user buffer", __func__);
4175 ret = -EFAULT;
4176 goto exit;
4177 }
4178 }
4179 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
4180 {
4181 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
4182 char extra[32];
4183 tANI_U8 len = 0;
4184
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004185 len = scnprintf(extra, sizeof(extra), "%s %d",
4186 "GETFASTTRANSITION", ft);
Sushant Kaushik231a4452015-07-15 16:23:56 +05304187 len = VOS_MIN(priv_data.total_len, len + 1);
4188 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004189 {
4190 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4191 "%s: failed to copy data to user buffer", __func__);
4192 ret = -EFAULT;
4193 goto exit;
4194 }
4195 }
4196 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
4197 {
4198 tANI_U8 *value = command;
4199 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
4200
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304201 ret = hdd_drv_cmd_validate(command, 25);
4202 if (ret)
4203 goto exit;
4204
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004205 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
4206 value = value + 26;
4207 /* Convert the value from ascii to integer */
4208 ret = kstrtou8(value, 10, &minTime);
4209 if (ret < 0)
4210 {
4211 /* If the input value is greater than max value of datatype, then also
4212 kstrtou8 fails */
4213 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4214 "%s: kstrtou8 failed range [%d - %d]", __func__,
4215 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
4216 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
4217 ret = -EINVAL;
4218 goto exit;
4219 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004220 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
4221 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
4222 {
4223 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4224 "scan min channel time value %d is out of range"
4225 " (Min: %d Max: %d)", minTime,
4226 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
4227 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
4228 ret = -EINVAL;
4229 goto exit;
4230 }
4231
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05304232 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
4233 TRACE_CODE_HDD_SETROAMSCANCHANNELMINTIME_IOCTL,
4234 pAdapter->sessionId, minTime));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004235 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4236 "%s: Received Command to change channel min time = %d", __func__, minTime);
4237
4238 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
4239 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
4240 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004241 else if (strncmp(command, "SENDACTIONFRAME", 15) == 0)
4242 {
4243 tANI_U8 *value = command;
4244 tANI_U8 channel = 0;
4245 tANI_U8 dwellTime = 0;
4246 tANI_U8 bufLen = 0;
4247 tANI_U8 *buf = NULL;
4248 tSirMacAddr targetApBssid;
4249 eHalStatus status = eHAL_STATUS_SUCCESS;
4250 struct ieee80211_channel chan;
4251 tANI_U8 finalLen = 0;
4252 tANI_U8 *finalBuf = NULL;
4253 tANI_U8 temp = 0;
4254 u64 cookie;
4255 hdd_station_ctx_t *pHddStaCtx = NULL;
4256 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4257
4258 /* if not associated, no need to send action frame */
4259 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
4260 {
4261 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
4262 ret = -EINVAL;
4263 goto exit;
4264 }
4265
4266 status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel,
4267 &dwellTime, &buf, &bufLen);
4268 if (eHAL_STATUS_SUCCESS != status)
4269 {
4270 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4271 "%s: Failed to parse send action frame data", __func__);
4272 ret = -EINVAL;
4273 goto exit;
4274 }
4275
4276 /* if the target bssid is different from currently associated AP,
4277 then no need to send action frame */
4278 if (VOS_TRUE != vos_mem_compare(targetApBssid,
4279 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
4280 {
4281 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__);
4282 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07004283 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08004284 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004285 goto exit;
4286 }
4287
4288 /* if the channel number is different from operating channel then
4289 no need to send action frame */
4290 if (channel != pHddStaCtx->conn_info.operationChannel)
4291 {
4292 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4293 "%s: channel(%d) is different from operating channel(%d)",
4294 __func__, channel, pHddStaCtx->conn_info.operationChannel);
4295 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07004296 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08004297 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004298 goto exit;
4299 }
4300 chan.center_freq = sme_ChnToFreq(channel);
4301
4302 finalLen = bufLen + 24;
4303 finalBuf = vos_mem_malloc(finalLen);
4304 if (NULL == finalBuf)
4305 {
4306 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__);
4307 ret = -ENOMEM;
Jeff Johnson11c33152013-04-16 17:52:40 -07004308 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08004309 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004310 goto exit;
4311 }
4312 vos_mem_zero(finalBuf, finalLen);
4313
4314 /* Fill subtype */
4315 temp = SIR_MAC_MGMT_ACTION << 4;
4316 vos_mem_copy(finalBuf + 0, &temp, sizeof(temp));
4317
4318 /* Fill type */
4319 temp = SIR_MAC_MGMT_FRAME;
4320 vos_mem_copy(finalBuf + 2, &temp, sizeof(temp));
4321
4322 /* Fill destination address (bssid of the AP) */
4323 vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid));
4324
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07004325 /* Fill source address (STA mac address) */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004326 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
4327
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07004328 /* Fill BSSID (AP mac address) */
4329 vos_mem_copy(finalBuf + 16, targetApBssid, sizeof(targetApBssid));
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004330
4331 /* Fill received buffer from 24th address */
4332 vos_mem_copy(finalBuf + 24, buf, bufLen);
4333
Jeff Johnson11c33152013-04-16 17:52:40 -07004334 /* done with the parsed buffer */
4335 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08004336 buf = NULL;
Jeff Johnson11c33152013-04-16 17:52:40 -07004337
Anand N Sunkade9adb1b2015-07-29 09:56:45 +05304338#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0))
4339 params.chan = &chan;
4340 params.offchan = 0;
4341 params.wait = dwellTime;
4342 params.buf = finalBuf;
4343 params.len = finalLen;
4344 params.no_cck = 1;
4345 params.dont_wait_for_ack = 1;
4346 ret = wlan_hdd_mgmt_tx(NULL, &pAdapter->wdev, &params, &cookie);
4347#else
DARAM SUDHA39eede62014-02-12 11:16:40 +05304348 wlan_hdd_mgmt_tx( NULL,
Yue Maf49ba872013-08-19 12:04:25 -07004349#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
4350 &(pAdapter->wdev),
4351#else
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07004352 pAdapter->dev,
Yue Maf49ba872013-08-19 12:04:25 -07004353#endif
4354 &chan, 0,
4355#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
4356 NL80211_CHAN_HT20, 1,
4357#endif
4358 dwellTime, finalBuf, finalLen, 1,
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004359 1, &cookie );
Anand N Sunkade9adb1b2015-07-29 09:56:45 +05304360#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0)*/
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004361 vos_mem_free(finalBuf);
4362 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004363 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
4364 {
4365 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
4366 char extra[32];
4367 tANI_U8 len = 0;
4368
4369 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004370 len = scnprintf(extra, sizeof(extra), "%s %d",
4371 "GETROAMSCANCHANNELMINTIME", val);
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05304372 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
4373 TRACE_CODE_HDD_GETROAMSCANCHANNELMINTIME_IOCTL,
4374 pAdapter->sessionId, val));
Sushant Kaushikbb8c52c2015-07-15 16:36:23 +05304375 len = VOS_MIN(priv_data.total_len, len + 1);
4376 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004377 {
4378 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4379 "%s: failed to copy data to user buffer", __func__);
4380 ret = -EFAULT;
4381 goto exit;
4382 }
4383 }
4384 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
4385 {
4386 tANI_U8 *value = command;
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07004387 tANI_U16 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004388
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304389 ret = hdd_drv_cmd_validate(command, 18);
4390 if (ret)
4391 goto exit;
4392
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004393 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
4394 value = value + 19;
4395 /* Convert the value from ascii to integer */
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07004396 ret = kstrtou16(value, 10, &maxTime);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004397 if (ret < 0)
4398 {
4399 /* If the input value is greater than max value of datatype, then also
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07004400 kstrtou16 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004401 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07004402 "%s: kstrtou16 failed range [%d - %d]", __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004403 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
4404 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
4405 ret = -EINVAL;
4406 goto exit;
4407 }
4408
4409 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
4410 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
4411 {
4412 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4413 "lfr mode value %d is out of range"
4414 " (Min: %d Max: %d)", maxTime,
4415 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
4416 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
4417 ret = -EINVAL;
4418 goto exit;
4419 }
4420
4421 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4422 "%s: Received Command to change channel max time = %d", __func__, maxTime);
4423
4424 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
4425 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
4426 }
4427 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
4428 {
4429 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
4430 char extra[32];
4431 tANI_U8 len = 0;
4432
4433 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004434 len = scnprintf(extra, sizeof(extra), "%s %d",
4435 "GETSCANCHANNELTIME", val);
Ratheesh S Pacbfa932015-07-16 15:27:18 +05304436 len = VOS_MIN(priv_data.total_len, len + 1);
4437 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004438 {
4439 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4440 "%s: failed to copy data to user buffer", __func__);
4441 ret = -EFAULT;
4442 goto exit;
4443 }
4444 }
4445 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
4446 {
4447 tANI_U8 *value = command;
4448 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
4449
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304450 ret = hdd_drv_cmd_validate(command, 15);
4451 if (ret)
4452 goto exit;
4453
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004454 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
4455 value = value + 16;
4456 /* Convert the value from ascii to integer */
4457 ret = kstrtou16(value, 10, &val);
4458 if (ret < 0)
4459 {
4460 /* If the input value is greater than max value of datatype, then also
4461 kstrtou16 fails */
4462 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4463 "%s: kstrtou16 failed range [%d - %d]", __func__,
4464 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
4465 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
4466 ret = -EINVAL;
4467 goto exit;
4468 }
4469
4470 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
4471 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
4472 {
4473 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4474 "scan home time value %d is out of range"
4475 " (Min: %d Max: %d)", val,
4476 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
4477 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
4478 ret = -EINVAL;
4479 goto exit;
4480 }
4481
4482 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4483 "%s: Received Command to change scan home time = %d", __func__, val);
4484
4485 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
4486 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
4487 }
4488 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
4489 {
4490 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
4491 char extra[32];
4492 tANI_U8 len = 0;
4493
4494 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004495 len = scnprintf(extra, sizeof(extra), "%s %d",
4496 "GETSCANHOMETIME", val);
Ratheesh S P728d7c62015-07-16 15:38:58 +05304497 len = VOS_MIN(priv_data.total_len, len + 1);
4498 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004499 {
4500 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4501 "%s: failed to copy data to user buffer", __func__);
4502 ret = -EFAULT;
4503 goto exit;
4504 }
4505 }
4506 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
4507 {
4508 tANI_U8 *value = command;
4509 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
4510
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304511 ret = hdd_drv_cmd_validate(command, 16);
4512 if (ret)
4513 goto exit;
4514
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004515 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
4516 value = value + 17;
4517 /* Convert the value from ascii to integer */
4518 ret = kstrtou8(value, 10, &val);
4519 if (ret < 0)
4520 {
4521 /* If the input value is greater than max value of datatype, then also
4522 kstrtou8 fails */
4523 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4524 "%s: kstrtou8 failed range [%d - %d]", __func__,
4525 CFG_ROAM_INTRA_BAND_MIN,
4526 CFG_ROAM_INTRA_BAND_MAX);
4527 ret = -EINVAL;
4528 goto exit;
4529 }
4530
4531 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
4532 (val > CFG_ROAM_INTRA_BAND_MAX))
4533 {
4534 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4535 "intra band mode value %d is out of range"
4536 " (Min: %d Max: %d)", val,
4537 CFG_ROAM_INTRA_BAND_MIN,
4538 CFG_ROAM_INTRA_BAND_MAX);
4539 ret = -EINVAL;
4540 goto exit;
4541 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004542 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4543 "%s: Received Command to change intra band = %d", __func__, val);
4544
4545 pHddCtx->cfg_ini->nRoamIntraBand = val;
4546 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
4547 }
4548 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
4549 {
4550 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
4551 char extra[32];
4552 tANI_U8 len = 0;
4553
4554 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004555 len = scnprintf(extra, sizeof(extra), "%s %d",
4556 "GETROAMINTRABAND", val);
Ratheesh S P2dd2a3e2015-07-16 15:34:23 +05304557 len = VOS_MIN(priv_data.total_len, len + 1);
4558 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004559 {
4560 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4561 "%s: failed to copy data to user buffer", __func__);
4562 ret = -EFAULT;
4563 goto exit;
4564 }
4565 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004566 else if (strncmp(command, "SETSCANNPROBES", 14) == 0)
4567 {
4568 tANI_U8 *value = command;
4569 tANI_U8 nProbes = CFG_ROAM_SCAN_N_PROBES_DEFAULT;
4570
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304571 ret = hdd_drv_cmd_validate(command, 14);
4572 if (ret)
4573 goto exit;
4574
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004575 /* Move pointer to ahead of SETSCANNPROBES<delimiter> */
4576 value = value + 15;
4577 /* Convert the value from ascii to integer */
4578 ret = kstrtou8(value, 10, &nProbes);
4579 if (ret < 0)
4580 {
4581 /* If the input value is greater than max value of datatype, then also
4582 kstrtou8 fails */
4583 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4584 "%s: kstrtou8 failed range [%d - %d]", __func__,
4585 CFG_ROAM_SCAN_N_PROBES_MIN,
4586 CFG_ROAM_SCAN_N_PROBES_MAX);
4587 ret = -EINVAL;
4588 goto exit;
4589 }
4590
4591 if ((nProbes < CFG_ROAM_SCAN_N_PROBES_MIN) ||
4592 (nProbes > CFG_ROAM_SCAN_N_PROBES_MAX))
4593 {
4594 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4595 "NProbes value %d is out of range"
4596 " (Min: %d Max: %d)", nProbes,
4597 CFG_ROAM_SCAN_N_PROBES_MIN,
4598 CFG_ROAM_SCAN_N_PROBES_MAX);
4599 ret = -EINVAL;
4600 goto exit;
4601 }
4602
4603 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4604 "%s: Received Command to Set nProbes = %d", __func__, nProbes);
4605
4606 pHddCtx->cfg_ini->nProbes = nProbes;
4607 sme_UpdateRoamScanNProbes((tHalHandle)(pHddCtx->hHal), nProbes);
4608 }
Mahesh A Saptasagarec7d1092015-04-02 13:41:34 +05304609 else if (strncmp(command, "GETSCANNPROBES", 14) == 0)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004610 {
4611 tANI_U8 val = sme_getRoamScanNProbes((tHalHandle)(pHddCtx->hHal));
4612 char extra[32];
4613 tANI_U8 len = 0;
4614
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004615 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Ratnam Rachuri6da525d2015-08-07 13:55:54 +05304616 len = VOS_MIN(priv_data.total_len, len + 1);
4617 if (copy_to_user(priv_data.buf, &extra, len)) {
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004618 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4619 "%s: failed to copy data to user buffer", __func__);
4620 ret = -EFAULT;
4621 goto exit;
4622 }
4623 }
4624 else if (strncmp(command, "SETSCANHOMEAWAYTIME", 19) == 0)
4625 {
4626 tANI_U8 *value = command;
4627 tANI_U16 homeAwayTime = CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT;
4628
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304629 ret = hdd_drv_cmd_validate(command, 19);
4630 if (ret)
4631 goto exit;
4632
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004633 /* Move pointer to ahead of SETSCANHOMEAWAYTIME<delimiter> */
4634 /* input value is in units of msec */
4635 value = value + 20;
4636 /* Convert the value from ascii to integer */
4637 ret = kstrtou16(value, 10, &homeAwayTime);
4638 if (ret < 0)
4639 {
4640 /* If the input value is greater than max value of datatype, then also
4641 kstrtou8 fails */
4642 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4643 "%s: kstrtou8 failed range [%d - %d]", __func__,
4644 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
4645 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
4646 ret = -EINVAL;
4647 goto exit;
4648 }
4649
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004650 if ((homeAwayTime < CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN) ||
4651 (homeAwayTime > CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX))
4652 {
4653 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4654 "homeAwayTime value %d is out of range"
4655 " (Min: %d Max: %d)", homeAwayTime,
4656 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
4657 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
4658 ret = -EINVAL;
4659 goto exit;
4660 }
4661
4662 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4663 "%s: Received Command to Set scan away time = %d", __func__, homeAwayTime);
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07004664 if (pHddCtx->cfg_ini->nRoamScanHomeAwayTime != homeAwayTime)
4665 {
4666 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
4667 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_TRUE);
4668 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004669 }
Mahesh A Saptasagarec7d1092015-04-02 13:41:34 +05304670 else if (strncmp(command, "GETSCANHOMEAWAYTIME", 19) == 0)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004671 {
4672 tANI_U16 val = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
4673 char extra[32];
4674 tANI_U8 len = 0;
4675
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004676 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Ratnam Rachuri51a5ad12015-08-07 14:06:37 +05304677 len = VOS_MIN(priv_data.total_len, len + 1);
4678 if (copy_to_user(priv_data.buf, &extra, len)) {
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004679 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4680 "%s: failed to copy data to user buffer", __func__);
4681 ret = -EFAULT;
4682 goto exit;
4683 }
4684 }
4685 else if (strncmp(command, "REASSOC", 7) == 0)
4686 {
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304687 ret = hdd_drv_cmd_validate(command, 7);
4688 if (ret)
4689 goto exit;
4690
4691 ret = hdd_parse_reassoc(pAdapter, command, priv_data.total_len);
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05304692 if (!ret)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004693 goto exit;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004694 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07004695 else if (strncmp(command, "SETWESMODE", 10) == 0)
4696 {
4697 tANI_U8 *value = command;
4698 tANI_BOOLEAN wesMode = CFG_ENABLE_WES_MODE_NAME_DEFAULT;
4699
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304700 ret = hdd_drv_cmd_validate(command, 10);
4701 if (ret)
4702 goto exit;
4703
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07004704 /* Move pointer to ahead of SETWESMODE<delimiter> */
4705 value = value + 11;
4706 /* Convert the value from ascii to integer */
4707 ret = kstrtou8(value, 10, &wesMode);
4708 if (ret < 0)
4709 {
4710 /* If the input value is greater than max value of datatype, then also
4711 kstrtou8 fails */
4712 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4713 "%s: kstrtou8 failed range [%d - %d]", __func__,
4714 CFG_ENABLE_WES_MODE_NAME_MIN,
4715 CFG_ENABLE_WES_MODE_NAME_MAX);
4716 ret = -EINVAL;
4717 goto exit;
4718 }
4719
4720 if ((wesMode < CFG_ENABLE_WES_MODE_NAME_MIN) ||
4721 (wesMode > CFG_ENABLE_WES_MODE_NAME_MAX))
4722 {
4723 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4724 "WES Mode value %d is out of range"
4725 " (Min: %d Max: %d)", wesMode,
4726 CFG_ENABLE_WES_MODE_NAME_MIN,
4727 CFG_ENABLE_WES_MODE_NAME_MAX);
4728 ret = -EINVAL;
4729 goto exit;
4730 }
4731 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4732 "%s: Received Command to Set WES Mode rssi diff = %d", __func__, wesMode);
4733
4734 pHddCtx->cfg_ini->isWESModeEnabled = wesMode;
4735 sme_UpdateWESMode((tHalHandle)(pHddCtx->hHal), wesMode);
4736 }
Mahesh A Saptasagarec7d1092015-04-02 13:41:34 +05304737 else if (strncmp(command, "GETWESMODE", 10) == 0)
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07004738 {
4739 tANI_BOOLEAN wesMode = sme_GetWESMode((tHalHandle)(pHddCtx->hHal));
4740 char extra[32];
4741 tANI_U8 len = 0;
4742
Arif Hussain826d9412013-11-12 16:44:54 -08004743 len = scnprintf(extra, sizeof(extra), "%s %d", command, wesMode);
Ratnam Rachuri8fe90c62015-08-07 14:03:26 +05304744 len = VOS_MIN(priv_data.total_len, len + 1);
4745 if (copy_to_user(priv_data.buf, &extra, len)) {
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07004746 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4747 "%s: failed to copy data to user buffer", __func__);
4748 ret = -EFAULT;
4749 goto exit;
4750 }
4751 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004752#endif /* WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_ESE || FEATURE_WLAN_LFR */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004753#ifdef FEATURE_WLAN_LFR
4754 else if (strncmp(command, "SETFASTROAM", 11) == 0)
4755 {
4756 tANI_U8 *value = command;
4757 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
4758
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05304759 if (pHddCtx->concurrency_mode == VOS_STA_MON) {
4760 hddLog(LOGE,
4761 FL("Roaming is always disabled in STA + MON concurrency"));
4762 ret = -EINVAL;
4763 goto exit;
4764 }
4765
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304766 ret = hdd_drv_cmd_validate(command, 11);
4767 if (ret)
4768 goto exit;
4769
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004770 /* Move pointer to ahead of SETFASTROAM<delimiter> */
4771 value = value + 12;
4772 /* Convert the value from ascii to integer */
4773 ret = kstrtou8(value, 10, &lfrMode);
4774 if (ret < 0)
4775 {
4776 /* If the input value is greater than max value of datatype, then also
4777 kstrtou8 fails */
4778 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4779 "%s: kstrtou8 failed range [%d - %d]", __func__,
4780 CFG_LFR_FEATURE_ENABLED_MIN,
4781 CFG_LFR_FEATURE_ENABLED_MAX);
4782 ret = -EINVAL;
4783 goto exit;
4784 }
4785
4786 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
4787 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
4788 {
4789 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4790 "lfr mode value %d is out of range"
4791 " (Min: %d Max: %d)", lfrMode,
4792 CFG_LFR_FEATURE_ENABLED_MIN,
4793 CFG_LFR_FEATURE_ENABLED_MAX);
4794 ret = -EINVAL;
4795 goto exit;
4796 }
4797
4798 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4799 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
4800
4801 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
4802 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
4803 }
4804#endif
4805#ifdef WLAN_FEATURE_VOWIFI_11R
4806 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
4807 {
4808 tANI_U8 *value = command;
4809 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
4810
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304811 ret = hdd_drv_cmd_validate(command, 17);
4812 if (ret)
4813 goto exit;
4814
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004815 /* Move pointer to ahead of SETFASTROAM<delimiter> */
4816 value = value + 18;
4817 /* Convert the value from ascii to integer */
4818 ret = kstrtou8(value, 10, &ft);
4819 if (ret < 0)
4820 {
4821 /* If the input value is greater than max value of datatype, then also
4822 kstrtou8 fails */
4823 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4824 "%s: kstrtou8 failed range [%d - %d]", __func__,
4825 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
4826 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
4827 ret = -EINVAL;
4828 goto exit;
4829 }
4830
4831 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
4832 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
4833 {
4834 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4835 "ft mode value %d is out of range"
4836 " (Min: %d Max: %d)", ft,
4837 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
4838 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
4839 ret = -EINVAL;
4840 goto exit;
4841 }
4842
4843 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4844 "%s: Received Command to change ft mode = %d", __func__, ft);
4845
4846 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
4847 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
4848 }
Padma, Santhosh Kumar778d8382015-03-04 17:41:22 +05304849 else if (strncmp(command, "SETDFSSCANMODE", 14) == 0)
4850 {
4851 tANI_U8 *value = command;
4852 tANI_U8 dfsScanMode = DFS_CHNL_SCAN_ENABLED_NORMAL;
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05304853
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304854 ret = hdd_drv_cmd_validate(command, 14);
4855 if (ret)
4856 goto exit;
4857
Padma, Santhosh Kumar778d8382015-03-04 17:41:22 +05304858 /* Move pointer to ahead of SETDFSSCANMODE<delimiter> */
4859 value = value + 15;
4860 /* Convert the value from ascii to integer */
4861 ret = kstrtou8(value, 10, &dfsScanMode);
4862 if (ret < 0)
4863 {
4864 /* If the input value is greater than max value of
4865 datatype, then also kstrtou8 fails
4866 */
4867 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4868 "%s: kstrtou8 failed range [%d - %d]", __func__,
4869 CFG_ENABLE_DFS_CHNL_SCAN_MIN,
4870 CFG_ENABLE_DFS_CHNL_SCAN_MAX);
4871 ret = -EINVAL;
4872 goto exit;
4873 }
4874
4875 if ((dfsScanMode < CFG_ENABLE_DFS_CHNL_SCAN_MIN) ||
4876 (dfsScanMode > CFG_ENABLE_DFS_CHNL_SCAN_MAX))
4877 {
4878 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4879 "dfsScanMode value %d is out of range"
4880 " (Min: %d Max: %d)", dfsScanMode,
4881 CFG_ENABLE_DFS_CHNL_SCAN_MIN,
4882 CFG_ENABLE_DFS_CHNL_SCAN_MAX);
4883 ret = -EINVAL;
4884 goto exit;
4885 }
4886 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4887 "%s: Received Command to Set DFS Scan Mode = %d",
4888 __func__, dfsScanMode);
4889
4890 ret = wlan_hdd_handle_dfs_chan_scan(pHddCtx, dfsScanMode);
4891 }
4892 else if (strncmp(command, "GETDFSSCANMODE", 14) == 0)
4893 {
4894 tANI_U8 dfsScanMode = sme_GetDFSScanMode(pHddCtx->hHal);
4895 char extra[32];
4896 tANI_U8 len = 0;
4897
4898 len = scnprintf(extra, sizeof(extra), "%s %d", command, dfsScanMode);
Ratheesh S P767224e2015-07-16 15:35:51 +05304899 len = VOS_MIN(priv_data.total_len, len + 1);
4900 if (copy_to_user(priv_data.buf, &extra, len))
Padma, Santhosh Kumar778d8382015-03-04 17:41:22 +05304901 {
4902 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4903 "%s: failed to copy data to user buffer", __func__);
4904 ret = -EFAULT;
4905 goto exit;
4906 }
4907 }
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05304908 else if (strncmp(command, "FASTREASSOC", 11) == 0)
4909 {
Selvaraj, Sridhar3714c4d2016-06-22 15:19:12 +05304910 ret = wlan_hdd_handle_fastreassoc(pAdapter, command);
4911 if (!ret)
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05304912 goto exit;
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05304913 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004914#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004915#ifdef FEATURE_WLAN_ESE
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004916 else if (strncmp(command, "SETCCXMODE", 10) == 0)
4917 {
4918 tANI_U8 *value = command;
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004919 tANI_U8 eseMode = CFG_ESE_FEATURE_ENABLED_DEFAULT;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004920
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304921 ret = hdd_drv_cmd_validate(command, 10);
4922 if (ret)
4923 goto exit;
4924
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004925 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07004926 then this operation is not permitted (return FAILURE) */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004927 if (sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07004928 hdd_is_okc_mode_enabled(pHddCtx) &&
4929 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
4930 {
4931 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004932 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07004933 " hence this operation is not permitted!", __func__);
4934 ret = -EPERM;
4935 goto exit;
4936 }
4937
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004938 /* Move pointer to ahead of SETCCXMODE<delimiter> */
4939 value = value + 11;
4940 /* Convert the value from ascii to integer */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004941 ret = kstrtou8(value, 10, &eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004942 if (ret < 0)
4943 {
4944 /* If the input value is greater than max value of datatype, then also
4945 kstrtou8 fails */
4946 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4947 "%s: kstrtou8 failed range [%d - %d]", __func__,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004948 CFG_ESE_FEATURE_ENABLED_MIN,
4949 CFG_ESE_FEATURE_ENABLED_MAX);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004950 ret = -EINVAL;
4951 goto exit;
4952 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004953 if ((eseMode < CFG_ESE_FEATURE_ENABLED_MIN) ||
4954 (eseMode > CFG_ESE_FEATURE_ENABLED_MAX))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004955 {
4956 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004957 "Ese mode value %d is out of range"
4958 " (Min: %d Max: %d)", eseMode,
4959 CFG_ESE_FEATURE_ENABLED_MIN,
4960 CFG_ESE_FEATURE_ENABLED_MAX);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004961 ret = -EINVAL;
4962 goto exit;
4963 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004964 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004965 "%s: Received Command to change ese mode = %d", __func__, eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004966
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004967 pHddCtx->cfg_ini->isEseIniFeatureEnabled = eseMode;
4968 sme_UpdateIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal), eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004969 }
4970#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004971 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
4972 {
4973 tANI_U8 *value = command;
4974 tANI_BOOLEAN roamScanControl = 0;
4975
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304976 ret = hdd_drv_cmd_validate(command, 18);
4977 if (ret)
4978 goto exit;
4979
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004980 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
4981 value = value + 19;
4982 /* Convert the value from ascii to integer */
4983 ret = kstrtou8(value, 10, &roamScanControl);
4984 if (ret < 0)
4985 {
4986 /* If the input value is greater than max value of datatype, then also
4987 kstrtou8 fails */
4988 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4989 "%s: kstrtou8 failed ", __func__);
4990 ret = -EINVAL;
4991 goto exit;
4992 }
4993
4994 if (0 != roamScanControl)
4995 {
4996 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4997 "roam scan control invalid value = %d",
4998 roamScanControl);
4999 ret = -EINVAL;
5000 goto exit;
5001 }
5002 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5003 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
5004
5005 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
5006 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07005007#ifdef FEATURE_WLAN_OKC
5008 else if (strncmp(command, "SETOKCMODE", 10) == 0)
5009 {
5010 tANI_U8 *value = command;
5011 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
5012
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05305013 ret = hdd_drv_cmd_validate(command, 10);
5014 if (ret)
5015 goto exit;
5016
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08005017 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07005018 then this operation is not permitted (return FAILURE) */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08005019 if (sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07005020 hdd_is_okc_mode_enabled(pHddCtx) &&
5021 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
5022 {
5023 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08005024 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07005025 " hence this operation is not permitted!", __func__);
5026 ret = -EPERM;
5027 goto exit;
5028 }
5029
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07005030 /* Move pointer to ahead of SETOKCMODE<delimiter> */
5031 value = value + 11;
5032 /* Convert the value from ascii to integer */
5033 ret = kstrtou8(value, 10, &okcMode);
5034 if (ret < 0)
5035 {
5036 /* If the input value is greater than max value of datatype, then also
5037 kstrtou8 fails */
5038 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5039 "%s: kstrtou8 failed range [%d - %d]", __func__,
5040 CFG_OKC_FEATURE_ENABLED_MIN,
5041 CFG_OKC_FEATURE_ENABLED_MAX);
5042 ret = -EINVAL;
5043 goto exit;
5044 }
5045
5046 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
5047 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
5048 {
5049 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5050 "Okc mode value %d is out of range"
5051 " (Min: %d Max: %d)", okcMode,
5052 CFG_OKC_FEATURE_ENABLED_MIN,
5053 CFG_OKC_FEATURE_ENABLED_MAX);
5054 ret = -EINVAL;
5055 goto exit;
5056 }
5057
5058 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5059 "%s: Received Command to change okc mode = %d", __func__, okcMode);
5060
5061 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
5062 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07005063#endif /* FEATURE_WLAN_OKC */
Mahesh A Saptasagarec7d1092015-04-02 13:41:34 +05305064 else if (strncmp(command, "GETROAMSCANCONTROL", 18) == 0)
Srinivas Girigowda100eb322013-03-15 16:48:20 -07005065 {
5066 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
5067 char extra[32];
5068 tANI_U8 len = 0;
5069
Sameer Thalappilb0a30232013-09-27 15:37:48 -07005070 len = scnprintf(extra, sizeof(extra), "%s %d",
5071 command, roamScanControl);
Ratnam Rachuri083ada82015-08-07 14:01:05 +05305072 len = VOS_MIN(priv_data.total_len, len + 1);
5073 if (copy_to_user(priv_data.buf, &extra, len)) {
Srinivas Girigowda100eb322013-03-15 16:48:20 -07005074 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5075 "%s: failed to copy data to user buffer", __func__);
5076 ret = -EFAULT;
5077 goto exit;
5078 }
5079 }
Gopichand Nakkala227c7f32013-06-26 22:44:57 +05305080#ifdef WLAN_FEATURE_PACKET_FILTERING
5081 else if (strncmp(command, "ENABLE_PKTFILTER_IPV6", 21) == 0)
5082 {
5083 tANI_U8 filterType = 0;
5084 tANI_U8 *value = command;
5085
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05305086 ret = hdd_drv_cmd_validate(command, 21);
5087 if (ret)
5088 goto exit;
5089
Gopichand Nakkala227c7f32013-06-26 22:44:57 +05305090 /* Move pointer to ahead of ENABLE_PKTFILTER_IPV6<delimiter> */
5091 value = value + 22;
5092
5093 /* Convert the value from ascii to integer */
5094 ret = kstrtou8(value, 10, &filterType);
5095 if (ret < 0)
5096 {
5097 /* If the input value is greater than max value of datatype,
5098 * then also kstrtou8 fails
5099 */
5100 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5101 "%s: kstrtou8 failed range ", __func__);
5102 ret = -EINVAL;
5103 goto exit;
5104 }
5105
5106 if (filterType != 0 && filterType != 1)
5107 {
5108 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5109 "%s: Accepted Values are 0 and 1 ", __func__);
5110 ret = -EINVAL;
5111 goto exit;
5112 }
5113 wlan_hdd_setIPv6Filter(WLAN_HDD_GET_CTX(pAdapter), filterType,
5114 pAdapter->sessionId);
5115 }
5116#endif
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05305117 else if (strncmp(command, "BTCOEXMODE", 10) == 0 )
5118 {
Kiet Lamad161252014-07-22 11:23:32 -07005119 char *dhcpPhase;
Satyanarayana Dash1faea4f2014-09-22 16:21:04 +05305120 int ret;
5121
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05305122 ret = hdd_drv_cmd_validate(command, 10);
5123 if (ret)
5124 goto exit;
5125
Kiet Lamad161252014-07-22 11:23:32 -07005126 dhcpPhase = command + 11;
5127 if ('1' == *dhcpPhase)
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05305128 {
Deepthi Gowribfd17132014-11-14 17:59:04 +05305129 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Kiet Lamad161252014-07-22 11:23:32 -07005130 FL("send DHCP START indication"));
c_hpothu9b781ba2013-12-30 20:57:45 +05305131
5132 pHddCtx->btCoexModeSet = TRUE;
Kiet Lamad161252014-07-22 11:23:32 -07005133
Satyanarayana Dash1faea4f2014-09-22 16:21:04 +05305134 ret = wlan_hdd_scan_abort(pAdapter);
5135 if (ret < 0)
5136 {
5137 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5138 FL("failed to abort existing scan %d"), ret);
5139 }
5140
Kiet Lamad161252014-07-22 11:23:32 -07005141 sme_DHCPStartInd(pHddCtx->hHal, pAdapter->device_mode,
5142 pAdapter->sessionId);
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05305143 }
Kiet Lamad161252014-07-22 11:23:32 -07005144 else if ('2' == *dhcpPhase)
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05305145 {
Deepthi Gowribfd17132014-11-14 17:59:04 +05305146 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Kiet Lamad161252014-07-22 11:23:32 -07005147 FL("send DHCP STOP indication"));
c_hpothu9b781ba2013-12-30 20:57:45 +05305148
5149 pHddCtx->btCoexModeSet = FALSE;
Kiet Lamad161252014-07-22 11:23:32 -07005150
5151 sme_DHCPStopInd(pHddCtx->hHal, pAdapter->device_mode,
5152 pAdapter->sessionId);
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05305153 }
5154 }
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07005155 else if (strncmp(command, "SCAN-ACTIVE", 11) == 0)
5156 {
Abhishek Singh58749d62016-02-03 15:27:20 +05305157 hddLog(LOG1,
5158 FL("making default scan to ACTIVE"));
c_hpothudbefd3e2014-04-28 15:59:47 +05305159 pHddCtx->scan_info.scan_mode = eSIR_ACTIVE_SCAN;
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07005160 }
5161 else if (strncmp(command, "SCAN-PASSIVE", 12) == 0)
5162 {
Abhishek Singh58749d62016-02-03 15:27:20 +05305163 hddLog(LOG1,
5164 FL("making default scan to PASSIVE"));
c_hpothudbefd3e2014-04-28 15:59:47 +05305165 pHddCtx->scan_info.scan_mode = eSIR_PASSIVE_SCAN;
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07005166 }
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05305167 else if (strncmp(command, "GETDWELLTIME", 12) == 0)
5168 {
5169 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
5170 char extra[32];
5171 tANI_U8 len = 0;
5172
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05305173 memset(extra, 0, sizeof(extra));
5174 ret = hdd_get_dwell_time(pCfg, command, extra, sizeof(extra), &len);
Ratnam Rachuri12d5d462015-08-07 14:10:23 +05305175 len = VOS_MIN(priv_data.total_len, len + 1);
5176 if (ret != 0 || copy_to_user(priv_data.buf, &extra, len)) {
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05305177 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5178 "%s: failed to copy data to user buffer", __func__);
5179 ret = -EFAULT;
5180 goto exit;
5181 }
5182 ret = len;
5183 }
5184 else if (strncmp(command, "SETDWELLTIME", 12) == 0)
5185 {
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05305186 ret = hdd_set_dwell_time(pAdapter, command);
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05305187 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07005188 else if ( strncasecmp(command, "MIRACAST", 8) == 0 )
5189 {
5190 tANI_U8 filterType = 0;
5191 tANI_U8 *value;
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05305192
5193 ret = hdd_drv_cmd_validate(command, 8);
5194 if (ret)
5195 goto exit;
5196
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07005197 value = command + 9;
5198
5199 /* Convert the value from ascii to integer */
5200 ret = kstrtou8(value, 10, &filterType);
5201 if (ret < 0)
5202 {
5203 /* If the input value is greater than max value of datatype,
5204 * then also kstrtou8 fails
5205 */
5206 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5207 "%s: kstrtou8 failed range ", __func__);
5208 ret = -EINVAL;
5209 goto exit;
5210 }
5211 if ((filterType < WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL ) ||
5212 (filterType > WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL))
5213 {
5214 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5215 "%s: Accepted Values are 0 to 2. 0-Disabled, 1-Source,"
5216 " 2-Sink ", __func__);
5217 ret = -EINVAL;
5218 goto exit;
5219 }
5220 //Filtertype value should be either 0-Disabled, 1-Source, 2-sink
5221 pHddCtx->drvr_miracast = filterType;
Kaushik, Sushant96122442014-10-21 16:40:18 +05305222 pScanInfo = &pHddCtx->scan_info;
5223 if (filterType && pScanInfo != NULL &&
5224 pHddCtx->scan_info.mScanPending)
5225 {
5226 /*Miracast Session started. Abort Scan */
5227 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5228 "%s, Aborting Scan For Miracast",__func__);
5229 hdd_abort_mac_scan(pHddCtx, pScanInfo->sessionId,
5230 eCSR_SCAN_ABORT_DEFAULT);
5231 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07005232 hdd_tx_rx_pkt_cnt_stat_timer_handler(pHddCtx);
Ganesh Kondabattini8f6e3b32014-08-25 16:07:54 +05305233 sme_SetMiracastMode(pHddCtx->hHal, pHddCtx->drvr_miracast);
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07005234 }
Leo Chang614d2072013-08-22 14:59:44 -07005235 else if (strncmp(command, "SETMCRATE", 9) == 0)
5236 {
Leo Chang614d2072013-08-22 14:59:44 -07005237 tANI_U8 *value = command;
5238 int targetRate;
Leo Chang1f98cbd2013-10-17 15:03:52 -07005239 tSirRateUpdateInd *rateUpdate;
5240 eHalStatus status;
Leo Chang614d2072013-08-22 14:59:44 -07005241
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05305242 ret = hdd_drv_cmd_validate(command, 9);
5243 if (ret)
5244 goto exit;
5245
Leo Chang614d2072013-08-22 14:59:44 -07005246 /* Only valid for SAP mode */
5247 if (WLAN_HDD_SOFTAP != pAdapter->device_mode)
5248 {
5249 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5250 "%s: SAP mode is not running", __func__);
5251 ret = -EFAULT;
5252 goto exit;
5253 }
5254
5255 /* Move pointer to ahead of SETMCRATE<delimiter> */
5256 /* input value is in units of hundred kbps */
5257 value = value + 10;
5258 /* Convert the value from ascii to integer, decimal base */
5259 ret = kstrtouint(value, 10, &targetRate);
5260
Leo Chang1f98cbd2013-10-17 15:03:52 -07005261 rateUpdate = (tSirRateUpdateInd *)vos_mem_malloc(sizeof(tSirRateUpdateInd));
5262 if (NULL == rateUpdate)
Leo Chang614d2072013-08-22 14:59:44 -07005263 {
Leo Chang1f98cbd2013-10-17 15:03:52 -07005264 hddLog(VOS_TRACE_LEVEL_ERROR,
5265 "%s: SETMCRATE indication alloc fail", __func__);
5266 ret = -EFAULT;
5267 goto exit;
5268 }
5269 vos_mem_zero(rateUpdate, sizeof(tSirRateUpdateInd ));
5270
5271 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5272 "MC Target rate %d", targetRate);
5273 /* Ignore unicast */
5274 rateUpdate->ucastDataRate = -1;
5275 rateUpdate->mcastDataRate24GHz = targetRate;
5276 rateUpdate->mcastDataRate5GHz = targetRate;
5277 rateUpdate->mcastDataRate24GHzTxFlag = 0;
5278 rateUpdate->mcastDataRate5GHzTxFlag = 0;
5279 status = sme_SendRateUpdateInd(pHddCtx->hHal, rateUpdate);
5280 if (eHAL_STATUS_SUCCESS != status)
5281 {
5282 hddLog(VOS_TRACE_LEVEL_ERROR,
5283 "%s: SET_MC_RATE failed", __func__);
5284 vos_mem_free(rateUpdate);
5285 ret = -EFAULT;
5286 goto exit;
Leo Chang614d2072013-08-22 14:59:44 -07005287 }
5288 }
jge35567202017-06-21 16:39:38 +08005289 else if (strncmp(command, "MAXTXPOWER", 10) == 0)
5290 {
5291 int status;
5292 int txPower;
5293 eHalStatus smeStatus;
5294 tANI_U8 *value = command;
5295 tSirMacAddr bssid = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
5296 tSirMacAddr selfMac = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
5297
5298 status = hdd_parse_setmaxtxpower_command(value, &txPower);
5299 if (status)
5300 {
5301 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5302 "Invalid MAXTXPOWER command ");
5303 ret = -EINVAL;
5304 goto exit;
5305 }
5306
5307 hddLog(VOS_TRACE_LEVEL_INFO, "max tx power %d selfMac: "
5308 MAC_ADDRESS_STR " bssId: " MAC_ADDRESS_STR " ",
5309 txPower, MAC_ADDR_ARRAY(selfMac),
5310 MAC_ADDR_ARRAY(bssid));
5311 smeStatus = sme_SetMaxTxPower((tHalHandle)(pHddCtx->hHal),
5312 bssid, selfMac, txPower) ;
5313 if( smeStatus != eHAL_STATUS_SUCCESS )
5314 {
5315 hddLog(VOS_TRACE_LEVEL_ERROR, "%s:Set max tx power failed",
5316 __func__);
5317 ret = -EINVAL;
5318 goto exit;
5319 }
5320
5321 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Set max tx power success",
5322 __func__);
5323 }
Rajeev79dbe4c2013-10-05 11:03:42 +05305324#ifdef FEATURE_WLAN_BATCH_SCAN
Rajeev Kumar8b373292014-01-08 20:36:55 -08005325 else if (strncmp(command, "WLS_BATCHING", 12) == 0)
Rajeev79dbe4c2013-10-05 11:03:42 +05305326 {
Rajeev Kumar8b373292014-01-08 20:36:55 -08005327 ret = hdd_handle_batch_scan_ioctl(pAdapter, &priv_data, command);
Rajeev79dbe4c2013-10-05 11:03:42 +05305328 }
5329#endif
Abhishek Singh00b71972016-01-07 10:51:04 +05305330#ifdef WLAN_FEATURE_RMC
5331 else if ((strncasecmp(command, "SETIBSSBEACONOUIDATA", 20) == 0) &&
5332 (WLAN_HDD_IBSS == pAdapter->device_mode))
5333 {
5334 int i = 0;
5335 tANI_U8 *ibss_ie;
5336 tANI_U32 command_len;
5337 tANI_U8 *value = command;
5338 tHalHandle hHal = pHddCtx->hHal;
5339 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
5340 tANI_U32 ibss_ie_length;
5341 tANI_U32 len, present;
5342 tANI_U8 *addIE;
5343 tANI_U8 *addIEData;
5344
5345 hddLog(LOG1,
5346 FL(" received command %s"),((char *) value));
5347 /* validate argument of command */
5348 if (strlen(value) <= 21)
5349 {
5350 hddLog(LOGE,
5351 FL("No arguements in command length %zu"), strlen(value));
5352 ret = -EFAULT;
5353 goto exit;
5354 }
5355
5356 /* moving to arguments of commands */
5357 value = value + 21;
5358 command_len = strlen(value);
5359
5360 /* oui_data can't be less than 3 bytes */
5361 if (command_len <= (2 * WLAN_HDD_IBSS_MIN_OUI_DATA_LENGTH))
5362 {
5363 hddLog(LOGE,
5364 FL("Invalid SETIBSSBEACONOUIDATA command length %d"),
5365 command_len);
5366 ret = -EFAULT;
5367 goto exit;
5368 }
5369 ibss_ie = vos_mem_malloc(command_len);
5370 if (!ibss_ie) {
5371 hddLog(LOGE,
5372 FL("Could not allocate memory for command length %d"),
5373 command_len);
5374 ret = -ENOMEM;
5375 goto exit;
5376 }
5377 vos_mem_zero(ibss_ie, command_len);
5378
5379 ibss_ie_length = hdd_parse_set_ibss_oui_data_command(value, ibss_ie,
5380 command_len);
5381 if (ibss_ie_length < (2 * WLAN_HDD_IBSS_MIN_OUI_DATA_LENGTH)) {
5382 hddLog(LOGE, FL("Could not parse command %s return length %d"),
5383 value, ibss_ie_length);
5384 ret = -EFAULT;
5385 vos_mem_free(ibss_ie);
5386 goto exit;
5387 }
5388
5389 hddLog(LOG1, FL("ibss_ie length %d ibss_ie:"), ibss_ie_length);
5390 while (i < ibss_ie_length)
5391 hddLog(LOG1, FL("0x%x"), ibss_ie[i++]);
5392
5393 /* Populate Vendor IE in Beacon */
5394 if ((ccmCfgGetInt(hHal,
5395 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
5396 &present)) != eHAL_STATUS_SUCCESS)
5397 {
5398 hddLog(LOGE,
5399 FL("unable to ftch WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG"));
5400 ret = -EFAULT;
5401 vos_mem_free(ibss_ie);
5402 goto exit;
5403 }
5404
5405 addIE = vos_mem_malloc(WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN);
5406 if (!addIE) {
5407 hddLog(LOGE,
5408 FL("Could not allocate memory for command length %d"),
5409 command_len);
5410 vos_mem_free(ibss_ie);
5411 ret = -ENOMEM;
5412 goto exit;
5413 }
5414 vos_mem_zero(addIE, WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN);
5415
5416 if (present)
5417 {
5418 if ((wlan_cfgGetStrLen(pMac,
5419 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, &len)) != eSIR_SUCCESS)
5420 {
5421 hddLog(LOGE,
5422 FL("unable to fetch WNI_CFG_PROBE_RSP_BCN_ADDNIE_LEN"));
5423 ret = -EFAULT;
5424 vos_mem_free(ibss_ie);
5425 vos_mem_free(addIE);
5426 goto exit;
5427 }
5428
5429 if (len <= WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN && len &&
5430 ((len + ibss_ie_length) <=
5431 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN))
5432 {
5433 if ((ccmCfgGetStr(hHal,
5434 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, addIE, &len))
5435 != eHAL_STATUS_SUCCESS)
5436 {
5437 hddLog(LOGE,
5438 FL("unable to fetch WNI_PROBE_RSP_BCN_ADDNIE_DATA"));
5439 ret = -EFAULT;
5440 vos_mem_free(ibss_ie);
5441 vos_mem_free(addIE);
5442 goto exit;
5443 }
5444 else
5445 {
5446 /* Curruntly only WPA IE is added before Vendor IE
5447 * so we can blindly place the Vendor IE after WPA
5448 * IE. If no WPA IE found replace all with Vendor IE.
5449 */
5450 len = hdd_find_ibss_wpa_ie_pos(addIE, len);
5451 }
5452 }
5453 else
5454 {
5455 hddLog(LOGE,
5456 FL("IE len exceed limit len %d,ibss_ie_length %d "),
5457 len, ibss_ie_length);
5458 ret = -EFAULT;
5459 vos_mem_free(addIE);
5460 vos_mem_free(ibss_ie);
5461 goto exit;
5462 }
5463 }
5464 else {
5465 len = 0;
5466 }
5467
5468 vos_mem_copy (addIE + len , ibss_ie, ibss_ie_length);
5469 len += ibss_ie_length;
5470
5471 if (ccmCfgSetStr(hHal,
5472 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, addIE, len, NULL,
5473 eANI_BOOLEAN_FALSE) != eHAL_STATUS_SUCCESS)
5474 {
5475 hddLog(LOGE,
5476 FL("unable to set WNI_CFG_PRBE_RSP_BCN_ADDNIE_DATA"));
5477 ret = -EFAULT;
5478 vos_mem_free(ibss_ie);
5479 vos_mem_free(addIE);
5480 goto exit;
5481 }
5482 vos_mem_free(addIE);
5483 if (ccmCfgSetInt(hHal,
5484 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 1,NULL,
5485 eANI_BOOLEAN_FALSE) != eHAL_STATUS_SUCCESS)
5486 {
5487 hddLog(LOGE,
5488 FL("unble to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG"));
5489 ret = -EFAULT;
5490 vos_mem_free(ibss_ie);
5491 goto exit;
5492 }
5493
5494 /* Populate Vendor IE in probe resp */
5495 if ((ccmCfgGetInt(hHal,
5496 WNI_CFG_PROBE_RSP_ADDNIE_FLAG,
5497 &present)) != eHAL_STATUS_SUCCESS)
5498 {
5499 hddLog(LOGE,
5500 FL("unable to fetch WNI_CFG_PROBE_RSP_ADDNIE_FLAG"));
5501 ret = -EFAULT;
5502 vos_mem_free(ibss_ie);
5503 goto exit;
5504 }
5505
5506 addIEData = vos_mem_malloc(WNI_CFG_PROBE_RSP_ADDNIE_DATA1_LEN);
5507 if (!addIEData) {
5508 hddLog(LOGE,
5509 FL("Could not allocate memory for command length %d"),
5510 command_len);
5511 vos_mem_free(ibss_ie);
5512 ret = -ENOMEM;
5513 goto exit;
5514 }
5515 vos_mem_zero(addIEData, WNI_CFG_PROBE_RSP_ADDNIE_DATA1_LEN);
5516
5517 if (present) {
5518 if (eSIR_SUCCESS != wlan_cfgGetStrLen(pMac,
5519 WNI_CFG_PROBE_RSP_ADDNIE_DATA1, &len)) {
5520 hddLog(LOGE,
5521 FL("unable to fetch WNI_CFG_PROBE_RSP_ADDNIE_DATA1"));
5522 ret = -EFAULT;
5523 vos_mem_free(ibss_ie);
5524 vos_mem_free(addIEData);
5525 goto exit;
5526 }
5527 if (len < WNI_CFG_PROBE_RSP_ADDNIE_DATA1_LEN && len &&
5528 (ibss_ie_length + len) <=
5529 WNI_CFG_PROBE_RSP_ADDNIE_DATA1_LEN) {
5530
5531 if ((ccmCfgGetStr(hHal,
5532 WNI_CFG_PROBE_RSP_ADDNIE_DATA1, addIEData, &len))
5533 != eHAL_STATUS_SUCCESS) {
5534 hddLog(LOGE,
5535 FL("unable fetch WNI_CFG_PROBE_RSP_ADDNIE_DATA1"));
5536 ret = -EFAULT;
5537 vos_mem_free(ibss_ie);
5538 vos_mem_free(addIEData);
5539 goto exit;
5540 }
5541 else {
5542 /* Curruntly only WPA IE is added before Vendor IE
5543 * so we can blindly place the Vendor IE after WPA
5544 * IE. If no WPA IE found replace all with Vendor IE.
5545 */
5546 len = hdd_find_ibss_wpa_ie_pos(addIEData, len);
5547 }
5548 }
5549 else
5550 {
5551 hddLog(LOGE,
5552 FL("IE len exceed limit len %d,ibss_ie_length %d "),
5553 len, ibss_ie_length);
5554 ret = -EFAULT;
5555 vos_mem_free(addIEData);
5556 vos_mem_free(ibss_ie);
5557 goto exit;
5558 }
5559 } /* probe rsp ADD IE present */
5560 else {
5561 /* probe rsp add IE is not present */
5562 len = 0;
5563 }
5564
5565 vos_mem_copy(addIEData +len , ibss_ie, ibss_ie_length);
5566 len += ibss_ie_length;
5567
5568 vos_mem_free(ibss_ie);
5569
5570 if (ccmCfgSetStr(hHal,
5571 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,
5572 (tANI_U8*)(addIEData),
5573 len, NULL,
5574 eANI_BOOLEAN_FALSE)
5575 == eHAL_STATUS_FAILURE) {
5576 hddLog(LOGE,
5577 FL("unable to copy to WNI_CFG_PROBE_RSP_ADDNIE_DATA1"));
5578 ret = -EFAULT;
5579 vos_mem_free(addIEData);
5580 goto exit;
5581 }
5582 vos_mem_free(addIEData);
5583 if (ccmCfgSetInt(WLAN_HDD_GET_HAL_CTX(pAdapter),
5584 WNI_CFG_PROBE_RSP_ADDNIE_FLAG, 1,NULL,
5585 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
5586 {
5587 hddLog(LOGE,
5588 FL("unable to copy WNI_CFG_PROBE_RSP_ADDNIE_FLAG"));
5589 ret = -EFAULT;
5590 goto exit;
5591 }
5592 }
5593 else if (strncasecmp(command, "SETRMCENABLE", 12) == 0)
5594 {
5595 tANI_U8 *value = command;
5596 tANI_U8 ucRmcEnable = 0;
5597 int status;
5598
5599 if ((WLAN_HDD_IBSS != pAdapter->device_mode) &&
5600 (WLAN_HDD_SOFTAP != pAdapter->device_mode))
5601 {
5602 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5603 "Received SETRMCENABLE command in invalid mode %d "
5604 "SETRMCENABLE command is only allowed in IBSS or SOFTAP mode",
5605 pAdapter->device_mode);
5606 ret = -EINVAL;
5607 goto exit;
5608 }
5609
5610 status = hdd_parse_setrmcenable_command(value, &ucRmcEnable);
5611 if (status)
5612 {
5613 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5614 "Invalid SETRMCENABLE command ");
5615 ret = -EINVAL;
5616 goto exit;
5617 }
5618
5619 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5620 "%s: ucRmcEnable %d ", __func__, ucRmcEnable);
5621
5622 if (TRUE == ucRmcEnable)
5623 {
5624 status = sme_EnableRMC( (tHalHandle)(pHddCtx->hHal),
5625 pAdapter->sessionId );
5626 }
5627 else if(FALSE == ucRmcEnable)
5628 {
5629 status = sme_DisableRMC( (tHalHandle)(pHddCtx->hHal),
5630 pAdapter->sessionId );
5631 }
5632 else
5633 {
5634 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5635 "Invalid SETRMCENABLE command %d", ucRmcEnable);
5636 ret = -EINVAL;
5637 goto exit;
5638 }
5639
5640 if (VOS_STATUS_SUCCESS != status)
5641 {
5642 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5643 "%s: SETRMC %d failed status %d", __func__, ucRmcEnable,
5644 status);
5645 ret = -EINVAL;
5646 goto exit;
5647 }
5648 }
5649 else if (strncasecmp(command, "SETRMCACTIONPERIOD", 18) == 0)
5650 {
5651 tANI_U8 *value = command;
5652 tANI_U32 uActionPeriod = 0;
5653 int status;
5654
5655 if ((WLAN_HDD_IBSS != pAdapter->device_mode) &&
5656 (WLAN_HDD_SOFTAP != pAdapter->device_mode))
5657 {
5658 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5659 "Received SETRMC command in invalid mode %d "
5660 "SETRMC command is only allowed in IBSS or SOFTAP mode",
5661 pAdapter->device_mode);
5662 ret = -EINVAL;
5663 goto exit;
5664 }
5665
5666 status = hdd_parse_setrmcactionperiod_command(value, &uActionPeriod);
5667 if (status)
5668 {
5669 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5670 "Invalid SETRMCACTIONPERIOD command ");
5671 ret = -EINVAL;
5672 goto exit;
5673 }
5674
5675 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5676 "%s: uActionPeriod %d ", __func__, uActionPeriod);
5677
5678 if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY,
5679 uActionPeriod, NULL, eANI_BOOLEAN_FALSE))
5680 {
5681 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5682 "%s: Could not set SETRMCACTIONPERIOD %d", __func__, uActionPeriod);
5683 ret = -EINVAL;
5684 goto exit;
5685 }
5686
5687 }
5688 else if (strncasecmp(command, "GETIBSSPEERINFOALL", 18) == 0)
5689 {
5690 /* Peer Info All Command */
5691 int status = eHAL_STATUS_SUCCESS;
5692 hdd_station_ctx_t *pHddStaCtx = NULL;
5693 char *extra = NULL;
5694 int idx = 0, length = 0;
5695 v_MACADDR_t *macAddr;
5696 v_U32_t txRateMbps = 0, numOfBytestoPrint = 0;
5697
5698 if (WLAN_HDD_IBSS == pAdapter->device_mode)
5699 {
5700 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5701 }
5702 else
5703 {
5704 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5705 "%s: pAdapter is not valid for this device mode",
5706 __func__);
5707 ret = -EINVAL;
5708 goto exit;
5709 }
5710
5711 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5712 "%s: Received GETIBSSPEERINFOALL Command", __func__);
5713
5714
5715 /* Handle the command */
5716 status = hdd_cfg80211_get_ibss_peer_info_all(pAdapter);
5717 if (VOS_STATUS_SUCCESS == status)
5718 {
5719 /* The variable extra needed to be allocated on the heap since
5720 * amount of memory required to copy the data for 32 devices
5721 * exceeds the size of 1024 bytes of default stack size. On
5722 * 64 bit devices, the default max stack size of 2048 bytes
5723 */
5724 extra = kmalloc(WLAN_MAX_BUF_SIZE, GFP_KERNEL);
5725
5726 if (NULL == extra)
5727 {
5728 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5729 "%s:kmalloc failed", __func__);
5730 ret = -EINVAL;
5731 goto exit;
5732 }
5733
5734 /* Copy number of stations */
5735 length = scnprintf( extra, WLAN_MAX_BUF_SIZE, "%d ",
5736 pHddStaCtx->ibss_peer_info.numIBSSPeers);
5737 numOfBytestoPrint = length;
5738 for (idx = 0; idx < pHddStaCtx->ibss_peer_info.numIBSSPeers; idx++)
5739 {
5740 macAddr =
5741 hdd_wlan_get_ibss_mac_addr_from_staid(pAdapter,
5742 pHddStaCtx->ibss_peer_info.ibssPeerList[idx].staIdx);
5743 if (NULL != macAddr)
5744 {
5745 txRateMbps =
5746 ((pHddStaCtx->ibss_peer_info.ibssPeerList[idx].txRate)*500*1000)/1000000;
5747
5748 length += scnprintf( (extra + length), WLAN_MAX_BUF_SIZE - length,
5749 "%02x:%02x:%02x:%02x:%02x:%02x %d %d ",
5750 macAddr->bytes[0], macAddr->bytes[1], macAddr->bytes[2],
5751 macAddr->bytes[3], macAddr->bytes[4], macAddr->bytes[5],
5752 (int)txRateMbps,
5753 (int)pHddStaCtx->ibss_peer_info.ibssPeerList[idx].rssi);
5754 }
5755 else
5756 {
5757 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5758 "%s: MAC ADDR is NULL for staIdx: %d", __func__,
5759 pHddStaCtx->ibss_peer_info.ibssPeerList[idx].staIdx);
5760 }
5761
5762 /*
5763 * VOS_TRACE() macro has limitation of 512 bytes for the print
5764 * buffer. Hence printing the data in two chunks. The first chunk
5765 * will have the data for 16 devices and the second chunk will
5766 * have the rest.
5767 */
5768 if (idx < NUM_OF_STA_DATA_TO_PRINT)
5769 {
5770 numOfBytestoPrint = length;
5771 }
5772 }
5773
5774 /*
5775 * Copy the data back into buffer, if the data to copy is
5776 * morethan 512 bytes than we will split the data and do
5777 * it in two shots
5778 */
5779 if (copy_to_user(priv_data.buf, extra, numOfBytestoPrint))
5780 {
5781 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5782 "%s: Copy into user data buffer failed ", __func__);
5783 ret = -EFAULT;
5784 kfree(extra);
5785 goto exit;
5786 }
5787 priv_data.buf[numOfBytestoPrint] = '\0';
5788 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED,
5789 "%s", priv_data.buf);
5790
5791 if (length > numOfBytestoPrint)
5792 {
5793 if (copy_to_user(priv_data.buf + numOfBytestoPrint,
5794 extra + numOfBytestoPrint,
5795 length - numOfBytestoPrint + 1))
5796 {
5797 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5798 "%s: Copy into user data buffer failed ", __func__);
5799 ret = -EFAULT;
5800 kfree(extra);
5801 goto exit;
5802 }
5803 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED,
5804 "%s", &priv_data.buf[numOfBytestoPrint]);
5805 }
5806
5807 /* Free temporary buffer */
5808 kfree(extra);
5809 }
5810
5811 else
5812 {
5813 /* Command failed, log error */
5814 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5815 "%s: GETIBSSPEERINFOALL command failed with status code %d",
5816 __func__, status);
5817 ret = -EINVAL;
5818 goto exit;
5819 }
5820 ret = 0;
5821 }
5822 else if(strncasecmp(command, "GETIBSSPEERINFO", 15) == 0)
5823 {
5824 /* Peer Info <Peer Addr> command */
5825 tANI_U8 *value = command;
5826 VOS_STATUS status;
5827 hdd_station_ctx_t *pHddStaCtx = NULL;
5828 char extra[128] = { 0 };
5829 v_U32_t length = 0;
5830 v_U8_t staIdx = 0;
5831 v_U32_t txRateMbps = 0;
5832 v_MACADDR_t peerMacAddr;
5833
5834 if (WLAN_HDD_IBSS == pAdapter->device_mode)
5835 {
5836 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5837 }
5838 else
5839 {
5840 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5841 "%s: pAdapter is not valid for this device mode",
5842 __func__);
5843 ret = -EINVAL;
5844 goto exit;
5845 }
5846
5847 /* if there are no peers, no need to continue with the command */
5848 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5849 "%s: Received GETIBSSPEERINFO Command", __func__);
5850
5851 if (eConnectionState_IbssConnected != pHddStaCtx->conn_info.connState)
5852 {
5853 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5854 "%s:No IBSS Peers coalesced", __func__);
5855 ret = -EINVAL;
5856 goto exit;
5857 }
5858
5859 /* Parse the incoming command buffer */
5860 status = hdd_parse_get_ibss_peer_info(value, &peerMacAddr);
5861 if (VOS_STATUS_SUCCESS != status)
5862 {
5863 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5864 "%s: Invalid GETIBSSPEERINFO command", __func__);
5865 ret = -EINVAL;
5866 goto exit;
5867 }
5868
5869 /* Get station index for the peer mac address */
5870 hdd_Ibss_GetStaId(pHddStaCtx, &peerMacAddr, &staIdx);
5871
5872 if (staIdx > HDD_MAX_NUM_IBSS_STA)
5873 {
5874 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5875 "%s: Invalid StaIdx %d returned", __func__, staIdx);
5876 ret = -EINVAL;
5877 goto exit;
5878 }
5879
5880 /* Handle the command */
5881 status = hdd_cfg80211_get_ibss_peer_info(pAdapter, staIdx);
5882 if (VOS_STATUS_SUCCESS == status)
5883 {
5884 v_U32_t txRate = pHddStaCtx->ibss_peer_info.ibssPeerList[0].txRate;
5885 txRateMbps = (txRate * 500 * 1000)/1000000;
5886
5887 length = scnprintf( extra, sizeof(extra), "%d %d", (int)txRateMbps,
5888 (int)pHddStaCtx->ibss_peer_info.ibssPeerList[0].rssi);
5889
5890 /* Copy the data back into buffer */
5891 if (copy_to_user(priv_data.buf, &extra, length+ 1))
5892 {
5893 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5894 "%s: copy data to user buffer failed GETIBSSPEERINFO command",
5895 __func__);
5896 ret = -EFAULT;
5897 goto exit;
5898 }
5899 }
5900 else
5901 {
5902 /* Command failed, log error */
5903 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5904 "%s: GETIBSSPEERINFO command failed with status code %d",
5905 __func__, status);
5906 ret = -EINVAL;
5907 goto exit;
5908 }
5909
5910 /* Success ! */
5911 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED,
5912 "%s", priv_data.buf);
5913 ret = 0;
5914 }
5915 else if (strncasecmp(command, "SETRMCTXRATE", 12) == 0)
5916 {
5917 tANI_U8 *value = command;
5918 tANI_U32 uRate = 0;
5919 tTxrateinfoflags txFlags = 0;
5920 tSirRateUpdateInd *rateUpdateParams;
5921 int status;
5922
5923 if ((WLAN_HDD_IBSS != pAdapter->device_mode) &&
5924 (WLAN_HDD_SOFTAP != pAdapter->device_mode))
5925 {
5926 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5927 "Received SETRMCTXRATE command in invalid mode %d "
5928 "SETRMC command is only allowed in IBSS or SOFTAP mode",
5929 pAdapter->device_mode);
5930 ret = -EINVAL;
5931 goto exit;
5932 }
5933
5934 status = hdd_parse_setrmcrate_command(value, &uRate, &txFlags);
5935 if (status)
5936 {
5937 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5938 "Invalid SETRMCTXRATE command ");
5939 ret = -EINVAL;
5940 goto exit;
5941 }
5942
5943 rateUpdateParams = vos_mem_malloc(sizeof(tSirRateUpdateInd));
5944 if (NULL == rateUpdateParams)
5945 {
5946 ret = -EINVAL;
5947 goto exit;
5948 }
5949
5950 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5951 "%s: uRate %d ", __func__, uRate);
5952
5953 vos_mem_zero(rateUpdateParams, sizeof(tSirRateUpdateInd ));
5954
5955 /* -1 implies ignore this param */
5956 rateUpdateParams->ucastDataRate = -1;
5957
5958 /*
5959 * Fill the user specifieed RMC rate param
5960 * and the derived tx flags.
5961 */
5962 rateUpdateParams->rmcDataRate = uRate;
5963 rateUpdateParams->rmcDataRateTxFlag = txFlags;
5964
5965 status = sme_SendRateUpdateInd((tHalHandle)(pHddCtx->hHal), rateUpdateParams);
5966 }
5967 else if (strncasecmp(command, "SETIBSSTXFAILEVENT", 18) == 0 )
5968 {
5969 char *value;
5970 tANI_U8 tx_fail_count = 0;
5971 tANI_U16 pid = 0;
5972
5973 value = command;
5974
5975 ret = hdd_ParseIBSSTXFailEventParams(value, &tx_fail_count, &pid);
5976
5977 if (0 != ret)
5978 {
5979 hddLog(VOS_TRACE_LEVEL_INFO,
5980 "%s: Failed to parse SETIBSSTXFAILEVENT arguments",
5981 __func__);
5982 goto exit;
5983 }
5984
5985 hddLog(VOS_TRACE_LEVEL_INFO, "%s: tx_fail_cnt=%hhu, pid=%hu",
5986 __func__, tx_fail_count, pid);
5987
5988 if (0 == tx_fail_count)
5989 {
5990 // Disable TX Fail Indication
5991 if (eHAL_STATUS_SUCCESS ==
5992 sme_TXFailMonitorStartStopInd(pHddCtx->hHal,
5993 tx_fail_count,
5994 NULL))
5995 {
5996 cesium_pid = 0;
5997 }
5998 else
5999 {
6000 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6001 "%s: failed to disable TX Fail Event ", __func__);
6002 ret = -EINVAL;
6003 }
6004 }
6005 else
6006 {
6007 if (eHAL_STATUS_SUCCESS ==
6008 sme_TXFailMonitorStartStopInd(pHddCtx->hHal,
6009 tx_fail_count,
6010 (void*)hdd_tx_fail_ind_callback))
6011 {
6012 cesium_pid = pid;
6013 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6014 "%s: Registered Cesium pid %u", __func__,
6015 cesium_pid);
6016 }
6017 else
6018 {
6019 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6020 "%s: Failed to enable TX Fail Monitoring", __func__);
6021 ret = -EINVAL;
6022 }
6023 }
6024 }
6025
6026#endif /* WLAN_FEATURE_RMC */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006027#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006028 else if (strncmp(command, "SETCCXROAMSCANCHANNELS", 22) == 0)
6029 {
6030 tANI_U8 *value = command;
6031 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
6032 tANI_U8 numChannels = 0;
6033 eHalStatus status = eHAL_STATUS_SUCCESS;
6034
6035 status = hdd_parse_channellist(value, ChannelList, &numChannels);
6036 if (eHAL_STATUS_SUCCESS != status)
6037 {
6038 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6039 "%s: Failed to parse channel list information", __func__);
6040 ret = -EINVAL;
6041 goto exit;
6042 }
6043
6044 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
6045 {
6046 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6047 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
6048 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
6049 ret = -EINVAL;
6050 goto exit;
6051 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006052 status = sme_SetEseRoamScanChannelList((tHalHandle)(pHddCtx->hHal),
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006053 ChannelList,
6054 numChannels);
6055 if (eHAL_STATUS_SUCCESS != status)
6056 {
6057 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6058 "%s: Failed to update channel list information", __func__);
6059 ret = -EINVAL;
6060 goto exit;
6061 }
6062 }
6063 else if (strncmp(command, "GETTSMSTATS", 11) == 0)
6064 {
6065 tANI_U8 *value = command;
6066 char extra[128] = {0};
6067 int len = 0;
6068 tANI_U8 tid = 0;
6069 hdd_station_ctx_t *pHddStaCtx = NULL;
6070 tAniTrafStrmMetrics tsmMetrics;
6071 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6072
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05306073 ret = hdd_drv_cmd_validate(command, 11);
6074 if (ret)
6075 goto exit;
6076
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006077 /* if not associated, return error */
6078 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
6079 {
6080 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:Not associated!",__func__);
6081 ret = -EINVAL;
6082 goto exit;
6083 }
6084
6085 /* Move pointer to ahead of GETTSMSTATS<delimiter> */
6086 value = value + 12;
6087 /* Convert the value from ascii to integer */
6088 ret = kstrtou8(value, 10, &tid);
6089 if (ret < 0)
6090 {
6091 /* If the input value is greater than max value of datatype, then also
6092 kstrtou8 fails */
6093 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6094 "%s: kstrtou8 failed range [%d - %d]", __func__,
6095 TID_MIN_VALUE,
6096 TID_MAX_VALUE);
6097 ret = -EINVAL;
6098 goto exit;
6099 }
6100
6101 if ((tid < TID_MIN_VALUE) || (tid > TID_MAX_VALUE))
6102 {
6103 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6104 "tid value %d is out of range"
6105 " (Min: %d Max: %d)", tid,
6106 TID_MIN_VALUE,
6107 TID_MAX_VALUE);
6108 ret = -EINVAL;
6109 goto exit;
6110 }
6111
6112 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6113 "%s: Received Command to get tsm stats tid = %d", __func__, tid);
6114
6115 if (VOS_STATUS_SUCCESS != hdd_get_tsm_stats(pAdapter, tid, &tsmMetrics))
6116 {
6117 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6118 "%s: failed to get tsm stats", __func__);
6119 ret = -EFAULT;
6120 goto exit;
6121 }
6122
6123 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6124 "UplinkPktQueueDly(%d)\n"
6125 "UplinkPktQueueDlyHist[0](%d)\n"
6126 "UplinkPktQueueDlyHist[1](%d)\n"
6127 "UplinkPktQueueDlyHist[2](%d)\n"
6128 "UplinkPktQueueDlyHist[3](%d)\n"
Arun Kumar Khandavallie8768212014-02-17 16:43:34 +05306129 "UplinkPktTxDly(%u)\n"
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006130 "UplinkPktLoss(%d)\n"
6131 "UplinkPktCount(%d)\n"
6132 "RoamingCount(%d)\n"
6133 "RoamingDly(%d)", tsmMetrics.UplinkPktQueueDly,
6134 tsmMetrics.UplinkPktQueueDlyHist[0],
6135 tsmMetrics.UplinkPktQueueDlyHist[1],
6136 tsmMetrics.UplinkPktQueueDlyHist[2],
6137 tsmMetrics.UplinkPktQueueDlyHist[3],
6138 tsmMetrics.UplinkPktTxDly, tsmMetrics.UplinkPktLoss,
6139 tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount, tsmMetrics.RoamingDly);
6140
6141 /* Output TSM stats is of the format
6142 GETTSMSTATS [PktQueueDly] [PktQueueDlyHist[0]]:[PktQueueDlyHist[1]] ...[RoamingDly]
6143 eg., GETTSMSTATS 10 1:0:0:161 20 1 17 8 39800 */
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006144 len = scnprintf(extra, sizeof(extra), "%s %d %d:%d:%d:%d %u %d %d %d %d", command,
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006145 tsmMetrics.UplinkPktQueueDly, tsmMetrics.UplinkPktQueueDlyHist[0],
6146 tsmMetrics.UplinkPktQueueDlyHist[1], tsmMetrics.UplinkPktQueueDlyHist[2],
6147 tsmMetrics.UplinkPktQueueDlyHist[3], tsmMetrics.UplinkPktTxDly,
6148 tsmMetrics.UplinkPktLoss, tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount,
6149 tsmMetrics.RoamingDly);
6150
Ratnam Rachurid53009c2015-08-07 13:59:00 +05306151 len = VOS_MIN(priv_data.total_len, len + 1);
6152 if (copy_to_user(priv_data.buf, &extra, len)) {
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006153 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6154 "%s: failed to copy data to user buffer", __func__);
6155 ret = -EFAULT;
6156 goto exit;
6157 }
6158 }
6159 else if (strncmp(command, "SETCCKMIE", 9) == 0)
6160 {
6161 tANI_U8 *value = command;
6162 tANI_U8 *cckmIe = NULL;
6163 tANI_U8 cckmIeLen = 0;
6164 eHalStatus status = eHAL_STATUS_SUCCESS;
6165
6166 status = hdd_parse_get_cckm_ie(value, &cckmIe, &cckmIeLen);
6167 if (eHAL_STATUS_SUCCESS != status)
6168 {
6169 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6170 "%s: Failed to parse cckm ie data", __func__);
6171 ret = -EINVAL;
6172 goto exit;
6173 }
6174
6175 if (cckmIeLen > DOT11F_IE_RSN_MAX_LEN)
6176 {
6177 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6178 "%s: CCKM Ie input length is more than max[%d]", __func__,
6179 DOT11F_IE_RSN_MAX_LEN);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08006180 vos_mem_free(cckmIe);
6181 cckmIe = NULL;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006182 ret = -EINVAL;
6183 goto exit;
6184 }
6185 sme_SetCCKMIe((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, cckmIe, cckmIeLen);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08006186 vos_mem_free(cckmIe);
6187 cckmIe = NULL;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006188 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006189 else if (strncmp(command, "CCXBEACONREQ", 12) == 0)
6190 {
6191 tANI_U8 *value = command;
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006192 tCsrEseBeaconReq eseBcnReq;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006193 eHalStatus status = eHAL_STATUS_SUCCESS;
Srinivas Girigowda0c6d7fe2014-05-28 18:18:10 -07006194
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006195 status = hdd_parse_ese_beacon_req(value, &eseBcnReq);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006196 if (eHAL_STATUS_SUCCESS != status)
6197 {
6198 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006199 "%s: Failed to parse ese beacon req", __func__);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006200 ret = -EINVAL;
6201 goto exit;
6202 }
Srinivas Girigowda0c6d7fe2014-05-28 18:18:10 -07006203 if (!hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))) {
6204 hddLog(VOS_TRACE_LEVEL_INFO, FL("Not associated"));
6205 hdd_indicateEseBcnReportNoResults (pAdapter,
6206 eseBcnReq.bcnReq[0].measurementToken,
6207 0x02, //BIT(1) set for measurement done
6208 0); // no BSS
6209 goto exit;
6210 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006211
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006212 status = sme_SetEseBeaconRequest((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, &eseBcnReq);
6213 if (eHAL_STATUS_SUCCESS != status)
6214 {
6215 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6216 "%s: sme_SetEseBeaconRequest failed (%d)", __func__, status);
6217 ret = -EINVAL;
6218 goto exit;
6219 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006220 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006221#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
c_hpothu92367912014-05-01 15:18:17 +05306222 else if (strncmp(command, "GETBCNMISSRATE", 14) == 0)
6223 {
6224 eHalStatus status;
6225 char buf[32], len;
6226 long waitRet;
6227 bcnMissRateContext_t getBcnMissRateCtx;
6228
6229 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6230
6231 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
6232 {
6233 hddLog(VOS_TRACE_LEVEL_WARN,
6234 FL("GETBCNMISSRATE: STA is not in connected state"));
6235 ret = -1;
6236 goto exit;
6237 }
6238
6239 init_completion(&(getBcnMissRateCtx.completion));
6240 getBcnMissRateCtx.magic = BCN_MISS_RATE_CONTEXT_MAGIC;
6241
6242 status = sme_getBcnMissRate((tHalHandle)(pHddCtx->hHal),
6243 pAdapter->sessionId,
6244 (void *)getBcnMissRateCB,
6245 (void *)(&getBcnMissRateCtx));
6246 if( eHAL_STATUS_SUCCESS != status)
6247 {
6248 hddLog(VOS_TRACE_LEVEL_INFO,
6249 FL("GETBCNMISSRATE: fail to post WDA cmd"));
6250 ret = -EINVAL;
6251 goto exit;
6252 }
6253
6254 waitRet = wait_for_completion_interruptible_timeout
6255 (&getBcnMissRateCtx.completion, BCN_MISS_RATE_TIME);
6256 if(waitRet <= 0)
6257 {
6258 hddLog(VOS_TRACE_LEVEL_ERROR,
6259 FL("failed to wait on bcnMissRateComp %d"), ret);
6260
6261 //Make magic number to zero so that callback is not called.
6262 spin_lock(&hdd_context_lock);
6263 getBcnMissRateCtx.magic = 0x0;
6264 spin_unlock(&hdd_context_lock);
6265 ret = -EINVAL;
6266 goto exit;
6267 }
6268
6269 hddLog(VOS_TRACE_LEVEL_INFO,
6270 FL("GETBCNMISSRATE: bcnMissRate: %d"), gbcnMissRate);
6271
6272 len = snprintf(buf, sizeof(buf), "GETBCNMISSRATE %d", gbcnMissRate);
6273 if (copy_to_user(priv_data.buf, &buf, len + 1))
6274 {
6275 hddLog(VOS_TRACE_LEVEL_ERROR,
6276 "%s: failed to copy data to user buffer", __func__);
6277 ret = -EFAULT;
6278 goto exit;
6279 }
6280 ret = len;
6281 }
Atul Mittal87ec2422014-09-24 13:12:50 +05306282#ifdef FEATURE_WLAN_TDLS
6283 else if (strncmp(command, "TDLSSECONDARYCHANNELOFFSET", 26) == 0) {
6284 tANI_U8 *value = command;
6285 int set_value;
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05306286
6287 ret = hdd_drv_cmd_validate(command, 26);
6288 if (ret)
6289 goto exit;
6290
Atul Mittal87ec2422014-09-24 13:12:50 +05306291 /* Move pointer to ahead of TDLSOFFCH*/
6292 value += 26;
c_manjeebbc40212015-12-08 13:52:59 +05306293 if (!(sscanf(value, "%d", &set_value))) {
6294 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6295 FL("No input identified"));
6296 ret = -EINVAL;
6297 goto exit;
6298 }
6299
Atul Mittal87ec2422014-09-24 13:12:50 +05306300 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6301 "%s: Tdls offchannel offset:%d",
6302 __func__, set_value);
6303 ret = iw_set_tdlssecoffchanneloffset(pHddCtx, set_value);
6304 if (ret < 0)
6305 {
6306 ret = -EINVAL;
6307 goto exit;
6308 }
6309
6310 } else if (strncmp(command, "TDLSOFFCHANNELMODE", 18) == 0) {
6311 tANI_U8 *value = command;
6312 int set_value;
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05306313
6314 ret = hdd_drv_cmd_validate(command, 18);
6315 if (ret)
6316 goto exit;
6317
Atul Mittal87ec2422014-09-24 13:12:50 +05306318 /* Move pointer to ahead of tdlsoffchnmode*/
6319 value += 18;
c_manjee82323892015-12-08 12:40:34 +05306320 ret = sscanf(value, "%d", &set_value);
6321 if (ret != 1) {
6322 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6323 FL("No input identified"));
6324 ret = -EINVAL;
6325 goto exit;
6326 }
Atul Mittal87ec2422014-09-24 13:12:50 +05306327 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6328 "%s: Tdls offchannel mode:%d",
6329 __func__, set_value);
6330 ret = iw_set_tdlsoffchannelmode(pAdapter, set_value);
6331 if (ret < 0)
6332 {
6333 ret = -EINVAL;
6334 goto exit;
6335 }
6336 } else if (strncmp(command, "TDLSOFFCHANNEL", 14) == 0) {
6337 tANI_U8 *value = command;
6338 int set_value;
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05306339
6340 ret = hdd_drv_cmd_validate(command, 14);
6341 if (ret)
6342 goto exit;
6343
Atul Mittal87ec2422014-09-24 13:12:50 +05306344 /* Move pointer to ahead of TDLSOFFCH*/
6345 value += 14;
c_manjeef6ccaf52015-12-08 11:52:11 +05306346 ret = sscanf(value, "%d", &set_value);
6347 if (ret != 1) {
6348 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6349 "Wrong value is given for hdd_set_tdls_offchannel");
6350 ret = -EINVAL;
6351 goto exit;
6352 }
6353
Atul Mittal87ec2422014-09-24 13:12:50 +05306354 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6355 "%s: Tdls offchannel num: %d",
6356 __func__, set_value);
6357 ret = iw_set_tdlsoffchannel(pHddCtx, set_value);
6358 if (ret < 0)
6359 {
6360 ret = -EINVAL;
6361 goto exit;
6362 }
6363 }
6364#endif
Satyanarayana Dash72806012014-12-02 14:30:08 +05306365 else if (strncmp(command, "GETFWSTATS", 10) == 0)
6366 {
6367 eHalStatus status;
6368 char *buf = NULL;
6369 char len;
6370 long waitRet;
6371 fwStatsContext_t fwStatsCtx;
Abhishek Singh08aa7762014-12-16 13:59:03 +05306372 tSirFwStatsResult *fwStatsRsp = &(pAdapter->fwStatsRsp);
Satyanarayana Dash72806012014-12-02 14:30:08 +05306373 tANI_U8 *ptr = command;
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05306374 int stats;
Satyanarayana Dash72806012014-12-02 14:30:08 +05306375
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05306376 ret = hdd_drv_cmd_validate(command, 10);
6377 if (ret)
6378 goto exit;
6379
6380 stats = *(ptr + 11) - '0';
Satyanarayana Dash72806012014-12-02 14:30:08 +05306381 hddLog(VOS_TRACE_LEVEL_INFO, FL("stats = %d "),stats);
6382 if (!IS_FEATURE_FW_STATS_ENABLE)
6383 {
6384 hddLog(VOS_TRACE_LEVEL_INFO,
6385 FL("Get Firmware stats feature not supported"));
6386 ret = -EINVAL;
6387 goto exit;
6388 }
6389
6390 if (FW_STATS_MAX <= stats || 0 >= stats)
6391 {
6392 hddLog(VOS_TRACE_LEVEL_INFO,
6393 FL(" stats %d not supported"),stats);
6394 ret = -EINVAL;
6395 goto exit;
6396 }
6397
6398 init_completion(&(fwStatsCtx.completion));
6399 fwStatsCtx.magic = FW_STATS_CONTEXT_MAGIC;
6400 fwStatsCtx.pAdapter = pAdapter;
6401 fwStatsRsp->type = 0;
6402 status = sme_GetFwStats( (tHalHandle)pHddCtx->hHal, stats,
Abhishek Singh08aa7762014-12-16 13:59:03 +05306403 &fwStatsCtx, hdd_FWStatisCB);
Satyanarayana Dash72806012014-12-02 14:30:08 +05306404 if (eHAL_STATUS_SUCCESS != status)
6405 {
6406 hddLog(VOS_TRACE_LEVEL_ERROR,
6407 FL(" fail to post WDA cmd status = %d"), status);
6408 ret = -EINVAL;
6409 goto exit;
6410 }
6411 waitRet = wait_for_completion_timeout
6412 (&(fwStatsCtx.completion), FW_STATE_WAIT_TIME);
6413 if (waitRet <= 0)
6414 {
6415 hddLog(VOS_TRACE_LEVEL_ERROR,
6416 FL("failed to wait on GwtFwstats"));
6417 //Make magic number to zero so that callback is not executed.
6418 spin_lock(&hdd_context_lock);
6419 fwStatsCtx.magic = 0x0;
6420 spin_unlock(&hdd_context_lock);
6421 ret = -EINVAL;
6422 goto exit;
6423 }
6424 if (fwStatsRsp->type)
6425 {
6426 buf = kmalloc(FW_STATE_RSP_LEN, GFP_KERNEL);
6427 if (!buf)
6428 {
6429 hddLog(VOS_TRACE_LEVEL_ERROR,
6430 FL(" failed to allocate memory"));
6431 ret = -ENOMEM;
6432 goto exit;
6433 }
6434 switch( fwStatsRsp->type )
6435 {
6436 case FW_UBSP_STATS:
6437 {
6438 len = snprintf(buf, FW_STATE_RSP_LEN,
6439 "GETFWSTATS: ubsp_enter_cnt %d ubsp_jump_ddr_cnt %d",
Abhishek Singh08aa7762014-12-16 13:59:03 +05306440 fwStatsRsp->fwStatsData.ubspStats.ubsp_enter_cnt,
6441 fwStatsRsp->fwStatsData.ubspStats.ubsp_jump_ddr_cnt);
Satyanarayana Dash72806012014-12-02 14:30:08 +05306442 }
6443 break;
6444 default:
6445 {
6446 hddLog(VOS_TRACE_LEVEL_ERROR, FL( "No handling for stats type %d"),fwStatsRsp->type);
6447 ret = -EFAULT;
6448 kfree(buf);
6449 goto exit;
6450 }
6451 }
6452 if (copy_to_user(priv_data.buf, buf, len + 1))
6453 {
6454 hddLog(VOS_TRACE_LEVEL_ERROR,
6455 FL(" failed to copy data to user buffer"));
6456 ret = -EFAULT;
6457 kfree(buf);
6458 goto exit;
6459 }
6460 ret = len;
6461 kfree(buf);
6462 }
6463 else
6464 {
6465 hddLog(VOS_TRACE_LEVEL_ERROR,
6466 FL("failed to fetch the stats"));
6467 ret = -EFAULT;
6468 goto exit;
6469 }
6470
6471 }
Agarwal Ashish8bd53ae2015-06-12 18:03:45 +05306472 else if (strncasecmp(command, "SET_FCC_CHANNEL", 15) == 0)
6473 {
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05306474 ret = hdd_drv_cmd_validate(command, 15);
6475 if (ret)
6476 goto exit;
6477
Agarwal Ashish8bd53ae2015-06-12 18:03:45 +05306478 /*
6479 * this command wld be called by user-space when it detects WLAN
6480 * ON after airplane mode is set. When APM is set, WLAN turns off.
6481 * But it can be turned back on. Otherwise; when APM is turned back
6482 * off, WLAN wld turn back on. So at that point the command is
6483 * expected to come down. 0 means disable, 1 means enable. The
6484 * constraint is removed when parameter 1 is set or different
6485 * country code is set
6486 */
6487 ret = hdd_cmd_setFccChannel(pHddCtx, command, 15);
6488 }
Mahesh A Saptasagarbeca12c2015-09-07 16:21:06 +05306489 else if (strncasecmp(command, "DISABLE_CA_EVENT", 16) == 0)
6490 {
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05306491 ret = hdd_drv_cmd_validate(command, 16);
6492 if (ret)
6493 goto exit;
6494
Mahesh A Saptasagarbeca12c2015-09-07 16:21:06 +05306495 ret = hdd_enable_disable_ca_event(pHddCtx, command, 16);
6496 }
Ashish Kumar Dhanotiya32d092b2018-02-20 21:43:57 +05306497 /*
6498 * command should be a string having format
6499 * SET_DISABLE_CHANNEL_LIST <num of channels>
6500 * <channels separated by spaces>
6501 */
6502 else if (strncmp(command, "SET_DISABLE_CHANNEL_LIST", 24) == 0) {
6503 tANI_U8 *ptr = command;
6504 ret = hdd_drv_cmd_validate(command, 24);
6505 if (ret)
6506 goto exit;
6507
6508 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6509 " Received Command to disable Channels %s",
6510 __func__);
6511 ret = hdd_parse_disable_chan_cmd(pAdapter, ptr);
6512 if (ret)
6513 goto exit;
6514 }
6515
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07006516 else {
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05306517 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
6518 TRACE_CODE_HDD_UNSUPPORTED_IOCTL,
6519 pAdapter->sessionId, 0));
Satyanarayana Dash72806012014-12-02 14:30:08 +05306520 hddLog( VOS_TRACE_LEVEL_WARN, FL("Unsupported GUI command %s"),
6521 command);
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07006522 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006523 }
6524exit:
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05306525 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07006526 if (command)
6527 {
6528 kfree(command);
6529 }
6530 return ret;
6531}
6532
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07006533#ifdef CONFIG_COMPAT
6534static int hdd_driver_compat_ioctl(hdd_adapter_t *pAdapter, struct ifreq *ifr)
6535{
6536 struct {
6537 compat_uptr_t buf;
6538 int used_len;
6539 int total_len;
6540 } compat_priv_data;
6541 hdd_priv_data_t priv_data;
6542 int ret = 0;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006543
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07006544 /*
6545 * Note that pAdapter and ifr have already been verified by caller,
6546 * and HDD context has also been validated
6547 */
6548 if (copy_from_user(&compat_priv_data, ifr->ifr_data,
6549 sizeof(compat_priv_data))) {
6550 ret = -EFAULT;
6551 goto exit;
6552 }
6553 priv_data.buf = compat_ptr(compat_priv_data.buf);
6554 priv_data.used_len = compat_priv_data.used_len;
6555 priv_data.total_len = compat_priv_data.total_len;
6556 ret = hdd_driver_command(pAdapter, &priv_data);
6557 exit:
6558 return ret;
6559}
6560#else /* CONFIG_COMPAT */
6561static int hdd_driver_compat_ioctl(hdd_adapter_t *pAdapter, struct ifreq *ifr)
6562{
6563 /* will never be invoked */
6564 return 0;
6565}
6566#endif /* CONFIG_COMPAT */
6567
6568static int hdd_driver_ioctl(hdd_adapter_t *pAdapter, struct ifreq *ifr)
6569{
6570 hdd_priv_data_t priv_data;
6571 int ret = 0;
6572
6573 /*
6574 * Note that pAdapter and ifr have already been verified by caller,
6575 * and HDD context has also been validated
6576 */
6577 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(priv_data))) {
6578 ret = -EFAULT;
6579 } else {
6580 ret = hdd_driver_command(pAdapter, &priv_data);
6581 }
6582 return ret;
6583}
6584
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05306585int __hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07006586{
6587 hdd_adapter_t *pAdapter;
6588 hdd_context_t *pHddCtx;
6589 int ret;
6590
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05306591 ENTER();
6592
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07006593 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6594 if (NULL == pAdapter) {
6595 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6596 "%s: HDD adapter context is Null", __func__);
6597 ret = -ENODEV;
6598 goto exit;
6599 }
6600 if (dev != pAdapter->dev) {
6601 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6602 "%s: HDD adapter/dev inconsistency", __func__);
6603 ret = -ENODEV;
6604 goto exit;
6605 }
6606
6607 if ((!ifr) || (!ifr->ifr_data)) {
6608 ret = -EINVAL;
6609 goto exit;
6610 }
6611
6612 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6613 ret = wlan_hdd_validate_context(pHddCtx);
6614 if (ret) {
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07006615 ret = -EBUSY;
6616 goto exit;
6617 }
6618
6619 switch (cmd) {
6620 case (SIOCDEVPRIVATE + 1):
6621 if (is_compat_task())
6622 ret = hdd_driver_compat_ioctl(pAdapter, ifr);
6623 else
6624 ret = hdd_driver_ioctl(pAdapter, ifr);
6625 break;
6626 default:
6627 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unknown ioctl %d",
6628 __func__, cmd);
6629 ret = -EINVAL;
6630 break;
6631 }
6632 exit:
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05306633 EXIT();
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07006634 return ret;
6635}
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006636
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05306637int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
6638{
6639 int ret;
6640
6641 vos_ssr_protect(__func__);
6642 ret = __hdd_ioctl(dev, ifr, cmd);
6643 vos_ssr_unprotect(__func__);
6644
6645 return ret;
6646}
6647
Katya Nigame7b69a82015-04-28 15:24:06 +05306648int hdd_mon_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
6649{
6650 return 0;
6651}
6652
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006653#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006654/**---------------------------------------------------------------------------
6655
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006656 \brief hdd_parse_ese_beacon_req() - Parse ese beacon request
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006657
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006658 This function parses the ese beacon request passed in the format
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006659 CCXBEACONREQ<space><Number of fields><space><Measurement token>
6660 <space>Channel 1<space>Scan Mode <space>Meas Duration<space>Channel N
6661 <space>Scan Mode N<space>Meas Duration N
6662 if the Number of bcn req fields (N) does not match with the actual number of fields passed
6663 then take N.
6664 <Meas Token><Channel><Scan Mode> and <Meas Duration> are treated as one pair
6665 For example, CCXBEACONREQ 2 1 1 1 30 2 44 0 40.
6666 This function does not take care of removing duplicate channels from the list
6667
6668 \param - pValue Pointer to data
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006669 \param - pEseBcnReq output pointer to store parsed ie information
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006670
6671 \return - 0 for success non-zero for failure
6672
6673 --------------------------------------------------------------------------*/
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006674static VOS_STATUS hdd_parse_ese_beacon_req(tANI_U8 *pValue,
6675 tCsrEseBeaconReq *pEseBcnReq)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006676{
6677 tANI_U8 *inPtr = pValue;
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306678 uint8_t input = 0;
6679 uint32_t tempInt = 0;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006680 int j = 0, i = 0, v = 0;
6681 char buf[32];
6682
6683 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
6684 /*no argument after the command*/
6685 if (NULL == inPtr)
6686 {
6687 return -EINVAL;
6688 }
6689 /*no space after the command*/
6690 else if (SPACE_ASCII_VALUE != *inPtr)
6691 {
6692 return -EINVAL;
6693 }
6694
6695 /*removing empty spaces*/
6696 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
6697
6698 /*no argument followed by spaces*/
6699 if ('\0' == *inPtr) return -EINVAL;
6700
6701 /*getting the first argument ie measurement token*/
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08006702 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006703 if (1 != v) return -EINVAL;
6704
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306705 v = kstrtos8(buf, 10, &input);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006706 if ( v < 0) return -EINVAL;
6707
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306708 input = VOS_MIN(input, SIR_ESE_MAX_MEAS_IE_REQS);
6709 pEseBcnReq->numBcnReqIe = input;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006710
Srinivas Girigowda725a88e2016-03-31 19:24:25 +05306711 hddLog(LOG1, "Number of Bcn Req Ie fields: %d", pEseBcnReq->numBcnReqIe);
6712
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006713
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006714 for (j = 0; j < (pEseBcnReq->numBcnReqIe); j++)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006715 {
6716 for (i = 0; i < 4; i++)
6717 {
6718 /*inPtr pointing to the beginning of first space after number of ie fields*/
6719 inPtr = strpbrk( inPtr, " " );
6720 /*no ie data after the number of ie fields argument*/
6721 if (NULL == inPtr) return -EINVAL;
6722
6723 /*removing empty space*/
6724 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
6725
6726 /*no ie data after the number of ie fields argument and spaces*/
6727 if ( '\0' == *inPtr ) return -EINVAL;
6728
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08006729 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006730 if (1 != v) return -EINVAL;
6731
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306732 v = kstrtou32(buf, 10, &tempInt);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006733 if (v < 0) return -EINVAL;
6734
6735 switch (i)
6736 {
6737 case 0: /* Measurement token */
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306738 if (!tempInt)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006739 {
6740 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306741 "Invalid Measurement Token: %u", tempInt);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006742 return -EINVAL;
6743 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006744 pEseBcnReq->bcnReq[j].measurementToken = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006745 break;
6746
6747 case 1: /* Channel number */
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306748 if ((!tempInt) ||
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006749 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
6750 {
6751 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306752 "Invalid Channel Number: %u", tempInt);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006753 return -EINVAL;
6754 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006755 pEseBcnReq->bcnReq[j].channel = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006756 break;
6757
6758 case 2: /* Scan mode */
Varun Reddy Yeturu0b18d5a2013-12-04 11:42:23 -08006759 if ((tempInt < eSIR_PASSIVE_SCAN) || (tempInt > eSIR_BEACON_TABLE))
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006760 {
6761 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306762 "Invalid Scan Mode(%u) Expected{0|1|2}", tempInt);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006763 return -EINVAL;
6764 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006765 pEseBcnReq->bcnReq[j].scanMode= tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006766 break;
6767
6768 case 3: /* Measurement duration */
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306769 if (((!tempInt) && (pEseBcnReq->bcnReq[j].scanMode != eSIR_BEACON_TABLE)) ||
6770 ((pEseBcnReq->bcnReq[j].scanMode == eSIR_BEACON_TABLE)))
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006771 {
6772 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306773 "Invalid Measurement Duration: %u", tempInt);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006774 return -EINVAL;
6775 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006776 pEseBcnReq->bcnReq[j].measurementDuration = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006777 break;
6778 }
6779 }
6780 }
6781
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006782 for (j = 0; j < pEseBcnReq->numBcnReqIe; j++)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006783 {
6784 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arun Kumar Khandavallie8768212014-02-17 16:43:34 +05306785 "Index(%d) Measurement Token(%u)Channel(%u) Scan Mode(%u) Measurement Duration(%u)\n",
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006786 j,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006787 pEseBcnReq->bcnReq[j].measurementToken,
6788 pEseBcnReq->bcnReq[j].channel,
6789 pEseBcnReq->bcnReq[j].scanMode,
6790 pEseBcnReq->bcnReq[j].measurementDuration);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006791 }
6792
6793 return VOS_STATUS_SUCCESS;
6794}
6795
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006796static void hdd_GetTsmStatsCB( tAniTrafStrmMetrics tsmMetrics, const tANI_U32 staId, void *pContext )
6797{
6798 struct statsContext *pStatsContext = NULL;
6799 hdd_adapter_t *pAdapter = NULL;
6800
6801 if (NULL == pContext)
6802 {
6803 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnsonc135a9a2017-09-19 08:37:24 -07006804 "%s: Bad param, pContext [%pK]",
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006805 __func__, pContext);
6806 return;
6807 }
6808
Jeff Johnson72a40512013-12-19 10:14:15 -08006809 /* there is a race condition that exists between this callback
6810 function and the caller since the caller could time out either
6811 before or while this code is executing. we use a spinlock to
6812 serialize these actions */
6813 spin_lock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006814
6815 pStatsContext = pContext;
6816 pAdapter = pStatsContext->pAdapter;
6817 if ((NULL == pAdapter) || (STATS_CONTEXT_MAGIC != pStatsContext->magic))
6818 {
6819 /* the caller presumably timed out so there is nothing we can do */
Jeff Johnson72a40512013-12-19 10:14:15 -08006820 spin_unlock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006821 hddLog(VOS_TRACE_LEVEL_WARN,
Jeff Johnsonc135a9a2017-09-19 08:37:24 -07006822 "%s: Invalid context, pAdapter [%pK] magic [%08x]",
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006823 __func__, pAdapter, pStatsContext->magic);
6824 return;
6825 }
6826
Jeff Johnson72a40512013-12-19 10:14:15 -08006827 /* context is valid so caller is still waiting */
6828
6829 /* paranoia: invalidate the magic */
6830 pStatsContext->magic = 0;
6831
6832 /* copy over the tsm stats */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006833 pAdapter->tsmStats.UplinkPktQueueDly = tsmMetrics.UplinkPktQueueDly;
6834 vos_mem_copy(pAdapter->tsmStats.UplinkPktQueueDlyHist,
6835 tsmMetrics.UplinkPktQueueDlyHist,
6836 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
6837 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
6838 pAdapter->tsmStats.UplinkPktTxDly = tsmMetrics.UplinkPktTxDly;
6839 pAdapter->tsmStats.UplinkPktLoss = tsmMetrics.UplinkPktLoss;
6840 pAdapter->tsmStats.UplinkPktCount = tsmMetrics.UplinkPktCount;
6841 pAdapter->tsmStats.RoamingCount = tsmMetrics.RoamingCount;
6842 pAdapter->tsmStats.RoamingDly = tsmMetrics.RoamingDly;
6843
Jeff Johnson72a40512013-12-19 10:14:15 -08006844 /* notify the caller */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006845 complete(&pStatsContext->completion);
Jeff Johnson72a40512013-12-19 10:14:15 -08006846
6847 /* serialization is complete */
6848 spin_unlock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006849}
6850
6851
6852
6853static VOS_STATUS hdd_get_tsm_stats(hdd_adapter_t *pAdapter, const tANI_U8 tid,
6854 tAniTrafStrmMetrics* pTsmMetrics)
6855{
6856 hdd_station_ctx_t *pHddStaCtx = NULL;
6857 eHalStatus hstatus;
Jeff Johnson72a40512013-12-19 10:14:15 -08006858 VOS_STATUS vstatus = VOS_STATUS_SUCCESS;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006859 long lrc;
6860 struct statsContext context;
6861 hdd_context_t *pHddCtx = NULL;
6862
6863 if (NULL == pAdapter)
6864 {
6865 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: pAdapter is NULL", __func__);
6866 return VOS_STATUS_E_FAULT;
6867 }
6868
6869 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6870 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6871
6872 /* we are connected prepare our callback context */
6873 init_completion(&context.completion);
6874 context.pAdapter = pAdapter;
6875 context.magic = STATS_CONTEXT_MAGIC;
6876
6877 /* query tsm stats */
6878 hstatus = sme_GetTsmStats(pHddCtx->hHal, hdd_GetTsmStatsCB,
6879 pHddStaCtx->conn_info.staId[ 0 ],
6880 pHddStaCtx->conn_info.bssId,
6881 &context, pHddCtx->pvosContext, tid);
6882
6883 if (eHAL_STATUS_SUCCESS != hstatus)
6884 {
Jeff Johnson72a40512013-12-19 10:14:15 -08006885 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unable to retrieve statistics",
6886 __func__);
6887 vstatus = VOS_STATUS_E_FAULT;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006888 }
6889 else
6890 {
6891 /* request was sent -- wait for the response */
6892 lrc = wait_for_completion_interruptible_timeout(&context.completion,
6893 msecs_to_jiffies(WLAN_WAIT_TIME_STATS));
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006894 if (lrc <= 0)
6895 {
6896 hddLog(VOS_TRACE_LEVEL_ERROR,
6897 "%s: SME %s while retrieving statistics",
6898 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson72a40512013-12-19 10:14:15 -08006899 vstatus = VOS_STATUS_E_TIMEOUT;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006900 }
6901 }
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006902
Jeff Johnson72a40512013-12-19 10:14:15 -08006903 /* either we never sent a request, we sent a request and received a
6904 response or we sent a request and timed out. if we never sent a
6905 request or if we sent a request and got a response, we want to
6906 clear the magic out of paranoia. if we timed out there is a
6907 race condition such that the callback function could be
6908 executing at the same time we are. of primary concern is if the
6909 callback function had already verified the "magic" but had not
6910 yet set the completion variable when a timeout occurred. we
6911 serialize these activities by invalidating the magic while
6912 holding a shared spinlock which will cause us to block if the
6913 callback is currently executing */
6914 spin_lock(&hdd_context_lock);
6915 context.magic = 0;
6916 spin_unlock(&hdd_context_lock);
6917
6918 if (VOS_STATUS_SUCCESS == vstatus)
6919 {
6920 pTsmMetrics->UplinkPktQueueDly = pAdapter->tsmStats.UplinkPktQueueDly;
6921 vos_mem_copy(pTsmMetrics->UplinkPktQueueDlyHist,
6922 pAdapter->tsmStats.UplinkPktQueueDlyHist,
6923 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
6924 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
6925 pTsmMetrics->UplinkPktTxDly = pAdapter->tsmStats.UplinkPktTxDly;
6926 pTsmMetrics->UplinkPktLoss = pAdapter->tsmStats.UplinkPktLoss;
6927 pTsmMetrics->UplinkPktCount = pAdapter->tsmStats.UplinkPktCount;
6928 pTsmMetrics->RoamingCount = pAdapter->tsmStats.RoamingCount;
6929 pTsmMetrics->RoamingDly = pAdapter->tsmStats.RoamingDly;
6930 }
6931 return vstatus;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006932}
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006933#endif /*FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006934
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006935#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -08006936void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
6937{
6938 eCsrBand band = -1;
6939 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
6940 switch (band)
6941 {
6942 case eCSR_BAND_ALL:
6943 *pBand = WLAN_HDD_UI_BAND_AUTO;
6944 break;
6945
6946 case eCSR_BAND_24:
6947 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
6948 break;
6949
6950 case eCSR_BAND_5G:
6951 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
6952 break;
6953
6954 default:
6955 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
6956 *pBand = -1;
6957 break;
6958 }
6959}
6960
6961/**---------------------------------------------------------------------------
6962
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006963 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
6964
6965 This function parses the send action frame data passed in the format
6966 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
6967
Srinivas Girigowda56076852013-08-20 14:00:50 -07006968 \param - pValue Pointer to input data
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006969 \param - pTargetApBssid Pointer to target Ap bssid
6970 \param - pChannel Pointer to the Target AP channel
6971 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
6972 \param - pBuf Pointer to data
6973 \param - pBufLen Pointer to data length
6974
6975 \return - 0 for success non-zero for failure
6976
6977 --------------------------------------------------------------------------*/
6978VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
6979 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
6980{
6981 tANI_U8 *inPtr = pValue;
6982 tANI_U8 *dataEnd;
6983 int tempInt;
6984 int j = 0;
6985 int i = 0;
6986 int v = 0;
6987 tANI_U8 tempBuf[32];
6988 tANI_U8 tempByte = 0;
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08006989 /* 12 hexa decimal digits, 5 ':' and '\0' */
6990 tANI_U8 macAddress[18];
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006991
6992 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
6993 /*no argument after the command*/
6994 if (NULL == inPtr)
6995 {
6996 return -EINVAL;
6997 }
6998
6999 /*no space after the command*/
7000 else if (SPACE_ASCII_VALUE != *inPtr)
7001 {
7002 return -EINVAL;
7003 }
7004
7005 /*removing empty spaces*/
7006 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
7007
7008 /*no argument followed by spaces*/
7009 if ('\0' == *inPtr)
7010 {
7011 return -EINVAL;
7012 }
7013
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07007014 v = sscanf(inPtr, "%17s", macAddress);
7015 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Srinivas Girigowda100eb322013-03-15 16:48:20 -07007016 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07007017 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7018 "Invalid MAC address or All hex inputs are not read (%d)", v);
7019 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07007020 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07007021
7022 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
7023 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
7024 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
7025 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
7026 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
7027 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07007028
7029 /* point to the next argument */
7030 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
7031 /*no argument after the command*/
7032 if (NULL == inPtr) return -EINVAL;
7033
7034 /*removing empty spaces*/
7035 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
7036
7037 /*no argument followed by spaces*/
7038 if ('\0' == *inPtr)
7039 {
7040 return -EINVAL;
7041 }
7042
7043 /*getting the next argument ie the channel number */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08007044 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07007045 if (1 != v) return -EINVAL;
7046
Srinivas Girigowda100eb322013-03-15 16:48:20 -07007047 v = kstrtos32(tempBuf, 10, &tempInt);
Agarwal Ashish353b3a82014-04-08 14:55:11 +05307048 if ( v < 0 || tempInt <= 0 || tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX )
Kiet Lambe150c22013-11-21 16:30:32 +05307049 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07007050
7051 *pChannel = tempInt;
7052
7053 /* point to the next argument */
7054 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
7055 /*no argument after the command*/
7056 if (NULL == inPtr) return -EINVAL;
7057 /*removing empty spaces*/
7058 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
7059
7060 /*no argument followed by spaces*/
7061 if ('\0' == *inPtr)
7062 {
7063 return -EINVAL;
7064 }
7065
7066 /*getting the next argument ie the dwell time */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08007067 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07007068 if (1 != v) return -EINVAL;
7069
Srinivas Girigowda100eb322013-03-15 16:48:20 -07007070 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda5a6e0672014-01-09 14:42:57 -08007071 if ( v < 0 || tempInt < 0) return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07007072
7073 *pDwellTime = tempInt;
7074
7075 /* point to the next argument */
7076 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
7077 /*no argument after the command*/
7078 if (NULL == inPtr) return -EINVAL;
7079 /*removing empty spaces*/
7080 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
7081
7082 /*no argument followed by spaces*/
7083 if ('\0' == *inPtr)
7084 {
7085 return -EINVAL;
7086 }
7087
7088 /* find the length of data */
7089 dataEnd = inPtr;
7090 while(('\0' != *dataEnd) )
7091 {
7092 dataEnd++;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07007093 }
Kiet Lambe150c22013-11-21 16:30:32 +05307094 *pBufLen = dataEnd - inPtr ;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07007095 if ( *pBufLen <= 0) return -EINVAL;
7096
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07007097 /* Allocate the number of bytes based on the number of input characters
7098 whether it is even or odd.
7099 if the number of input characters are even, then we need N/2 byte.
7100 if the number of input characters are odd, then we need do (N+1)/2 to
7101 compensate rounding off.
7102 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
7103 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
7104 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07007105 if (NULL == *pBuf)
7106 {
7107 hddLog(VOS_TRACE_LEVEL_FATAL,
7108 "%s: vos_mem_alloc failed ", __func__);
7109 return -EINVAL;
7110 }
7111
7112 /* the buffer received from the upper layer is character buffer,
7113 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
7114 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
7115 and f0 in 3rd location */
7116 for (i = 0, j = 0; j < *pBufLen; j += 2)
7117 {
Kiet Lambe150c22013-11-21 16:30:32 +05307118 if( j+1 == *pBufLen)
7119 {
7120 tempByte = hdd_parse_hex(inPtr[j]);
7121 }
7122 else
7123 {
7124 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
7125 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07007126 (*pBuf)[i++] = tempByte;
7127 }
7128 *pBufLen = i;
7129 return VOS_STATUS_SUCCESS;
7130}
7131
Srinivas Girigowda100eb322013-03-15 16:48:20 -07007132/**---------------------------------------------------------------------------
7133
Srinivas Girigowdade697412013-02-14 16:31:48 -08007134 \brief hdd_parse_channellist() - HDD Parse channel list
7135
7136 This function parses the channel list passed in the format
7137 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07007138 if the Number of channels (N) does not match with the actual number of channels passed
7139 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
7140 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
7141 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
7142 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08007143
7144 \param - pValue Pointer to input channel list
7145 \param - ChannelList Pointer to local output array to record channel list
7146 \param - pNumChannels Pointer to number of roam scan channels
7147
7148 \return - 0 for success non-zero for failure
7149
7150 --------------------------------------------------------------------------*/
7151VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
7152{
7153 tANI_U8 *inPtr = pValue;
7154 int tempInt;
7155 int j = 0;
7156 int v = 0;
7157 char buf[32];
7158
7159 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
7160 /*no argument after the command*/
7161 if (NULL == inPtr)
7162 {
7163 return -EINVAL;
7164 }
7165
7166 /*no space after the command*/
7167 else if (SPACE_ASCII_VALUE != *inPtr)
7168 {
7169 return -EINVAL;
7170 }
7171
7172 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07007173 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08007174
7175 /*no argument followed by spaces*/
7176 if ('\0' == *inPtr)
7177 {
7178 return -EINVAL;
7179 }
7180
7181 /*getting the first argument ie the number of channels*/
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08007182 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07007183 if (1 != v) return -EINVAL;
7184
Srinivas Girigowdade697412013-02-14 16:31:48 -08007185 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07007186 if ((v < 0) ||
7187 (tempInt <= 0) ||
7188 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
7189 {
7190 return -EINVAL;
7191 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08007192
7193 *pNumChannels = tempInt;
7194
7195 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
7196 "Number of channels are: %d", *pNumChannels);
7197
7198 for (j = 0; j < (*pNumChannels); j++)
7199 {
7200 /*inPtr pointing to the beginning of first space after number of channels*/
7201 inPtr = strpbrk( inPtr, " " );
7202 /*no channel list after the number of channels argument*/
7203 if (NULL == inPtr)
7204 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07007205 if (0 != j)
7206 {
7207 *pNumChannels = j;
7208 return VOS_STATUS_SUCCESS;
7209 }
7210 else
7211 {
7212 return -EINVAL;
7213 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08007214 }
7215
7216 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07007217 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08007218
7219 /*no channel list after the number of channels argument and spaces*/
7220 if ( '\0' == *inPtr )
7221 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07007222 if (0 != j)
7223 {
7224 *pNumChannels = j;
7225 return VOS_STATUS_SUCCESS;
7226 }
7227 else
7228 {
7229 return -EINVAL;
7230 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08007231 }
7232
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08007233 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07007234 if (1 != v) return -EINVAL;
7235
Srinivas Girigowdade697412013-02-14 16:31:48 -08007236 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07007237 if ((v < 0) ||
7238 (tempInt <= 0) ||
7239 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
7240 {
7241 return -EINVAL;
7242 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08007243 pChannelList[j] = tempInt;
7244
7245 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
7246 "Channel %d added to preferred channel list",
7247 pChannelList[j] );
7248 }
7249
Srinivas Girigowdade697412013-02-14 16:31:48 -08007250 return VOS_STATUS_SUCCESS;
7251}
7252
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07007253
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05307254/**
7255 * hdd_parse_reassoc_command_v1_data() - HDD Parse reassoc command data
7256 * This function parses the reasoc command data passed in the format
7257 * REASSOC<space><bssid><space><channel>
7258 *
7259 * @pValue: Pointer to input data (its a NUL terminated string)
7260 * @pTargetApBssid: Pointer to target Ap bssid
7261 * @pChannel: Pointer to the Target AP channel
7262 *
7263 * Return: 0 for success non-zero for failure
7264 */
7265static int hdd_parse_reassoc_command_v1_data(const tANI_U8 *pValue,
7266 tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07007267{
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05307268 const tANI_U8 *inPtr = pValue;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07007269 int tempInt;
7270 int v = 0;
7271 tANI_U8 tempBuf[32];
Kiet Lamaa8e15a2014-02-11 23:30:06 -08007272 /* 12 hexa decimal digits, 5 ':' and '\0' */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08007273 tANI_U8 macAddress[18];
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07007274
7275 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
7276 /*no argument after the command*/
7277 if (NULL == inPtr)
7278 {
7279 return -EINVAL;
7280 }
7281
7282 /*no space after the command*/
7283 else if (SPACE_ASCII_VALUE != *inPtr)
7284 {
7285 return -EINVAL;
7286 }
7287
7288 /*removing empty spaces*/
7289 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
7290
7291 /*no argument followed by spaces*/
7292 if ('\0' == *inPtr)
7293 {
7294 return -EINVAL;
7295 }
7296
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07007297 v = sscanf(inPtr, "%17s", macAddress);
7298 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07007299 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07007300 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7301 "Invalid MAC address or All hex inputs are not read (%d)", v);
7302 return -EINVAL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07007303 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07007304
7305 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
7306 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
7307 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
7308 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
7309 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
7310 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07007311
7312 /* point to the next argument */
7313 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
7314 /*no argument after the command*/
7315 if (NULL == inPtr) return -EINVAL;
7316
7317 /*removing empty spaces*/
7318 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
7319
7320 /*no argument followed by spaces*/
7321 if ('\0' == *inPtr)
7322 {
7323 return -EINVAL;
7324 }
7325
7326 /*getting the next argument ie the channel number */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08007327 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07007328 if (1 != v) return -EINVAL;
7329
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07007330 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07007331 if ((v < 0) ||
Padma, Santhosh Kumar0fa809b2014-11-13 14:56:56 +05307332 (tempInt < 0) ||
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07007333 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
7334 {
7335 return -EINVAL;
7336 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07007337
7338 *pChannel = tempInt;
7339 return VOS_STATUS_SUCCESS;
7340}
7341
7342#endif
7343
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08007344#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07007345/**---------------------------------------------------------------------------
7346
7347 \brief hdd_parse_get_cckm_ie() - HDD Parse and fetch the CCKM IE
7348
7349 This function parses the SETCCKM IE command
7350 SETCCKMIE<space><ie data>
7351
7352 \param - pValue Pointer to input data
7353 \param - pCckmIe Pointer to output cckm Ie
7354 \param - pCckmIeLen Pointer to output cckm ie length
7355
7356 \return - 0 for success non-zero for failure
7357
7358 --------------------------------------------------------------------------*/
7359VOS_STATUS hdd_parse_get_cckm_ie(tANI_U8 *pValue, tANI_U8 **pCckmIe,
7360 tANI_U8 *pCckmIeLen)
7361{
7362 tANI_U8 *inPtr = pValue;
7363 tANI_U8 *dataEnd;
7364 int j = 0;
7365 int i = 0;
7366 tANI_U8 tempByte = 0;
7367
7368 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
7369 /*no argument after the command*/
7370 if (NULL == inPtr)
7371 {
7372 return -EINVAL;
7373 }
7374
7375 /*no space after the command*/
7376 else if (SPACE_ASCII_VALUE != *inPtr)
7377 {
7378 return -EINVAL;
7379 }
7380
7381 /*removing empty spaces*/
7382 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
7383
7384 /*no argument followed by spaces*/
7385 if ('\0' == *inPtr)
7386 {
7387 return -EINVAL;
7388 }
7389
7390 /* find the length of data */
7391 dataEnd = inPtr;
7392 while(('\0' != *dataEnd) )
7393 {
7394 dataEnd++;
7395 ++(*pCckmIeLen);
7396 }
7397 if ( *pCckmIeLen <= 0) return -EINVAL;
7398
7399 /* Allocate the number of bytes based on the number of input characters
7400 whether it is even or odd.
7401 if the number of input characters are even, then we need N/2 byte.
7402 if the number of input characters are odd, then we need do (N+1)/2 to
7403 compensate rounding off.
7404 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
7405 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
7406 *pCckmIe = vos_mem_malloc((*pCckmIeLen + 1)/2);
7407 if (NULL == *pCckmIe)
7408 {
7409 hddLog(VOS_TRACE_LEVEL_FATAL,
7410 "%s: vos_mem_alloc failed ", __func__);
7411 return -EINVAL;
7412 }
7413 vos_mem_zero(*pCckmIe, (*pCckmIeLen + 1)/2);
7414 /* the buffer received from the upper layer is character buffer,
7415 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
7416 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
7417 and f0 in 3rd location */
7418 for (i = 0, j = 0; j < *pCckmIeLen; j += 2)
7419 {
7420 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
7421 (*pCckmIe)[i++] = tempByte;
7422 }
7423 *pCckmIeLen = i;
7424
7425 return VOS_STATUS_SUCCESS;
7426}
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08007427#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07007428
Jeff Johnson295189b2012-06-20 16:38:30 -07007429/**---------------------------------------------------------------------------
7430
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07007431 \brief hdd_is_valid_mac_address() - Validate MAC address
7432
7433 This function validates whether the given MAC address is valid or not
7434 Expected MAC address is of the format XX:XX:XX:XX:XX:XX
7435 where X is the hexa decimal digit character and separated by ':'
7436 This algorithm works even if MAC address is not separated by ':'
7437
7438 This code checks given input string mac contains exactly 12 hexadecimal digits.
7439 and a separator colon : appears in the input string only after
7440 an even number of hex digits.
7441
7442 \param - pMacAddr pointer to the input MAC address
7443 \return - 1 for valid and 0 for invalid
7444
7445 --------------------------------------------------------------------------*/
7446
7447v_BOOL_t hdd_is_valid_mac_address(const tANI_U8 *pMacAddr)
7448{
7449 int xdigit = 0;
7450 int separator = 0;
7451 while (*pMacAddr)
7452 {
7453 if (isxdigit(*pMacAddr))
7454 {
7455 xdigit++;
7456 }
7457 else if (':' == *pMacAddr)
7458 {
7459 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
7460 break;
7461
7462 ++separator;
7463 }
7464 else
7465 {
7466 separator = -1;
7467 /* Invalid MAC found */
7468 return 0;
7469 }
7470 ++pMacAddr;
7471 }
7472 return (xdigit == 12 && (separator == 5 || separator == 0));
7473}
7474
7475/**---------------------------------------------------------------------------
7476
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307477 \brief __hdd_open() - HDD Open function
Jeff Johnson295189b2012-06-20 16:38:30 -07007478
7479 \param - dev Pointer to net_device structure
7480
7481 \return - 0 for success non-zero for failure
7482
7483 --------------------------------------------------------------------------*/
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307484int __hdd_open(struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07007485{
7486 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7487 hdd_context_t *pHddCtx;
7488 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7489 VOS_STATUS status;
7490 v_BOOL_t in_standby = TRUE;
7491
7492 if (NULL == pAdapter)
7493 {
7494 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Agarwal Ashish971c2882013-10-30 20:11:12 +05307495 "%s: pAdapter is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007496 return -ENODEV;
7497 }
7498
7499 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05307500 MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_OPEN_REQUEST,
7501 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson295189b2012-06-20 16:38:30 -07007502 if (NULL == pHddCtx)
7503 {
7504 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007505 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007506 return -ENODEV;
7507 }
7508
7509 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7510 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
7511 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07007512 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
7513 {
7514 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307515 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07007516 in_standby = FALSE;
7517 break;
7518 }
7519 else
7520 {
7521 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7522 pAdapterNode = pNext;
7523 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007524 }
7525
7526 if (TRUE == in_standby)
7527 {
7528 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
7529 {
7530 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
7531 "wlan out of power save", __func__);
7532 return -EINVAL;
7533 }
7534 }
7535
Jeff Johnson6a81ca42013-04-05 10:37:08 -07007536 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07007537 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
7538 {
7539 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007540 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007541 /* Enable TX queues only when we are connected */
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05307542 hddLog(VOS_TRACE_LEVEL_INFO, FL("Enabling queues"));
Jeff Johnson295189b2012-06-20 16:38:30 -07007543 netif_tx_start_all_queues(dev);
7544 }
7545
7546 return 0;
7547}
7548
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307549/**---------------------------------------------------------------------------
7550
7551 \brief hdd_open() - Wrapper function for __hdd_open to protect it from SSR
7552
7553 This is called in response to ifconfig up
7554
7555 \param - dev Pointer to net_device structure
7556
7557 \return - 0 for success non-zero for failure
7558
7559 --------------------------------------------------------------------------*/
7560int hdd_open(struct net_device *dev)
7561{
7562 int ret;
7563
7564 vos_ssr_protect(__func__);
7565 ret = __hdd_open(dev);
7566 vos_ssr_unprotect(__func__);
7567
7568 return ret;
7569}
7570
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +05307571int __hdd_mon_open (struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07007572{
7573 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05307574 hdd_adapter_t *sta_adapter;
7575 hdd_context_t *hdd_ctx;
Jeff Johnson295189b2012-06-20 16:38:30 -07007576
7577 if(pAdapter == NULL) {
7578 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007579 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007580 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007581 }
7582
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05307583 if (vos_get_concurrency_mode() != VOS_STA_MON)
7584 return 0;
7585
7586 hdd_ctx = WLAN_HDD_GET_CTX(pAdapter);
7587 if (wlan_hdd_validate_context(hdd_ctx))
7588 return -EINVAL;
7589
7590 sta_adapter = hdd_get_adapter(hdd_ctx, WLAN_HDD_INFRA_STATION);
7591 if (!sta_adapter) {
7592 hddLog(LOGE, FL("No valid STA interface"));
7593 return -EINVAL;
7594 }
7595
7596 if (!test_bit(DEVICE_IFACE_OPENED, &sta_adapter->event_flags)) {
7597 hddLog(LOGE, FL("STA Interface is not OPENED"));
7598 return -EINVAL;
7599 }
7600
7601 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
7602
Jeff Johnson295189b2012-06-20 16:38:30 -07007603 return 0;
7604}
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +05307605
7606int hdd_mon_open (struct net_device *dev)
7607{
7608 int ret;
7609
7610 vos_ssr_protect(__func__);
7611 ret = __hdd_mon_open(dev);
7612 vos_ssr_unprotect(__func__);
7613
7614 return ret;
7615}
7616
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05307617int __hdd_mon_stop (struct net_device *dev)
7618{
7619 hdd_adapter_t *mon_adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7620 hdd_context_t *hdd_ctx;
7621
7622 if (vos_get_concurrency_mode() != VOS_STA_MON)
7623 return 0;
7624
7625 if(!mon_adapter) {
7626 hddLog(LOGE, FL("HDD adapter is Null"));
7627 return -EINVAL;
7628 }
7629
7630 hdd_ctx = WLAN_HDD_GET_CTX(mon_adapter);
7631 if (wlan_hdd_validate_context(hdd_ctx))
7632 return -EINVAL;
7633
7634 if (!test_bit(DEVICE_IFACE_OPENED, &mon_adapter->event_flags)) {
7635 hddLog(LOGE, FL("NETDEV Interface is not OPENED"));
7636 return -ENODEV;
7637 }
7638
7639 clear_bit(DEVICE_IFACE_OPENED, &mon_adapter->event_flags);
7640 hdd_stop_adapter(hdd_ctx, mon_adapter, VOS_FALSE);
7641
7642 return 0;
7643}
7644
Katya Nigame7b69a82015-04-28 15:24:06 +05307645int hdd_mon_stop(struct net_device *dev)
7646{
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05307647 int ret;
7648
7649 vos_ssr_protect(__func__);
7650 ret = __hdd_mon_stop(dev);
7651 vos_ssr_unprotect(__func__);
7652
7653 return ret;
Katya Nigame7b69a82015-04-28 15:24:06 +05307654}
7655
Jeff Johnson295189b2012-06-20 16:38:30 -07007656/**---------------------------------------------------------------------------
7657
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307658 \brief __hdd_stop() - HDD stop function
Jeff Johnson295189b2012-06-20 16:38:30 -07007659
7660 \param - dev Pointer to net_device structure
7661
7662 \return - 0 for success non-zero for failure
7663
7664 --------------------------------------------------------------------------*/
7665
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307666int __hdd_stop (struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07007667{
Vinay Krishna Eranna90f43532014-10-27 16:45:54 +05307668 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07007669 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7670 hdd_context_t *pHddCtx;
7671 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7672 VOS_STATUS status;
7673 v_BOOL_t enter_standby = TRUE;
7674
7675 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07007676 if (NULL == pAdapter)
7677 {
7678 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Agarwal Ashish971c2882013-10-30 20:11:12 +05307679 "%s: pAdapter is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007680 return -ENODEV;
7681 }
Sachin Ahuja9b4958f2015-01-15 21:37:00 +05307682 MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_STOP_REQUEST,
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05307683 pAdapter->sessionId, pAdapter->device_mode));
Vinay Krishna Eranna90f43532014-10-27 16:45:54 +05307684
7685 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7686 ret = wlan_hdd_validate_context(pHddCtx);
7687 if (ret)
Jeff Johnson295189b2012-06-20 16:38:30 -07007688 {
Vinay Krishna Eranna90f43532014-10-27 16:45:54 +05307689 return ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07007690 }
7691
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307692 /* Nothing to be done if the interface is not opened */
7693 if (VOS_FALSE == test_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags))
7694 {
7695 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7696 "%s: NETDEV Interface is not OPENED", __func__);
7697 return -ENODEV;
7698 }
7699
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05307700 if (pHddCtx->concurrency_mode == VOS_STA_MON) {
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05307701 /*
Rajeev Kumar Sirasanagandlaa74e1222018-01-09 17:38:55 +05307702 * In STA + Monitor mode concurrency, no point in running
7703 * capture on monitor interface, when STA interface is stopped
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05307704 */
Rajeev Kumar Sirasanagandlaa74e1222018-01-09 17:38:55 +05307705 wlan_hdd_stop_mon(pHddCtx, true);
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05307706 }
7707
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307708 /* Make sure the interface is marked as closed */
Jeff Johnson6a81ca42013-04-05 10:37:08 -07007709 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07007710 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307711
7712 /* Disable TX on the interface, after this hard_start_xmit() will not
7713 * be called on that interface
7714 */
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05307715 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
Jeff Johnson295189b2012-06-20 16:38:30 -07007716 netif_tx_disable(pAdapter->dev);
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307717
7718 /* Mark the interface status as "down" for outside world */
Jeff Johnson295189b2012-06-20 16:38:30 -07007719 netif_carrier_off(pAdapter->dev);
7720
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307721 /* The interface is marked as down for outside world (aka kernel)
7722 * But the driver is pretty much alive inside. The driver needs to
7723 * tear down the existing connection on the netdev (session)
7724 * cleanup the data pipes and wait until the control plane is stabilized
7725 * for this interface. The call also needs to wait until the above
7726 * mentioned actions are completed before returning to the caller.
7727 * Notice that the hdd_stop_adapter is requested not to close the session
7728 * That is intentional to be able to scan if it is a STA/P2P interface
7729 */
7730 hdd_stop_adapter(pHddCtx, pAdapter, VOS_FALSE);
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05307731#ifdef FEATURE_WLAN_TDLS
7732 mutex_lock(&pHddCtx->tdls_lock);
7733#endif
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307734 /* DeInit the adapter. This ensures datapath cleanup as well */
c_hpothu002231a2015-02-05 14:58:51 +05307735 hdd_deinit_adapter(pHddCtx, pAdapter, TRUE);
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05307736#ifdef FEATURE_WLAN_TDLS
7737 mutex_unlock(&pHddCtx->tdls_lock);
7738#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007739 /* SoftAP ifaces should never go in power save mode
7740 making sure same here. */
7741 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07007742 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07007743 )
7744 {
7745 /* SoftAP mode, so return from here */
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307746 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
7747 "%s: In SAP MODE", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007748 EXIT();
7749 return 0;
7750 }
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307751 /* Find if any iface is up. If any iface is up then can't put device to
7752 * sleep/power save mode
7753 */
Jeff Johnson295189b2012-06-20 16:38:30 -07007754 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7755 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
7756 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07007757 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
7758 {
7759 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307760 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07007761 enter_standby = FALSE;
7762 break;
7763 }
7764 else
7765 {
7766 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7767 pAdapterNode = pNext;
7768 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007769 }
7770
7771 if (TRUE == enter_standby)
7772 {
7773 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
7774 "entering standby", __func__);
7775 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
7776 {
7777 /*log and return success*/
7778 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
7779 "wlan in power save", __func__);
7780 }
7781 }
7782
7783 EXIT();
7784 return 0;
7785}
7786
7787/**---------------------------------------------------------------------------
7788
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307789 \brief hdd_stop() - wrapper_function for __hdd_stop to protect it from SSR
Jeff Johnson295189b2012-06-20 16:38:30 -07007790
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307791 This is called in response to ifconfig down
7792
7793 \param - dev Pointer to net_device structure
7794
7795 \return - 0 for success non-zero for failure
7796-----------------------------------------------------------------------------*/
7797int hdd_stop (struct net_device *dev)
7798{
7799 int ret;
7800
7801 vos_ssr_protect(__func__);
7802 ret = __hdd_stop(dev);
7803 vos_ssr_unprotect(__func__);
7804
7805 return ret;
7806}
7807
7808/**---------------------------------------------------------------------------
7809
7810 \brief __hdd_uninit() - HDD uninit function
Jeff Johnson295189b2012-06-20 16:38:30 -07007811
7812 \param - dev Pointer to net_device structure
7813
7814 \return - void
7815
7816 --------------------------------------------------------------------------*/
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307817static void __hdd_uninit (struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07007818{
7819 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05307820 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07007821 ENTER();
7822
7823 do
7824 {
7825 if (NULL == pAdapter)
7826 {
7827 hddLog(VOS_TRACE_LEVEL_FATAL,
7828 "%s: NULL pAdapter", __func__);
7829 break;
7830 }
7831
7832 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
7833 {
7834 hddLog(VOS_TRACE_LEVEL_FATAL,
7835 "%s: Invalid magic", __func__);
7836 break;
7837 }
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05307838 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7839 if (NULL == pHddCtx)
Jeff Johnson295189b2012-06-20 16:38:30 -07007840 {
7841 hddLog(VOS_TRACE_LEVEL_FATAL,
7842 "%s: NULL pHddCtx", __func__);
7843 break;
7844 }
7845
7846 if (dev != pAdapter->dev)
7847 {
7848 hddLog(VOS_TRACE_LEVEL_FATAL,
7849 "%s: Invalid device reference", __func__);
7850 /* we haven't validated all cases so let this go for now */
7851 }
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05307852#ifdef FEATURE_WLAN_TDLS
7853 mutex_lock(&pHddCtx->tdls_lock);
7854#endif
c_hpothu002231a2015-02-05 14:58:51 +05307855 hdd_deinit_adapter(pHddCtx, pAdapter, TRUE);
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05307856#ifdef FEATURE_WLAN_TDLS
7857 mutex_unlock(&pHddCtx->tdls_lock);
7858#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007859
7860 /* after uninit our adapter structure will no longer be valid */
7861 pAdapter->dev = NULL;
7862 pAdapter->magic = 0;
Manjeet Singh47ee8472016-04-11 11:57:18 +05307863 pAdapter->pHddCtx = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007864 } while (0);
7865
7866 EXIT();
7867}
7868
7869/**---------------------------------------------------------------------------
7870
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307871 \brief hdd_uninit() - Wrapper function to protect __hdd_uninit from SSR
7872
7873 This is called during the netdev unregister to uninitialize all data
7874associated with the device
7875
7876 \param - dev Pointer to net_device structure
7877
7878 \return - void
7879
7880 --------------------------------------------------------------------------*/
7881static void hdd_uninit (struct net_device *dev)
7882{
7883 vos_ssr_protect(__func__);
7884 __hdd_uninit(dev);
7885 vos_ssr_unprotect(__func__);
7886}
7887
7888/**---------------------------------------------------------------------------
7889
Jeff Johnson295189b2012-06-20 16:38:30 -07007890 \brief hdd_release_firmware() -
7891
7892 This function calls the release firmware API to free the firmware buffer.
7893
7894 \param - pFileName Pointer to the File Name.
7895 pCtx - Pointer to the adapter .
7896
7897
7898 \return - 0 for success, non zero for failure
7899
7900 --------------------------------------------------------------------------*/
7901
7902VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
7903{
7904 VOS_STATUS status = VOS_STATUS_SUCCESS;
7905 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
7906 ENTER();
7907
7908
7909 if (!strcmp(WLAN_FW_FILE, pFileName)) {
7910
7911 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
7912
7913 if(pHddCtx->fw) {
7914 release_firmware(pHddCtx->fw);
7915 pHddCtx->fw = NULL;
7916 }
7917 else
7918 status = VOS_STATUS_E_FAILURE;
7919 }
7920 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
7921 if(pHddCtx->nv) {
7922 release_firmware(pHddCtx->nv);
7923 pHddCtx->nv = NULL;
7924 }
7925 else
7926 status = VOS_STATUS_E_FAILURE;
7927
7928 }
7929
7930 EXIT();
7931 return status;
7932}
7933
7934/**---------------------------------------------------------------------------
7935
7936 \brief hdd_request_firmware() -
7937
7938 This function reads the firmware file using the request firmware
7939 API and returns the the firmware data and the firmware file size.
7940
7941 \param - pfileName - Pointer to the file name.
7942 - pCtx - Pointer to the adapter .
7943 - ppfw_data - Pointer to the pointer of the firmware data.
7944 - pSize - Pointer to the file size.
7945
7946 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
7947
7948 --------------------------------------------------------------------------*/
7949
7950
7951VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
7952{
7953 int status;
7954 VOS_STATUS retval = VOS_STATUS_SUCCESS;
7955 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
7956 ENTER();
7957
7958 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
7959
7960 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
7961
7962 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
7963 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
7964 __func__, pfileName);
7965 retval = VOS_STATUS_E_FAILURE;
7966 }
7967
7968 else {
7969 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
7970 *pSize = pHddCtx->fw->size;
7971 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
7972 __func__, *pSize);
7973 }
7974 }
7975 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
7976
7977 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
7978
7979 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
7980 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
7981 __func__, pfileName);
7982 retval = VOS_STATUS_E_FAILURE;
7983 }
7984
7985 else {
7986 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
7987 *pSize = pHddCtx->nv->size;
7988 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
7989 __func__, *pSize);
7990 }
7991 }
7992
7993 EXIT();
7994 return retval;
7995}
7996/**---------------------------------------------------------------------------
7997 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
7998
7999 This is the function invoked by SME to inform the result of a full power
8000 request issued by HDD
8001
8002 \param - callbackcontext - Pointer to cookie
8003 status - result of request
8004
8005 \return - None
8006
8007--------------------------------------------------------------------------*/
8008void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
8009{
8010 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
8011
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07008012 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07008013 if(&pHddCtx->full_pwr_comp_var)
8014 {
8015 complete(&pHddCtx->full_pwr_comp_var);
8016 }
8017}
8018
Abhishek Singh00b71972016-01-07 10:51:04 +05308019#ifdef WLAN_FEATURE_RMC
8020static void hdd_tx_fail_ind_callback(v_U8_t *MacAddr, v_U8_t seqNo)
8021{
8022 int payload_len;
8023 struct sk_buff *skb;
8024 struct nlmsghdr *nlh;
8025 v_U8_t *data;
8026
8027 payload_len = ETH_ALEN;
8028
8029 if (0 == cesium_pid)
8030 {
8031 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: cesium process not registered",
8032 __func__);
8033 return;
8034 }
8035
8036 if ((skb = nlmsg_new(payload_len,GFP_ATOMIC)) == NULL)
8037 {
8038 hddLog(VOS_TRACE_LEVEL_ERROR,
8039 "%s: nlmsg_new() failed for msg size[%d]",
8040 __func__, NLMSG_SPACE(payload_len));
8041 return;
8042 }
8043
8044 nlh = nlmsg_put(skb, cesium_pid, seqNo, 0, payload_len, NLM_F_REQUEST);
8045
8046 if (NULL == nlh)
8047 {
8048 hddLog(VOS_TRACE_LEVEL_ERROR,
8049 "%s: nlmsg_put() failed for msg size[%d]",
8050 __func__, NLMSG_SPACE(payload_len));
8051
8052 kfree_skb(skb);
8053 return;
8054 }
8055
8056 data = nlmsg_data(nlh);
8057 memcpy(data, MacAddr, ETH_ALEN);
8058
8059 if (nlmsg_unicast(cesium_nl_srv_sock, skb, cesium_pid) < 0)
8060 {
8061 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: nlmsg_unicast() failed for msg size[%d]",
8062 __func__, NLMSG_SPACE(payload_len));
8063 }
8064
8065 return;
8066}
8067
8068/**---------------------------------------------------------------------------
8069 \brief hdd_ParseuserParams - return a pointer to the next argument
8070
8071 \return - status
8072
8073--------------------------------------------------------------------------*/
8074static int hdd_ParseUserParams(tANI_U8 *pValue, tANI_U8 **ppArg)
8075{
8076 tANI_U8 *pVal;
8077
8078 pVal = strchr(pValue, ' ');
8079
8080 if (NULL == pVal)
8081 {
8082 /* no argument remains */
8083 return -EINVAL;
8084 }
8085 else if (SPACE_ASCII_VALUE != *pVal)
8086 {
8087 /* no space after the current argument */
8088 return -EINVAL;
8089 }
8090
8091 pVal++;
8092
8093 /* remove empty spaces */
8094 while ((SPACE_ASCII_VALUE == *pVal) && ('\0' != *pVal))
8095 {
8096 pVal++;
8097 }
8098
8099 /* no argument followed by spaces */
8100 if ('\0' == *pVal)
8101 {
8102 return -EINVAL;
8103 }
8104
8105 *ppArg = pVal;
8106
8107 return 0;
8108}
8109
8110/**----------------------------------------------------------------------------
8111 \brief hdd_ParseIBSSTXFailEventParams - Parse params for SETIBSSTXFAILEVENT
8112
8113 \return - status
8114
8115------------------------------------------------------------------------------*/
8116static int hdd_ParseIBSSTXFailEventParams(tANI_U8 *pValue,
8117 tANI_U8 *tx_fail_count,
8118 tANI_U16 *pid)
8119{
8120 tANI_U8 *param = NULL;
8121 int ret;
8122
8123 ret = hdd_ParseUserParams(pValue, &param);
8124
8125 if (0 == ret && NULL != param)
8126 {
8127 if (1 != sscanf(param, "%hhu", tx_fail_count))
8128 {
8129 ret = -EINVAL;
8130 goto done;
8131 }
8132 }
8133 else
8134 {
8135 goto done;
8136 }
8137
8138 if (0 == *tx_fail_count)
8139 {
8140 *pid = 0;
8141 goto done;
8142 }
8143
8144 pValue = param;
8145 pValue++;
8146
8147 ret = hdd_ParseUserParams(pValue, &param);
8148
8149 if (0 == ret)
8150 {
8151 if (1 != sscanf(param, "%hu", pid))
8152 {
8153 ret = -EINVAL;
8154 goto done;
8155 }
8156 }
8157 else
8158 {
8159 goto done;
8160 }
8161
8162done:
8163 return ret;
8164}
8165
8166static int hdd_open_cesium_nl_sock()
8167{
8168#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
8169 struct netlink_kernel_cfg cfg = {
8170 .groups = WLAN_NLINK_MCAST_GRP_ID,
8171 .input = NULL
8172 };
8173#endif
8174 int ret = 0;
8175
8176#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
8177 cesium_nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_CESIUM,
8178#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0))
8179 THIS_MODULE,
8180#endif
8181 &cfg);
8182#else
8183 cesium_nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_CESIUM,
8184 WLAN_NLINK_MCAST_GRP_ID, NULL, NULL, THIS_MODULE);
8185#endif
8186
8187 if (cesium_nl_srv_sock == NULL)
8188 {
8189 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8190 "NLINK: cesium netlink_kernel_create failed");
8191 ret = -ECONNREFUSED;
8192 }
8193
8194 return ret;
8195}
8196
8197static void hdd_close_cesium_nl_sock()
8198{
8199 if (NULL != cesium_nl_srv_sock)
8200 {
8201 netlink_kernel_release(cesium_nl_srv_sock);
8202 cesium_nl_srv_sock = NULL;
8203 }
8204}
8205#endif /* WLAN_FEATURE_RMC */
Jeff Johnson295189b2012-06-20 16:38:30 -07008206/**---------------------------------------------------------------------------
8207
8208 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
8209
8210 This is the function invoked by SME to inform the result of BMPS
8211 request issued by HDD
8212
8213 \param - callbackcontext - Pointer to cookie
8214 status - result of request
8215
8216 \return - None
8217
8218--------------------------------------------------------------------------*/
8219void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
8220{
8221
8222 struct completion *completion_var = (struct completion*) callbackContext;
8223
Arif Hussain6d2a3322013-11-17 19:50:10 -08008224 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07008225 if(completion_var != NULL)
8226 {
8227 complete(completion_var);
8228 }
8229}
8230
8231/**---------------------------------------------------------------------------
8232
8233 \brief hdd_get_cfg_file_size() -
8234
8235 This function reads the configuration file using the request firmware
8236 API and returns the configuration file size.
8237
8238 \param - pCtx - Pointer to the adapter .
8239 - pFileName - Pointer to the file name.
8240 - pBufSize - Pointer to the buffer size.
8241
8242 \return - 0 for success, non zero for failure
8243
8244 --------------------------------------------------------------------------*/
8245
8246VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
8247{
8248 int status;
8249 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
8250
8251 ENTER();
8252
8253 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
8254
8255 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
8256 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
8257 status = VOS_STATUS_E_FAILURE;
8258 }
8259 else {
8260 *pBufSize = pHddCtx->fw->size;
8261 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
8262 release_firmware(pHddCtx->fw);
8263 pHddCtx->fw = NULL;
8264 }
8265
8266 EXIT();
8267 return VOS_STATUS_SUCCESS;
8268}
8269
8270/**---------------------------------------------------------------------------
8271
8272 \brief hdd_read_cfg_file() -
8273
8274 This function reads the configuration file using the request firmware
8275 API and returns the cfg data and the buffer size of the configuration file.
8276
8277 \param - pCtx - Pointer to the adapter .
8278 - pFileName - Pointer to the file name.
8279 - pBuffer - Pointer to the data buffer.
8280 - pBufSize - Pointer to the buffer size.
8281
8282 \return - 0 for success, non zero for failure
8283
8284 --------------------------------------------------------------------------*/
8285
8286VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
8287 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
8288{
8289 int status;
8290 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
8291
8292 ENTER();
8293
8294 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
8295
8296 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
8297 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
8298 return VOS_STATUS_E_FAILURE;
8299 }
8300 else {
8301 if(*pBufSize != pHddCtx->fw->size) {
8302 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
8303 "file size", __func__);
8304 release_firmware(pHddCtx->fw);
8305 pHddCtx->fw = NULL;
8306 return VOS_STATUS_E_FAILURE;
8307 }
8308 else {
8309 if(pBuffer) {
8310 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
8311 }
8312 release_firmware(pHddCtx->fw);
8313 pHddCtx->fw = NULL;
8314 }
8315 }
8316
8317 EXIT();
8318
8319 return VOS_STATUS_SUCCESS;
8320}
8321
8322/**---------------------------------------------------------------------------
8323
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05308324 \brief __hdd_set_mac_address() -
Jeff Johnson295189b2012-06-20 16:38:30 -07008325
8326 This function sets the user specified mac address using
8327 the command ifconfig wlanX hw ether <mac adress>.
8328
8329 \param - dev - Pointer to the net device.
8330 - addr - Pointer to the sockaddr.
8331 \return - 0 for success, non zero for failure
8332
8333 --------------------------------------------------------------------------*/
8334
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05308335static int __hdd_set_mac_address(struct net_device *dev, void *addr)
Jeff Johnson295189b2012-06-20 16:38:30 -07008336{
Mahesh A Saptasagar74088392015-02-05 17:22:09 +05308337 hdd_adapter_t *pAdapter;
8338 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07008339 struct sockaddr *psta_mac_addr = addr;
8340 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
Mahesh A Saptasagar74088392015-02-05 17:22:09 +05308341 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07008342
8343 ENTER();
Mahesh A Saptasagar74088392015-02-05 17:22:09 +05308344 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
8345 if (NULL == pAdapter)
8346 {
8347 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8348 "%s: Adapter is NULL",__func__);
8349 return -EINVAL;
8350 }
8351 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
8352 ret = wlan_hdd_validate_context(pHddCtx);
8353 if (0 != ret)
8354 {
Mahesh A Saptasagar74088392015-02-05 17:22:09 +05308355 return ret;
8356 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008357
8358 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
Jeff Johnson295189b2012-06-20 16:38:30 -07008359 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
8360
8361 EXIT();
8362 return halStatus;
8363}
8364
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05308365/**---------------------------------------------------------------------------
8366
8367 \brief hdd_set_mac_address() -
8368
8369 Wrapper function to protect __hdd_set_mac_address() function from ssr
8370
8371 \param - dev - Pointer to the net device.
8372 - addr - Pointer to the sockaddr.
8373 \return - 0 for success, non zero for failure
8374
8375 --------------------------------------------------------------------------*/
8376static int hdd_set_mac_address(struct net_device *dev, void *addr)
8377{
8378 int ret;
8379
8380 vos_ssr_protect(__func__);
8381 ret = __hdd_set_mac_address(dev, addr);
8382 vos_ssr_unprotect(__func__);
8383
8384 return ret;
8385}
8386
Jeff Johnson295189b2012-06-20 16:38:30 -07008387tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
8388{
8389 int i;
8390 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
8391 {
Abhishek Singheb183782014-02-06 13:37:21 +05308392 if( 0 == ((pHddCtx->cfg_ini->intfAddrMask) & (1 << i)) )
Jeff Johnson295189b2012-06-20 16:38:30 -07008393 break;
8394 }
8395
8396 if( VOS_MAX_CONCURRENCY_PERSONA == i)
8397 return NULL;
8398
8399 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
8400 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
8401}
8402
8403void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
8404{
8405 int i;
8406 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
8407 {
8408 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
8409 {
8410 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
8411 break;
8412 }
8413 }
8414 return;
8415}
8416
8417#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
8418 static struct net_device_ops wlan_drv_ops = {
8419 .ndo_open = hdd_open,
8420 .ndo_stop = hdd_stop,
8421 .ndo_uninit = hdd_uninit,
8422 .ndo_start_xmit = hdd_hard_start_xmit,
8423 .ndo_tx_timeout = hdd_tx_timeout,
8424 .ndo_get_stats = hdd_stats,
8425 .ndo_do_ioctl = hdd_ioctl,
8426 .ndo_set_mac_address = hdd_set_mac_address,
8427 .ndo_select_queue = hdd_select_queue,
8428#ifdef WLAN_FEATURE_PACKET_FILTERING
8429#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
8430 .ndo_set_rx_mode = hdd_set_multicast_list,
8431#else
8432 .ndo_set_multicast_list = hdd_set_multicast_list,
8433#endif //LINUX_VERSION_CODE
8434#endif
8435 };
Jeff Johnson295189b2012-06-20 16:38:30 -07008436 static struct net_device_ops wlan_mon_drv_ops = {
8437 .ndo_open = hdd_mon_open,
Katya Nigame7b69a82015-04-28 15:24:06 +05308438 .ndo_stop = hdd_mon_stop,
Jeff Johnson295189b2012-06-20 16:38:30 -07008439 .ndo_uninit = hdd_uninit,
8440 .ndo_start_xmit = hdd_mon_hard_start_xmit,
8441 .ndo_tx_timeout = hdd_tx_timeout,
8442 .ndo_get_stats = hdd_stats,
Katya Nigame7b69a82015-04-28 15:24:06 +05308443 .ndo_do_ioctl = hdd_mon_ioctl,
Jeff Johnson295189b2012-06-20 16:38:30 -07008444 .ndo_set_mac_address = hdd_set_mac_address,
8445 };
Mahesh A Saptasagar305e2632015-03-04 12:57:33 +05308446
Jeff Johnson295189b2012-06-20 16:38:30 -07008447#endif
8448
8449void hdd_set_station_ops( struct net_device *pWlanDev )
8450{
8451#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
Jeff Johnson295189b2012-06-20 16:38:30 -07008452 pWlanDev->netdev_ops = &wlan_drv_ops;
8453#else
8454 pWlanDev->open = hdd_open;
8455 pWlanDev->stop = hdd_stop;
8456 pWlanDev->uninit = hdd_uninit;
8457 pWlanDev->hard_start_xmit = NULL;
8458 pWlanDev->tx_timeout = hdd_tx_timeout;
8459 pWlanDev->get_stats = hdd_stats;
8460 pWlanDev->do_ioctl = hdd_ioctl;
Jeff Johnson295189b2012-06-20 16:38:30 -07008461 pWlanDev->set_mac_address = hdd_set_mac_address;
8462#endif
8463}
8464
Katya Nigam1fd24402015-02-16 14:52:19 +05308465void hdd_set_ibss_ops( hdd_adapter_t *pAdapter )
8466{
8467 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
8468 wlan_drv_ops.ndo_start_xmit = hdd_ibss_hard_start_xmit;
8469 #else
8470 pAdapter->dev->hard_start_xmit = hdd_ibss_hard_start_xmit;
8471 #endif
8472}
8473
Jeff Johnsoneed415b2013-01-18 16:11:20 -08008474static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07008475{
8476 struct net_device *pWlanDev = NULL;
8477 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07008478 /*
8479 * cfg80211 initialization and registration....
8480 */
Anand N Sunkadc34abbd2015-07-29 09:52:59 +05308481 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name,
8482#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0))
8483 NET_NAME_UNKNOWN,
8484#endif
8485 ether_setup, NUM_TX_QUEUES);
Jeff Johnson295189b2012-06-20 16:38:30 -07008486 if(pWlanDev != NULL)
8487 {
8488
8489 //Save the pointer to the net_device in the HDD adapter
8490 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
8491
Jeff Johnson295189b2012-06-20 16:38:30 -07008492 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
8493
8494 pAdapter->dev = pWlanDev;
8495 pAdapter->pHddCtx = pHddCtx;
8496 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
Agarwal Ashish47d18112014-08-04 19:55:07 +05308497 spin_lock_init(&pAdapter->lock_for_active_session);
Jeff Johnson295189b2012-06-20 16:38:30 -07008498
Rajeev79dbe4c2013-10-05 11:03:42 +05308499#ifdef FEATURE_WLAN_BATCH_SCAN
Rajeev79dbe4c2013-10-05 11:03:42 +05308500 pAdapter->pBatchScanRsp = NULL;
8501 pAdapter->numScanList = 0;
Rajeev Kumar20140c12013-10-21 19:39:02 -07008502 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
Kiet Lamaa8e15a2014-02-11 23:30:06 -08008503 pAdapter->prev_batch_id = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05308504 mutex_init(&pAdapter->hdd_batch_scan_lock);
8505#endif
8506
Jeff Johnson295189b2012-06-20 16:38:30 -07008507 pAdapter->isLinkUpSvcNeeded = FALSE;
8508 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
8509 //Init the net_device structure
8510 strlcpy(pWlanDev->name, name, IFNAMSIZ);
8511
8512 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
8513 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
8514 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
8515 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
8516
8517 hdd_set_station_ops( pAdapter->dev );
8518
8519 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07008520 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
8521 pAdapter->wdev.wiphy = pHddCtx->wiphy;
8522 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07008523 /* set pWlanDev's parent to underlying device */
8524 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
Kumar Anand82c009f2014-05-29 00:29:42 -07008525
8526 hdd_wmm_init( pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07008527 }
8528
8529 return pAdapter;
8530}
8531
8532VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
8533{
8534 struct net_device *pWlanDev = pAdapter->dev;
8535 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
8536 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
8537 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
8538
8539 if( rtnl_lock_held )
8540 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08008541 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07008542 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
8543 {
8544 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
8545 return VOS_STATUS_E_FAILURE;
8546 }
8547 }
8548 if (register_netdevice(pWlanDev))
8549 {
8550 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
8551 return VOS_STATUS_E_FAILURE;
8552 }
8553 }
8554 else
8555 {
8556 if(register_netdev(pWlanDev))
8557 {
8558 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
8559 return VOS_STATUS_E_FAILURE;
8560 }
8561 }
8562 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
8563
8564 return VOS_STATUS_SUCCESS;
8565}
8566
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008567static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07008568{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008569 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07008570
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008571 if (NULL == pAdapter)
8572 {
8573 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
8574 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07008575 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008576
8577 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
8578 {
8579 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
8580 return eHAL_STATUS_NOT_INITIALIZED;
8581 }
8582
8583 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
8584
Sameer Thalappilbee426e2013-10-30 10:30:30 -07008585#ifndef WLAN_OPEN_SOURCE
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008586 /* need to make sure all of our scheduled work has completed.
8587 * This callback is called from MC thread context, so it is safe to
8588 * to call below flush workqueue API from here.
Sameer Thalappilbee426e2013-10-30 10:30:30 -07008589 *
8590 * Even though this is called from MC thread context, if there is a faulty
8591 * work item in the system, that can hang this call forever. So flushing
8592 * this global work queue is not safe; and now we make sure that
8593 * individual work queues are stopped correctly. But the cancel work queue
8594 * is a GPL only API, so the proprietary version of the driver would still
8595 * rely on the global work queue flush.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008596 */
8597 flush_scheduled_work();
Sameer Thalappilbee426e2013-10-30 10:30:30 -07008598#endif
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008599
8600 /* We can be blocked while waiting for scheduled work to be
8601 * flushed, and the adapter structure can potentially be freed, in
8602 * which case the magic will have been reset. So make sure the
8603 * magic is still good, and hence the adapter structure is still
8604 * valid, before signaling completion */
8605 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
8606 {
8607 complete(&pAdapter->session_close_comp_var);
8608 }
8609
Jeff Johnson295189b2012-06-20 16:38:30 -07008610 return eHAL_STATUS_SUCCESS;
8611}
Manjeet Singh47ee8472016-04-11 11:57:18 +05308612/**
8613 * hdd_close_tx_queues() - close tx queues
8614 * @hdd_ctx: hdd global context
8615 *
8616 * Return: None
8617 */
8618static void hdd_close_tx_queues(hdd_context_t *hdd_ctx)
8619{
8620 VOS_STATUS status;
8621 hdd_adapter_t *adapter;
8622 hdd_adapter_list_node_t *adapter_node = NULL, *next_adapter = NULL;
8623 /* Not validating hdd_ctx as it's already done by the caller */
8624 ENTER();
8625 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
8626 while (NULL != adapter_node && VOS_STATUS_SUCCESS == status) {
8627 adapter = adapter_node->pAdapter;
8628 if (adapter && adapter->dev) {
8629 netif_tx_disable (adapter->dev);
8630 netif_carrier_off(adapter->dev);
8631 }
8632 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
8633 &next_adapter);
8634 adapter_node = next_adapter;
8635 }
8636 EXIT();
8637}
Jeff Johnson295189b2012-06-20 16:38:30 -07008638
8639VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
8640{
8641 struct net_device *pWlanDev = pAdapter->dev;
8642 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
8643 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
8644 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
8645 VOS_STATUS status = VOS_STATUS_E_FAILURE;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308646 long rc = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07008647
Nirav Shah7e3c8132015-06-22 23:51:42 +05308648 spin_lock_init( &pAdapter->sta_hash_lock);
8649 pAdapter->is_sta_id_hash_initialized = VOS_FALSE;
8650
Jeff Johnson295189b2012-06-20 16:38:30 -07008651 INIT_COMPLETION(pAdapter->session_open_comp_var);
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07008652 sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07008653 //Open a SME session for future operation
8654 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07008655 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07008656 if ( !HAL_STATUS_SUCCESS( halStatus ) )
8657 {
8658 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07008659 "sme_OpenSession() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07008660 halStatus, halStatus );
8661 status = VOS_STATUS_E_FAILURE;
8662 goto error_sme_open;
8663 }
8664
8665 //Block on a completion variable. Can't wait forever though.
Vinay Krishna Eranna0fe2e7c2014-04-09 21:32:08 +05308666 rc = wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07008667 &pAdapter->session_open_comp_var,
8668 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308669 if (rc <= 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07008670 {
8671 hddLog(VOS_TRACE_LEVEL_FATAL,
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308672 "Session is not opened within timeout period code %ld", rc );
Jeff Johnson295189b2012-06-20 16:38:30 -07008673 status = VOS_STATUS_E_FAILURE;
8674 goto error_sme_open;
8675 }
8676
8677 // Register wireless extensions
8678 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
8679 {
8680 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07008681 "hdd_register_wext() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07008682 halStatus, halStatus );
8683 status = VOS_STATUS_E_FAILURE;
8684 goto error_register_wext;
8685 }
Katya Nigam1fd24402015-02-16 14:52:19 +05308686
Jeff Johnson295189b2012-06-20 16:38:30 -07008687 //Safe to register the hard_start_xmit function again
Katya Nigam1fd24402015-02-16 14:52:19 +05308688 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
8689 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
8690 #else
8691 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
8692 #endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008693
8694 //Set the Connection State to Not Connected
Abhishek Singhf4669da2014-05-26 15:07:49 +05308695 hddLog(VOS_TRACE_LEVEL_INFO,
8696 "%s: Set HDD connState to eConnectionState_NotConnected",
8697 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008698 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
8699
8700 //Set the default operation channel
8701 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
8702
8703 /* Make the default Auth Type as OPEN*/
8704 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
8705
8706 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
8707 {
8708 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07008709 "hdd_init_tx_rx() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07008710 status, status );
8711 goto error_init_txrx;
8712 }
8713
8714 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
8715
8716 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
8717 {
8718 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07008719 "hdd_wmm_adapter_init() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07008720 status, status );
8721 goto error_wmm_init;
8722 }
8723
8724 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
8725
8726 return VOS_STATUS_SUCCESS;
8727
8728error_wmm_init:
8729 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
8730 hdd_deinit_tx_rx(pAdapter);
8731error_init_txrx:
8732 hdd_UnregisterWext(pWlanDev);
8733error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008734 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07008735 {
8736 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008737 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Agrawal Ashish5a3522c2016-03-02 15:08:28 +05308738 pAdapter->sessionId, FALSE, VOS_TRUE,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008739 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07008740 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308741 unsigned long rc;
8742
Jeff Johnson295189b2012-06-20 16:38:30 -07008743 //Block on a completion variable. Can't wait forever though.
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308744 rc = wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07008745 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008746 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308747 if (rc <= 0)
8748 hddLog(VOS_TRACE_LEVEL_ERROR,
8749 FL("Session is not opened within timeout period code %ld"), rc);
Jeff Johnson295189b2012-06-20 16:38:30 -07008750 }
8751}
8752error_sme_open:
8753 return status;
8754}
8755
Jeff Johnson295189b2012-06-20 16:38:30 -07008756void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
8757{
8758 hdd_cfg80211_state_t *cfgState;
8759
8760 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
8761
8762 if( NULL != cfgState->buf )
8763 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308764 long rc;
Jeff Johnson295189b2012-06-20 16:38:30 -07008765 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
8766 rc = wait_for_completion_interruptible_timeout(
8767 &pAdapter->tx_action_cnf_event,
8768 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308769 if (rc <= 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07008770 {
Deepthi Gowri91b3e9c2015-08-25 13:14:58 +05308771 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8772 "%s ERROR: HDD Wait for Action Confirmation Failed!! %ld"
8773 , __func__, rc);
8774
8775 // Inform tx status as FAILURE to upper layer and free cfgState->buf
8776 hdd_sendActionCnf( pAdapter, FALSE );
Jeff Johnson295189b2012-06-20 16:38:30 -07008777 }
8778 }
8779 return;
8780}
Jeff Johnson295189b2012-06-20 16:38:30 -07008781
c_hpothu002231a2015-02-05 14:58:51 +05308782void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
Jeff Johnson295189b2012-06-20 16:38:30 -07008783{
8784 ENTER();
8785 switch ( pAdapter->device_mode )
8786 {
Katya Nigam1fd24402015-02-16 14:52:19 +05308787 case WLAN_HDD_IBSS:
8788 {
8789 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
8790 {
8791 hdd_ibss_deinit_tx_rx( pAdapter );
8792 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
8793 }
8794 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008795 case WLAN_HDD_INFRA_STATION:
8796 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07008797 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07008798 {
8799 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
8800 {
8801 hdd_deinit_tx_rx( pAdapter );
8802 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
8803 }
8804
8805 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
8806 {
8807 hdd_wmm_adapter_close( pAdapter );
8808 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
8809 }
8810
Jeff Johnson295189b2012-06-20 16:38:30 -07008811 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07008812 break;
8813 }
8814
8815 case WLAN_HDD_SOFTAP:
8816 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07008817 {
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05308818
8819 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
8820 {
8821 hdd_wmm_adapter_close( pAdapter );
8822 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
8823 }
8824
Jeff Johnson295189b2012-06-20 16:38:30 -07008825 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07008826
c_hpothu002231a2015-02-05 14:58:51 +05308827 hdd_unregister_hostapd(pAdapter, rtnl_held);
Agrawal Ashisha0584d42016-09-29 13:03:45 +05308828 /* set con_mode to STA only when no SAP concurrency mode */
8829 if (!(hdd_get_concurrency_mode() & (VOS_SAP | VOS_P2P_GO)))
8830 hdd_set_conparam(0);
Jeff Johnson295189b2012-06-20 16:38:30 -07008831 break;
8832 }
8833
8834 case WLAN_HDD_MONITOR:
8835 {
Jeff Johnson295189b2012-06-20 16:38:30 -07008836 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
8837 {
8838 hdd_deinit_tx_rx( pAdapter );
8839 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
8840 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008841 break;
8842 }
8843
8844
8845 default:
8846 break;
8847 }
8848
8849 EXIT();
8850}
8851
8852void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
8853{
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -08008854 struct net_device *pWlanDev = NULL;
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05308855
8856 ENTER();
8857 if (NULL == pAdapter)
8858 {
8859 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8860 "%s: HDD adapter is Null", __func__);
8861 return;
8862 }
8863
8864 pWlanDev = pAdapter->dev;
Jeff Johnson295189b2012-06-20 16:38:30 -07008865
Rajeev79dbe4c2013-10-05 11:03:42 +05308866#ifdef FEATURE_WLAN_BATCH_SCAN
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05308867 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
8868 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Rajeev Kumarf999e582014-01-09 17:33:29 -08008869 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05308870 || (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)
8871 )
8872 {
Rajeev Kumarf999e582014-01-09 17:33:29 -08008873 if (pAdapter)
Rajeev79dbe4c2013-10-05 11:03:42 +05308874 {
Rajeev Kumarf999e582014-01-09 17:33:29 -08008875 if (eHDD_BATCH_SCAN_STATE_STARTED == pAdapter->batchScanState)
8876 {
8877 hdd_deinit_batch_scan(pAdapter);
8878 }
Rajeev79dbe4c2013-10-05 11:03:42 +05308879 }
Rajeev Kumarf999e582014-01-09 17:33:29 -08008880 }
Rajeev79dbe4c2013-10-05 11:03:42 +05308881#endif
8882
Jeff Johnson295189b2012-06-20 16:38:30 -07008883 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
8884 if( rtnl_held )
8885 {
8886 unregister_netdevice(pWlanDev);
8887 }
8888 else
8889 {
8890 unregister_netdev(pWlanDev);
8891 }
8892 // note that the pAdapter is no longer valid at this point
8893 // since the memory has been reclaimed
8894 }
8895
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05308896 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07008897}
8898
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008899void hdd_set_pwrparams(hdd_context_t *pHddCtx)
8900{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308901 VOS_STATUS status;
8902 hdd_adapter_t *pAdapter = NULL;
8903 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008904
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308905 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008906
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308907 /*loop through all adapters.*/
8908 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008909 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308910 pAdapter = pAdapterNode->pAdapter;
8911 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
8912 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008913
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308914 { // we skip this registration for modes other than STA and P2P client modes.
8915 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
8916 pAdapterNode = pNext;
8917 continue;
8918 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008919
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308920 //Apply Dynamic DTIM For P2P
8921 //Only if ignoreDynamicDtimInP2pMode is not set in ini
8922 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
8923 pHddCtx->cfg_ini->enableModulatedDTIM) &&
8924 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
8925 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
8926 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
8927 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
8928 (eConnectionState_Associated ==
8929 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
8930 (pHddCtx->cfg_ini->fIsBmpsEnabled))
8931 {
8932 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008933
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308934 powerRequest.uIgnoreDTIM = 1;
8935 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
8936
8937 if (pHddCtx->cfg_ini->enableModulatedDTIM)
8938 {
8939 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
8940 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
8941 }
8942 else
8943 {
8944 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
8945 }
8946
8947 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
8948 * specified during Enter/Exit BMPS when LCD off*/
8949 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
8950 NULL, eANI_BOOLEAN_FALSE);
8951 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
8952 NULL, eANI_BOOLEAN_FALSE);
8953
8954 /* switch to the DTIM specified in cfg.ini */
8955 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Abhishek Singh1e390cf2015-10-27 13:45:17 +05308956 "Switch to DTIM %d Listen interval %d",
8957 powerRequest.uDTIMPeriod,
8958 powerRequest.uListenInterval);
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308959 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
8960 break;
8961
8962 }
8963
8964 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
8965 pAdapterNode = pNext;
8966 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008967}
8968
8969void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
8970{
8971 /*Switch back to DTIM 1*/
8972 tSirSetPowerParamsReq powerRequest = { 0 };
8973
8974 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
8975 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07008976 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008977
8978 /* Update ignoreDTIM and ListedInterval in CFG with default values */
8979 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
8980 NULL, eANI_BOOLEAN_FALSE);
8981 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
8982 NULL, eANI_BOOLEAN_FALSE);
8983
8984 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8985 "Switch to DTIM%d",powerRequest.uListenInterval);
8986 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
8987
8988}
8989
Jeff Johnson295189b2012-06-20 16:38:30 -07008990VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
8991{
8992 VOS_STATUS status = VOS_STATUS_SUCCESS;
Sushant Kaushik4928e542014-12-29 15:25:54 +05308993 if (WLAN_HDD_IS_UNLOAD_IN_PROGRESS(pHddCtx))
8994 {
8995 hddLog( LOGE, FL("Wlan Unload in progress"));
8996 return VOS_STATUS_E_PERM;
8997 }
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05308998
8999 if (wlan_hdd_check_monitor_state(pHddCtx)) {
9000 hddLog(LOG1, FL("Monitor mode is started, cannot enable BMPS"));
9001 return VOS_STATUS_SUCCESS;
9002 }
9003
Jeff Johnson295189b2012-06-20 16:38:30 -07009004 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
9005 {
9006 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
9007 }
9008
9009 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
9010 {
9011 sme_StartAutoBmpsTimer(pHddCtx->hHal);
9012 }
9013
9014 if (pHddCtx->cfg_ini->fIsImpsEnabled)
9015 {
9016 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
9017 }
9018
9019 return status;
9020}
9021
9022VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
9023{
9024 hdd_adapter_t *pAdapter = NULL;
9025 eHalStatus halStatus;
9026 VOS_STATUS status = VOS_STATUS_E_INVAL;
9027 v_BOOL_t disableBmps = FALSE;
9028 v_BOOL_t disableImps = FALSE;
9029
9030 switch(session_type)
9031 {
9032 case WLAN_HDD_INFRA_STATION:
9033 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07009034 case WLAN_HDD_P2P_CLIENT:
9035 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07009036 //Exit BMPS -> Is Sta/P2P Client is already connected
9037 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
9038 if((NULL != pAdapter)&&
9039 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
9040 {
9041 disableBmps = TRUE;
9042 }
9043
9044 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
9045 if((NULL != pAdapter)&&
9046 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
9047 {
9048 disableBmps = TRUE;
9049 }
9050
9051 //Exit both Bmps and Imps incase of Go/SAP Mode
9052 if((WLAN_HDD_SOFTAP == session_type) ||
9053 (WLAN_HDD_P2P_GO == session_type))
9054 {
9055 disableBmps = TRUE;
9056 disableImps = TRUE;
9057 }
9058
9059 if(TRUE == disableImps)
9060 {
9061 if (pHddCtx->cfg_ini->fIsImpsEnabled)
9062 {
9063 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
9064 }
9065 }
9066
9067 if(TRUE == disableBmps)
9068 {
9069 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
9070 {
9071 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
9072
9073 if(eHAL_STATUS_SUCCESS != halStatus)
9074 {
9075 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08009076 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009077 VOS_ASSERT(0);
9078 return status;
9079 }
9080 }
9081
9082 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
9083 {
9084 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
9085
9086 if(eHAL_STATUS_SUCCESS != halStatus)
9087 {
9088 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08009089 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009090 VOS_ASSERT(0);
9091 return status;
9092 }
9093 }
9094 }
9095
9096 if((TRUE == disableBmps) ||
9097 (TRUE == disableImps))
9098 {
9099 /* Now, get the chip into Full Power now */
9100 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
9101 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
9102 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
9103
9104 if(halStatus != eHAL_STATUS_SUCCESS)
9105 {
9106 if(halStatus == eHAL_STATUS_PMC_PENDING)
9107 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309108 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07009109 //Block on a completion variable. Can't wait forever though
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309110 ret = wait_for_completion_interruptible_timeout(
9111 &pHddCtx->full_pwr_comp_var,
9112 msecs_to_jiffies(1000));
9113 if (ret <= 0)
9114 {
9115 hddLog(VOS_TRACE_LEVEL_ERROR,
9116 "%s: wait on full_pwr_comp_var failed %ld",
9117 __func__, ret);
9118 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009119 }
9120 else
9121 {
9122 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08009123 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009124 VOS_ASSERT(0);
9125 return status;
9126 }
9127 }
9128
9129 status = VOS_STATUS_SUCCESS;
9130 }
9131
9132 break;
9133 }
9134 return status;
9135}
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +05309136
9137void hdd_monPostMsgCb(tANI_U32 *magic, struct completion *cmpVar)
9138{
9139 if (magic == NULL || cmpVar == NULL) {
9140 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnsonc135a9a2017-09-19 08:37:24 -07009141 FL("invalid arguments %pK %pK"), magic, cmpVar);
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +05309142 return;
9143 }
9144 if (*magic != MON_MODE_MSG_MAGIC) {
9145 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9146 FL("maic: %x"), *magic);
9147 return;
9148 }
9149
9150 complete(cmpVar);
9151 return;
9152}
9153
Katya Nigame7b69a82015-04-28 15:24:06 +05309154void hdd_init_mon_mode (hdd_adapter_t *pAdapter)
9155 {
9156 hdd_mon_ctx_t *pMonCtx = NULL;
9157 pMonCtx = WLAN_HDD_GET_MONITOR_CTX_PTR(pAdapter);
9158
9159 pMonCtx->state = 0;
9160 pMonCtx->ChannelNo = 1;
9161 pMonCtx->ChannelBW = 20;
Katya Nigamd7d3a1f2015-06-11 14:04:24 +05309162 pMonCtx->crcCheckEnabled = 1;
9163 pMonCtx->typeSubtypeBitmap = 0xFFFF00000000;
9164 pMonCtx->is80211to803ConReq = 1;
Katya Nigame7b69a82015-04-28 15:24:06 +05309165 pMonCtx->numOfMacFilters = 0;
9166 }
9167
Jeff Johnson295189b2012-06-20 16:38:30 -07009168
9169hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08009170 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07009171 tANI_U8 rtnl_held )
9172{
9173 hdd_adapter_t *pAdapter = NULL;
9174 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
9175 VOS_STATUS status = VOS_STATUS_E_FAILURE;
9176 VOS_STATUS exitbmpsStatus;
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05309177 v_CONTEXT_t pVosContext = NULL;
9178
9179 /* No need to check for NULL, reaching this step
9180 * means vos context is initialized
9181 */
9182 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07009183
Arif Hussain6d2a3322013-11-17 19:50:10 -08009184 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d",__func__,iface_name,session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07009185
Nirav Shah436658f2014-02-28 17:05:45 +05309186 if(macAddr == NULL)
9187 {
9188 /* Not received valid macAddr */
9189 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9190 "%s:Unable to add virtual intf: Not able to get"
9191 "valid mac address",__func__);
9192 return NULL;
9193 }
9194
Jeff Johnson295189b2012-06-20 16:38:30 -07009195 //Disable BMPS incase of Concurrency
9196 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
9197
9198 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
9199 {
9200 //Fail to Exit BMPS
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309201 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Exit BMPS", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009202 VOS_ASSERT(0);
9203 return NULL;
9204 }
9205
9206 switch(session_type)
9207 {
9208 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07009209 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07009210 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07009211 {
9212 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
9213
9214 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309215 {
9216 hddLog(VOS_TRACE_LEVEL_FATAL,
9217 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07009218 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309219 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009220
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05309221#ifdef FEATURE_WLAN_TDLS
9222 /* A Mutex Lock is introduced while changing/initializing the mode to
9223 * protect the concurrent access for the Adapters by TDLS module.
9224 */
Rajesh Chauhana34c6e62014-03-25 16:37:58 +05309225 mutex_lock(&pHddCtx->tdls_lock);
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05309226#endif
9227
Jeff Johnsone7245742012-09-05 17:12:55 -07009228 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
9229 NL80211_IFTYPE_P2P_CLIENT:
9230 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07009231
Jeff Johnson295189b2012-06-20 16:38:30 -07009232 pAdapter->device_mode = session_type;
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05309233#ifdef FEATURE_WLAN_TDLS
9234 mutex_unlock(&pHddCtx->tdls_lock);
9235#endif
Sunil Dutt66485cb2013-12-19 19:05:03 +05309236
Mahesh A Saptasagar67ab9222015-10-21 15:38:41 +05309237 hdd_initialize_adapter_common(pAdapter);
Sunil Dutt66485cb2013-12-19 19:05:03 +05309238 status = hdd_init_station_mode( pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07009239 if( VOS_STATUS_SUCCESS != status )
9240 goto err_free_netdev;
9241
9242 status = hdd_register_interface( pAdapter, rtnl_held );
9243 if( VOS_STATUS_SUCCESS != status )
9244 {
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05309245#ifdef FEATURE_WLAN_TDLS
9246 mutex_lock(&pHddCtx->tdls_lock);
9247#endif
c_hpothu002231a2015-02-05 14:58:51 +05309248 hdd_deinit_adapter(pHddCtx, pAdapter, rtnl_held);
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05309249#ifdef FEATURE_WLAN_TDLS
9250 mutex_unlock(&pHddCtx->tdls_lock);
9251#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009252 goto err_free_netdev;
9253 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05309254
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05309255 // Workqueue which gets scheduled in IPv4 notification callback.
Anand N Sunkaddc63c792015-06-03 14:33:24 +05309256 vos_init_work(&pAdapter->ipv4NotifierWorkQueue, hdd_ipv4_notifier_work_queue);
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05309257
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05309258#ifdef WLAN_NS_OFFLOAD
9259 // Workqueue which gets scheduled in IPv6 notification callback.
Anand N Sunkaddc63c792015-06-03 14:33:24 +05309260 vos_init_work(&pAdapter->ipv6NotifierWorkQueue, hdd_ipv6_notifier_work_queue);
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05309261#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009262 //Stop the Interface TX queue.
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05309263 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
Jeff Johnson295189b2012-06-20 16:38:30 -07009264 netif_tx_disable(pAdapter->dev);
9265 //netif_tx_disable(pWlanDev);
9266 netif_carrier_off(pAdapter->dev);
9267
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +05309268 if (WLAN_HDD_P2P_CLIENT == session_type ||
9269 WLAN_HDD_P2P_DEVICE == session_type)
9270 {
9271 /* Initialize the work queue to defer the
9272 * back to back RoC request */
Anand N Sunkaddc63c792015-06-03 14:33:24 +05309273 vos_init_delayed_work(&pAdapter->roc_work,
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +05309274 hdd_p2p_roc_work_queue);
9275 }
9276
Jeff Johnson295189b2012-06-20 16:38:30 -07009277 break;
9278 }
9279
Jeff Johnson295189b2012-06-20 16:38:30 -07009280 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07009281 case WLAN_HDD_SOFTAP:
9282 {
9283 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
9284 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309285 {
9286 hddLog(VOS_TRACE_LEVEL_FATAL,
9287 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07009288 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309289 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009290
Jeff Johnson295189b2012-06-20 16:38:30 -07009291 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
9292 NL80211_IFTYPE_AP:
9293 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07009294 pAdapter->device_mode = session_type;
9295
Mahesh A Saptasagar67ab9222015-10-21 15:38:41 +05309296 hdd_initialize_adapter_common(pAdapter);
Hanumanth Reddy Pothula15bc0fa2017-02-03 17:24:17 +05309297 status = hdd_init_ap_mode(pAdapter, false);
Jeff Johnson295189b2012-06-20 16:38:30 -07009298 if( VOS_STATUS_SUCCESS != status )
9299 goto err_free_netdev;
9300
Nirav Shah7e3c8132015-06-22 23:51:42 +05309301 status = hdd_sta_id_hash_attach(pAdapter);
9302 if (VOS_STATUS_SUCCESS != status)
9303 {
9304 hddLog(VOS_TRACE_LEVEL_FATAL,
9305 FL("failed to attach hash for session %d"), session_type);
9306 hdd_deinit_adapter(pHddCtx, pAdapter, rtnl_held);
9307 goto err_free_netdev;
9308 }
9309
Jeff Johnson295189b2012-06-20 16:38:30 -07009310 status = hdd_register_hostapd( pAdapter, rtnl_held );
9311 if( VOS_STATUS_SUCCESS != status )
9312 {
c_hpothu002231a2015-02-05 14:58:51 +05309313 hdd_deinit_adapter(pHddCtx, pAdapter, rtnl_held);
Jeff Johnson295189b2012-06-20 16:38:30 -07009314 goto err_free_netdev;
9315 }
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05309316 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
Jeff Johnson295189b2012-06-20 16:38:30 -07009317 netif_tx_disable(pAdapter->dev);
9318 netif_carrier_off(pAdapter->dev);
9319
9320 hdd_set_conparam( 1 );
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +05309321
Hanumanth Reddy Pothulab4537b82018-03-02 12:20:38 +05309322 // Workqueue which gets scheduled in IPv4 notification callback.
9323 vos_init_work(&pAdapter->ipv4NotifierWorkQueue,
9324 hdd_ipv4_notifier_work_queue);
9325
9326#ifdef WLAN_NS_OFFLOAD
9327 // Workqueue which gets scheduled in IPv6 notification callback.
9328 vos_init_work(&pAdapter->ipv6NotifierWorkQueue,
9329 hdd_ipv6_notifier_work_queue);
9330#endif
9331
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +05309332 if (WLAN_HDD_P2P_GO == session_type)
9333 {
9334 /* Initialize the work queue to
9335 * defer the back to back RoC request */
9336 INIT_DELAYED_WORK(&pAdapter->roc_work,
9337 hdd_p2p_roc_work_queue);
9338 }
Bhargav Shahd0715912015-10-01 18:17:37 +05309339
Jeff Johnson295189b2012-06-20 16:38:30 -07009340 break;
9341 }
9342 case WLAN_HDD_MONITOR:
9343 {
Jeff Johnson295189b2012-06-20 16:38:30 -07009344 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
9345 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309346 {
9347 hddLog(VOS_TRACE_LEVEL_FATAL,
9348 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07009349 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309350 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009351
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05309352 pAdapter->device_mode = session_type;
9353 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
9354
Katya Nigame7b69a82015-04-28 15:24:06 +05309355 // Register wireless extensions
9356 if( VOS_STATUS_SUCCESS != (status = hdd_register_wext(pAdapter->dev)))
9357 {
9358 hddLog(VOS_TRACE_LEVEL_FATAL,
9359 "hdd_register_wext() failed with status code %08d [x%08x]",
9360 status, status );
9361 status = VOS_STATUS_E_FAILURE;
9362 }
9363
Jeff Johnson295189b2012-06-20 16:38:30 -07009364#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
9365 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
9366#else
9367 pAdapter->dev->open = hdd_mon_open;
9368 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
Katya Nigame7b69a82015-04-28 15:24:06 +05309369 pAdapter->dev->stop = hdd_mon_stop;
9370 pAdapter->dev->do_ioctl = hdd_mon_ioctl;
Jeff Johnson295189b2012-06-20 16:38:30 -07009371#endif
Katya Nigame7b69a82015-04-28 15:24:06 +05309372 hdd_init_mon_mode( pAdapter );
Mahesh A Saptasagar67ab9222015-10-21 15:38:41 +05309373 hdd_initialize_adapter_common(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07009374 hdd_init_tx_rx( pAdapter );
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05309375
9376 if (VOS_MONITOR_MODE != hdd_get_conparam())
9377 WLANTL_SetMonRxCbk( pVosContext, hdd_rx_packet_monitor_cbk );
9378
Jeff Johnson295189b2012-06-20 16:38:30 -07009379 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05309380 status = hdd_register_interface( pAdapter, rtnl_held );
Katya Nigame7b69a82015-04-28 15:24:06 +05309381 //Stop the Interface TX queue.
9382 netif_tx_disable(pAdapter->dev);
9383 netif_carrier_off(pAdapter->dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07009384 }
9385 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07009386 case WLAN_HDD_FTM:
9387 {
9388 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
9389
9390 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309391 {
9392 hddLog(VOS_TRACE_LEVEL_FATAL,
9393 FL("failed to allocate adapter for session %d"), session_type);
9394 return NULL;
9395 }
9396
Jeff Johnson295189b2012-06-20 16:38:30 -07009397 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
9398 * message while loading driver in FTM mode. */
9399 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
9400 pAdapter->device_mode = session_type;
9401 status = hdd_register_interface( pAdapter, rtnl_held );
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05309402
Mahesh A Saptasagar67ab9222015-10-21 15:38:41 +05309403 hdd_initialize_adapter_common(pAdapter);
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05309404 hdd_init_tx_rx( pAdapter );
9405
9406 //Stop the Interface TX queue.
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05309407 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05309408 netif_tx_disable(pAdapter->dev);
9409 netif_carrier_off(pAdapter->dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07009410 }
9411 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07009412 default:
9413 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309414 hddLog(VOS_TRACE_LEVEL_FATAL,"%s Invalid session type %d",
9415 __func__, session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07009416 VOS_ASSERT(0);
9417 return NULL;
9418 }
9419 }
9420
Jeff Johnson295189b2012-06-20 16:38:30 -07009421 if( VOS_STATUS_SUCCESS == status )
9422 {
Mahesh A Saptasagar67ab9222015-10-21 15:38:41 +05309423 //Add it to the hdd's session list.
Jeff Johnson295189b2012-06-20 16:38:30 -07009424 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
9425 if( NULL == pHddAdapterNode )
9426 {
9427 status = VOS_STATUS_E_NOMEM;
9428 }
9429 else
9430 {
9431 pHddAdapterNode->pAdapter = pAdapter;
9432 status = hdd_add_adapter_back ( pHddCtx,
9433 pHddAdapterNode );
9434 }
9435 }
9436
9437 if( VOS_STATUS_SUCCESS != status )
9438 {
9439 if( NULL != pAdapter )
9440 {
9441 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
9442 pAdapter = NULL;
9443 }
9444 if( NULL != pHddAdapterNode )
9445 {
9446 vos_mem_free( pHddAdapterNode );
9447 }
9448
9449 goto resume_bmps;
9450 }
9451
9452 if(VOS_STATUS_SUCCESS == status)
9453 {
9454 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07009455 //Initialize the WoWL service
9456 if(!hdd_init_wowl(pAdapter))
9457 {
9458 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
9459 goto err_free_netdev;
9460 }
Manjeet Singh3ed79242017-01-11 19:04:32 +05309461 //Initialize the TSF capture data
9462 wlan_hdd_tsf_init(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07009463 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009464 return pAdapter;
9465
9466err_free_netdev:
9467 free_netdev(pAdapter->dev);
9468 wlan_hdd_release_intf_addr( pHddCtx,
9469 pAdapter->macAddressCurrent.bytes );
9470
9471resume_bmps:
9472 //If bmps disabled enable it
9473 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
9474 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05309475 if (pHddCtx->hdd_wlan_suspended)
9476 {
9477 hdd_set_pwrparams(pHddCtx);
9478 }
9479 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07009480 }
9481 return NULL;
9482}
9483
9484VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
9485 tANI_U8 rtnl_held )
9486{
9487 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
9488 VOS_STATUS status;
9489
9490 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
9491 if( VOS_STATUS_SUCCESS != status )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309492 {
9493 hddLog(VOS_TRACE_LEVEL_WARN,"%s: adapter list empty %d",
9494 __func__, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07009495 return status;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309496 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009497
9498 while ( pCurrent->pAdapter != pAdapter )
9499 {
9500 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
9501 if( VOS_STATUS_SUCCESS != status )
9502 break;
9503
9504 pCurrent = pNext;
9505 }
9506 pAdapterNode = pCurrent;
9507 if( VOS_STATUS_SUCCESS == status )
9508 {
9509 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
9510 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05309511
9512#ifdef FEATURE_WLAN_TDLS
9513
9514 /* A Mutex Lock is introduced while changing/initializing the mode to
9515 * protect the concurrent access for the Adapters by TDLS module.
9516 */
Rajesh Chauhana34c6e62014-03-25 16:37:58 +05309517 mutex_lock(&pHddCtx->tdls_lock);
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05309518#endif
9519
Jeff Johnson295189b2012-06-20 16:38:30 -07009520 hdd_remove_adapter( pHddCtx, pAdapterNode );
9521 vos_mem_free( pAdapterNode );
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08009522 pAdapterNode = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07009523
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05309524#ifdef FEATURE_WLAN_TDLS
9525 mutex_unlock(&pHddCtx->tdls_lock);
9526#endif
9527
Jeff Johnson295189b2012-06-20 16:38:30 -07009528
9529 /* If there is a single session of STA/P2P client, re-enable BMPS */
Agarwal Ashish51325b52014-06-16 16:50:49 +05309530 if ((!vos_concurrent_open_sessions_running()) &&
9531 ((pHddCtx->no_of_open_sessions[VOS_STA_MODE] >= 1) ||
9532 (pHddCtx->no_of_open_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
Jeff Johnson295189b2012-06-20 16:38:30 -07009533 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05309534 if (pHddCtx->hdd_wlan_suspended)
9535 {
9536 hdd_set_pwrparams(pHddCtx);
9537 }
9538 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07009539 }
9540
9541 return VOS_STATUS_SUCCESS;
9542 }
9543
9544 return VOS_STATUS_E_FAILURE;
9545}
9546
9547VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
9548{
9549 hdd_adapter_list_node_t *pHddAdapterNode;
9550 VOS_STATUS status;
9551
9552 ENTER();
9553
9554 do
9555 {
9556 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
9557 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
9558 {
9559 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
9560 vos_mem_free( pHddAdapterNode );
9561 }
9562 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
9563
9564 EXIT();
9565
9566 return VOS_STATUS_SUCCESS;
9567}
9568
9569void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
9570{
9571 v_U8_t addIE[1] = {0};
9572
9573 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
9574 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
9575 eANI_BOOLEAN_FALSE) )
9576 {
9577 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08009578 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07009579 }
9580
9581 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
9582 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
9583 eANI_BOOLEAN_FALSE) )
9584 {
9585 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08009586 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07009587 }
9588
9589 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
9590 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
9591 eANI_BOOLEAN_FALSE) )
9592 {
9593 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08009594 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07009595 }
9596}
9597
Anurag Chouhan83026002016-12-13 22:46:21 +05309598VOS_STATUS hdd_cleanup_ap_events(hdd_adapter_t *adapter)
9599{
9600#ifdef DHCP_SERVER_OFFLOAD
9601 vos_event_destroy(&adapter->dhcp_status.vos_event);
9602#endif
Anurag Chouhan0b29de02016-12-16 13:18:40 +05309603#ifdef MDNS_OFFLOAD
9604 vos_event_destroy(&adapter->mdns_status.vos_event);
9605#endif
Anurag Chouhan83026002016-12-13 22:46:21 +05309606 return VOS_STATUS_SUCCESS;
9607}
9608
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05309609int wlan_hdd_stop_mon(hdd_context_t *hdd_ctx, bool wait)
9610{
9611 hdd_mon_ctx_t *mon_ctx;
9612 long ret;
9613 v_U32_t magic;
9614 struct completion cmp_var;
9615 void (*func_ptr)(tANI_U32 *magic, struct completion *cmpVar) = NULL;
9616 hdd_adapter_t *adapter;
9617
9618 adapter = hdd_get_adapter(hdd_ctx, WLAN_HDD_MONITOR);
9619 if (!adapter) {
9620 hddLog(LOGE, FL("Invalid STA + MON mode"));
9621 return -EINVAL;
9622 }
9623
9624 mon_ctx = WLAN_HDD_GET_MONITOR_CTX_PTR(adapter);
9625 if (!mon_ctx)
9626 return 0;
9627
9628 if (mon_ctx->state != MON_MODE_START)
9629 return 0;
9630
9631 mon_ctx->state = MON_MODE_STOP;
9632 if (wait) {
9633 func_ptr = hdd_monPostMsgCb;
9634 magic = MON_MODE_MSG_MAGIC;
9635 init_completion(&cmp_var);
9636 }
9637
9638 if (VOS_STATUS_SUCCESS != wlan_hdd_mon_postMsg(&magic, &cmp_var,
9639 mon_ctx,
9640 hdd_monPostMsgCb)) {
9641 hddLog(LOGE, FL("failed to stop MON MODE"));
9642 mon_ctx->state = MON_MODE_START;
9643 magic = 0;
9644 return -EINVAL;
9645 }
9646
9647 if (!wait)
9648 goto bmps_roaming;
9649
9650 ret = wait_for_completion_timeout(&cmp_var, MON_MODE_MSG_TIMEOUT);
9651 magic = 0;
9652 if (ret <= 0 ) {
9653 hddLog(LOGE,
9654 FL("timeout on stop monitor mode completion %ld"), ret);
9655 return -EINVAL;
9656 }
9657
9658bmps_roaming:
9659 hddLog(LOG1, FL("Enable BMPS"));
9660 hdd_enable_bmps_imps(hdd_ctx);
9661 hdd_restore_roaming(hdd_ctx);
9662
9663 return 0;
9664}
9665
9666bool wlan_hdd_check_monitor_state(hdd_context_t *hdd_ctx)
9667{
9668 hdd_adapter_t *mon_adapter;
9669 hdd_mon_ctx_t *mon_ctx;
9670
9671 if (hdd_ctx->concurrency_mode != VOS_STA_MON)
9672 return false;
9673
9674 mon_adapter = hdd_get_adapter(hdd_ctx, WLAN_HDD_MONITOR);
9675 if (!mon_adapter) {
9676 hddLog(LOGE, FL("Invalid concurrency mode"));
9677 return false;
9678 }
9679
9680 mon_ctx = WLAN_HDD_GET_MONITOR_CTX_PTR(mon_adapter);
9681 if (mon_ctx->state == MON_MODE_START)
9682 return true;
9683
9684 return false;
9685}
9686
9687int wlan_hdd_check_and_stop_mon(hdd_adapter_t *sta_adapter, bool wait)
9688{
9689 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(sta_adapter);
9690
9691 if ((sta_adapter->device_mode != WLAN_HDD_INFRA_STATION) ||
9692 !wlan_hdd_check_monitor_state(hdd_ctx))
9693 return 0;
9694
9695 if (wlan_hdd_stop_mon(hdd_ctx, wait))
9696 return -EINVAL;
9697
9698 return 0;
9699}
9700
9701void hdd_disable_roaming(hdd_context_t *hdd_ctx)
9702{
9703 if (!hdd_ctx)
9704 return;
9705
9706 if (!hdd_ctx->cfg_ini->isFastRoamIniFeatureEnabled) {
9707 hdd_ctx->roaming_ini_original = CFG_LFR_FEATURE_ENABLED_MIN;
9708 return;
9709 }
9710
9711 hddLog(LOG1, FL("Disable driver and firmware roaming"));
9712
9713 hdd_ctx->roaming_ini_original =
9714 hdd_ctx->cfg_ini->isFastRoamIniFeatureEnabled;
9715
9716 hdd_ctx->cfg_ini->isFastRoamIniFeatureEnabled =
9717 CFG_LFR_FEATURE_ENABLED_MIN;
9718
9719 sme_UpdateIsFastRoamIniFeatureEnabled(hdd_ctx->hHal,
9720 CFG_LFR_FEATURE_ENABLED_MIN);
9721}
9722
9723void hdd_restore_roaming(hdd_context_t *hdd_ctx)
9724{
9725 if (!hdd_ctx->roaming_ini_original)
9726 return;
9727
9728 hddLog(LOG1, FL("Enable driver and firmware roaming"));
9729
9730 hdd_ctx->cfg_ini->isFastRoamIniFeatureEnabled =
9731 CFG_LFR_FEATURE_ENABLED_MAX;
9732
9733 hdd_ctx->roaming_ini_original = CFG_LFR_FEATURE_ENABLED_MIN;
9734
9735 sme_UpdateIsFastRoamIniFeatureEnabled(hdd_ctx->hHal,
9736 CFG_LFR_FEATURE_ENABLED_MAX);
9737}
Anurag Chouhan83026002016-12-13 22:46:21 +05309738
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05309739VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
9740 const v_BOOL_t bCloseSession )
Jeff Johnson295189b2012-06-20 16:38:30 -07009741{
9742 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
9743 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
Kaushik, Sushant4975a572014-10-21 16:07:48 +05309744 hdd_scaninfo_t *pScanInfo = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07009745 union iwreq_data wrqu;
Kaushik, Sushant7005e372014-04-08 11:36:54 +05309746 v_U8_t retry = 0;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309747 long ret;
Nirav Shah7e3c8132015-06-22 23:51:42 +05309748 VOS_STATUS status;
Jeff Johnson295189b2012-06-20 16:38:30 -07009749
Anand N Sunkad26d71b92014-12-24 18:08:22 +05309750 if (pHddCtx->isLogpInProgress) {
9751 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
9752 "%s:LOGP in Progress. Ignore!!!",__func__);
9753 return VOS_STATUS_E_FAILURE;
9754 }
9755
Jeff Johnson295189b2012-06-20 16:38:30 -07009756 ENTER();
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +05309757
Kaushik, Sushant4975a572014-10-21 16:07:48 +05309758 pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07009759 switch(pAdapter->device_mode)
9760 {
Nirav Shah0cf4d892015-11-05 16:27:27 +05309761 case WLAN_HDD_IBSS:
9762 if ( VOS_TRUE == bCloseSession )
9763 {
9764 status = hdd_sta_id_hash_detach(pAdapter);
9765 if (status != VOS_STATUS_SUCCESS)
9766 hddLog(VOS_TRACE_LEVEL_ERROR,
9767 FL("sta id hash detach failed"));
9768 }
9769
Jeff Johnson295189b2012-06-20 16:38:30 -07009770 case WLAN_HDD_INFRA_STATION:
9771 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07009772 case WLAN_HDD_P2P_DEVICE:
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05309773 {
9774 hdd_station_ctx_t *pstation = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Mahesh A Saptasagare4d05d42015-07-02 16:17:20 +05309775#ifdef FEATURE_WLAN_TDLS
9776 mutex_lock(&pHddCtx->tdls_lock);
9777 wlan_hdd_tdls_exit(pAdapter, TRUE);
9778 mutex_unlock(&pHddCtx->tdls_lock);
9779#endif
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05309780 if( hdd_connIsConnected(pstation) ||
9781 (pstation->conn_info.connState == eConnectionState_Connecting) )
Jeff Johnson295189b2012-06-20 16:38:30 -07009782 {
Abhishek Singhe21a5212017-06-09 09:42:58 +05309783 /*
9784 * Indicate sme of disconnect so that in progress connection
9785 * or preauth can be aborted.
9786 */
9787 sme_abortConnection(WLAN_HDD_GET_HAL_CTX(pAdapter),
9788 pAdapter->sessionId);
Abhishek Singh99f17b82017-02-06 16:57:56 +05309789 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07009790 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
9791 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
9792 pAdapter->sessionId,
9793 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
9794 else
9795 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
9796 pAdapter->sessionId,
9797 eCSR_DISCONNECT_REASON_UNSPECIFIED);
Abhishek Singh7b52ed52016-02-11 17:45:54 +05309798 /* Success implies disconnect command got queued up successfully
9799 * Or cmd not queued as scan for SSID is in progress
9800 */
9801 if((eHAL_STATUS_SUCCESS == halStatus) ||
9802 (eHAL_STATUS_CMD_NOT_QUEUED == halStatus))
Jeff Johnson295189b2012-06-20 16:38:30 -07009803 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309804 ret = wait_for_completion_interruptible_timeout(
9805 &pAdapter->disconnect_comp_var,
9806 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Abhishek Singh7b52ed52016-02-11 17:45:54 +05309807 if (ret <= 0 &&
9808 (eHAL_STATUS_CMD_NOT_QUEUED != halStatus))
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309809 {
9810 hddLog(VOS_TRACE_LEVEL_ERROR,
9811 "%s: wait on disconnect_comp_var failed %ld",
9812 __func__, ret);
9813 }
9814 }
9815 else
9816 {
9817 hddLog(LOGE, "%s: failed to post disconnect event to SME",
9818 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009819 }
9820 memset(&wrqu, '\0', sizeof(wrqu));
9821 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
9822 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
9823 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
9824 }
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05309825 else if(pstation->conn_info.connState ==
9826 eConnectionState_Disconnecting)
9827 {
9828 ret = wait_for_completion_interruptible_timeout(
9829 &pAdapter->disconnect_comp_var,
9830 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
9831 if (ret <= 0)
9832 {
9833 hddLog(VOS_TRACE_LEVEL_ERROR,
9834 FL("wait on disconnect_comp_var failed %ld"), ret);
9835 }
9836 }
Sachin Ahuja27dd2402016-08-01 20:30:31 +05309837 if(pScanInfo != NULL && pHddCtx->scan_info.mScanPending)
Jeff Johnson295189b2012-06-20 16:38:30 -07009838 {
Mahesh A Saptasagar0b61dcc2016-02-15 14:23:38 +05309839 wlan_hdd_scan_abort(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07009840 }
Abhishek Singh3ac179b2015-09-21 10:01:34 +05309841 if ((pAdapter->device_mode != WLAN_HDD_INFRA_STATION) &&
9842 (pAdapter->device_mode != WLAN_HDD_IBSS))
Kaushik, Sushant7005e372014-04-08 11:36:54 +05309843 {
9844 while (pAdapter->is_roc_inprogress)
9845 {
9846 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9847 "%s: ROC in progress for session %d!!!",
9848 __func__, pAdapter->sessionId);
9849 // waiting for ROC to expire
9850 msleep(500);
9851 /* In GO present case , if retry exceeds 3,
9852 it means something went wrong. */
9853 if ( retry++ > MAX_WAIT_FOR_ROC_COMPLETION )
9854 {
9855 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9856 "%s: ROC completion is not received.!!!", __func__);
Deepthi Gowri70498252015-01-20 15:56:45 +05309857 if (eHAL_STATUS_SUCCESS !=
9858 sme_CancelRemainOnChannel( WLAN_HDD_GET_HAL_CTX( pAdapter),
9859 pAdapter->sessionId ))
9860 {
9861 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9862 FL("Failed to Cancel Remain on Channel"));
9863 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +05309864 wait_for_completion_interruptible_timeout(
9865 &pAdapter->cancel_rem_on_chan_var,
9866 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
9867 break;
9868 }
9869 }
Anand N Sunkaddc63c792015-06-03 14:33:24 +05309870 vos_flush_delayed_work(&pAdapter->roc_work);
Kaushik, Sushant7005e372014-04-08 11:36:54 +05309871 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05309872#ifdef WLAN_NS_OFFLOAD
Anand N Sunkaddc63c792015-06-03 14:33:24 +05309873 vos_flush_work(&pAdapter->ipv6NotifierWorkQueue);
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05309874#endif
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +05309875
Anand N Sunkaddc63c792015-06-03 14:33:24 +05309876 vos_flush_work(&pAdapter->ipv4NotifierWorkQueue);
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +05309877
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05309878 /* It is possible that the caller of this function does not
9879 * wish to close the session
9880 */
9881 if (VOS_TRUE == bCloseSession &&
9882 test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07009883 {
9884 INIT_COMPLETION(pAdapter->session_close_comp_var);
9885 if (eHAL_STATUS_SUCCESS ==
Agrawal Ashish5a3522c2016-03-02 15:08:28 +05309886 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId, FALSE,
9887 VOS_FALSE, hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07009888 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309889 unsigned long ret;
9890
Jeff Johnson295189b2012-06-20 16:38:30 -07009891 //Block on a completion variable. Can't wait forever though.
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309892 ret = wait_for_completion_timeout(
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05309893 &pAdapter->session_close_comp_var,
9894 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309895 if ( 0 >= ret)
9896 {
9897 hddLog(LOGE, "%s: failure waiting for session_close_comp_var %ld",
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05309898 __func__, ret);
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309899 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009900 }
9901 }
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05309902 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009903 break;
9904
9905 case WLAN_HDD_SOFTAP:
9906 case WLAN_HDD_P2P_GO:
Nirav Shah0cf4d892015-11-05 16:27:27 +05309907 if ( VOS_TRUE == bCloseSession )
9908 {
9909 status = hdd_sta_id_hash_detach(pAdapter);
9910 if (status != VOS_STATUS_SUCCESS)
9911 hddLog(VOS_TRACE_LEVEL_ERROR,
9912 FL("sta id hash detach failed"));
9913 }
9914
Jeff Johnson295189b2012-06-20 16:38:30 -07009915 //Any softap specific cleanup here...
Anurag Chouhan83026002016-12-13 22:46:21 +05309916 hdd_cleanup_ap_events(pAdapter);
Kaushik, Sushant7005e372014-04-08 11:36:54 +05309917 if (pAdapter->device_mode == WLAN_HDD_P2P_GO) {
9918 while (pAdapter->is_roc_inprogress) {
9919 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9920 "%s: ROC in progress for session %d!!!",
9921 __func__, pAdapter->sessionId);
9922 msleep(500);
9923 if ( retry++ > MAX_WAIT_FOR_ROC_COMPLETION ) {
9924 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9925 "%s: ROC completion is not received.!!!", __func__);
9926 WLANSAP_CancelRemainOnChannel(
9927 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
9928 wait_for_completion_interruptible_timeout(
9929 &pAdapter->cancel_rem_on_chan_var,
9930 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
9931 break;
9932 }
9933 }
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +05309934
Anand N Sunkaddc63c792015-06-03 14:33:24 +05309935 vos_flush_delayed_work(&pAdapter->roc_work);
Kaushik, Sushant7005e372014-04-08 11:36:54 +05309936 }
Agrawal Ashish17ef5082016-10-17 18:33:21 +05309937#ifdef SAP_AUTH_OFFLOAD
9938 if (pHddCtx->cfg_ini->enable_sap_auth_offload)
9939 hdd_set_sap_auth_offload(pAdapter, FALSE);
9940#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009941 mutex_lock(&pHddCtx->sap_lock);
9942 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
9943 {
9944 VOS_STATUS status;
9945 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9946
9947 //Stop Bss.
9948 status = WLANSAP_StopBss(pHddCtx->pvosContext);
9949 if (VOS_IS_STATUS_SUCCESS(status))
9950 {
9951 hdd_hostapd_state_t *pHostapdState =
9952 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
9953
9954 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
9955
9956 if (!VOS_IS_STATUS_SUCCESS(status))
9957 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309958 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss %d",
9959 __func__, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07009960 }
9961 }
9962 else
9963 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07009964 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009965 }
9966 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
Agarwal Ashish51325b52014-06-16 16:50:49 +05309967 wlan_hdd_decr_active_session(pHddCtx, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07009968
9969 if (eHAL_STATUS_FAILURE ==
9970 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
9971 0, NULL, eANI_BOOLEAN_FALSE))
9972 {
9973 hddLog(LOGE,
9974 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07009975 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009976 }
9977
9978 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
9979 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
9980 eANI_BOOLEAN_FALSE) )
9981 {
9982 hddLog(LOGE,
9983 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
9984 }
9985
9986 // Reset WNI_CFG_PROBE_RSP Flags
9987 wlan_hdd_reset_prob_rspies(pAdapter);
9988 kfree(pAdapter->sessionCtx.ap.beacon);
9989 pAdapter->sessionCtx.ap.beacon = NULL;
9990 }
9991 mutex_unlock(&pHddCtx->sap_lock);
Hanumanth Reddy Pothulab4537b82018-03-02 12:20:38 +05309992
9993#ifdef WLAN_NS_OFFLOAD
9994 vos_flush_work(&pAdapter->ipv6NotifierWorkQueue);
9995#endif
9996 vos_flush_work(&pAdapter->ipv4NotifierWorkQueue);
9997
Jeff Johnson295189b2012-06-20 16:38:30 -07009998 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07009999
Jeff Johnson295189b2012-06-20 16:38:30 -070010000 case WLAN_HDD_MONITOR:
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +053010001 if (VOS_MONITOR_MODE != hdd_get_conparam())
10002 wlan_hdd_stop_mon(pHddCtx, true);
10003 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -070010004
Jeff Johnson295189b2012-06-20 16:38:30 -070010005 default:
10006 break;
10007 }
10008
10009 EXIT();
10010 return VOS_STATUS_SUCCESS;
10011}
10012
Kapil Gupta137ef892016-12-13 19:38:00 +053010013/**
10014 * wlan_hdd_restart_sap() - to restart SAP in driver internally
10015 * @ap_adapter: - Pointer to SAP hdd_adapter_t structure
10016 *
10017 * wlan_hdd_restart_sap first delete SAP and do cleanup.
10018 * After that WLANSAP_StartBss start re-start process of SAP.
10019 *
10020 * Return: None
10021 */
10022static void wlan_hdd_restart_sap(hdd_adapter_t *ap_adapter)
10023{
10024 hdd_ap_ctx_t *pHddApCtx;
10025 hdd_hostapd_state_t *pHostapdState;
10026 VOS_STATUS vos_status;
10027 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(ap_adapter);
Rajeev Kumar Sirasanagandla5b21a9c2018-01-08 17:05:11 +053010028#ifdef USE_CFG80211_DEL_STA_V2
Kapil Gupta137ef892016-12-13 19:38:00 +053010029 struct station_del_parameters delStaParams;
10030#endif
10031 tsap_Config_t *pConfig;
10032
10033 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
10034 pConfig = &pHddApCtx->sapConfig;
10035
10036 mutex_lock(&pHddCtx->sap_lock);
10037 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags)) {
Rajeev Kumar Sirasanagandla5b21a9c2018-01-08 17:05:11 +053010038#ifdef USE_CFG80211_DEL_STA_V2
Kapil Gupta137ef892016-12-13 19:38:00 +053010039 delStaParams.mac = NULL;
10040 delStaParams.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
10041 delStaParams.reason_code = eCsrForcedDeauthSta;
10042 wlan_hdd_cfg80211_del_station(ap_adapter->wdev.wiphy, ap_adapter->dev,
10043 &delStaParams);
10044#else
10045 wlan_hdd_cfg80211_del_station(ap_adapter->wdev.wiphy, ap_adapter->dev,
10046 NULL);
10047#endif
10048 hdd_cleanup_actionframe(pHddCtx, ap_adapter);
10049
10050 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
10051 vos_event_reset(&pHostapdState->vosEvent);
10052
10053 if (VOS_STATUS_SUCCESS == WLANSAP_StopBss(pHddCtx->pvosContext)) {
10054 vos_status = vos_wait_single_event(&pHostapdState->vosEvent,
10055 10000);
10056 if (!VOS_IS_STATUS_SUCCESS(vos_status)) {
10057 hddLog(LOGE, FL("SAP Stop Failed"));
10058 goto end;
10059 }
10060 }
10061 clear_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
10062 wlan_hdd_decr_active_session(pHddCtx, ap_adapter->device_mode);
10063 hddLog(LOG1, FL("SAP Stop Success"));
10064
10065 if (0 != wlan_hdd_cfg80211_update_apies(ap_adapter)) {
10066 hddLog(LOGE, FL("SAP Not able to set AP IEs"));
10067 goto end;
10068 }
10069
10070 if (WLANSAP_StartBss(pHddCtx->pvosContext, hdd_hostapd_SAPEventCB,
10071 pConfig, (v_PVOID_t)ap_adapter->dev) != VOS_STATUS_SUCCESS) {
10072 hddLog(LOGE, FL("SAP Start Bss fail"));
10073 goto end;
10074 }
10075
10076 hddLog(LOG1, FL("Waiting for SAP to start"));
10077 vos_status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
10078 if (!VOS_IS_STATUS_SUCCESS(vos_status)) {
10079 hddLog(LOGE, FL("SAP Start failed"));
10080 goto end;
10081 }
10082 hddLog(LOG1, FL("SAP Start Success"));
10083 set_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
10084 wlan_hdd_incr_active_session(pHddCtx, ap_adapter->device_mode);
10085 pHostapdState->bCommit = TRUE;
Anurag Chouhanb2951ae2017-03-12 13:41:35 +053010086 if (!VOS_IS_STATUS_SUCCESS(hdd_dhcp_mdns_offload(ap_adapter))) {
10087 hddLog(VOS_TRACE_LEVEL_ERROR, FL("DHCP/MDNS offload Failed!!"));
10088 vos_event_reset(&pHostapdState->vosEvent);
10089 if (VOS_STATUS_SUCCESS == WLANSAP_StopBss(pHddCtx->pvosContext)) {
10090 vos_status = vos_wait_single_event(&pHostapdState->vosEvent,
10091 10000);
10092 if (!VOS_IS_STATUS_SUCCESS(vos_status)) {
10093 hddLog(LOGE, FL("SAP Stop Failed"));
10094 goto end;
10095 }
10096 }
10097 }
Kapil Gupta137ef892016-12-13 19:38:00 +053010098 }
10099end:
10100 mutex_unlock(&pHddCtx->sap_lock);
10101 return;
10102}
10103
10104/**
10105 * __hdd_sap_restart_handle() - to handle restarting of SAP
10106 * @work: name of the work
10107 *
10108 * Purpose of this function is to trigger sap start. this function
10109 * will be called from workqueue.
10110 *
10111 * Return: void.
10112 */
10113static void __hdd_sap_restart_handle(struct work_struct *work)
10114{
10115 hdd_adapter_t *sap_adapter;
10116 hdd_context_t *hdd_ctx = container_of(work,
10117 hdd_context_t,
10118 sap_start_work);
10119 if (0 != wlan_hdd_validate_context(hdd_ctx)) {
10120 vos_ssr_unprotect(__func__);
10121 return;
10122 }
10123 sap_adapter = hdd_get_adapter(hdd_ctx,
10124 WLAN_HDD_SOFTAP);
10125 if (sap_adapter == NULL) {
10126 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
10127 FL("sap_adapter is NULL"));
10128 vos_ssr_unprotect(__func__);
10129 return;
10130 }
10131
10132 if (hdd_ctx->is_ch_avoid_in_progress) {
10133 sap_adapter->sessionCtx.ap.sapConfig.channel = AUTO_CHANNEL_SELECT;
10134 wlan_hdd_restart_sap(sap_adapter);
10135 hdd_change_ch_avoidance_status(hdd_ctx, false);
10136 }
Agrawal Ashish574b3e62017-02-09 18:58:34 +053010137 if (hdd_ctx->cfg_ini->enable_sap_auth_offload)
10138 wlan_hdd_restart_sap(sap_adapter);
Kapil Gupta137ef892016-12-13 19:38:00 +053010139}
10140
10141/**
10142 * hdd_sap_restart_handle() - to handle restarting of SAP
10143 * @work: name of the work
10144 *
10145 * Purpose of this function is to trigger sap start. this function
10146 * will be called from workqueue.
10147 *
10148 * Return: void.
10149 */
10150static void hdd_sap_restart_handle(struct work_struct *work)
10151{
10152 vos_ssr_protect(__func__);
10153 __hdd_sap_restart_handle(work);
10154 vos_ssr_unprotect(__func__);
10155}
10156
10157
Abhishek Singh78c691f2017-11-30 13:48:44 +053010158/**
10159 * __hdd_force_scc_with_ecsa_handle() - to handle force scc using ecsa
10160 * @work: name of the work
10161 *
10162 * Purpose of this function is to force SCC using ECSA. This function
10163 * will be called from workqueue.
10164 *
10165 * Return: void.
10166 */
10167static void
10168__hdd_force_scc_with_ecsa_handle(struct work_struct *work)
10169{
10170 hdd_adapter_t *sap_adapter;
10171 hdd_station_ctx_t *sta_ctx;
10172 hdd_adapter_t *sta_adapter;
Ganesh Kondabattini3655a6d2018-01-08 20:25:39 +053010173 ptSapContext sap_ctx = NULL;
10174 v_CONTEXT_t vos_ctx;
10175 tANI_U8 target_channel;
10176 tsap_Config_t *sap_config;
10177 bool sta_sap_scc_on_dfs_chan;
10178 eNVChannelEnabledType chan_state;
Abhishek Singh78c691f2017-11-30 13:48:44 +053010179 hdd_context_t *hdd_ctx = container_of(to_delayed_work(work),
10180 hdd_context_t,
10181 ecsa_chan_change_work);
10182
10183 if (wlan_hdd_validate_context(hdd_ctx))
10184 return;
10185
10186 sap_adapter = hdd_get_adapter(hdd_ctx,
10187 WLAN_HDD_SOFTAP);
10188 if (!sap_adapter) {
10189 hddLog(LOGE, FL("sap_adapter is NULL"));
10190 return;
10191 }
10192
Ganesh Kondabattini3655a6d2018-01-08 20:25:39 +053010193 vos_ctx = hdd_ctx->pvosContext;
10194 if (!vos_ctx) {
10195 hddLog(LOGE, FL("vos_ctx is NULL"));
10196 return;
10197 }
10198
10199 sap_ctx = VOS_GET_SAP_CB(vos_ctx);
10200 if (!sap_ctx) {
10201 hddLog(LOGE, FL("sap_ctx is NULL"));
10202 return;
10203 }
10204
10205 sap_config = &sap_adapter->sessionCtx.ap.sapConfig;
10206
10207 sta_sap_scc_on_dfs_chan = hdd_is_sta_sap_scc_allowed_on_dfs_chan(hdd_ctx);
10208
Abhishek Singh78c691f2017-11-30 13:48:44 +053010209 sta_adapter = hdd_get_adapter(hdd_ctx,
10210 WLAN_HDD_INFRA_STATION);
10211 if (!sta_adapter) {
10212 hddLog(LOGE, FL("sta_adapter is NULL"));
10213 return;
10214 }
10215 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(sta_adapter);
10216
10217 if (sta_ctx->conn_info.connState != eConnectionState_Associated) {
Ganesh Kondabattini3655a6d2018-01-08 20:25:39 +053010218 chan_state = vos_nv_getChannelEnabledState(sap_ctx->channel);
10219 hddLog(LOG1, FL("sta not in connected state %d, sta_sap_scc_on_dfs_chan %d, chan_state %d"),
10220 sta_ctx->conn_info.connState, sta_sap_scc_on_dfs_chan,
10221 chan_state);
10222 if (sta_sap_scc_on_dfs_chan &&
10223 (chan_state == NV_CHANNEL_DFS)) {
10224 hddLog(LOG1, FL("Switch SAP to user configured channel"));
10225 target_channel = sap_config->user_config_channel;
10226 goto switch_channel;
10227
10228 }
Abhishek Singh78c691f2017-11-30 13:48:44 +053010229 return;
10230 }
10231
Ganesh Kondabattini3655a6d2018-01-08 20:25:39 +053010232 target_channel = sta_ctx->conn_info.operationChannel;
10233switch_channel:
10234 hddLog(LOGE, FL("Switch SAP to %d channel"),
10235 target_channel);
10236 wlansap_set_channel_change(vos_ctx, target_channel, true);
Abhishek Singh78c691f2017-11-30 13:48:44 +053010237}
10238
10239/**
10240 * hdd_force_scc_with_ecsa_handle() - to handle force scc using ecsa
10241 * @work: name of the work
10242 *
10243 * Purpose of this function is to force SCC using ECSA. This function
10244 * will be called from workqueue.
10245 *
10246 * Return: void.
10247 */
10248static void
10249hdd_force_scc_with_ecsa_handle(struct work_struct *work)
10250{
10251 vos_ssr_protect(__func__);
10252 __hdd_force_scc_with_ecsa_handle(work);
10253 vos_ssr_unprotect(__func__);
10254}
10255
Ganesh Kondabattini3655a6d2018-01-08 20:25:39 +053010256/**
10257 * hdd_is_sta_sap_scc_allowed_on_dfs_chan() - check if sta+sap scc allowed on
10258 * dfs chan
10259 * @hdd_ctx: pointer to hdd context
10260 *
10261 * This function used to check if sta+sap scc allowed on DFS channel.
10262 *
10263 * Return: None
10264 */
10265bool hdd_is_sta_sap_scc_allowed_on_dfs_chan(hdd_context_t *hdd_ctx)
10266{
10267 if (hdd_ctx->cfg_ini->force_scc_with_ecsa &&
10268 hdd_ctx->cfg_ini->sta_sap_scc_on_dfs_chan)
10269 return true;
10270 else
10271 return false;
10272}
10273
Jeff Johnson295189b2012-06-20 16:38:30 -070010274VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
10275{
10276 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
10277 VOS_STATUS status;
10278 hdd_adapter_t *pAdapter;
10279
10280 ENTER();
10281
10282 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10283
10284 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
10285 {
10286 pAdapter = pAdapterNode->pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -070010287
Agarwal Ashish3a38bd12014-06-12 15:16:52 +053010288 hdd_stop_adapter( pHddCtx, pAdapter, VOS_TRUE );
Jeff Johnson295189b2012-06-20 16:38:30 -070010289
10290 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10291 pAdapterNode = pNext;
10292 }
10293
10294 EXIT();
10295
10296 return VOS_STATUS_SUCCESS;
10297}
10298
Rajeev Kumarf999e582014-01-09 17:33:29 -080010299
10300#ifdef FEATURE_WLAN_BATCH_SCAN
10301/**---------------------------------------------------------------------------
10302
10303 \brief hdd_deinit_batch_scan () - This function cleans up batch scan data
10304 structures
10305
10306 \param - pAdapter Pointer to HDD adapter
10307
10308 \return - None
10309
10310 --------------------------------------------------------------------------*/
10311void hdd_deinit_batch_scan(hdd_adapter_t *pAdapter)
10312{
10313 tHddBatchScanRsp *pNode;
10314 tHddBatchScanRsp *pPrev;
10315
Siddharth Bhalb3e9b792014-02-24 15:14:16 +053010316 if (NULL == pAdapter)
Rajeev Kumarf999e582014-01-09 17:33:29 -080010317 {
Siddharth Bhalb3e9b792014-02-24 15:14:16 +053010318 hddLog(VOS_TRACE_LEVEL_ERROR,
10319 "%s: Adapter context is Null", __func__);
10320 return;
10321 }
10322
10323 pNode = pAdapter->pBatchScanRsp;
10324 while (pNode)
10325 {
10326 pPrev = pNode;
10327 pNode = pNode->pNext;
10328 vos_mem_free((v_VOID_t * )pPrev);
Rajeev Kumarf999e582014-01-09 17:33:29 -080010329 }
10330
10331 pAdapter->pBatchScanRsp = NULL;
10332 pAdapter->numScanList = 0;
10333 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
10334 pAdapter->prev_batch_id = 0;
10335
10336 return;
10337}
10338#endif
10339
10340
Jeff Johnson295189b2012-06-20 16:38:30 -070010341VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
10342{
10343 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
10344 VOS_STATUS status;
10345 hdd_adapter_t *pAdapter;
10346
10347 ENTER();
10348
10349 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10350
10351 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
10352 {
10353 pAdapter = pAdapterNode->pAdapter;
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +053010354 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
Jeff Johnson295189b2012-06-20 16:38:30 -070010355 netif_tx_disable(pAdapter->dev);
Hanumanth Reddy Pothulad864f312017-01-18 16:16:08 +053010356
10357 if (pHddCtx->cfg_ini->sap_internal_restart &&
10358 pAdapter->device_mode == WLAN_HDD_SOFTAP) {
10359 hddLog(LOG1, FL("driver supports sap restart"));
10360 vos_flush_work(&pHddCtx->sap_start_work);
10361 hdd_sap_indicate_disconnect_for_sta(pAdapter);
10362 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Hanumanth Reddy Pothula15bc0fa2017-02-03 17:24:17 +053010363 hdd_softap_deinit_tx_rx(pAdapter, true);
10364 hdd_sap_destroy_timers(pAdapter);
Hanumanth Reddy Pothulad864f312017-01-18 16:16:08 +053010365 } else {
10366 netif_carrier_off(pAdapter->dev);
10367 }
Jeff Johnson295189b2012-06-20 16:38:30 -070010368
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -070010369 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +053010370 pAdapter->sessionCtx.monitor.state = MON_MODE_STOP;
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -070010371
Jeff Johnson295189b2012-06-20 16:38:30 -070010372 hdd_deinit_tx_rx(pAdapter);
Agarwal Ashish6267caa2014-08-06 19:16:21 +053010373
Katya Nigam1fd24402015-02-16 14:52:19 +053010374 if(pAdapter->device_mode == WLAN_HDD_IBSS )
10375 hdd_ibss_deinit_tx_rx(pAdapter);
10376
Nirav Shah7e3c8132015-06-22 23:51:42 +053010377 status = hdd_sta_id_hash_detach(pAdapter);
10378 if (status != VOS_STATUS_SUCCESS)
10379 hddLog(VOS_TRACE_LEVEL_ERROR,
10380 FL("sta id hash detach failed for session id %d"),
10381 pAdapter->sessionId);
10382
Agarwal Ashish6267caa2014-08-06 19:16:21 +053010383 wlan_hdd_decr_active_session(pHddCtx, pAdapter->device_mode);
10384
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +053010385 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
10386 {
10387 hdd_wmm_adapter_close( pAdapter );
10388 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
10389 }
Jeff Johnson295189b2012-06-20 16:38:30 -070010390
Siddharth Bhal2db319d2014-12-03 12:37:18 +053010391 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
10392 {
10393 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
10394 }
10395
Rajeev Kumarf999e582014-01-09 17:33:29 -080010396#ifdef FEATURE_WLAN_BATCH_SCAN
10397 if (eHDD_BATCH_SCAN_STATE_STARTED == pAdapter->batchScanState)
10398 {
10399 hdd_deinit_batch_scan(pAdapter);
10400 }
10401#endif
10402
Mahesh A Saptasagarf5b8eff2015-01-31 01:07:07 +053010403#ifdef FEATURE_WLAN_TDLS
10404 mutex_lock(&pHddCtx->tdls_lock);
Pradeep Reddy POTTETI2d4d5c42015-03-03 14:34:19 +053010405 wlan_hdd_tdls_exit(pAdapter, TRUE);
Mahesh A Saptasagarf5b8eff2015-01-31 01:07:07 +053010406 mutex_unlock(&pHddCtx->tdls_lock);
10407#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070010408 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10409 pAdapterNode = pNext;
10410 }
10411
10412 EXIT();
10413
10414 return VOS_STATUS_SUCCESS;
10415}
10416
Abhishek Singhbbe0b2a2016-12-05 11:57:36 +053010417/**
Abhishek Singh5a597e62016-12-05 15:16:30 +053010418 * hdd_get_bss_entry() - Get the bss entry matching the chan, bssid and ssid
10419 * @wiphy: wiphy
10420 * @channel: channel of the BSS to find
10421 * @bssid: bssid of the BSS to find
10422 * @ssid: ssid of the BSS to find
10423 * @ssid_len: ssid len of of the BSS to find
10424 *
10425 * The API is a wrapper to get bss from kernel matching the chan,
10426 * bssid and ssid
10427 *
10428 * Return: Void
10429 */
10430#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) \
10431 && !defined(WITH_BACKPORTS) && !defined(IEEE80211_PRIVACY)
10432
10433struct cfg80211_bss* hdd_get_bss_entry(struct wiphy *wiphy,
10434 struct ieee80211_channel *channel,
10435 const u8 *bssid,
10436 const u8 *ssid, size_t ssid_len)
10437{
10438 return cfg80211_get_bss(wiphy, channel, bssid,
10439 ssid, ssid_len,
10440 WLAN_CAPABILITY_ESS,
10441 WLAN_CAPABILITY_ESS);
10442}
10443#else
10444struct cfg80211_bss* hdd_get_bss_entry(struct wiphy *wiphy,
10445 struct ieee80211_channel *channel,
10446 const u8 *bssid,
10447 const u8 *ssid, size_t ssid_len)
10448{
10449 return cfg80211_get_bss(wiphy, channel, bssid,
10450 ssid, ssid_len,
10451 IEEE80211_BSS_TYPE_ESS,
10452 IEEE80211_PRIVACY_ANY);
10453}
10454#endif
10455
Rajeev Kumar Sirasanagandla5b21a9c2018-01-08 17:05:11 +053010456#if defined(CFG80211_CONNECT_BSS) || \
10457 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
10458
10459#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) || \
10460 defined (CFG80211_CONNECT_TIMEOUT_REASON_CODE)
10461/**
10462 * hdd_connect_bss() - helper function to send connection status to supplicant
10463 * @dev: network device
10464 * @bssid: bssid to which we want to associate
10465 * @bss: information about connected bss
10466 * @req_ie: Request Information Element
10467 * @req_ie_len: len of the req IE
10468 * @resp_ie: Response IE
10469 * @resp_ie_len: len of ht response IE
10470 * @status: status
10471 * @gfp: Kernel Flag
10472 *
10473 * This is a helper function to send connection status to supplicant
10474 * and gets invoked from wrapper API
10475 *
10476 * Return: Void
10477 */
10478static void hdd_connect_bss(struct net_device *dev,
10479 const u8 *bssid,
10480 struct cfg80211_bss *bss,
10481 const u8 *req_ie,
10482 size_t req_ie_len,
10483 const u8 *resp_ie,
10484 size_t resp_ie_len,
10485 u16 status,
10486 gfp_t gfp)
10487{
10488 cfg80211_connect_bss(dev, bssid, bss, req_ie, req_ie_len,
10489 resp_ie, resp_ie_len, status, gfp, NL80211_TIMEOUT_UNSPECIFIED);
10490}
10491#else
10492/**
10493 * hdd_connect_bss() - helper function to send connection status to supplicant
10494 * @dev: network device
10495 * @bssid: bssid to which we want to associate
10496 * @bss: information about connected bss
10497 * @req_ie: Request Information Element
10498 * @req_ie_len: len of the req IE
10499 * @resp_ie: Response IE
10500 * @resp_ie_len: len of ht response IE
10501 * @status: status
10502 * @gfp: Kernel Flag
10503 *
10504 * This is a helper function to send connection status to supplicant
10505 * and gets invoked from wrapper API
10506 *
10507 * Return: Void
10508 */
10509static void hdd_connect_bss(struct net_device *dev,
10510 const u8 *bssid,
10511 struct cfg80211_bss *bss,
10512 const u8 *req_ie,
10513 size_t req_ie_len,
10514 const u8 *resp_ie,
10515 size_t resp_ie_len,
10516 u16 status,
10517 gfp_t gfp)
10518{
10519 cfg80211_connect_bss(dev, bssid, bss, req_ie, req_ie_len,
10520 resp_ie, resp_ie_len, status, gfp);
10521}
10522#endif
10523
Abhishek Singh5a597e62016-12-05 15:16:30 +053010524/**
Abhishek Singhbbe0b2a2016-12-05 11:57:36 +053010525 * hdd_connect_result() - API to send connection status to supplicant
10526 * @dev: network device
10527 * @bssid: bssid to which we want to associate
10528 * @roam_info: information about connected bss
10529 * @req_ie: Request Information Element
10530 * @req_ie_len: len of the req IE
10531 * @resp_ie: Response IE
10532 * @resp_ie_len: len of ht response IE
10533 * @status: status
10534 * @gfp: Kernel Flag
10535 *
10536 * The API is a wrapper to send connection status to supplicant
10537 *
10538 * Return: Void
10539 */
Abhishek Singhbbe0b2a2016-12-05 11:57:36 +053010540void hdd_connect_result(struct net_device *dev,
10541 const u8 *bssid,
10542 tCsrRoamInfo *roam_info,
10543 const u8 *req_ie,
10544 size_t req_ie_len,
10545 const u8 *resp_ie,
10546 size_t resp_ie_len,
10547 u16 status,
10548 gfp_t gfp)
10549{
10550 hdd_adapter_t *padapter = (hdd_adapter_t *) netdev_priv(dev);
10551 struct cfg80211_bss *bss = NULL;
10552
10553 if (WLAN_STATUS_SUCCESS == status) {
10554 struct ieee80211_channel *chan;
10555 int freq;
10556 int chan_no = roam_info->pBssDesc->channelId;;
10557
10558 if (chan_no <= 14)
10559 freq = ieee80211_channel_to_frequency(chan_no,
Rajeev Kumar Sirasanagandla5b21a9c2018-01-08 17:05:11 +053010560 HDD_NL80211_BAND_2GHZ);
Abhishek Singhbbe0b2a2016-12-05 11:57:36 +053010561 else
10562 freq = ieee80211_channel_to_frequency(chan_no,
Rajeev Kumar Sirasanagandla5b21a9c2018-01-08 17:05:11 +053010563 HDD_NL80211_BAND_5GHZ);
Abhishek Singhbbe0b2a2016-12-05 11:57:36 +053010564
10565 chan = ieee80211_get_channel(padapter->wdev.wiphy, freq);
Abhishek Singh5a597e62016-12-05 15:16:30 +053010566 bss = hdd_get_bss_entry(padapter->wdev.wiphy,
10567 chan, bssid,
10568 roam_info->u.pConnectedProfile->SSID.ssId,
10569 roam_info->u.pConnectedProfile->SSID.length);
Abhishek Singhbbe0b2a2016-12-05 11:57:36 +053010570 }
10571
Rajeev Kumar Sirasanagandla5b21a9c2018-01-08 17:05:11 +053010572 hdd_connect_bss(dev, bssid, bss, req_ie, req_ie_len, resp_ie, resp_ie_len,
10573 status, gfp);
Abhishek Singhbbe0b2a2016-12-05 11:57:36 +053010574}
10575#else
Rajeev Kumar Sirasanagandla5b21a9c2018-01-08 17:05:11 +053010576/**
10577 * hdd_connect_result() - API to send connection status to supplicant
10578 * @dev: network device
10579 * @bssid: bssid to which we want to associate
10580 * @roam_info: 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 * The API is a wrapper to send connection status to supplicant
10589 *
10590 * Return: Void
10591 */
Abhishek Singhbbe0b2a2016-12-05 11:57:36 +053010592void hdd_connect_result(struct net_device *dev,
10593 const u8 *bssid,
10594 tCsrRoamInfo *roam_info,
10595 const u8 *req_ie,
10596 size_t req_ie_len,
10597 const u8 * resp_ie,
10598 size_t resp_ie_len,
10599 u16 status,
10600 gfp_t gfp)
10601{
10602 cfg80211_connect_result(dev, bssid, req_ie, req_ie_len,
10603 resp_ie, resp_ie_len, status, gfp);
10604}
10605#endif
10606
Jeff Johnson295189b2012-06-20 16:38:30 -070010607VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
10608{
10609 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
10610 VOS_STATUS status;
10611 hdd_adapter_t *pAdapter;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +053010612 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -070010613
10614 ENTER();
10615
10616 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10617
10618 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
10619 {
10620 pAdapter = pAdapterNode->pAdapter;
10621
Kumar Anand82c009f2014-05-29 00:29:42 -070010622 hdd_wmm_init( pAdapter );
10623
Jeff Johnson295189b2012-06-20 16:38:30 -070010624 switch(pAdapter->device_mode)
10625 {
10626 case WLAN_HDD_INFRA_STATION:
10627 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -070010628 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +053010629
10630 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
10631
Jeff Johnson295189b2012-06-20 16:38:30 -070010632 hdd_init_station_mode(pAdapter);
10633 /* Open the gates for HDD to receive Wext commands */
10634 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -070010635 pHddCtx->scan_info.mScanPending = FALSE;
10636 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -070010637
10638 //Trigger the initial scan
Mukul Sharmae74e42c2015-08-06 23:55:49 +053010639 if (!pHddCtx->isLogpInProgress)
10640 hdd_wlan_initial_scan(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -070010641
10642 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +053010643 if (eConnectionState_Associated == connState ||
10644 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -070010645 {
10646 union iwreq_data wrqu;
10647 memset(&wrqu, '\0', sizeof(wrqu));
10648 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
10649 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
10650 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -070010651 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -070010652
Jeff Johnson295189b2012-06-20 16:38:30 -070010653 /* indicate disconnected event to nl80211 */
Mahesh A Saptasagar9ff4bcc2016-06-01 17:17:50 +053010654 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, false,
Mahesh A Saptasagarb5a15142016-05-25 11:27:43 +053010655 WLAN_REASON_UNSPECIFIED);
Jeff Johnson295189b2012-06-20 16:38:30 -070010656 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +053010657 else if (eConnectionState_Connecting == connState)
10658 {
10659 /*
10660 * Indicate connect failure to supplicant if we were in the
10661 * process of connecting
10662 */
Abhishek Singhbbe0b2a2016-12-05 11:57:36 +053010663 hdd_connect_result(pAdapter->dev, NULL, NULL,
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +053010664 NULL, 0, NULL, 0,
10665 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
10666 GFP_KERNEL);
10667 }
Jeff Johnson295189b2012-06-20 16:38:30 -070010668 break;
10669
10670 case WLAN_HDD_SOFTAP:
Hanumanth Reddy Pothulad864f312017-01-18 16:16:08 +053010671 if (pHddCtx->cfg_ini->sap_internal_restart) {
Hanumanth Reddy Pothula15bc0fa2017-02-03 17:24:17 +053010672 hdd_init_ap_mode(pAdapter, true);
Hanumanth Reddy Pothulad864f312017-01-18 16:16:08 +053010673 status = hdd_sta_id_hash_attach(pAdapter);
10674 if (VOS_STATUS_SUCCESS != status)
10675 {
10676 hddLog(VOS_TRACE_LEVEL_FATAL,
10677 FL("failed to attach hash for"));
10678 }
10679 }
Jeff Johnson295189b2012-06-20 16:38:30 -070010680 break;
10681
10682 case WLAN_HDD_P2P_GO:
Sameer Thalappiledf0d792013-08-09 14:31:03 -070010683 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send stop ap to supplicant",
Jeff Johnson295189b2012-06-20 16:38:30 -070010684 __func__);
Sameer Thalappiledf0d792013-08-09 14:31:03 -070010685 cfg80211_ap_stopped(pAdapter->dev, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -070010686 break;
10687
10688 case WLAN_HDD_MONITOR:
10689 /* monitor interface start */
10690 break;
10691 default:
10692 break;
10693 }
10694
10695 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10696 pAdapterNode = pNext;
10697 }
10698
10699 EXIT();
10700
10701 return VOS_STATUS_SUCCESS;
10702}
10703
10704VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
10705{
10706 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
10707 hdd_adapter_t *pAdapter;
10708 VOS_STATUS status;
10709 v_U32_t roamId;
c_hpothu6ff1c3c2013-10-01 19:01:57 +053010710 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -070010711
10712 ENTER();
10713
10714 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10715
10716 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
10717 {
10718 pAdapter = pAdapterNode->pAdapter;
10719
10720 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
10721 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
10722 {
10723 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10724 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10725
Abhishek Singhf4669da2014-05-26 15:07:49 +053010726 hddLog(VOS_TRACE_LEVEL_INFO,
10727 "%s: Set HDD connState to eConnectionState_NotConnected",
10728 __func__);
Ganesh Kondabattini04338412015-09-14 15:39:09 +053010729 spin_lock_bh(&pAdapter->lock_for_active_session);
10730 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState)
10731 {
10732 wlan_hdd_decr_active_session(pHddCtx, pAdapter->device_mode);
10733 }
Jeff Johnson295189b2012-06-20 16:38:30 -070010734 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
Ganesh Kondabattini04338412015-09-14 15:39:09 +053010735 spin_unlock_bh(&pAdapter->lock_for_active_session);
Jeff Johnson295189b2012-06-20 16:38:30 -070010736 init_completion(&pAdapter->disconnect_comp_var);
10737 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
10738 eCSR_DISCONNECT_REASON_UNSPECIFIED);
10739
c_hpothu6ff1c3c2013-10-01 19:01:57 +053010740 ret = wait_for_completion_interruptible_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -070010741 &pAdapter->disconnect_comp_var,
10742 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +053010743 if (0 >= ret)
10744 hddLog(LOGE, "%s: failure waiting for disconnect_comp_var %ld",
10745 __func__, ret);
Jeff Johnson295189b2012-06-20 16:38:30 -070010746
10747 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
10748 pHddCtx->isAmpAllowed = VOS_FALSE;
10749 sme_RoamConnect(pHddCtx->hHal,
10750 pAdapter->sessionId, &(pWextState->roamProfile),
10751 &roamId);
10752 }
10753
10754 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10755 pAdapterNode = pNext;
10756 }
10757
10758 EXIT();
10759
10760 return VOS_STATUS_SUCCESS;
10761}
10762
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -070010763void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
10764{
10765 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
10766 VOS_STATUS status;
10767 hdd_adapter_t *pAdapter;
10768 hdd_station_ctx_t *pHddStaCtx;
10769 hdd_ap_ctx_t *pHddApCtx;
10770 hdd_hostapd_state_t * pHostapdState;
10771 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
10772 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
10773 const char *p2pMode = "DEV";
10774 const char *ccMode = "Standalone";
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -070010775
10776 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10777 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
10778 {
10779 pAdapter = pAdapterNode->pAdapter;
10780 switch (pAdapter->device_mode) {
10781 case WLAN_HDD_INFRA_STATION:
10782 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10783 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
10784 staChannel = pHddStaCtx->conn_info.operationChannel;
10785 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
10786 }
10787 break;
10788 case WLAN_HDD_P2P_CLIENT:
10789 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10790 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
10791 p2pChannel = pHddStaCtx->conn_info.operationChannel;
10792 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
10793 p2pMode = "CLI";
10794 }
10795 break;
10796 case WLAN_HDD_P2P_GO:
10797 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
10798 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
10799 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
10800 p2pChannel = pHddApCtx->operatingChannel;
10801 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
10802 }
10803 p2pMode = "GO";
10804 break;
10805 case WLAN_HDD_SOFTAP:
10806 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
10807 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
10808 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
10809 apChannel = pHddApCtx->operatingChannel;
10810 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
10811 }
10812 break;
10813 default:
10814 break;
10815 }
10816 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10817 pAdapterNode = pNext;
10818 }
10819 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
10820 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
10821 }
Yeshwanth Sriram Guntuka0004c0b2017-12-06 14:43:49 +053010822 hddLog(VOS_TRACE_LEVEL_ERROR, "wlan(%d) " MAC_ADDRESS_STR " %s",
10823 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -070010824 if (p2pChannel > 0) {
Sushant Kaushikdc3184b2015-10-09 12:00:21 +053010825 hddLog(VOS_TRACE_LEVEL_ERROR, "p2p-%s(%d) " MAC_ADDRESS_STR,
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -070010826 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
10827 }
10828 if (apChannel > 0) {
Sushant Kaushikdc3184b2015-10-09 12:00:21 +053010829 hddLog(VOS_TRACE_LEVEL_ERROR, "AP(%d) " MAC_ADDRESS_STR,
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -070010830 apChannel, MAC_ADDR_ARRAY(apBssid));
10831 }
10832
10833 if (p2pChannel > 0 && apChannel > 0) {
10834 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
10835 }
10836}
10837
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -070010838bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -070010839{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -070010840 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -070010841}
10842
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -070010843/* Once SSR is disabled then it cannot be set. */
10844void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -070010845{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -070010846 if (HDD_SSR_DISABLED == isSsrRequired)
10847 return;
10848
Jeff Johnson295189b2012-06-20 16:38:30 -070010849 isSsrRequired = value;
10850}
10851
Hema Aparna Medicharla6b4d4f32015-06-23 04:09:12 +053010852void hdd_set_pre_close( hdd_context_t *pHddCtx)
10853{
10854 sme_PreClose(pHddCtx->hHal);
10855}
10856
Jeff Johnson295189b2012-06-20 16:38:30 -070010857VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
10858 hdd_adapter_list_node_t** ppAdapterNode)
10859{
10860 VOS_STATUS status;
Mukul Sharmaae1266d2015-06-26 15:29:53 +053010861 spin_lock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010862 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
10863 (hdd_list_node_t**) ppAdapterNode );
Mukul Sharmaae1266d2015-06-26 15:29:53 +053010864 spin_unlock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010865 return status;
10866}
10867
10868VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
10869 hdd_adapter_list_node_t* pAdapterNode,
10870 hdd_adapter_list_node_t** pNextAdapterNode)
10871{
10872 VOS_STATUS status;
Mukul Sharmaae1266d2015-06-26 15:29:53 +053010873 spin_lock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010874 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
10875 (hdd_list_node_t*) pAdapterNode,
10876 (hdd_list_node_t**)pNextAdapterNode );
10877
Mukul Sharmaae1266d2015-06-26 15:29:53 +053010878 spin_unlock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010879 return status;
10880}
10881
10882VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
10883 hdd_adapter_list_node_t* pAdapterNode)
10884{
10885 VOS_STATUS status;
Mukul Sharmaae1266d2015-06-26 15:29:53 +053010886 spin_lock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010887 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
10888 &pAdapterNode->node );
Mukul Sharmaae1266d2015-06-26 15:29:53 +053010889 spin_unlock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010890 return status;
10891}
10892
10893VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
10894 hdd_adapter_list_node_t** ppAdapterNode)
10895{
10896 VOS_STATUS status;
Mukul Sharmaae1266d2015-06-26 15:29:53 +053010897 spin_lock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010898 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
10899 (hdd_list_node_t**) ppAdapterNode );
Mukul Sharmaae1266d2015-06-26 15:29:53 +053010900 spin_unlock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010901 return status;
10902}
10903
10904VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
10905 hdd_adapter_list_node_t* pAdapterNode)
10906{
10907 VOS_STATUS status;
Mukul Sharmaae1266d2015-06-26 15:29:53 +053010908 spin_lock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010909 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
10910 (hdd_list_node_t*) pAdapterNode );
Mukul Sharmaae1266d2015-06-26 15:29:53 +053010911 spin_unlock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010912 return status;
10913}
10914
10915VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
10916 hdd_adapter_list_node_t* pAdapterNode)
10917{
10918 VOS_STATUS status;
Mukul Sharmaae1266d2015-06-26 15:29:53 +053010919 spin_lock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010920 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
10921 (hdd_list_node_t*) pAdapterNode );
Mukul Sharmaae1266d2015-06-26 15:29:53 +053010922 spin_unlock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010923 return status;
10924}
10925
10926hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
10927 tSirMacAddr macAddr )
10928{
10929 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
10930 hdd_adapter_t *pAdapter;
10931 VOS_STATUS status;
10932
10933 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10934
10935 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
10936 {
10937 pAdapter = pAdapterNode->pAdapter;
10938
10939 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
10940 macAddr, sizeof(tSirMacAddr) ) )
10941 {
10942 return pAdapter;
10943 }
10944 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10945 pAdapterNode = pNext;
10946 }
10947
10948 return NULL;
10949
10950}
10951
10952hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
10953{
10954 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
10955 hdd_adapter_t *pAdapter;
10956 VOS_STATUS status;
10957
10958 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10959
10960 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
10961 {
10962 pAdapter = pAdapterNode->pAdapter;
10963
10964 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
10965 IFNAMSIZ ) )
10966 {
10967 return pAdapter;
10968 }
10969 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10970 pAdapterNode = pNext;
10971 }
10972
10973 return NULL;
10974
10975}
10976
Ganesh Kondabattinicbfdc392015-09-11 19:12:59 +053010977hdd_adapter_t *hdd_get_adapter_by_sme_session_id( hdd_context_t *pHddCtx,
10978 tANI_U32 sme_session_id )
10979{
10980 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
10981 hdd_adapter_t *pAdapter;
10982 VOS_STATUS vos_status;
10983
10984
10985 vos_status = hdd_get_front_adapter( pHddCtx, &pAdapterNode);
10986
10987 while ((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == vos_status))
10988 {
10989 pAdapter = pAdapterNode->pAdapter;
10990
10991 if (pAdapter->sessionId == sme_session_id)
10992 return pAdapter;
10993
10994 vos_status = hdd_get_next_adapter(pHddCtx, pAdapterNode, &pNext);
10995 pAdapterNode = pNext;
10996 }
10997
10998 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
10999 "%s: sme_session_id %d does not exist with host",
11000 __func__, sme_session_id);
11001
11002 return NULL;
11003}
11004
Jeff Johnson295189b2012-06-20 16:38:30 -070011005hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
11006{
11007 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
11008 hdd_adapter_t *pAdapter;
11009 VOS_STATUS status;
11010
11011 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
11012
11013 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
11014 {
11015 pAdapter = pAdapterNode->pAdapter;
11016
11017 if( pAdapter && (mode == pAdapter->device_mode) )
11018 {
11019 return pAdapter;
11020 }
11021 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
11022 pAdapterNode = pNext;
11023 }
11024
11025 return NULL;
11026
11027}
11028
11029//Remove this function later
11030hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
11031{
11032 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
11033 hdd_adapter_t *pAdapter;
11034 VOS_STATUS status;
11035
11036 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
11037
11038 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
11039 {
11040 pAdapter = pAdapterNode->pAdapter;
11041
11042 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
11043 {
11044 return pAdapter;
11045 }
11046
11047 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
11048 pAdapterNode = pNext;
11049 }
11050
11051 return NULL;
11052
11053}
11054
Jeff Johnson295189b2012-06-20 16:38:30 -070011055/**---------------------------------------------------------------------------
11056
Mahesh A Saptasgar64534612014-09-23 13:13:33 +053011057 \brief hdd_get_operating_channel() -
Jeff Johnson295189b2012-06-20 16:38:30 -070011058
11059 This API returns the operating channel of the requested device mode
11060
11061 \param - pHddCtx - Pointer to the HDD context.
11062 - mode - Device mode for which operating channel is required
11063 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
11064 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
11065 \return - channel number. "0" id the requested device is not found OR it is not connected.
11066 --------------------------------------------------------------------------*/
11067v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
11068{
11069 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
11070 VOS_STATUS status;
11071 hdd_adapter_t *pAdapter;
11072 v_U8_t operatingChannel = 0;
11073
11074 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
11075
11076 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
11077 {
11078 pAdapter = pAdapterNode->pAdapter;
11079
11080 if( mode == pAdapter->device_mode )
11081 {
11082 switch(pAdapter->device_mode)
11083 {
11084 case WLAN_HDD_INFRA_STATION:
11085 case WLAN_HDD_P2P_CLIENT:
11086 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
11087 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
11088 break;
11089 case WLAN_HDD_SOFTAP:
11090 case WLAN_HDD_P2P_GO:
11091 /*softap connection info */
11092 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
11093 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
11094 break;
11095 default:
11096 break;
11097 }
11098
11099 break; //Found the device of interest. break the loop
11100 }
11101
11102 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
11103 pAdapterNode = pNext;
11104 }
11105 return operatingChannel;
11106}
11107
11108#ifdef WLAN_FEATURE_PACKET_FILTERING
11109/**---------------------------------------------------------------------------
11110
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +053011111 \brief __hdd_set_multicast_list() -
Jeff Johnson295189b2012-06-20 16:38:30 -070011112
11113 This used to set the multicast address list.
11114
11115 \param - dev - Pointer to the WLAN device.
11116 - skb - Pointer to OS packet (sk_buff).
Mahesh A Saptasagar74088392015-02-05 17:22:09 +053011117 \return - success/fail
Jeff Johnson295189b2012-06-20 16:38:30 -070011118
11119 --------------------------------------------------------------------------*/
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +053011120static void __hdd_set_multicast_list(struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -070011121{
Mahesh A Saptasagar74088392015-02-05 17:22:09 +053011122 hdd_adapter_t *pAdapter;
11123 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -070011124 int mc_count;
Mahesh A Saptasagar74088392015-02-05 17:22:09 +053011125 int i = 0, ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -070011126 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +053011127
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +053011128 ENTER();
11129
Mahesh A Saptasagar74088392015-02-05 17:22:09 +053011130 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Gopichand Nakkala0f276812013-02-24 14:45:51 +053011131 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -070011132 {
11133 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +053011134 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -070011135 return;
11136 }
Mahesh A Saptasagar74088392015-02-05 17:22:09 +053011137 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11138 ret = wlan_hdd_validate_context(pHddCtx);
11139 if (0 != ret)
11140 {
Mahesh A Saptasagar74088392015-02-05 17:22:09 +053011141 return;
11142 }
Jeff Johnson295189b2012-06-20 16:38:30 -070011143 if (dev->flags & IFF_ALLMULTI)
11144 {
11145 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070011146 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +053011147 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -070011148 }
Mahesh A Saptasagar74088392015-02-05 17:22:09 +053011149 else
Jeff Johnson295189b2012-06-20 16:38:30 -070011150 {
11151 mc_count = netdev_mc_count(dev);
11152 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070011153 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -070011154 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
11155 {
11156 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070011157 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +053011158 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -070011159 return;
11160 }
11161
Gopichand Nakkala0f276812013-02-24 14:45:51 +053011162 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -070011163
11164 netdev_for_each_mc_addr(ha, dev) {
11165 if (i == mc_count)
11166 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +053011167 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
11168 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
Arif Hussain6d2a3322013-11-17 19:50:10 -080011169 hddLog(VOS_TRACE_LEVEL_INFO, "%s: mlist[%d] = "MAC_ADDRESS_STR,
Mahesh A Saptasagar74088392015-02-05 17:22:09 +053011170 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +053011171 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -070011172 i++;
11173 }
11174 }
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +053011175
Ganesh Kondabattinifb37e652015-10-09 15:46:47 +053011176 if (pHddCtx->hdd_wlan_suspended)
11177 {
11178 /*
11179 * Configure the Mcast address list to FW
11180 * If wlan is already in suspend mode
11181 */
11182 wlan_hdd_set_mc_addr_list(pAdapter, TRUE);
11183 }
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +053011184 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -070011185 return;
11186}
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +053011187
11188static void hdd_set_multicast_list(struct net_device *dev)
11189{
11190 vos_ssr_protect(__func__);
11191 __hdd_set_multicast_list(dev);
11192 vos_ssr_unprotect(__func__);
11193}
Jeff Johnson295189b2012-06-20 16:38:30 -070011194#endif
11195
11196/**---------------------------------------------------------------------------
11197
11198 \brief hdd_select_queue() -
11199
11200 This function is registered with the Linux OS for network
11201 core to decide which queue to use first.
11202
11203 \param - dev - Pointer to the WLAN device.
11204 - skb - Pointer to OS packet (sk_buff).
11205 \return - ac, Queue Index/access category corresponding to UP in IP header
11206
11207 --------------------------------------------------------------------------*/
11208v_U16_t hdd_select_queue(struct net_device *dev,
Anand N Sunkade9adb1b2015-07-29 09:56:45 +053011209 struct sk_buff *skb
11210#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0))
11211 , void *accel_priv
11212#endif
11213#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0))
11214 , select_queue_fallback_t fallback
11215#endif
11216)
Jeff Johnson295189b2012-06-20 16:38:30 -070011217{
11218 return hdd_wmm_select_queue(dev, skb);
11219}
11220
11221
11222/**---------------------------------------------------------------------------
11223
11224 \brief hdd_wlan_initial_scan() -
11225
11226 This function triggers the initial scan
11227
11228 \param - pAdapter - Pointer to the HDD adapter.
11229
11230 --------------------------------------------------------------------------*/
11231void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
11232{
11233 tCsrScanRequest scanReq;
11234 tCsrChannelInfo channelInfo;
11235 eHalStatus halStatus;
Jeff Johnson02797792013-10-26 19:17:13 -070011236 tANI_U32 scanId;
Jeff Johnson295189b2012-06-20 16:38:30 -070011237 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11238
11239 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
11240 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
11241 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
11242
11243 if(sme_Is11dSupported(pHddCtx->hHal))
11244 {
11245 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
11246 if ( HAL_STATUS_SUCCESS( halStatus ) )
11247 {
11248 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
11249 if( !scanReq.ChannelInfo.ChannelList )
11250 {
11251 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
11252 vos_mem_free(channelInfo.ChannelList);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -080011253 channelInfo.ChannelList = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -070011254 return;
11255 }
11256 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
11257 channelInfo.numOfChannels);
11258 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
11259 vos_mem_free(channelInfo.ChannelList);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -080011260 channelInfo.ChannelList = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -070011261 }
11262
11263 scanReq.scanType = eSIR_PASSIVE_SCAN;
11264 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
11265 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
11266 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
11267 }
11268 else
11269 {
11270 scanReq.scanType = eSIR_ACTIVE_SCAN;
11271 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
11272 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
11273 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
11274 }
11275
11276 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
11277 if ( !HAL_STATUS_SUCCESS( halStatus ) )
11278 {
11279 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
11280 __func__, halStatus );
11281 }
11282
11283 if(sme_Is11dSupported(pHddCtx->hHal))
11284 vos_mem_free(scanReq.ChannelInfo.ChannelList);
11285}
11286
Jeff Johnson295189b2012-06-20 16:38:30 -070011287/**---------------------------------------------------------------------------
11288
11289 \brief hdd_full_power_callback() - HDD full power callback function
11290
11291 This is the function invoked by SME to inform the result of a full power
11292 request issued by HDD
11293
11294 \param - callbackcontext - Pointer to cookie
11295 \param - status - result of request
11296
11297 \return - None
11298
11299 --------------------------------------------------------------------------*/
11300static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
11301{
Jeff Johnson72a40512013-12-19 10:14:15 -080011302 struct statsContext *pContext = callbackContext;
Jeff Johnson295189b2012-06-20 16:38:30 -070011303
11304 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnsonc135a9a2017-09-19 08:37:24 -070011305 "%s: context = %pK, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -070011306
11307 if (NULL == callbackContext)
11308 {
11309 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnsonc135a9a2017-09-19 08:37:24 -070011310 "%s: Bad param, context [%pK]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070011311 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -070011312 return;
11313 }
11314
Jeff Johnson72a40512013-12-19 10:14:15 -080011315 /* there is a race condition that exists between this callback
11316 function and the caller since the caller could time out either
11317 before or while this code is executing. we use a spinlock to
11318 serialize these actions */
11319 spin_lock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070011320
11321 if (POWER_CONTEXT_MAGIC != pContext->magic)
11322 {
11323 /* the caller presumably timed out so there is nothing we can do */
Jeff Johnson72a40512013-12-19 10:14:15 -080011324 spin_unlock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070011325 hddLog(VOS_TRACE_LEVEL_WARN,
11326 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070011327 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -070011328 return;
11329 }
11330
Jeff Johnson72a40512013-12-19 10:14:15 -080011331 /* context is valid so caller is still waiting */
11332
11333 /* paranoia: invalidate the magic */
11334 pContext->magic = 0;
11335
11336 /* notify the caller */
Jeff Johnson295189b2012-06-20 16:38:30 -070011337 complete(&pContext->completion);
Jeff Johnson72a40512013-12-19 10:14:15 -080011338
11339 /* serialization is complete */
11340 spin_unlock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070011341}
11342
Katya Nigamf0511f62015-05-05 16:40:57 +053011343void wlan_hdd_mon_set_typesubtype( hdd_mon_ctx_t *pMonCtx,int type)
11344{
11345 pMonCtx->typeSubtypeBitmap = 0;
11346 if( type%10 ) /* Management Packets */
11347 pMonCtx->typeSubtypeBitmap |= 0xFFFF;
11348 type/=10;
11349 if( type%10 ) /* Control Packets */
11350 pMonCtx->typeSubtypeBitmap |= 0xFFFF0000;
11351 type/=10;
11352 if( type%10 ) /* Data Packets */
11353 pMonCtx->typeSubtypeBitmap |= 0xFFFF00000000;
11354}
11355
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053011356VOS_STATUS wlan_hdd_mon_postMsg(tANI_U32 *magic, struct completion *cmpVar,
11357 hdd_mon_ctx_t *pMonCtx , void* callback)
Katya Nigamf0511f62015-05-05 16:40:57 +053011358{
11359 vos_msg_t monMsg;
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053011360 tSirMonModeReq *pMonModeReq;
Katya Nigamf0511f62015-05-05 16:40:57 +053011361
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053011362 if (MON_MODE_START == pMonCtx->state)
11363 monMsg.type = WDA_MON_START_REQ;
11364 else if (MON_MODE_STOP == pMonCtx->state)
11365 monMsg.type = WDA_MON_STOP_REQ;
11366 else {
11367 hddLog(VOS_TRACE_LEVEL_ERROR,
11368 FL("invalid monitor state %d"), pMonCtx->state);
Katya Nigamf0511f62015-05-05 16:40:57 +053011369 return VOS_STATUS_E_FAILURE;
11370 }
11371
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053011372 pMonModeReq = vos_mem_malloc(sizeof(tSirMonModeReq));
11373 if (pMonModeReq == NULL) {
11374 hddLog(VOS_TRACE_LEVEL_ERROR,
11375 FL("fail to allocate memory for monitor mode req"));
11376 return VOS_STATUS_E_FAILURE;
11377 }
Katya Nigamf0511f62015-05-05 16:40:57 +053011378
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053011379 pMonModeReq->magic = magic;
11380 pMonModeReq->cmpVar = cmpVar;
11381 pMonModeReq->data = pMonCtx;
11382 pMonModeReq->callback = callback;
Katya Nigamf0511f62015-05-05 16:40:57 +053011383
Katya Nigamf0511f62015-05-05 16:40:57 +053011384 monMsg.reserved = 0;
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053011385 monMsg.bodyptr = pMonModeReq;
Katya Nigamf0511f62015-05-05 16:40:57 +053011386 monMsg.bodyval = 0;
11387
11388 if (VOS_STATUS_SUCCESS != vos_mq_post_message(
11389 VOS_MODULE_ID_WDA,(vos_msg_t *)&monMsg)) {
11390 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: : Failed to post Msg to HAL",__func__);
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053011391 vos_mem_free(pMonModeReq);
Katya Nigamf0511f62015-05-05 16:40:57 +053011392 }
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053011393 return VOS_STATUS_SUCCESS;
Katya Nigamf0511f62015-05-05 16:40:57 +053011394}
11395
Katya Nigame7b69a82015-04-28 15:24:06 +053011396void wlan_hdd_mon_close(hdd_context_t *pHddCtx)
11397{
11398 VOS_STATUS vosStatus;
11399 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053011400 long ret;
11401 hdd_mon_ctx_t *pMonCtx = NULL;
11402 v_U32_t magic;
11403 struct completion cmpVar;
Hanumantha Reddy Pothulac99bc062015-09-08 14:59:26 +053011404
Katya Nigame7b69a82015-04-28 15:24:06 +053011405 hdd_adapter_t *pAdapter = hdd_get_adapter(pHddCtx,WLAN_HDD_MONITOR);
11406 if(pAdapter == NULL || pVosContext == NULL)
11407 {
11408 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:pAdapter is NULL",__func__);
11409 return ;
11410 }
Katya Nigamf0511f62015-05-05 16:40:57 +053011411
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053011412 pMonCtx = WLAN_HDD_GET_MONITOR_CTX_PTR(pAdapter);
11413 if (pMonCtx!= NULL && pMonCtx->state == MON_MODE_START) {
11414 pMonCtx->state = MON_MODE_STOP;
11415 magic = MON_MODE_MSG_MAGIC;
11416 init_completion(&cmpVar);
11417 if (VOS_STATUS_SUCCESS !=
11418 wlan_hdd_mon_postMsg(&magic, &cmpVar,
11419 pMonCtx, hdd_monPostMsgCb)) {
11420 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
11421 FL("failed to post MON MODE REQ"));
11422 pMonCtx->state = MON_MODE_START;
11423 magic = 0;
11424 return;
11425 }
11426 ret = wait_for_completion_timeout(&cmpVar, MON_MODE_MSG_TIMEOUT);
11427 magic = 0;
11428 if (ret <= 0 ) {
11429 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
11430 FL("timeout on monitor mode completion %ld"), ret);
11431 }
11432 }
11433
Katya Nigame7b69a82015-04-28 15:24:06 +053011434 hdd_UnregisterWext(pAdapter->dev);
11435
11436 vos_mon_stop( pVosContext );
11437
11438 vosStatus = vos_sched_close( pVosContext );
11439 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
11440 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
11441 "%s: Failed to close VOSS Scheduler",__func__);
11442 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
11443 }
11444
11445 vosStatus = vos_nv_close();
11446 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
11447 {
11448 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
11449 "%s: Failed to close NV", __func__);
11450 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
11451 }
11452
11453 vos_close(pVosContext);
11454
11455 #ifdef WLAN_KD_READY_NOTIFIER
11456 nl_srv_exit(pHddCtx->ptt_pid);
11457 #else
11458 nl_srv_exit();
11459 #endif
11460
Katya Nigame7b69a82015-04-28 15:24:06 +053011461 hdd_close_all_adapters( pHddCtx );
Katya Nigame7b69a82015-04-28 15:24:06 +053011462}
Agrawal Ashish33ec71e2015-11-26 20:20:58 +053011463/**
11464 * hdd_wlan_free_wiphy_channels - free Channel pointer for wiphy
11465 * @ wiphy: the wiphy to validate against
11466 *
11467 * Return: void
11468 */
11469void hdd_wlan_free_wiphy_channels(struct wiphy *wiphy)
11470{
11471 int i =0;
Rajeev Kumar Sirasanagandla5b21a9c2018-01-08 17:05:11 +053011472 for (i = 0; i < HDD_NUM_NL80211_BANDS; i++)
Agrawal Ashish33ec71e2015-11-26 20:20:58 +053011473 {
11474 if (NULL != wiphy->bands[i] &&
11475 (NULL != wiphy->bands[i]->channels))
11476 {
11477 vos_mem_free(wiphy->bands[i]->channels);
11478 wiphy->bands[i]->channels = NULL;
11479 }
11480 }
11481}
Jeff Johnson295189b2012-06-20 16:38:30 -070011482/**---------------------------------------------------------------------------
11483
11484 \brief hdd_wlan_exit() - HDD WLAN exit function
11485
11486 This is the driver exit point (invoked during rmmod)
11487
11488 \param - pHddCtx - Pointer to the HDD Context
11489
11490 \return - None
11491
11492 --------------------------------------------------------------------------*/
11493void hdd_wlan_exit(hdd_context_t *pHddCtx)
11494{
11495 eHalStatus halStatus;
11496 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
11497 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +053011498 struct wiphy *wiphy = pHddCtx->wiphy;
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -080011499 hdd_adapter_t* pAdapter = NULL;
Jeff Johnson72a40512013-12-19 10:14:15 -080011500 struct statsContext powerContext;
Jeff Johnson295189b2012-06-20 16:38:30 -070011501 long lrc;
c_hpothu5ab05e92014-06-13 17:34:05 +053011502 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -070011503
11504 ENTER();
11505
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053011506
Katya Nigame7b69a82015-04-28 15:24:06 +053011507 if (VOS_MONITOR_MODE == hdd_get_conparam())
11508 {
11509 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: MONITOR MODE",__func__);
11510 wlan_hdd_mon_close(pHddCtx);
Hanumantha Reddy Pothulac99bc062015-09-08 14:59:26 +053011511 goto free_hdd_ctx;
Katya Nigame7b69a82015-04-28 15:24:06 +053011512 }
11513 else if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -080011514 {
11515 // Unloading, restart logic is no more required.
11516 wlan_hdd_restart_deinit(pHddCtx);
Jeff Johnsone7245742012-09-05 17:12:55 -070011517
Agarwal Ashishb20e0ff2014-12-17 22:50:19 +053011518#ifdef FEATURE_WLAN_TDLS
11519 /* At the time of driver unloading; if tdls connection is present;
11520 * hdd_rx_packet_cbk calls wlan_hdd_tdls_find_peer.
11521 * wlan_hdd_tdls_find_peer always checks for valid context;
11522 * as load/unload in progress there can be a race condition.
11523 * hdd_rx_packet_cbk calls wlan_hdd_tdls_find_peer only
11524 * when tdls state is enabled.
11525 * As soon as driver set load/unload flag; tdls flag also needs
11526 * to be disabled so that hdd_rx_packet_cbk won't call
11527 * wlan_hdd_tdls_find_peer.
11528 */
Masti, Narayanraddi20494af2015-12-17 20:56:42 +053011529 wlan_hdd_tdls_set_mode(pHddCtx, eTDLS_SUPPORT_DISABLED, FALSE,
11530 HDD_SET_TDLS_MODE_SOURCE_USER);
Agarwal Ashishb20e0ff2014-12-17 22:50:19 +053011531#endif
11532
c_hpothu5ab05e92014-06-13 17:34:05 +053011533 vosStatus = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
11534 while (NULL != pAdapterNode && VOS_STATUS_E_EMPTY != vosStatus)
Jeff Johnson295189b2012-06-20 16:38:30 -070011535 {
c_hpothu5ab05e92014-06-13 17:34:05 +053011536 pAdapter = pAdapterNode->pAdapter;
11537 if (NULL != pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -070011538 {
Mahesh A Saptasagar305e2632015-03-04 12:57:33 +053011539 /* Disable TX on the interface, after this hard_start_xmit() will
11540 * not be called on that interface
11541 */
11542 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
11543 netif_tx_disable(pAdapter->dev);
11544
11545 /* Mark the interface status as "down" for outside world */
11546 netif_carrier_off(pAdapter->dev);
11547
Agarwal Ashish9ffa5b92014-11-18 21:07:02 +053011548 /* DeInit the adapter. This ensures that all data packets
11549 * are freed.
11550 */
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +053011551#ifdef FEATURE_WLAN_TDLS
11552 mutex_lock(&pHddCtx->tdls_lock);
11553#endif
c_hpothu002231a2015-02-05 14:58:51 +053011554 hdd_deinit_adapter(pHddCtx, pAdapter, FALSE);
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +053011555#ifdef FEATURE_WLAN_TDLS
11556 mutex_unlock(&pHddCtx->tdls_lock);
11557#endif
Masti, Narayanraddi26378462016-01-05 18:20:28 +053011558 vos_flush_delayed_work(&pHddCtx->scan_ctxt.scan_work);
11559
11560 wlan_hdd_init_deinit_defer_scan_context(&pHddCtx->scan_ctxt);
Agarwal Ashish9ffa5b92014-11-18 21:07:02 +053011561
c_hpothu5ab05e92014-06-13 17:34:05 +053011562 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode ||
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +053011563 WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ||
11564 WLAN_HDD_MONITOR == pAdapter->device_mode)
c_hpothu5ab05e92014-06-13 17:34:05 +053011565 {
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +053011566 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode ||
11567 WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)
11568 wlan_hdd_cfg80211_deregister_frames(pAdapter);
11569
c_hpothu5ab05e92014-06-13 17:34:05 +053011570 hdd_UnregisterWext(pAdapter->dev);
11571 }
Kaushik, Sushant4975a572014-10-21 16:07:48 +053011572
Jeff Johnson295189b2012-06-20 16:38:30 -070011573 }
c_hpothu5ab05e92014-06-13 17:34:05 +053011574 vosStatus = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
11575 pAdapterNode = pNext;
Jeff Johnson295189b2012-06-20 16:38:30 -070011576 }
mukul sharmabab477d2015-06-11 17:14:55 +053011577
Kaushik, Sushant4975a572014-10-21 16:07:48 +053011578 // Cancel any outstanding scan requests. We are about to close all
11579 // of our adapters, but an adapter structure is what SME passes back
11580 // to our callback function. Hence if there are any outstanding scan
11581 // requests then there is a race condition between when the adapter
11582 // is closed and when the callback is invoked.We try to resolve that
11583 // race condition here by canceling any outstanding scans before we
11584 // close the adapters.
11585 // Note that the scans may be cancelled in an asynchronous manner,
11586 // so ideally there needs to be some kind of synchronization. Rather
11587 // than introduce a new synchronization here, we will utilize the
11588 // fact that we are about to Request Full Power, and since that is
11589 // synchronized, the expectation is that by the time Request Full
11590 // Power has completed all scans will be cancelled.
11591 if (pHddCtx->scan_info.mScanPending)
11592 {
Hema Aparna Medicharlaf05f6cd2015-01-21 14:44:19 +053011593 if(NULL != pAdapter)
11594 {
11595 hddLog(VOS_TRACE_LEVEL_INFO,
11596 FL("abort scan mode: %d sessionId: %d"),
11597 pAdapter->device_mode,
11598 pAdapter->sessionId);
11599 }
11600 hdd_abort_mac_scan(pHddCtx,
11601 pHddCtx->scan_info.sessionId,
11602 eCSR_SCAN_ABORT_DEFAULT);
Kaushik, Sushant4975a572014-10-21 16:07:48 +053011603 }
Jeff Johnson295189b2012-06-20 16:38:30 -070011604 }
c_hpothu5ab05e92014-06-13 17:34:05 +053011605 else
Jeff Johnson88ba7742013-02-27 14:36:02 -080011606 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +053011607 hddLog(VOS_TRACE_LEVEL_INFO,"%s: FTM MODE",__func__);
Hanumantha Reddy Pothula45af96b2015-02-12 16:07:58 +053011608 if (pHddCtx->ftm.ftm_state == WLAN_FTM_STARTING)
11609 {
11610 INIT_COMPLETION(pHddCtx->ftm.startCmpVar);
11611 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
11612 "%s: in middle of FTM START", __func__);
11613 lrc = wait_for_completion_timeout(&pHddCtx->ftm.startCmpVar,
11614 msecs_to_jiffies(20000));
11615 if(!lrc)
11616 {
11617 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
11618 "%s: timedout on ftmStartCmpVar fatal error", __func__);
11619 }
11620 }
Jeff Johnson88ba7742013-02-27 14:36:02 -080011621 wlan_hdd_ftm_close(pHddCtx);
11622 goto free_hdd_ctx;
11623 }
c_hpothu6ff1c3c2013-10-01 19:01:57 +053011624
Jeff Johnson295189b2012-06-20 16:38:30 -070011625 /* DeRegister with platform driver as client for Suspend/Resume */
11626 vosStatus = hddDeregisterPmOps(pHddCtx);
11627 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
11628 {
11629 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
11630 VOS_ASSERT(0);
11631 }
11632
11633 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
11634 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
11635 {
11636 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
11637 }
Jeff Johnson295189b2012-06-20 16:38:30 -070011638
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -070011639 //Stop the traffic monitor timer
Mahesh A Saptasagard461e432016-07-20 15:01:40 +053011640 if ((pHddCtx->cfg_ini->dynSplitscan) && (VOS_TIMER_STATE_RUNNING ==
11641 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr)))
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -070011642 {
11643 vos_timer_stop(&pHddCtx->tx_rx_trafficTmr);
11644 }
11645
11646 // Destroy the traffic monitor timer
Mahesh A Saptasagard461e432016-07-20 15:01:40 +053011647 if ((pHddCtx->cfg_ini->dynSplitscan) &&
11648 (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
11649 &pHddCtx->tx_rx_trafficTmr))))
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -070011650 {
11651 hddLog(VOS_TRACE_LEVEL_ERROR,
11652 "%s: Cannot deallocate Traffic monitor timer", __func__);
11653 }
11654
Bhargav Shahd0715912015-10-01 18:17:37 +053011655 if (VOS_TIMER_STATE_RUNNING ==
11656 vos_timer_getCurrentState(&pHddCtx->delack_timer)) {
11657 vos_timer_stop(&pHddCtx->delack_timer);
11658 }
11659
11660 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
11661 &pHddCtx->delack_timer))) {
11662 hddLog(VOS_TRACE_LEVEL_ERROR,
11663 "%s: Cannot deallocate Bus bandwidth timer", __func__);
11664 }
11665
Masti, Narayanraddi44b0db02015-12-22 11:54:35 +053011666 if (VOS_TIMER_STATE_RUNNING ==
11667 vos_timer_getCurrentState(&pHddCtx->tdls_source_timer)) {
11668 vos_timer_stop(&pHddCtx->tdls_source_timer);
11669 }
11670
Abhishek Singh8a3e4dc2017-01-02 10:39:18 +053011671 vos_set_snoc_high_freq_voting(false);
11672
Masti, Narayanraddi44b0db02015-12-22 11:54:35 +053011673 vos_timer_destroy(&pHddCtx->tdls_source_timer);
11674
Jeff Johnson295189b2012-06-20 16:38:30 -070011675 //Disable IMPS/BMPS as we do not want the device to enter any power
11676 //save mode during shutdown
11677 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
11678 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
11679 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
11680
11681 //Ensure that device is in full power as we will touch H/W during vos_Stop
11682 init_completion(&powerContext.completion);
11683 powerContext.magic = POWER_CONTEXT_MAGIC;
11684
11685 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
11686 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
11687
11688 if (eHAL_STATUS_SUCCESS != halStatus)
11689 {
11690 if (eHAL_STATUS_PMC_PENDING == halStatus)
11691 {
11692 /* request was sent -- wait for the response */
11693 lrc = wait_for_completion_interruptible_timeout(
11694 &powerContext.completion,
11695 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
Jeff Johnson295189b2012-06-20 16:38:30 -070011696 if (lrc <= 0)
11697 {
11698 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070011699 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -070011700 }
11701 }
11702 else
11703 {
11704 hddLog(VOS_TRACE_LEVEL_ERROR,
11705 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070011706 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -070011707 /* continue -- need to clean up as much as possible */
11708 }
11709 }
Hanumantha Reddy Pothula81b42b22015-05-12 13:52:00 +053011710 if ((eHAL_STATUS_SUCCESS == halStatus) ||
11711 (eHAL_STATUS_PMC_PENDING == halStatus && lrc > 0))
11712 {
11713 /* This will issue a dump command which will clean up
11714 BTQM queues and unblock MC thread */
11715 vos_fwDumpReq(274, 0, 0, 0, 0, 1);
11716 }
Jeff Johnson295189b2012-06-20 16:38:30 -070011717
Jeff Johnson72a40512013-12-19 10:14:15 -080011718 /* either we never sent a request, we sent a request and received a
11719 response or we sent a request and timed out. if we never sent a
11720 request or if we sent a request and got a response, we want to
11721 clear the magic out of paranoia. if we timed out there is a
11722 race condition such that the callback function could be
11723 executing at the same time we are. of primary concern is if the
11724 callback function had already verified the "magic" but had not
11725 yet set the completion variable when a timeout occurred. we
11726 serialize these activities by invalidating the magic while
11727 holding a shared spinlock which will cause us to block if the
11728 callback is currently executing */
11729 spin_lock(&hdd_context_lock);
11730 powerContext.magic = 0;
11731 spin_unlock(&hdd_context_lock);
11732
Hema Aparna Medicharlaa6cf65e2015-06-01 16:23:28 +053011733 /* If Device is shutdown, no point for SME to wait for responses
11734 from device. Pre Close SME */
11735 if(wcnss_device_is_shutdown())
11736 {
11737 sme_PreClose(pHddCtx->hHal);
11738 }
Yue Ma0d4891e2013-08-06 17:01:45 -070011739 hdd_debugfs_exit(pHddCtx);
11740
Ratheesh S P35ed8b12015-04-27 14:01:07 +053011741#ifdef WLAN_NS_OFFLOAD
Ratheesh S P36dbc932015-08-07 14:28:57 +053011742 hddLog(LOG1, FL("Unregister IPv6 notifier"));
Ratheesh S P35ed8b12015-04-27 14:01:07 +053011743 unregister_inet6addr_notifier(&pHddCtx->ipv6_notifier);
11744#endif
Ratheesh S P36dbc932015-08-07 14:28:57 +053011745 hddLog(LOG1, FL("Unregister IPv4 notifier"));
Ratheesh S P35ed8b12015-04-27 14:01:07 +053011746 unregister_inetaddr_notifier(&pHddCtx->ipv4_notifier);
11747
Jeff Johnson295189b2012-06-20 16:38:30 -070011748 // Unregister the Net Device Notifier
11749 unregister_netdevice_notifier(&hdd_netdev_notifier);
11750
Jeff Johnson295189b2012-06-20 16:38:30 -070011751 hdd_stop_all_adapters( pHddCtx );
11752
Jeff Johnson295189b2012-06-20 16:38:30 -070011753#ifdef WLAN_BTAMP_FEATURE
11754 vosStatus = WLANBAP_Stop(pVosContext);
11755 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
11756 {
11757 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
11758 "%s: Failed to stop BAP",__func__);
11759 }
11760#endif //WLAN_BTAMP_FEATURE
11761
11762 //Stop all the modules
11763 vosStatus = vos_stop( pVosContext );
11764 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
11765 {
11766 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
11767 "%s: Failed to stop VOSS",__func__);
11768 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
Hanumantha Reddy Pothulabd9601a2016-02-12 13:22:27 +053011769 if (isSsrPanicOnFailure())
11770 VOS_BUG(0);
Jeff Johnson295189b2012-06-20 16:38:30 -070011771 }
11772
Jeff Johnson295189b2012-06-20 16:38:30 -070011773 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -070011774 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -070011775
11776 //Close the scheduler before calling vos_close to make sure no thread is
11777 // scheduled after the each module close is called i.e after all the data
11778 // structures are freed.
11779 vosStatus = vos_sched_close( pVosContext );
11780 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
11781 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
11782 "%s: Failed to close VOSS Scheduler",__func__);
11783 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
11784 }
Jeff Johnsone7245742012-09-05 17:12:55 -070011785#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
11786 /* Destroy the wake lock */
Sushant Kaushik83392fa2015-05-05 17:44:40 +053011787 vos_wake_lock_destroy(&pHddCtx->rx_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -070011788#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -080011789 /* Destroy the wake lock */
Sushant Kaushik83392fa2015-05-05 17:44:40 +053011790 vos_wake_lock_destroy(&pHddCtx->sap_wake_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070011791
Mihir Shete7a24b5f2013-12-21 12:18:31 +053011792#ifdef CONFIG_ENABLE_LINUX_REG
11793 vosStatus = vos_nv_close();
11794 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
11795 {
11796 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
11797 "%s: Failed to close NV", __func__);
11798 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
11799 }
11800#endif
11801
Jeff Johnson295189b2012-06-20 16:38:30 -070011802 //Close VOSS
11803 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
11804 vos_close(pVosContext);
11805
Jeff Johnson295189b2012-06-20 16:38:30 -070011806 //Close Watchdog
11807 if(pHddCtx->cfg_ini->fIsLogpEnabled)
11808 vos_watchdog_close(pVosContext);
11809
Gopichand Nakkalaa0358482013-06-12 17:05:47 +053011810 //Clean up HDD Nlink Service
11811 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Gopichand Nakkalaa0358482013-06-12 17:05:47 +053011812
Manjeet Singh47ee8472016-04-11 11:57:18 +053011813 hdd_close_tx_queues(pHddCtx);
c_manjeecfd1efb2015-09-25 19:32:34 +053011814 wlan_free_fwr_mem_dump_buffer();
11815 memdump_deinit();
11816
Vinay Krishna Erannad938c422014-03-10 17:14:21 +053011817#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +053011818 if (pHddCtx->cfg_ini->wlanLoggingEnable)
Vinay Krishna Erannad938c422014-03-10 17:14:21 +053011819 {
11820 wlan_logging_sock_deactivate_svc();
11821 }
11822#endif
11823
Vinay Krishna Erannaef30b522014-08-26 17:48:16 +053011824#ifdef WLAN_KD_READY_NOTIFIER
11825 nl_srv_exit(pHddCtx->ptt_pid);
11826#else
11827 nl_srv_exit();
11828#endif /* WLAN_KD_READY_NOTIFIER */
11829
Abhishek Singh00b71972016-01-07 10:51:04 +053011830#ifdef WLAN_FEATURE_RMC
11831 hdd_close_cesium_nl_sock();
11832#endif /* WLAN_FEATURE_RMC */
Vinay Krishna Erannaef30b522014-08-26 17:48:16 +053011833
Jeff Johnson295189b2012-06-20 16:38:30 -070011834 hdd_close_all_adapters( pHddCtx );
11835
Padma, Santhosh Kumar9cd38332015-11-17 12:18:10 +053011836 vos_flush_delayed_work(&pHddCtx->spoof_mac_addr_work);
Abhishek Singh78c691f2017-11-30 13:48:44 +053011837 vos_flush_delayed_work(&pHddCtx->ecsa_chan_change_work);
Kapil Gupta137ef892016-12-13 19:38:00 +053011838 vos_flush_work(&pHddCtx->sap_start_work);
Padma, Santhosh Kumar9cd38332015-11-17 12:18:10 +053011839
Hanumantha Reddy Pothula97f9bc92015-08-10 17:21:20 +053011840free_hdd_ctx:
Jeff Johnson295189b2012-06-20 16:38:30 -070011841 /* free the power on lock from platform driver */
11842 if (free_riva_power_on_lock("wlan"))
11843 {
11844 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
11845 __func__);
11846 }
11847
c_hpothu78c7b602014-05-17 17:35:49 +053011848 //Free up dynamically allocated members inside HDD Adapter
11849 if (pHddCtx->cfg_ini)
11850 {
11851 kfree(pHddCtx->cfg_ini);
11852 pHddCtx->cfg_ini= NULL;
11853 }
11854
Hanumantha Reddy Pothula6fe221c2016-01-28 15:01:09 +053011855 /* FTM/MONITOR mode, WIPHY did not registered
Leo Changf04ddad2013-09-18 13:46:38 -070011856 If un-register here, system crash will happen */
Hanumantha Reddy Pothula6fe221c2016-01-28 15:01:09 +053011857 if (!(VOS_FTM_MODE == hdd_get_conparam() ||
11858 VOS_MONITOR_MODE == hdd_get_conparam()))
Leo Changf04ddad2013-09-18 13:46:38 -070011859 {
11860 wiphy_unregister(wiphy) ;
Agrawal Ashish33ec71e2015-11-26 20:20:58 +053011861 hdd_wlan_free_wiphy_channels(wiphy);
Leo Changf04ddad2013-09-18 13:46:38 -070011862 }
Jeff Johnson295189b2012-06-20 16:38:30 -070011863 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -070011864 if (hdd_is_ssr_required())
11865 {
11866 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -070011867 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -070011868 msleep(5000);
11869 }
11870 hdd_set_ssr_required (VOS_FALSE);
11871}
11872
11873
11874/**---------------------------------------------------------------------------
11875
11876 \brief hdd_update_config_from_nv() - Function to update the contents of
11877 the running configuration with parameters taken from NV storage
11878
11879 \param - pHddCtx - Pointer to the HDD global context
11880
11881 \return - VOS_STATUS_SUCCESS if successful
11882
11883 --------------------------------------------------------------------------*/
11884static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
11885{
Jeff Johnson295189b2012-06-20 16:38:30 -070011886 v_BOOL_t itemIsValid = VOS_FALSE;
11887 VOS_STATUS status;
11888 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
11889 v_U8_t macLoop;
11890
11891 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
11892 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
11893 if(status != VOS_STATUS_SUCCESS)
11894 {
Arif Hussain6d2a3322013-11-17 19:50:10 -080011895 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed");
Jeff Johnson295189b2012-06-20 16:38:30 -070011896 return VOS_STATUS_E_FAILURE;
11897 }
11898
11899 if (itemIsValid == VOS_TRUE)
11900 {
Arif Hussain6d2a3322013-11-17 19:50:10 -080011901 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV");
Jeff Johnson295189b2012-06-20 16:38:30 -070011902 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
11903 VOS_MAX_CONCURRENCY_PERSONA);
11904 if(status != VOS_STATUS_SUCCESS)
11905 {
11906 /* Get MAC from NV fail, not update CFG info
11907 * INI MAC value will be used for MAC setting */
Arif Hussain6d2a3322013-11-17 19:50:10 -080011908 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed");
Jeff Johnson295189b2012-06-20 16:38:30 -070011909 return VOS_STATUS_E_FAILURE;
11910 }
11911
11912 /* If first MAC is not valid, treat all others are not valid
11913 * Then all MACs will be got from ini file */
11914 if(vos_is_macaddr_zero(&macFromNV[0]))
11915 {
11916 /* MAC address in NV file is not configured yet */
11917 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
11918 return VOS_STATUS_E_INVAL;
11919 }
11920
11921 /* Get MAC address from NV, update CFG info */
11922 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
11923 {
11924 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
11925 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +053011926 hddLog(VOS_TRACE_LEVEL_ERROR,"not valid MAC from NV for %d", macLoop);
Jeff Johnson295189b2012-06-20 16:38:30 -070011927 /* This MAC is not valid, skip it
11928 * This MAC will be got from ini file */
11929 }
11930 else
11931 {
11932 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
11933 (v_U8_t *)&macFromNV[macLoop].bytes[0],
11934 VOS_MAC_ADDR_SIZE);
11935 }
11936 }
11937 }
11938 else
11939 {
11940 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
11941 return VOS_STATUS_E_FAILURE;
11942 }
Jeff Johnson295189b2012-06-20 16:38:30 -070011943
Jeff Johnson295189b2012-06-20 16:38:30 -070011944
11945 return VOS_STATUS_SUCCESS;
11946}
11947
11948/**---------------------------------------------------------------------------
11949
11950 \brief hdd_post_voss_start_config() - HDD post voss start config helper
11951
11952 \param - pAdapter - Pointer to the HDD
11953
11954 \return - None
11955
11956 --------------------------------------------------------------------------*/
11957VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
11958{
11959 eHalStatus halStatus;
11960 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +053011961 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -070011962
Jeff Johnson295189b2012-06-20 16:38:30 -070011963
11964 // Send ready indication to the HDD. This will kick off the MAC
11965 // into a 'running' state and should kick off an initial scan.
11966 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
11967 if ( !HAL_STATUS_SUCCESS( halStatus ) )
11968 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +053011969 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -070011970 "code %08d [x%08x]",__func__, halStatus, halStatus );
11971 return VOS_STATUS_E_FAILURE;
11972 }
11973
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +053011974 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -070011975 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
11976 // And RIVA will crash
11977 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
11978 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +053011979 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
11980 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
11981
11982
Jeff Johnson295189b2012-06-20 16:38:30 -070011983 return VOS_STATUS_SUCCESS;
11984}
11985
Jeff Johnson295189b2012-06-20 16:38:30 -070011986/* wake lock APIs for HDD */
Sushant Kaushik83392fa2015-05-05 17:44:40 +053011987void hdd_prevent_suspend(uint32_t reason)
Jeff Johnson295189b2012-06-20 16:38:30 -070011988{
Sushant Kaushik83392fa2015-05-05 17:44:40 +053011989
11990 vos_wake_lock_acquire(&wlan_wake_lock, reason);
11991
Jeff Johnson295189b2012-06-20 16:38:30 -070011992}
11993
Sushant Kaushik83392fa2015-05-05 17:44:40 +053011994void hdd_allow_suspend(uint32_t reason)
Jeff Johnson295189b2012-06-20 16:38:30 -070011995{
Sushant Kaushik83392fa2015-05-05 17:44:40 +053011996
11997 vos_wake_lock_release(&wlan_wake_lock, reason);
11998
Jeff Johnson295189b2012-06-20 16:38:30 -070011999}
12000
Sushant Kaushik83392fa2015-05-05 17:44:40 +053012001void hdd_prevent_suspend_timeout(v_U32_t timeout, uint32_t reason)
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -070012002{
Sushant Kaushik83392fa2015-05-05 17:44:40 +053012003
12004 vos_wake_lock_timeout_release(&wlan_wake_lock, timeout,
12005 reason);
12006
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -070012007}
12008
Jeff Johnson295189b2012-06-20 16:38:30 -070012009/**---------------------------------------------------------------------------
12010
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070012011 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
12012 information between Host and Riva
12013
12014 This function gets reported version of FW
12015 It also finds the version of Riva headers used to compile the host
12016 It compares the above two and prints a warning if they are different
12017 It gets the SW and HW version string
12018 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
12019 indicating the features they support through a bitmap
12020
12021 \param - pHddCtx - Pointer to HDD context
12022
12023 \return - void
12024
12025 --------------------------------------------------------------------------*/
12026
12027void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
12028{
12029
12030 tSirVersionType versionCompiled;
12031 tSirVersionType versionReported;
12032 tSirVersionString versionString;
12033 tANI_U8 fwFeatCapsMsgSupported = 0;
12034 VOS_STATUS vstatus;
12035
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -080012036 memset(&versionCompiled, 0, sizeof(versionCompiled));
12037 memset(&versionReported, 0, sizeof(versionReported));
12038
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070012039 /* retrieve and display WCNSS version information */
12040 do {
12041
12042 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
12043 &versionCompiled);
12044 if (!VOS_IS_STATUS_SUCCESS(vstatus))
12045 {
12046 hddLog(VOS_TRACE_LEVEL_FATAL,
12047 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070012048 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070012049 break;
12050 }
12051
12052 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
12053 &versionReported);
12054 if (!VOS_IS_STATUS_SUCCESS(vstatus))
12055 {
12056 hddLog(VOS_TRACE_LEVEL_FATAL,
12057 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070012058 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070012059 break;
12060 }
12061
12062 if ((versionCompiled.major != versionReported.major) ||
12063 (versionCompiled.minor != versionReported.minor) ||
12064 (versionCompiled.version != versionReported.version) ||
12065 (versionCompiled.revision != versionReported.revision))
12066 {
12067 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
12068 "Host expected %u.%u.%u.%u\n",
12069 WLAN_MODULE_NAME,
12070 (int)versionReported.major,
12071 (int)versionReported.minor,
12072 (int)versionReported.version,
12073 (int)versionReported.revision,
12074 (int)versionCompiled.major,
12075 (int)versionCompiled.minor,
12076 (int)versionCompiled.version,
12077 (int)versionCompiled.revision);
12078 }
12079 else
12080 {
12081 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
12082 WLAN_MODULE_NAME,
12083 (int)versionReported.major,
12084 (int)versionReported.minor,
12085 (int)versionReported.version,
12086 (int)versionReported.revision);
12087 }
12088
12089 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
12090 versionString,
12091 sizeof(versionString));
12092 if (!VOS_IS_STATUS_SUCCESS(vstatus))
12093 {
12094 hddLog(VOS_TRACE_LEVEL_FATAL,
12095 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070012096 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070012097 break;
12098 }
12099
12100 pr_info("%s: WCNSS software version %s\n",
12101 WLAN_MODULE_NAME, versionString);
Sushant Kaushik084f6592015-09-10 13:11:56 +053012102 vos_mem_copy(pHddCtx->fw_Version, versionString, sizeof(versionString));
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070012103
12104 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
12105 versionString,
12106 sizeof(versionString));
12107 if (!VOS_IS_STATUS_SUCCESS(vstatus))
12108 {
12109 hddLog(VOS_TRACE_LEVEL_FATAL,
12110 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070012111 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070012112 break;
12113 }
12114
12115 pr_info("%s: WCNSS hardware version %s\n",
12116 WLAN_MODULE_NAME, versionString);
12117
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -070012118 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
12119 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070012120 send the message only if it the riva is 1.1
12121 minor numbers for different riva branches:
12122 0 -> (1.0)Mainline Build
12123 1 -> (1.1)Mainline Build
12124 2->(1.04) Stability Build
12125 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -070012126 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070012127 ((versionReported.minor>=1) && (versionReported.version>=1)))
12128 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
12129 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -070012130
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070012131 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -080012132 {
12133#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
12134 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
12135 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
12136#endif
Ravi Joshid2ca7c42013-07-23 08:37:49 -070012137 /* Indicate if IBSS heartbeat monitoring needs to be offloaded */
12138 if (!pHddCtx->cfg_ini->enableIbssHeartBeatOffload)
12139 {
12140 sme_disableFeatureCapablity(IBSS_HEARTBEAT_OFFLOAD);
12141 }
12142
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070012143 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -080012144 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070012145
12146 } while (0);
12147
12148}
Neelansh Mittaledafed22014-09-04 18:54:39 +053012149void wlan_hdd_send_svc_nlink_msg(int type, void *data, int len)
12150{
12151 struct sk_buff *skb;
12152 struct nlmsghdr *nlh;
12153 tAniMsgHdr *ani_hdr;
Hanumantha Reddy Pothulacf2c7ea2015-04-27 14:50:47 +053012154 int flags = GFP_KERNEL;
Bhargav shah23c94942015-10-13 12:48:35 +053012155 void *nl_data = NULL;
Neelansh Mittaledafed22014-09-04 18:54:39 +053012156
Hanumantha Reddy Pothulacf2c7ea2015-04-27 14:50:47 +053012157 if (in_interrupt() || irqs_disabled() || in_atomic())
12158 flags = GFP_ATOMIC;
12159
12160 skb = alloc_skb(NLMSG_SPACE(WLAN_NL_MAX_PAYLOAD), flags);
Neelansh Mittaledafed22014-09-04 18:54:39 +053012161
12162 if(skb == NULL) {
12163 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
12164 "%s: alloc_skb failed", __func__);
12165 return;
12166 }
12167
12168 nlh = (struct nlmsghdr *)skb->data;
12169 nlh->nlmsg_pid = 0; /* from kernel */
12170 nlh->nlmsg_flags = 0;
12171 nlh->nlmsg_seq = 0;
12172 nlh->nlmsg_type = WLAN_NL_MSG_SVC;
12173
12174 ani_hdr = NLMSG_DATA(nlh);
12175 ani_hdr->type = type;
12176
12177 switch(type) {
12178 case WLAN_SVC_SAP_RESTART_IND:
12179 ani_hdr->length = 0;
12180 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr)));
12181 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr)));
12182 break;
Bhargav Shahd0715912015-10-01 18:17:37 +053012183 case WLAN_SVC_WLAN_TP_IND:
12184 ani_hdr->length = len;
12185 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr)
12186 + len));
12187 nl_data = (char *)ani_hdr + sizeof(tAniMsgHdr);
12188 memcpy(nl_data, data, len);
12189 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + len));
12190 break;
Bhargav shah23c94942015-10-13 12:48:35 +053012191 case WLAN_MSG_RPS_ENABLE_IND:
12192 ani_hdr->length = len;
12193 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + len));
12194 nl_data = (char *)ani_hdr + sizeof(tAniMsgHdr);
12195 memcpy(nl_data, data, len);
12196 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + len));
12197 break;
Neelansh Mittaledafed22014-09-04 18:54:39 +053012198 default:
12199 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
12200 "Attempt to send unknown nlink message %d", type);
12201 kfree_skb(skb);
12202 return;
12203 }
12204
12205 nl_srv_bcast(skb);
12206
12207 return;
12208}
12209
Bhargav Shahd0715912015-10-01 18:17:37 +053012210/**
12211 * hdd_request_tcp_delack() - Find the Delack value based on RX packet
12212 * @pHddCtx: Valid Global HDD context pointer
12213 * @rx_packets: Number of RX packet in perticular time
12214 *
12215 * Based on the RX packet this function calculate next value of tcp delack.
12216 * This function compare rx packet value to high and low threshold limit.
12217 *
12218 * Return: void
12219 */
12220void hdd_request_tcp_delack(hdd_context_t *pHddCtx, uint64_t rx_packets)
12221{
12222 /* average of rx_packets and prev_rx is taken so that
12223 bus width doesnot fluctuate much */
12224 uint64_t temp_rx = (rx_packets + pHddCtx->prev_rx)/2;
12225 TP_IND_TYPE next_rx_level = pHddCtx->cur_rx_level;
Neelansh Mittaledafed22014-09-04 18:54:39 +053012226
Bhargav Shahd0715912015-10-01 18:17:37 +053012227 pHddCtx->prev_rx = rx_packets;
12228 if (temp_rx > pHddCtx->cfg_ini->tcpDelAckThresholdHigh)
12229 next_rx_level = TP_IND_HIGH;
12230 else if (temp_rx <= pHddCtx->cfg_ini->tcpDelAckThresholdLow)
12231 next_rx_level = TP_IND_LOW;
12232
12233 hdd_set_delack_value(pHddCtx, next_rx_level);
12234}
12235
12236#define HDD_BW_GET_DIFF(x, y) ((x) >= (y) ? (x) - (y) : (ULONG_MAX - (y) + (x)))
12237
12238/**
12239 * hdd_tcp_delack_compute_function() - get link status
12240 * @priv: Valid Global HDD context pointer
12241 *
12242 * This function find number of RX packet during timer life span.
12243 * It request tcp delack with number of RX packet and re-configure delack timer
12244 * for tcpDelAckComputeInterval timer interval.
12245 *
12246 * Return: void
12247 */
12248void hdd_tcp_delack_compute_function(void *priv)
12249{
12250 hdd_context_t *pHddCtx = (hdd_context_t *)priv;
12251 hdd_adapter_t *pAdapter = NULL;
12252 v_U32_t rx_packets = 0;
12253 hdd_adapter_list_node_t *pAdapterNode = NULL;
12254 VOS_STATUS status = 0;
12255
12256 for (status = hdd_get_front_adapter(pHddCtx, &pAdapterNode);
12257 NULL != pAdapterNode && VOS_STATUS_SUCCESS == status;
12258 status = hdd_get_next_adapter(pHddCtx, pAdapterNode, &pAdapterNode)) {
12259 if ((pAdapter = pAdapterNode->pAdapter) == NULL)
12260 continue;
12261
12262 rx_packets += HDD_BW_GET_DIFF(pAdapter->stats.rx_packets,
12263 pAdapter->prev_rx_packets);
12264 pAdapter->prev_rx_packets = pAdapter->stats.rx_packets;
12265 }
12266
12267 hdd_request_tcp_delack(pHddCtx, rx_packets);
12268
12269 vos_timer_start(&pHddCtx->delack_timer,
12270 pHddCtx->cfg_ini->tcpDelAckComputeInterval);
12271}
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070012272
12273/**---------------------------------------------------------------------------
12274
Gopichand Nakkalafce506f2013-07-03 23:55:16 +053012275 \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
12276
12277 \param - pHddCtx - Pointer to the hdd context
12278
12279 \return - true if hardware supports 5GHz
12280
12281 --------------------------------------------------------------------------*/
Vinay Krishna Erannafacf5e22014-02-24 13:16:25 +053012282boolean hdd_is_5g_supported(hdd_context_t * pHddCtx)
Gopichand Nakkalafce506f2013-07-03 23:55:16 +053012283{
12284 /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
12285 * then hardware support 5Ghz.
12286 */
12287 if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode())
12288 {
Ratheesh S P36dbc932015-08-07 14:28:57 +053012289 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware supports 5Ghz", __func__);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +053012290 return true;
12291 }
12292 else
12293 {
Ratheesh S P36dbc932015-08-07 14:28:57 +053012294 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware doesn't supports 5Ghz",
Gopichand Nakkalafce506f2013-07-03 23:55:16 +053012295 __func__);
12296 return false;
12297 }
12298}
12299
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053012300/**---------------------------------------------------------------------------
12301
12302 \brief hdd_generate_iface_mac_addr_auto() - HDD Mac Interface Auto
12303 generate function
12304
12305 This is generate the random mac address for WLAN interface
12306
12307 \param - pHddCtx - Pointer to HDD context
12308 idx - Start interface index to get auto
12309 generated mac addr.
12310 mac_addr - Mac address
12311
12312 \return - 0 for success, < 0 for failure
12313
12314 --------------------------------------------------------------------------*/
12315
12316static int hdd_generate_iface_mac_addr_auto(hdd_context_t *pHddCtx,
12317 int idx, v_MACADDR_t mac_addr)
12318{
12319 int i;
12320 unsigned int serialno;
12321 serialno = wcnss_get_serial_number();
12322
12323 if (0 != serialno)
12324 {
12325 /* MAC address has 3 bytes of OUI so we have a maximum of 3
12326 bytes of the serial number that can be used to generate
12327 the other 3 bytes of the MAC address. Mask off all but
12328 the lower 3 bytes (this will also make sure we don't
12329 overflow in the next step) */
12330 serialno &= 0x00FFFFFF;
12331
12332 /* we need a unique address for each session */
12333 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
12334
12335 /* autogen other Mac addresses */
12336 for (i = idx; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
12337 {
12338 /* start with the entire default address */
12339 pHddCtx->cfg_ini->intfMacAddr[i] = mac_addr;
12340 /* then replace the lower 3 bytes */
12341 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
12342 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
12343 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
12344
Nachiket Kukadede2e24f2017-09-25 16:24:27 +053012345 if (0 == memcmp(&pHddCtx->cfg_ini->intfMacAddr[i].bytes[0],
12346 &mac_addr.bytes[0], VOS_MAC_ADDR_SIZE))
12347 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] +=
12348 VOS_MAX_CONCURRENCY_PERSONA;
12349
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053012350 serialno++;
12351 hddLog(VOS_TRACE_LEVEL_ERROR,
12352 "%s: Derived Mac Addr: "
12353 MAC_ADDRESS_STR, __func__,
12354 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[i].bytes));
12355 }
12356
12357 }
12358 else
12359 {
12360 hddLog(LOGE, FL("Failed to Get Serial NO"));
12361 return -1;
12362 }
12363 return 0;
12364}
Gopichand Nakkalafce506f2013-07-03 23:55:16 +053012365
Katya Nigame7b69a82015-04-28 15:24:06 +053012366int wlan_hdd_mon_open(hdd_context_t *pHddCtx)
12367{
12368 VOS_STATUS status;
12369 v_CONTEXT_t pVosContext= NULL;
12370 hdd_adapter_t *pAdapter= NULL;
12371
12372 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
12373
12374 if (NULL == pVosContext)
12375 {
12376 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
12377 "%s: Trying to open VOSS without a PreOpen", __func__);
12378 VOS_ASSERT(0);
12379 return VOS_STATUS_E_FAILURE;
12380 }
12381
12382 status = vos_nv_open();
12383 if (!VOS_IS_STATUS_SUCCESS(status))
12384 {
12385 /* NV module cannot be initialized */
12386 hddLog( VOS_TRACE_LEVEL_FATAL,
12387 "%s: vos_nv_open failed", __func__);
12388 return VOS_STATUS_E_FAILURE;
12389 }
12390
12391 status = vos_init_wiphy_from_nv_bin();
12392 if (!VOS_IS_STATUS_SUCCESS(status))
12393 {
12394 /* NV module cannot be initialized */
12395 hddLog( VOS_TRACE_LEVEL_FATAL,
12396 "%s: vos_init_wiphy failed", __func__);
12397 goto err_vos_nv_close;
12398 }
12399
12400 status = vos_open( &pVosContext, pHddCtx->parent_dev);
12401 if ( !VOS_IS_STATUS_SUCCESS( status ))
12402 {
12403 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
12404 goto err_vos_nv_close;
12405 }
12406
12407 status = vos_mon_start( pVosContext );
12408 if ( !VOS_IS_STATUS_SUCCESS( status ) )
12409 {
12410 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
12411 goto err_vosclose;
12412 }
12413
12414 WLANTL_SetMonRxCbk( pVosContext, hdd_rx_packet_monitor_cbk );
12415 WDA_featureCapsExchange(pVosContext);
12416 wcnss_wlan_set_drvdata(pHddCtx->parent_dev, pHddCtx);
12417
12418 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_MONITOR, "wlan%d",
12419 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
12420 if( pAdapter == NULL )
12421 {
12422 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
12423 goto err_close_adapter;
12424 }
12425
12426 //Initialize the nlink service
12427 if(nl_srv_init() != 0)
12428 {
12429 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
12430 goto err_close_adapter;
12431 }
12432 return VOS_STATUS_SUCCESS;
12433
12434err_close_adapter:
12435 hdd_close_all_adapters( pHddCtx );
12436 vos_mon_stop( pVosContext );
12437err_vosclose:
12438 status = vos_sched_close( pVosContext );
12439 if (!VOS_IS_STATUS_SUCCESS(status)) {
12440 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
12441 "%s: Failed to close VOSS Scheduler", __func__);
12442 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
12443 }
12444 vos_close(pVosContext );
12445
12446err_vos_nv_close:
12447 vos_nv_close();
12448
12449return status;
12450}
Gopichand Nakkalafce506f2013-07-03 23:55:16 +053012451/**---------------------------------------------------------------------------
12452
Mihir Shetefc7ff5b2014-01-27 11:30:05 +053012453 \brief hdd_11d_scan_done - callback to be executed when 11d scan is
12454 completed to flush out the scan results
12455
12456 11d scan is done during driver load and is a passive scan on all
12457 channels supported by the device, 11d scans may find some APs on
12458 frequencies which are forbidden to be used in the regulatory domain
12459 the device is operating in. If these APs are notified to the supplicant
12460 it may try to connect to these APs, thus flush out all the scan results
12461 which are present in SME after 11d scan is done.
12462
12463 \return - eHalStatus
12464
12465 --------------------------------------------------------------------------*/
12466static eHalStatus hdd_11d_scan_done(tHalHandle halHandle, void *pContext,
12467 tANI_U32 scanId, eCsrScanStatus status)
12468{
12469 ENTER();
12470
12471 sme_ScanFlushResult(halHandle, 0);
12472
12473 EXIT();
12474
12475 return eHAL_STATUS_SUCCESS;
12476}
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012477/**---------------------------------------------------------------------------
12478
12479 \brief hdd_init_frame_logging_done - callback to be executed when mgmt frame
12480 logging is completed successfully.
12481
12482 \return - None
12483
12484 --------------------------------------------------------------------------*/
c_manjeecfd1efb2015-09-25 19:32:34 +053012485void hdd_init_frame_logging_done(void *fwlogInitCbContext, tAniLoggingInitRsp *pRsp)
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012486{
Siddharth Bhald1be97f2015-05-27 22:39:59 +053012487 hdd_context_t* pHddCtx = (hdd_context_t*)fwlogInitCbContext;
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012488
12489 if (NULL == pHddCtx)
12490 {
12491 hddLog(VOS_TRACE_LEVEL_ERROR,
12492 "%s: HDD context is NULL",__func__);
12493 return;
12494 }
12495
c_manjeecfd1efb2015-09-25 19:32:34 +053012496 if ((pRsp->status == VOS_STATUS_SUCCESS) &&
Mahesh A Saptasagarfabb1a02015-06-29 12:17:04 +053012497 (TRUE == pHddCtx->cfg_ini->enableMgmtLogging))
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012498 {
12499 hddLog(VOS_TRACE_LEVEL_INFO, FL("Mgmt Frame Logging init successful"));
12500 pHddCtx->mgmt_frame_logging = TRUE;
12501 }
12502 else
12503 {
12504 hddLog(VOS_TRACE_LEVEL_INFO, FL("Mgmt Frame Logging init not success"));
12505 pHddCtx->mgmt_frame_logging = FALSE;
c_manjeecfd1efb2015-09-25 19:32:34 +053012506 return;
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012507 }
12508
c_manjeecfd1efb2015-09-25 19:32:34 +053012509 /*Check feature supported by FW*/
12510 if(TRUE == sme_IsFeatureSupportedByFW(MEMORY_DUMP_SUPPORTED))
12511 {
12512 //Store fwr mem dump size given by firmware.
12513 wlan_store_fwr_mem_dump_size(pRsp->fw_mem_dump_max_size);
12514 }
12515 else
12516 {
12517 wlan_store_fwr_mem_dump_size(0);
12518 }
12519
12520
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012521}
12522/**---------------------------------------------------------------------------
12523
12524 \brief hdd_init_frame_logging - function to initialize frame logging.
12525 Currently only Mgmt Frames are logged in both TX
12526 and Rx direction and are sent to userspace
12527 application using logger thread when queried.
12528
12529 \return - None
12530
12531 --------------------------------------------------------------------------*/
Siddharth Bhald1be97f2015-05-27 22:39:59 +053012532void hdd_init_frame_logging(hdd_context_t* pHddCtx)
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012533{
12534 eHalStatus halStatus = eHAL_STATUS_FAILURE;
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053012535 tSirFWLoggingInitParam wlanFWLoggingInitParam = {0};
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012536
Siddharth Bhald1be97f2015-05-27 22:39:59 +053012537 if (TRUE != sme_IsFeatureSupportedByFW(MGMT_FRAME_LOGGING) &&
12538 TRUE != sme_IsFeatureSupportedByFW(LOGGING_ENHANCEMENT))
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012539 {
12540 hddLog(VOS_TRACE_LEVEL_INFO, FL("MGMT_FRAME_LOGGING not supp by FW"));
12541 return;
12542 }
12543
c_manjeecfd1efb2015-09-25 19:32:34 +053012544 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Configuring %s %s %s %s Logging",__func__,
Siddharth Bhald1be97f2015-05-27 22:39:59 +053012545 pHddCtx->cfg_ini->enableFWLogging?"FW Log,":"",
12546 pHddCtx->cfg_ini->enableContFWLogging ? "Cont FW log,":"",
c_manjeecfd1efb2015-09-25 19:32:34 +053012547 pHddCtx->cfg_ini->enableMgmtLogging ? "Mgmt Pkt Log":"",
12548 pHddCtx->cfg_ini->enableFwrMemDump ? "Fw Mem dump":"");
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012549
Siddharth Bhald1be97f2015-05-27 22:39:59 +053012550 if (pHddCtx->cfg_ini->enableFWLogging ||
12551 pHddCtx->cfg_ini->enableContFWLogging)
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012552 {
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053012553 wlanFWLoggingInitParam.enableFlag |= WLAN_QXDM_LOG_EN;
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012554 }
12555
Sushant Kaushik46804902015-07-08 14:46:03 +053012556 if (pHddCtx->cfg_ini->enableMgmtLogging)
12557 {
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053012558 wlanFWLoggingInitParam.enableFlag |= WLAN_FRAME_LOG_EN;
Sushant Kaushik46804902015-07-08 14:46:03 +053012559 }
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012560 if (pHddCtx->cfg_ini->enableBMUHWtracing)
12561 {
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053012562 wlanFWLoggingInitParam.enableFlag |= WLAN_BMUHW_TRACE_LOG_EN;
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012563 }
c_manjeecfd1efb2015-09-25 19:32:34 +053012564 if(pHddCtx->cfg_ini->enableFwrMemDump &&
12565 (TRUE == sme_IsFeatureSupportedByFW(MEMORY_DUMP_SUPPORTED)))
12566 {
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053012567 wlanFWLoggingInitParam.enableFlag |= WLAN_FW_MEM_DUMP_EN;
c_manjeecfd1efb2015-09-25 19:32:34 +053012568 }
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053012569 if( wlanFWLoggingInitParam.enableFlag == 0 )
c_manjeecfd1efb2015-09-25 19:32:34 +053012570 {
12571 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Logging not enabled", __func__);
12572 return;
12573 }
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053012574 wlanFWLoggingInitParam.frameType = WLAN_FRAME_LOGGING_FRAMETYPE_MGMT;
12575 wlanFWLoggingInitParam.frameSize = WLAN_MGMT_LOGGING_FRAMESIZE_128BYTES;
12576 wlanFWLoggingInitParam.bufferMode = WLAN_FRAME_LOGGING_BUFFERMODE_CIRCULAR;
12577 wlanFWLoggingInitParam.continuousFrameLogging =
Siddharth Bhald1be97f2015-05-27 22:39:59 +053012578 pHddCtx->cfg_ini->enableContFWLogging;
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012579
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053012580 wlanFWLoggingInitParam.enableFlag &= ~WLAN_DPU_TXP_LOG_EN;
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012581
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053012582 wlanFWLoggingInitParam.minLogBufferSize =
Siddharth Bhald1be97f2015-05-27 22:39:59 +053012583 pHddCtx->cfg_ini->minLoggingBufferSize;
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053012584 wlanFWLoggingInitParam.maxLogBufferSize =
Siddharth Bhald1be97f2015-05-27 22:39:59 +053012585 pHddCtx->cfg_ini->maxLoggingBufferSize;
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053012586 wlanFWLoggingInitParam.fwlogInitCallback = hdd_init_frame_logging_done;
12587 wlanFWLoggingInitParam.fwlogInitCbContext= pHddCtx;
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012588
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053012589 halStatus = sme_InitMgmtFrameLogging(pHddCtx->hHal, &wlanFWLoggingInitParam);
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012590
12591 if (eHAL_STATUS_SUCCESS != halStatus)
12592 {
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053012593 hddLog(LOGE, FL("sme_InitMgmtFrameLogging failed, returned %d"),
12594 halStatus);
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012595 }
12596
12597 return;
12598}
Mihir Shetefc7ff5b2014-01-27 11:30:05 +053012599
Bhargav shah23c94942015-10-13 12:48:35 +053012600static void hdd_dp_util_send_rps_ind(hdd_context_t *hdd_ctxt)
12601{
12602 hdd_adapter_t *adapter;
12603 hdd_adapter_list_node_t *adapter_node, *next;
12604 VOS_STATUS status = VOS_STATUS_SUCCESS;
12605 struct wlan_rps_data rps_data;
12606 int count;
12607
12608 if(!hdd_ctxt->cfg_ini->rps_mask)
12609 {
12610 return;
12611 }
12612
12613 for (count=0; count < WLAN_SVC_IFACE_NUM_QUEUES; count++)
12614 {
12615 rps_data.cpu_map[count] = hdd_ctxt->cfg_ini->rps_mask;
12616 }
12617
12618 rps_data.num_queues = WLAN_SVC_IFACE_NUM_QUEUES;
12619
12620 hddLog(LOG1, FL("0x%x 0x%x 0x%x 0x%x 0x%x 0x%x"),
12621 rps_data.cpu_map[0], rps_data.cpu_map[1],rps_data.cpu_map[2],
12622 rps_data.cpu_map[3], rps_data.cpu_map[4], rps_data.cpu_map[5]);
12623
12624 status = hdd_get_front_adapter (hdd_ctxt, &adapter_node);
12625
12626 while (NULL != adapter_node && VOS_STATUS_SUCCESS == status)
12627 {
12628 adapter = adapter_node->pAdapter;
12629 if (NULL != adapter) {
12630 strlcpy(rps_data.ifname, adapter->dev->name,
12631 sizeof(rps_data.ifname));
12632 wlan_hdd_send_svc_nlink_msg(WLAN_MSG_RPS_ENABLE_IND,
12633 (void *)&rps_data,sizeof(rps_data));
12634 }
12635 status = hdd_get_next_adapter (hdd_ctxt, adapter_node, &next);
12636 adapter_node = next;
12637 }
12638}
12639
Masti, Narayanraddi26378462016-01-05 18:20:28 +053012640void wlan_hdd_schedule_defer_scan(struct work_struct *work)
12641{
12642 scan_context_t *scan_ctx =
12643 container_of(work, scan_context_t, scan_work.work);
12644
12645 if (NULL == scan_ctx)
12646 {
12647 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
12648 FL("scan_ctx is NULL"));
12649 return;
12650 }
12651
12652 if (unlikely(TDLS_CTX_MAGIC != scan_ctx->magic))
12653 return;
12654
12655 scan_ctx->attempt++;
12656
12657 wlan_hdd_cfg80211_scan(scan_ctx->wiphy,
12658#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
12659 scan_ctx->dev,
12660#endif
12661 scan_ctx->scan_request);
12662}
12663
12664int wlan_hdd_copy_defer_scan_context(hdd_context_t *pHddCtx,
12665 struct wiphy *wiphy,
12666#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
12667 struct net_device *dev,
12668#endif
12669 struct cfg80211_scan_request *request)
12670{
12671 scan_context_t *scan_ctx;
12672
12673 ENTER();
12674 if (0 != (wlan_hdd_validate_context(pHddCtx)))
12675 {
12676 return -1;
12677 }
12678
12679 scan_ctx = &pHddCtx->scan_ctxt;
12680
12681 scan_ctx->wiphy = wiphy;
12682#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
12683 scan_ctx->dev = dev;
12684#endif
12685
12686 scan_ctx->scan_request = request;
12687
12688 EXIT();
12689 return 0;
12690}
12691
12692void wlan_hdd_defer_scan_init_work(hdd_context_t *pHddCtx,
12693 struct wiphy *wiphy,
12694#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
12695 struct net_device *dev,
12696#endif
12697 struct cfg80211_scan_request *request,
12698 unsigned long delay)
12699{
12700 if (TDLS_CTX_MAGIC != pHddCtx->scan_ctxt.magic)
12701 {
12702#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
12703 wlan_hdd_copy_defer_scan_context(pHddCtx, wiphy, dev, request);
12704#else
12705 wlan_hdd_copy_defer_scan_context(pHddCtx, wiphy, request);
12706#endif
12707 pHddCtx->scan_ctxt.attempt = 0;
12708 pHddCtx->scan_ctxt.magic = TDLS_CTX_MAGIC;
12709 }
12710 schedule_delayed_work(&pHddCtx->scan_ctxt.scan_work, delay);
12711}
12712
12713void wlan_hdd_init_deinit_defer_scan_context(scan_context_t *scan_ctx)
12714{
12715 scan_ctx->magic = 0;
12716 scan_ctx->attempt = 0;
12717 scan_ctx->reject = 0;
12718 scan_ctx->scan_request = NULL;
12719
12720 return;
12721}
12722
Mihir Shetefc7ff5b2014-01-27 11:30:05 +053012723/**---------------------------------------------------------------------------
12724
Jeff Johnson295189b2012-06-20 16:38:30 -070012725 \brief hdd_wlan_startup() - HDD init function
12726
12727 This is the driver startup code executed once a WLAN device has been detected
12728
12729 \param - dev - Pointer to the underlying device
12730
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -080012731 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -070012732
12733 --------------------------------------------------------------------------*/
12734
12735int hdd_wlan_startup(struct device *dev )
12736{
12737 VOS_STATUS status;
12738 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -070012739 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -070012740 hdd_context_t *pHddCtx = NULL;
12741 v_CONTEXT_t pVosContext= NULL;
12742#ifdef WLAN_BTAMP_FEATURE
12743 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
12744 WLANBAP_ConfigType btAmpConfig;
12745 hdd_config_t *pConfig;
12746#endif
12747 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -070012748 struct wiphy *wiphy;
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053012749 v_MACADDR_t mac_addr;
Jeff Johnson295189b2012-06-20 16:38:30 -070012750
12751 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -070012752 /*
12753 * cfg80211: wiphy allocation
12754 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +053012755 wiphy = wlan_hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t)) ;
Jeff Johnson295189b2012-06-20 16:38:30 -070012756
12757 if(wiphy == NULL)
12758 {
12759 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -080012760 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -070012761 }
Jeff Johnson295189b2012-06-20 16:38:30 -070012762 pHddCtx = wiphy_priv(wiphy);
12763
Jeff Johnson295189b2012-06-20 16:38:30 -070012764 //Initialize the adapter context to zeros.
12765 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
12766
Jeff Johnson295189b2012-06-20 16:38:30 -070012767 pHddCtx->wiphy = wiphy;
Sushant Kaushik83392fa2015-05-05 17:44:40 +053012768 hdd_prevent_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_INIT);
Mihir Shete18156292014-03-11 15:38:30 +053012769 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_LOAD_IN_PROGRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -070012770
12771 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
12772
Siddharth Bhalcd92b782015-06-29 12:25:40 +053012773 /* register for riva power on lock to platform driver
12774 * Locking power early to ensure FW doesn't reset by kernel while
12775 * host driver is busy initializing itself */
12776 if (req_riva_power_on_lock("wlan"))
12777 {
12778 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
12779 __func__);
12780 goto err_free_hdd_context;
12781 }
12782
Jeff Johnson295189b2012-06-20 16:38:30 -070012783 /*Get vos context here bcoz vos_open requires it*/
12784 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
12785
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -080012786 if(pVosContext == NULL)
12787 {
12788 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
12789 goto err_free_hdd_context;
12790 }
12791
Jeff Johnson295189b2012-06-20 16:38:30 -070012792 //Save the Global VOSS context in adapter context for future.
12793 pHddCtx->pvosContext = pVosContext;
12794
12795 //Save the adapter context in global context for future.
12796 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
12797
Jeff Johnson295189b2012-06-20 16:38:30 -070012798 pHddCtx->parent_dev = dev;
Sreelakshmi Konamkif0646d52016-12-09 12:35:31 +053012799 pHddCtx->last_scan_reject_session_id = 0xFF;
12800 pHddCtx->last_scan_reject_reason = 0;
Sreelakshmi Konamki20ebed92016-10-27 12:13:30 +053012801 pHddCtx->last_scan_reject_timestamp = 0;
Abhishek Singhe4b12562017-06-20 16:53:39 +053012802 pHddCtx->scan_reject_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -070012803
12804 init_completion(&pHddCtx->full_pwr_comp_var);
12805 init_completion(&pHddCtx->standby_comp_var);
12806 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -070012807 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -080012808 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Kiet Lam46b8e4e2013-11-06 21:49:53 +053012809 init_completion(&pHddCtx->wiphy_channel_update_event);
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +053012810 init_completion(&pHddCtx->ssr_comp_var);
Mahesh A Saptasagar67ab9222015-10-21 15:38:41 +053012811 init_completion(&pHddCtx->mc_sus_event_var);
12812 init_completion(&pHddCtx->tx_sus_event_var);
12813 init_completion(&pHddCtx->rx_sus_event_var);
12814
Amar Singhala49cbc52013-10-08 18:37:44 -070012815
mukul sharma4bd8d2e2015-08-13 20:33:25 +053012816 hdd_init_ll_stats_ctx(pHddCtx);
Anurag Chouhan6ee81542017-02-09 18:09:27 +053012817 hdd_init_nud_stats_ctx(pHddCtx);
mukul sharma4bd8d2e2015-08-13 20:33:25 +053012818
Amar Singhala49cbc52013-10-08 18:37:44 -070012819#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhalfddc28c2013-09-05 13:03:40 -070012820 init_completion(&pHddCtx->linux_reg_req);
Amar Singhala49cbc52013-10-08 18:37:44 -070012821#else
12822 init_completion(&pHddCtx->driver_crda_req);
12823#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070012824
Padma, Santhosh Kumara1aa4a32015-06-19 19:00:46 +053012825#ifdef WLAN_FEATURE_EXTSCAN
12826 init_completion(&pHddCtx->ext_scan_context.response_event);
12827#endif /* WLAN_FEATURE_EXTSCAN */
12828
Kamath Vinayak4000c9a2013-08-23 14:24:27 +053012829 spin_lock_init(&pHddCtx->schedScan_lock);
Kapil Gupta137ef892016-12-13 19:38:00 +053012830 vos_spin_lock_init(&pHddCtx->sap_update_info_lock);
Kamath Vinayak4000c9a2013-08-23 14:24:27 +053012831
Jeff Johnson295189b2012-06-20 16:38:30 -070012832 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
12833
Padma, Santhosh Kumar9cd38332015-11-17 12:18:10 +053012834 vos_init_delayed_work(&pHddCtx->spoof_mac_addr_work,
12835 hdd_processSpoofMacAddrRequest);
Kapil Gupta137ef892016-12-13 19:38:00 +053012836 vos_init_work(&pHddCtx->sap_start_work, hdd_sap_restart_handle);
Abhishek Singh78c691f2017-11-30 13:48:44 +053012837 vos_init_delayed_work(&pHddCtx->ecsa_chan_change_work,
12838 hdd_force_scc_with_ecsa_handle);
Padma, Santhosh Kumar9cd38332015-11-17 12:18:10 +053012839
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +053012840#ifdef FEATURE_WLAN_TDLS
12841 /* tdls_lock is initialized before an hdd_open_adapter ( which is
12842 * invoked by other instances also) to protect the concurrent
12843 * access for the Adapters by TDLS module.
12844 */
12845 mutex_init(&pHddCtx->tdls_lock);
12846#endif
Siddharth Bhal76972212014-10-15 16:22:51 +053012847 mutex_init(&pHddCtx->spoofMacAddr.macSpoofingLock);
Mukul Sharma1fd6efd2015-02-14 00:29:14 +053012848 mutex_init(&pHddCtx->wmmLock);
12849
Srinivas Girigowda8bf64cb2015-09-30 19:50:09 +053012850 hdd_init_offloaded_packets_ctx(pHddCtx);
Agarwal Ashish1f422872014-07-22 00:11:55 +053012851 /* By default Strict Regulatory For FCC should be false */
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +053012852
Agarwal Ashish1f422872014-07-22 00:11:55 +053012853 pHddCtx->nEnableStrictRegulatoryForFCC = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -070012854 // Load all config first as TL config is needed during vos_open
12855 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
12856 if(pHddCtx->cfg_ini == NULL)
12857 {
12858 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
12859 goto err_free_hdd_context;
12860 }
12861
12862 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
12863
12864 // Read and parse the qcom_cfg.ini file
12865 status = hdd_parse_config_ini( pHddCtx );
12866 if ( VOS_STATUS_SUCCESS != status )
12867 {
12868 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
12869 __func__, WLAN_INI_FILE);
12870 goto err_config;
12871 }
Arif Hussaind5218912013-12-05 01:10:55 -080012872#ifdef MEMORY_DEBUG
12873 if (pHddCtx->cfg_ini->IsMemoryDebugSupportEnabled)
12874 vos_mem_init();
12875
12876 hddLog(VOS_TRACE_LEVEL_INFO, "%s: gEnableMemoryDebug=%d",
12877 __func__, pHddCtx->cfg_ini->IsMemoryDebugSupportEnabled);
12878#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070012879
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +053012880 /* INI has been read, initialise the configuredMcastBcastFilter with
12881 * INI value as this will serve as the default value
12882 */
12883 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
12884 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
12885 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +053012886
12887 if (false == hdd_is_5g_supported(pHddCtx))
12888 {
12889 //5Ghz is not supported.
12890 if (1 != pHddCtx->cfg_ini->nBandCapability)
12891 {
12892 hddLog(VOS_TRACE_LEVEL_INFO,
12893 "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__);
12894 pHddCtx->cfg_ini->nBandCapability = 1;
12895 }
12896 }
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +053012897
12898 /* If SNR Monitoring is enabled, FW has to parse all beacons
12899 * for calcaluting and storing the average SNR, so set Nth beacon
12900 * filter to 1 to enable FW to parse all the beaocons
12901 */
12902 if (1 == pHddCtx->cfg_ini->fEnableSNRMonitoring)
12903 {
12904 /* The log level is deliberately set to WARN as overriding
12905 * nthBeaconFilter to 1 will increase power cosumption and this
12906 * might just prove helpful to detect the power issue.
12907 */
12908 hddLog(VOS_TRACE_LEVEL_WARN,
12909 "%s: Setting pHddCtx->cfg_ini->nthBeaconFilter = 1", __func__);
12910 pHddCtx->cfg_ini->nthBeaconFilter = 1;
12911 }
Jeff Johnson295189b2012-06-20 16:38:30 -070012912 /*
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +053012913 * cfg80211: Initialization ...
Jeff Johnson295189b2012-06-20 16:38:30 -070012914 */
Manjeet Singh61016fa2016-12-02 11:10:19 +053012915 if (0 < wlan_hdd_cfg80211_init(dev, wiphy, pHddCtx->cfg_ini))
Jeff Johnson295189b2012-06-20 16:38:30 -070012916 {
Manjeet Singh61016fa2016-12-02 11:10:19 +053012917 hddLog(VOS_TRACE_LEVEL_FATAL,
12918 "%s: wlan_hdd_cfg80211_init return failure", __func__);
12919 goto err_config;
Jeff Johnson295189b2012-06-20 16:38:30 -070012920 }
Jeff Johnson295189b2012-06-20 16:38:30 -070012921
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -080012922 // Update VOS trace levels based upon the cfg.ini
12923 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
12924 pHddCtx->cfg_ini->vosTraceEnableBAP);
12925 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
12926 pHddCtx->cfg_ini->vosTraceEnableTL);
12927 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
12928 pHddCtx->cfg_ini->vosTraceEnableWDI);
12929 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
12930 pHddCtx->cfg_ini->vosTraceEnableHDD);
12931 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
12932 pHddCtx->cfg_ini->vosTraceEnableSME);
12933 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
12934 pHddCtx->cfg_ini->vosTraceEnablePE);
Katya Nigam70d68332013-09-16 16:49:45 +053012935 hdd_vos_trace_enable(VOS_MODULE_ID_PMC,
12936 pHddCtx->cfg_ini->vosTraceEnablePMC);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -080012937 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
12938 pHddCtx->cfg_ini->vosTraceEnableWDA);
12939 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
12940 pHddCtx->cfg_ini->vosTraceEnableSYS);
12941 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
12942 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -080012943 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
12944 pHddCtx->cfg_ini->vosTraceEnableSAP);
12945 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
12946 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -080012947
Jeff Johnson295189b2012-06-20 16:38:30 -070012948 // Update WDI trace levels based upon the cfg.ini
12949 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
12950 pHddCtx->cfg_ini->wdiTraceEnableDAL);
12951 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
12952 pHddCtx->cfg_ini->wdiTraceEnableCTL);
12953 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
12954 pHddCtx->cfg_ini->wdiTraceEnableDAT);
12955 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
12956 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -070012957
Jeff Johnson88ba7742013-02-27 14:36:02 -080012958 if (VOS_FTM_MODE == hdd_get_conparam())
12959 {
Jeff Johnson295189b2012-06-20 16:38:30 -070012960 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
12961 {
12962 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
12963 goto err_free_hdd_context;
12964 }
12965 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
Sachin Ahuja38ef5e02015-03-13 17:31:16 +053012966 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_NO_LOAD_UNLOAD_IN_PROGRESS;
c_hpothu2de0ef62014-04-15 16:16:15 +053012967 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -070012968 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -080012969 }
Jeff Johnson295189b2012-06-20 16:38:30 -070012970
Katya Nigame7b69a82015-04-28 15:24:06 +053012971 if( VOS_MONITOR_MODE == hdd_get_conparam())
12972 {
12973 if ( VOS_STATUS_SUCCESS != wlan_hdd_mon_open(pHddCtx))
12974 {
12975 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_mon_open Failed",__func__);
12976 goto err_free_hdd_context;
12977 }
12978 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Driver loaded in Monitor Mode",__func__);
12979 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_NO_LOAD_UNLOAD_IN_PROGRESS;
12980 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
12981 return VOS_STATUS_SUCCESS;
12982 }
12983
Jeff Johnson88ba7742013-02-27 14:36:02 -080012984 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -070012985 if(pHddCtx->cfg_ini->fIsLogpEnabled)
12986 {
12987 status = vos_watchdog_open(pVosContext,
12988 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
12989
12990 if(!VOS_IS_STATUS_SUCCESS( status ))
12991 {
12992 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Ashish Kumar Dhanotiya532bdef2017-05-09 17:31:59 +053012993 goto err_config;
Jeff Johnson295189b2012-06-20 16:38:30 -070012994 }
12995 }
12996
12997 pHddCtx->isLogpInProgress = FALSE;
12998 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
12999
Amar Singhala49cbc52013-10-08 18:37:44 -070013000#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -070013001 /* initialize the NV module. This is required so that
13002 we can initialize the channel information in wiphy
13003 from the NV.bin data. The channel information in
13004 wiphy needs to be initialized before wiphy registration */
13005
13006 status = vos_nv_open();
13007 if (!VOS_IS_STATUS_SUCCESS(status))
13008 {
13009 /* NV module cannot be initialized */
13010 hddLog( VOS_TRACE_LEVEL_FATAL,
13011 "%s: vos_nv_open failed", __func__);
Vinay Krishna Eranna2025d892014-09-18 16:51:42 +053013012 goto err_wdclose;
Amar Singhal0a402232013-10-11 20:57:16 -070013013 }
13014
13015 status = vos_init_wiphy_from_nv_bin();
13016 if (!VOS_IS_STATUS_SUCCESS(status))
13017 {
13018 /* NV module cannot be initialized */
13019 hddLog( VOS_TRACE_LEVEL_FATAL,
13020 "%s: vos_init_wiphy failed", __func__);
13021 goto err_vos_nv_close;
13022 }
13023
Amar Singhala49cbc52013-10-08 18:37:44 -070013024#endif
Mahesh A Saptasagarc3ed0122016-01-19 16:45:11 +053013025 //Initialize the nlink service
13026 if(nl_srv_init() != 0)
13027 {
13028 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
13029 goto err_vos_nv_close;
13030 }
13031
13032#ifdef WLAN_KD_READY_NOTIFIER
13033 pHddCtx->kd_nl_init = 1;
13034#endif /* WLAN_KD_READY_NOTIFIER */
13035
Girish Gowlibf0e1ab2015-01-19 16:05:16 +053013036 vos_set_roam_delay_stats_enabled(pHddCtx->cfg_ini->gEnableRoamDelayStats);
Arun Kumar Khandavalliebb19482014-03-25 13:56:53 +053013037 status = vos_open( &pVosContext, pHddCtx->parent_dev);
Jeff Johnson295189b2012-06-20 16:38:30 -070013038 if ( !VOS_IS_STATUS_SUCCESS( status ))
13039 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -080013040 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
Mahesh A Saptasagarc3ed0122016-01-19 16:45:11 +053013041 goto err_nl_srv;
Jeff Johnson295189b2012-06-20 16:38:30 -070013042 }
13043
Jeff Johnson295189b2012-06-20 16:38:30 -070013044 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
13045
13046 if ( NULL == pHddCtx->hHal )
13047 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -080013048 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -070013049 goto err_vosclose;
13050 }
13051
Jeff Johnsonbc676b42013-02-14 16:04:08 -080013052 status = vos_preStart( pHddCtx->pvosContext );
13053 if ( !VOS_IS_STATUS_SUCCESS( status ) )
13054 {
13055 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053013056 goto err_vosclose;
Jeff Johnsonbc676b42013-02-14 16:04:08 -080013057 }
Jeff Johnsone7245742012-09-05 17:12:55 -070013058
Arif Hussaineaf68602013-12-30 23:10:44 -080013059 if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan)
13060 {
13061 pHddCtx->cfg_ini->enableDFSChnlScan = enable_dfs_chan_scan;
13062 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_dfs_chan_scan set to %d",
13063 __func__, enable_dfs_chan_scan);
13064 }
13065 if (0 == enable_11d || 1 == enable_11d)
13066 {
13067 pHddCtx->cfg_ini->Is11dSupportEnabled = enable_11d;
13068 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_11d set to %d",
13069 __func__, enable_11d);
13070 }
13071
Jeff Johnsonbc676b42013-02-14 16:04:08 -080013072 /* Note that the vos_preStart() sequence triggers the cfg download.
13073 The cfg download must occur before we update the SME config
13074 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -070013075 status = hdd_set_sme_config( pHddCtx );
13076
13077 if ( VOS_STATUS_SUCCESS != status )
13078 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -080013079 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053013080 goto err_vosclose;
Jeff Johnsonbc676b42013-02-14 16:04:08 -080013081 }
Jeff Johnson295189b2012-06-20 16:38:30 -070013082
Jeff Johnson295189b2012-06-20 16:38:30 -070013083 /* In the integrated architecture we update the configuration from
13084 the INI file and from NV before vOSS has been started so that
13085 the final contents are available to send down to the cCPU */
13086
13087 // Apply the cfg.ini to cfg.dat
13088 if (FALSE == hdd_update_config_dat(pHddCtx))
13089 {
13090 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053013091 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -070013092 }
13093
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053013094 // Get mac addr from platform driver
13095 ret = wcnss_get_wlan_mac_address((char*)&mac_addr.bytes);
13096
13097 if ((0 == ret) && (!vos_is_macaddr_zero(&mac_addr)))
Jeff Johnson295189b2012-06-20 16:38:30 -070013098 {
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053013099 /* Store the mac addr for first interface */
13100 pHddCtx->cfg_ini->intfMacAddr[0] = mac_addr;
13101
13102 hddLog(VOS_TRACE_LEVEL_ERROR,
13103 "%s: WLAN Mac Addr: "
13104 MAC_ADDRESS_STR, __func__,
13105 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
13106
13107 /* Here, passing Arg2 as 1 because we do not want to change the
13108 last 3 bytes (means non OUI bytes) of first interface mac
13109 addr.
13110 */
13111 if (0 != hdd_generate_iface_mac_addr_auto(pHddCtx, 1, mac_addr))
13112 {
13113 hddLog(VOS_TRACE_LEVEL_ERROR,
13114 "%s: Failed to generate wlan interface mac addr "
13115 "using MAC from ini file ", __func__);
13116 }
13117 }
13118 else if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
13119 {
13120 // Apply the NV to cfg.dat
13121 /* Prima Update MAC address only at here */
Jeff Johnson295189b2012-06-20 16:38:30 -070013122#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
13123 /* There was not a valid set of MAC Addresses in NV. See if the
13124 default addresses were modified by the cfg.ini settings. If so,
13125 we'll use them, but if not, we'll autogenerate a set of MAC
13126 addresses based upon the device serial number */
13127
13128 static const v_MACADDR_t default_address =
13129 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
Jeff Johnson295189b2012-06-20 16:38:30 -070013130
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053013131 if (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
13132 sizeof(default_address)))
Jeff Johnson295189b2012-06-20 16:38:30 -070013133 {
13134 /* cfg.ini has the default address, invoke autogen logic */
13135
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053013136 /* Here, passing Arg2 as 0 because we want to change the
13137 last 3 bytes (means non OUI bytes) of all the interfaces
13138 mac addr.
13139 */
13140 if (0 != hdd_generate_iface_mac_addr_auto(pHddCtx, 0,
13141 default_address))
Jeff Johnson295189b2012-06-20 16:38:30 -070013142 {
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053013143 hddLog(VOS_TRACE_LEVEL_ERROR,
13144 "%s: Failed to generate wlan interface mac addr "
13145 "using MAC from ini file " MAC_ADDRESS_STR, __func__,
13146 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
Jeff Johnson295189b2012-06-20 16:38:30 -070013147 }
Jeff Johnson295189b2012-06-20 16:38:30 -070013148 }
13149 else
13150#endif //WLAN_AUTOGEN_MACADDR_FEATURE
13151 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -080013152 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -070013153 "%s: Invalid MAC address in NV, using MAC from ini file "
13154 MAC_ADDRESS_STR, __func__,
13155 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
13156 }
13157 }
13158 {
13159 eHalStatus halStatus;
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053013160
13161 /* Set the MAC Address Currently this is used by HAL to
13162 * add self sta. Remove this once self sta is added as
13163 * part of session open.
13164 */
Jeff Johnson295189b2012-06-20 16:38:30 -070013165 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
13166 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
13167 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053013168
Jeff Johnson295189b2012-06-20 16:38:30 -070013169 if (!HAL_STATUS_SUCCESS( halStatus ))
13170 {
13171 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
13172 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053013173 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -070013174 }
13175 }
Jeff Johnson295189b2012-06-20 16:38:30 -070013176
13177 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
13178 Note: Firmware image will be read and downloaded inside vos_start API */
13179 status = vos_start( pHddCtx->pvosContext );
13180 if ( !VOS_IS_STATUS_SUCCESS( status ) )
13181 {
13182 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
Hanumantha Reddy Pothulabd9601a2016-02-12 13:22:27 +053013183 if (isSsrPanicOnFailure())
13184 VOS_BUG(0);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053013185 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -070013186 }
13187
Leo Chang6cec3e22014-01-21 15:33:49 -080013188#ifdef FEATURE_WLAN_CH_AVOID
13189 /* Plug in avoid channel notification callback
13190 * This should happen before ADD_SELF_STA
13191 * FW will send first IND with ADD_SELF_STA REQ from host */
Pradeep Reddy POTTETI5c2e16d2014-06-27 16:47:38 +053013192
13193 /* check the Channel Avoidance is enabled */
13194 if (TRUE == pHddCtx->cfg_ini->fenableCHAvoidance)
13195 {
13196 sme_AddChAvoidCallback(pHddCtx->hHal,
13197 hdd_hostapd_ch_avoid_cb);
13198 }
Leo Chang6cec3e22014-01-21 15:33:49 -080013199#endif /* FEATURE_WLAN_CH_AVOID */
13200
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070013201 /* Exchange capability info between Host and FW and also get versioning info from FW */
13202 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -070013203
Agarwal Ashishad9281b2014-06-10 14:57:30 +053013204#ifdef CONFIG_ENABLE_LINUX_REG
13205 status = wlan_hdd_init_channels(pHddCtx);
13206 if ( !VOS_IS_STATUS_SUCCESS( status ) )
13207 {
13208 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: wlan_hdd_init_channels failed",
13209 __func__);
13210 goto err_vosstop;
13211 }
13212#endif
13213
Jeff Johnson295189b2012-06-20 16:38:30 -070013214 status = hdd_post_voss_start_config( pHddCtx );
13215 if ( !VOS_IS_STATUS_SUCCESS( status ) )
13216 {
13217 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
13218 __func__);
13219 goto err_vosstop;
13220 }
Amar Singhala49cbc52013-10-08 18:37:44 -070013221
13222#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +053013223 wlan_hdd_cfg80211_update_reg_info( wiphy );
13224
13225 /* registration of wiphy dev with cfg80211 */
13226 if (0 > wlan_hdd_cfg80211_register(wiphy))
13227 {
13228 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
13229 goto err_vosstop;
13230 }
Amar Singhala49cbc52013-10-08 18:37:44 -070013231#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070013232
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053013233#ifdef CONFIG_ENABLE_LINUX_REG
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053013234 /* registration of wiphy dev with cfg80211 */
13235 if (0 > wlan_hdd_cfg80211_register(wiphy))
13236 {
13237 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
13238 goto err_vosstop;
13239 }
13240
Agarwal Ashish6db9d532014-09-30 18:19:10 +053013241 status = wlan_hdd_init_channels_for_cc(pHddCtx, INIT);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053013242 if ( !VOS_IS_STATUS_SUCCESS( status ) )
13243 {
13244 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: wlan_hdd_init_channels_for_cc failed",
13245 __func__);
13246 goto err_unregister_wiphy;
13247 }
13248#endif
13249
c_hpothu4a298be2014-12-22 21:12:51 +053013250 wcnss_wlan_set_drvdata(pHddCtx->parent_dev, pHddCtx);
13251
Jeff Johnson295189b2012-06-20 16:38:30 -070013252 if (VOS_STA_SAP_MODE == hdd_get_conparam())
13253 {
13254 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
13255 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
13256 }
13257 else
13258 {
Jeff Johnson295189b2012-06-20 16:38:30 -070013259 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
13260 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
13261 if (pAdapter != NULL)
13262 {
Katya Nigama7d81d72014-11-12 12:44:34 +053013263 if (pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated && !(pHddCtx->cfg_ini->intfMacAddr[0].bytes[0] & 0x02))
Jeff Johnson295189b2012-06-20 16:38:30 -070013264 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +053013265 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
13266 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
13267 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -070013268
Gopichand Nakkala49f96f62013-02-06 14:38:17 +053013269 /* Generate the P2P Device Address. This consists of the device's
13270 * primary MAC address with the locally administered bit set.
13271 */
13272 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -070013273 }
13274 else
13275 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +053013276 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
13277 if (p2p_dev_addr != NULL)
13278 {
13279 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
13280 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
13281 }
13282 else
13283 {
13284 hddLog(VOS_TRACE_LEVEL_FATAL,
13285 "%s: Failed to allocate mac_address for p2p_device",
13286 __func__);
13287 goto err_close_adapter;
13288 }
Jeff Johnson295189b2012-06-20 16:38:30 -070013289 }
Jeff Johnsone7245742012-09-05 17:12:55 -070013290
13291 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
13292 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
13293 if ( NULL == pP2pAdapter )
13294 {
13295 hddLog(VOS_TRACE_LEVEL_FATAL,
13296 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070013297 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -070013298 goto err_close_adapter;
13299 }
Jeff Johnsone7245742012-09-05 17:12:55 -070013300 }
Jeff Johnson295189b2012-06-20 16:38:30 -070013301 }
Jeff Johnson295189b2012-06-20 16:38:30 -070013302
13303 if( pAdapter == NULL )
13304 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -080013305 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
13306 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -070013307 }
Jeff Johnsone7245742012-09-05 17:12:55 -070013308
Arif Hussain66559122013-11-21 10:11:40 -080013309 if (country_code)
13310 {
13311 eHalStatus ret;
Arif Hussaincb607082013-12-20 11:57:42 -080013312 INIT_COMPLETION(pAdapter->change_country_code);
Arif Hussain66559122013-11-21 10:11:40 -080013313 hdd_checkandupdate_dfssetting(pAdapter, country_code);
13314#ifndef CONFIG_ENABLE_LINUX_REG
13315 hdd_checkandupdate_phymode(pAdapter, country_code);
13316#endif
Arif Hussaineaf68602013-12-30 23:10:44 -080013317 ret = sme_ChangeCountryCode(pHddCtx->hHal,
13318 (void *)(tSmeChangeCountryCallback)
13319 wlan_hdd_change_country_code_callback,
Arif Hussain66559122013-11-21 10:11:40 -080013320 country_code,
13321 pAdapter, pHddCtx->pvosContext,
Abhishek Singha306a442013-11-07 18:39:01 +053013322 eSIR_TRUE, eSIR_TRUE);
Arif Hussain66559122013-11-21 10:11:40 -080013323 if (eHAL_STATUS_SUCCESS == ret)
13324 {
Arif Hussaincb607082013-12-20 11:57:42 -080013325 ret = wait_for_completion_interruptible_timeout(
13326 &pAdapter->change_country_code,
13327 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
13328
13329 if (0 >= ret)
13330 {
13331 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
13332 "%s: SME while setting country code timed out", __func__);
13333 }
Arif Hussain66559122013-11-21 10:11:40 -080013334 }
13335 else
13336 {
Arif Hussaincb607082013-12-20 11:57:42 -080013337 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
13338 "%s: SME Change Country code from module param fail ret=%d",
13339 __func__, ret);
Arif Hussain66559122013-11-21 10:11:40 -080013340 }
13341 }
13342
Jeff Johnson295189b2012-06-20 16:38:30 -070013343#ifdef WLAN_BTAMP_FEATURE
13344 vStatus = WLANBAP_Open(pVosContext);
13345 if(!VOS_IS_STATUS_SUCCESS(vStatus))
13346 {
13347 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
13348 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -070013349 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -070013350 }
13351
13352 vStatus = BSL_Init(pVosContext);
13353 if(!VOS_IS_STATUS_SUCCESS(vStatus))
13354 {
13355 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
13356 "%s: Failed to Init BSL",__func__);
13357 goto err_bap_close;
13358 }
13359 vStatus = WLANBAP_Start(pVosContext);
13360 if (!VOS_IS_STATUS_SUCCESS(vStatus))
13361 {
13362 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
13363 "%s: Failed to start TL",__func__);
13364 goto err_bap_close;
13365 }
13366
13367 pConfig = pHddCtx->cfg_ini;
13368 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
13369 status = WLANBAP_SetConfig(&btAmpConfig);
13370
13371#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -070013372
Mihir Shete9c238772014-10-15 14:35:16 +053013373 /*
13374 * UapsdMask is 0xf if U-APSD is enbaled for all AC's...
13375 * The value of CFG_QOS_WMM_UAPSD_MASK_DEFAULT is 0xaa(Magic Value)
13376 * which is greater than 0xf. So the below check is safe to make
13377 * sure that there is no entry for UapsdMask in the ini
13378 */
13379 if (CFG_QOS_WMM_UAPSD_MASK_DEFAULT == pHddCtx->cfg_ini->UapsdMask)
13380 {
13381 if(IS_DYNAMIC_WMM_PS_ENABLED)
13382 {
13383 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: Enable UAPSD for VI & VO",
13384 __func__);
13385 pHddCtx->cfg_ini->UapsdMask =
13386 CFG_QOS_WMM_UAPSD_MASK_DYMANIC_WMM_PS_DEFAULT;
13387 }
13388 else
13389 {
13390 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: Do not enable UAPSD",
13391 __func__);
13392 pHddCtx->cfg_ini->UapsdMask =
13393 CFG_QOS_WMM_UAPSD_MASK_LEGACY_WMM_PS_DEFAULT;
13394 }
13395 }
13396
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -070013397#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
13398 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
13399 {
13400 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
13401 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
13402 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
13403 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
13404 }
13405#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070013406
Agarwal Ashish4b87f922014-06-18 03:03:21 +053013407 wlan_hdd_tdls_init(pHddCtx);
13408
Masti, Narayanraddi26378462016-01-05 18:20:28 +053013409 wlan_hdd_init_deinit_defer_scan_context(&pHddCtx->scan_ctxt);
13410
13411 vos_init_delayed_work(&pHddCtx->scan_ctxt.scan_work,
13412 wlan_hdd_schedule_defer_scan);
13413
Mihir Shetefc7ff5b2014-01-27 11:30:05 +053013414 sme_Register11dScanDoneCallback(pHddCtx->hHal, hdd_11d_scan_done);
13415
Jeff Johnson295189b2012-06-20 16:38:30 -070013416 /* Register with platform driver as client for Suspend/Resume */
13417 status = hddRegisterPmOps(pHddCtx);
13418 if ( !VOS_IS_STATUS_SUCCESS( status ) )
13419 {
13420 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
13421#ifdef WLAN_BTAMP_FEATURE
13422 goto err_bap_stop;
13423#else
Jeff Johnsone7245742012-09-05 17:12:55 -070013424 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -070013425#endif //WLAN_BTAMP_FEATURE
13426 }
13427
Yue Ma0d4891e2013-08-06 17:01:45 -070013428 /* Open debugfs interface */
13429 if (VOS_STATUS_SUCCESS != hdd_debugfs_init(pAdapter))
13430 {
13431 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
13432 "%s: hdd_debugfs_init failed!", __func__);
Yue Ma0d4891e2013-08-06 17:01:45 -070013433 }
13434
Jeff Johnson295189b2012-06-20 16:38:30 -070013435 /* Register TM level change handler function to the platform */
13436 status = hddDevTmRegisterNotifyCallback(pHddCtx);
13437 if ( !VOS_IS_STATUS_SUCCESS( status ) )
13438 {
13439 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
13440 goto err_unregister_pmops;
13441 }
Jeff Johnson295189b2012-06-20 16:38:30 -070013442
Jeff Johnson295189b2012-06-20 16:38:30 -070013443 // register net device notifier for device change notification
13444 ret = register_netdevice_notifier(&hdd_netdev_notifier);
13445
13446 if(ret < 0)
13447 {
13448 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
Siddharth Bhalcd92b782015-06-29 12:25:40 +053013449 goto err_unregister_pmops;
Jeff Johnson295189b2012-06-20 16:38:30 -070013450 }
13451
Jeff Johnson295189b2012-06-20 16:38:30 -070013452 //Initialize the BTC service
13453 if(btc_activate_service(pHddCtx) != 0)
13454 {
13455 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
Mahesh A Saptasagarc3ed0122016-01-19 16:45:11 +053013456 goto err_reg_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -070013457 }
13458
Padma, Santhosh Kumar2762e9d2015-10-20 15:02:57 +053013459#ifdef FEATURE_OEM_DATA_SUPPORT
13460 //Initialize the OEM service
13461 if (oem_activate_service(pHddCtx) != 0)
13462 {
13463 hddLog(VOS_TRACE_LEVEL_FATAL,
13464 "%s: oem_activate_service failed", __func__);
Hanumanth Reddy Pothula13789c42017-09-12 15:18:13 +053013465 goto err_btc_activate_service;
Padma, Santhosh Kumar2762e9d2015-10-20 15:02:57 +053013466 }
13467#endif
13468
Jeff Johnson295189b2012-06-20 16:38:30 -070013469#ifdef PTT_SOCK_SVC_ENABLE
13470 //Initialize the PTT service
13471 if(ptt_sock_activate_svc(pHddCtx) != 0)
13472 {
13473 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
Hanumanth Reddy Pothula13789c42017-09-12 15:18:13 +053013474 goto err_oem_activate_service;
Jeff Johnson295189b2012-06-20 16:38:30 -070013475 }
13476#endif
13477
Abhishek Singh00b71972016-01-07 10:51:04 +053013478#ifdef WLAN_FEATURE_RMC
13479 if (hdd_open_cesium_nl_sock() < 0)
13480 {
13481 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_open_cesium_nl_sock failed", __func__);
Hanumanth Reddy Pothula13789c42017-09-12 15:18:13 +053013482 goto err_ptt_sock_activate_svc;
Abhishek Singh00b71972016-01-07 10:51:04 +053013483 }
13484#endif
13485
Vinay Krishna Erannad938c422014-03-10 17:14:21 +053013486#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
13487 if(pHddCtx->cfg_ini && pHddCtx->cfg_ini->wlanLoggingEnable)
13488 {
Deepthi Gowri78083a32014-11-04 12:55:51 +053013489 if(wlan_logging_sock_activate_svc(
13490 pHddCtx->cfg_ini->wlanLoggingFEToConsole,
Sushant Kaushik33200572015-08-05 16:46:20 +053013491 pHddCtx->cfg_ini->wlanLoggingNumBuf,
13492 pHddCtx->cfg_ini->wlanPerPktStatsLogEnable,
13493 pHddCtx->cfg_ini->wlanPerPktStatsNumBuf))
Deepthi Gowri78083a32014-11-04 12:55:51 +053013494 {
13495 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wlan_logging_sock_activate_svc"
13496 " failed", __func__);
Hanumanth Reddy Pothula13789c42017-09-12 15:18:13 +053013497 goto err_open_cesium_nl_sock;
Deepthi Gowri78083a32014-11-04 12:55:51 +053013498 }
13499 //TODO: To Remove enableDhcpDebug and use gEnableDebugLog for
13500 //EAPOL and DHCP
Sachin Ahuja8c65f382014-12-12 15:34:21 +053013501 if (!pHddCtx->cfg_ini->gEnableDebugLog)
13502 pHddCtx->cfg_ini->gEnableDebugLog =
Sushant Kaushik6e4e2bc2015-10-05 17:23:07 +053013503 VOS_PKT_PROTO_TYPE_EAPOL | VOS_PKT_PROTO_TYPE_DHCP |
13504 VOS_PKT_PROTO_TYPE_ARP;
Vinay Krishna Erannad938c422014-03-10 17:14:21 +053013505 }
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053013506
Siddharth Bhald1be97f2015-05-27 22:39:59 +053013507 if (pHddCtx->cfg_ini->wlanLoggingEnable &&
13508 (pHddCtx->cfg_ini->enableFWLogging ||
Siddharth Bhaldb963232015-06-25 19:34:35 +053013509 pHddCtx->cfg_ini->enableMgmtLogging ||
c_manjeecfd1efb2015-09-25 19:32:34 +053013510 pHddCtx->cfg_ini->enableContFWLogging ||
13511 pHddCtx->cfg_ini->enableFwrMemDump )
13512 )
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053013513 {
Siddharth Bhald1be97f2015-05-27 22:39:59 +053013514 hdd_init_frame_logging(pHddCtx);
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053013515 }
13516 else
13517 {
Siddharth Bhald1be97f2015-05-27 22:39:59 +053013518 hddLog(VOS_TRACE_LEVEL_INFO, FL("Logging disabled in ini"));
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053013519 }
13520
Vinay Krishna Erannad938c422014-03-10 17:14:21 +053013521#endif
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053013522
Agrawal Ashish17ef5082016-10-17 18:33:21 +053013523#ifdef SAP_AUTH_OFFLOAD
13524 if (!sme_IsFeatureSupportedByFW(SAP_OFFLOADS))
13525 {
13526 hddLog(VOS_TRACE_LEVEL_INFO, FL(" SAP AUTH OFFLOAD not supp by FW"));
13527 pHddCtx->cfg_ini->enable_sap_auth_offload = 0;
13528 }
13529#endif
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053013530
Sushant Kaushik215778f2015-05-21 14:05:36 +053013531 if (vos_is_multicast_logging())
13532 wlan_logging_set_log_level();
13533
Jeff Johnson295189b2012-06-20 16:38:30 -070013534 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -070013535 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -070013536 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -070013537 /* Action frame registered in one adapter which will
13538 * applicable to all interfaces
13539 */
Agarwal Ashish8fa0e9a2014-05-23 00:40:12 +053013540 wlan_hdd_cfg80211_register_frames(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -070013541 }
Jeff Johnson295189b2012-06-20 16:38:30 -070013542
13543 mutex_init(&pHddCtx->sap_lock);
Mahesh A Saptasagar60627942014-10-13 13:55:14 +053013544 mutex_init(&pHddCtx->roc_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070013545
Jeff Johnsone7245742012-09-05 17:12:55 -070013546#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
13547 /* Initialize the wake lcok */
Sushant Kaushik83392fa2015-05-05 17:44:40 +053013548 vos_wake_lock_init(&pHddCtx->rx_wake_lock,
Jeff Johnsone7245742012-09-05 17:12:55 -070013549 "qcom_rx_wakelock");
Sushant Kaushik83392fa2015-05-05 17:44:40 +053013550
Jeff Johnsone7245742012-09-05 17:12:55 -070013551#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -080013552 /* Initialize the wake lcok */
Sushant Kaushik83392fa2015-05-05 17:44:40 +053013553 vos_wake_lock_init(&pHddCtx->sap_wake_lock,
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -080013554 "qcom_sap_wakelock");
Sushant Kaushik83392fa2015-05-05 17:44:40 +053013555
Jeff Johnsone7245742012-09-05 17:12:55 -070013556
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -070013557 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
13558 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -070013559
Katya Nigam5c306ea2014-06-19 15:39:54 +053013560 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_NO_LOAD_UNLOAD_IN_PROGRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -070013561 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
Sushant Kaushik83392fa2015-05-05 17:44:40 +053013562 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_INIT);
Katya Nigam5c306ea2014-06-19 15:39:54 +053013563
13564#ifdef FEATURE_WLAN_SCAN_PNO
13565 /*SME must send channel update configuration to RIVA*/
13566 sme_UpdateChannelConfig(pHddCtx->hHal);
13567#endif
Abhishek Singhf644b272014-08-21 02:59:39 +053013568 /* Send the update default channel list to the FW*/
13569 sme_UpdateChannelList(pHddCtx->hHal);
Mukul Sharma45063942015-04-01 20:07:59 +053013570
13571 /* Fwr capabilities received, Set the Dot11 mode */
Abhishek Singh41ebce12016-02-03 10:43:21 +053013572 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter),
13573 hdd_cfg_xlate_to_csr_phy_mode(pHddCtx->cfg_ini->dot11Mode));
Mukul Sharma45063942015-04-01 20:07:59 +053013574 sme_SetDefDot11Mode(pHddCtx->hHal);
13575
Abhishek Singha306a442013-11-07 18:39:01 +053013576#ifndef CONFIG_ENABLE_LINUX_REG
13577 /*updating wiphy so that regulatory user hints can be processed*/
13578 if (wiphy)
13579 {
13580 regulatory_hint(wiphy, "00");
13581 }
13582#endif
Jeff Johnsone7245742012-09-05 17:12:55 -070013583 // Initialize the restart logic
13584 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +053013585
Hanumanth Reddy Pothula146bca42016-11-08 12:01:07 +053013586 if (pHddCtx->cfg_ini->fIsLogpEnabled) {
13587 vos_wdthread_init_timer_work(vos_process_wd_timer);
13588 /* Initialize the timer to detect thread stuck issues */
13589 vos_thread_stuck_timer_init(
13590 &((VosContextType*)pVosContext)->vosWatchdog);
13591 }
13592
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -070013593 //Register the traffic monitor timer now
13594 if ( pHddCtx->cfg_ini->dynSplitscan)
13595 {
13596 vos_timer_init(&pHddCtx->tx_rx_trafficTmr,
13597 VOS_TIMER_TYPE_SW,
13598 hdd_tx_rx_pkt_cnt_stat_timer_handler,
13599 (void *)pHddCtx);
13600 }
Srinivas Dasari030bad32015-02-18 23:23:54 +053013601 wlan_hdd_cfg80211_nan_init(pHddCtx);
13602
Bhargav Shahd0715912015-10-01 18:17:37 +053013603 mutex_init(&pHddCtx->cur_rx_level_lock);
13604 vos_timer_init(&pHddCtx->delack_timer, VOS_TIMER_TYPE_SW,
13605 hdd_tcp_delack_compute_function,(void *)pHddCtx);
Masti, Narayanraddi44b0db02015-12-22 11:54:35 +053013606 vos_timer_init(&pHddCtx->tdls_source_timer, VOS_TIMER_TYPE_SW,
13607 wlan_hdd_change_tdls_mode, (void *)pHddCtx);
Bhargav Shahd0715912015-10-01 18:17:37 +053013608
Dino Mycle6fb96c12014-06-10 11:52:40 +053013609#ifdef WLAN_FEATURE_EXTSCAN
13610 sme_EXTScanRegisterCallback(pHddCtx->hHal,
13611 wlan_hdd_cfg80211_extscan_callback,
13612 pHddCtx);
13613#endif /* WLAN_FEATURE_EXTSCAN */
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053013614
Padma, Santhosh Kumar2ccac212015-10-20 17:27:27 +053013615#ifdef FEATURE_OEM_DATA_SUPPORT
13616 sme_OemDataRegisterCallback(pHddCtx->hHal,
13617 wlan_hdd_cfg80211_oemdata_callback,
13618 pHddCtx);
13619#endif /* FEATURE_OEM_DATA_SUPPORT */
13620
Gupta, Kapil7c34b322015-09-30 13:12:35 +053013621 sme_set_rssi_threshold_breached_cb(pHddCtx->hHal, hdd_rssi_threshold_breached_cb);
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053013622#ifdef WLAN_NS_OFFLOAD
13623 // Register IPv6 notifier to notify if any change in IP
13624 // So that we can reconfigure the offload parameters
13625 pHddCtx->ipv6_notifier.notifier_call = wlan_hdd_ipv6_changed;
13626 ret = register_inet6addr_notifier(&pHddCtx->ipv6_notifier);
13627 if (ret)
13628 {
Ratheesh S P36dbc932015-08-07 14:28:57 +053013629 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Failed to register IPv6 notifier"));
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053013630 }
13631 else
13632 {
Ratheesh S P36dbc932015-08-07 14:28:57 +053013633 hddLog(VOS_TRACE_LEVEL_INFO, FL("Registered IPv6 notifier"));
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053013634 }
13635#endif
13636
Sravan Kumar Kairamb0edc612016-10-26 13:55:24 +053013637 vos_mem_set((uint8_t *)&pHddCtx->bad_sta, HDD_MAX_STA_COUNT, 0);
13638
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053013639 // Register IPv4 notifier to notify if any change in IP
13640 // So that we can reconfigure the offload parameters
13641 pHddCtx->ipv4_notifier.notifier_call = wlan_hdd_ipv4_changed;
13642 ret = register_inetaddr_notifier(&pHddCtx->ipv4_notifier);
13643 if (ret)
13644 {
Ratheesh S P36dbc932015-08-07 14:28:57 +053013645 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Failed to register IPv4 notifier"));
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053013646 }
13647 else
13648 {
Ratheesh S P36dbc932015-08-07 14:28:57 +053013649 hddLog(VOS_TRACE_LEVEL_INFO, FL("Registered IPv4 notifier"));
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053013650 }
c_manjeecfd1efb2015-09-25 19:32:34 +053013651 /*Fw mem dump procfs initialization*/
13652 memdump_init();
Bhargav shah23c94942015-10-13 12:48:35 +053013653 hdd_dp_util_send_rps_ind(pHddCtx);
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053013654
Nishank Aggarwalc11826c2016-12-15 18:54:10 +053013655 pHddCtx->is_ap_mode_wow_supported =
13656 sme_IsFeatureSupportedByFW(SAP_MODE_WOW);
Sravan Kumar Kairam091e5b62017-01-23 14:14:20 +053013657
Hanumanth Reddy Pothulae92bcc12017-05-19 13:56:35 +053013658 pHddCtx->is_fatal_event_log_sup =
13659 sme_IsFeatureSupportedByFW(FATAL_EVENT_LOGGING);
13660 hddLog(VOS_TRACE_LEVEL_INFO, FL("FATAL_EVENT_LOGGING: %d"),
13661 pHddCtx->is_fatal_event_log_sup);
13662
Sravan Kumar Kairam091e5b62017-01-23 14:14:20 +053013663 hdd_assoc_registerFwdEapolCB(pVosContext);
13664
Ashish Kumar Dhanotiya32d092b2018-02-20 21:43:57 +053013665 mutex_init(&pHddCtx->cache_channel_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070013666 goto success;
13667
Hanumanth Reddy Pothula13789c42017-09-12 15:18:13 +053013668err_open_cesium_nl_sock:
13669#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
13670 hdd_close_cesium_nl_sock();
13671#endif
13672
13673err_ptt_sock_activate_svc:
13674#ifdef PTT_SOCK_SVC_ENABLE
13675 ptt_sock_deactivate_svc(pHddCtx);
13676#endif
13677
13678err_oem_activate_service:
13679#ifdef FEATURE_OEM_DATA_SUPPORT
13680 oem_deactivate_service();
13681#endif
13682
13683err_btc_activate_service:
13684 btc_deactivate_service();
13685
Jeff Johnson295189b2012-06-20 16:38:30 -070013686err_reg_netdev:
13687 unregister_netdevice_notifier(&hdd_netdev_notifier);
13688
Jeff Johnson295189b2012-06-20 16:38:30 -070013689err_unregister_pmops:
13690 hddDevTmUnregisterNotifyCallback(pHddCtx);
13691 hddDeregisterPmOps(pHddCtx);
13692
Yue Ma0d4891e2013-08-06 17:01:45 -070013693 hdd_debugfs_exit(pHddCtx);
13694
Jeff Johnson295189b2012-06-20 16:38:30 -070013695#ifdef WLAN_BTAMP_FEATURE
13696err_bap_stop:
13697 WLANBAP_Stop(pVosContext);
13698#endif
13699
13700#ifdef WLAN_BTAMP_FEATURE
13701err_bap_close:
13702 WLANBAP_Close(pVosContext);
13703#endif
13704
Jeff Johnson295189b2012-06-20 16:38:30 -070013705err_close_adapter:
13706 hdd_close_all_adapters( pHddCtx );
Mahesh A Saptasagar9ecefe42014-07-15 18:43:49 +053013707#ifdef CONFIG_ENABLE_LINUX_REG
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053013708err_unregister_wiphy:
Mahesh A Saptasagar9ecefe42014-07-15 18:43:49 +053013709#endif
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +053013710 wiphy_unregister(wiphy) ;
Agrawal Ashish33ec71e2015-11-26 20:20:58 +053013711 hdd_wlan_free_wiphy_channels(wiphy);
13712
Jeff Johnson295189b2012-06-20 16:38:30 -070013713err_vosstop:
13714 vos_stop(pVosContext);
13715
Amar Singhala49cbc52013-10-08 18:37:44 -070013716err_vosclose:
Jeff Johnson295189b2012-06-20 16:38:30 -070013717 status = vos_sched_close( pVosContext );
13718 if (!VOS_IS_STATUS_SUCCESS(status)) {
13719 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
13720 "%s: Failed to close VOSS Scheduler", __func__);
13721 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
13722 }
Amar Singhala49cbc52013-10-08 18:37:44 -070013723 vos_close(pVosContext );
13724
Mahesh A Saptasagarc3ed0122016-01-19 16:45:11 +053013725err_nl_srv:
13726#ifdef WLAN_KD_READY_NOTIFIER
13727 nl_srv_exit(pHddCtx->ptt_pid);
13728#else
13729 nl_srv_exit();
13730#endif /* WLAN_KD_READY_NOTIFIER */
Amar Singhal0a402232013-10-11 20:57:16 -070013731err_vos_nv_close:
13732
c_hpothue6a36282014-03-19 12:27:38 +053013733#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -070013734 vos_nv_close();
13735
c_hpothu70f8d812014-03-22 22:59:23 +053013736#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070013737
13738err_wdclose:
13739 if(pHddCtx->cfg_ini->fIsLogpEnabled)
13740 vos_watchdog_close(pVosContext);
13741
Jeff Johnson295189b2012-06-20 16:38:30 -070013742err_config:
13743 kfree(pHddCtx->cfg_ini);
13744 pHddCtx->cfg_ini= NULL;
13745
13746err_free_hdd_context:
Sushant Kaushik83392fa2015-05-05 17:44:40 +053013747 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_INIT);
Siddharth Bhalcd92b782015-06-29 12:25:40 +053013748 free_riva_power_on_lock("wlan");
Jeff Johnson295189b2012-06-20 16:38:30 -070013749 wiphy_free(wiphy) ;
13750 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -070013751 VOS_BUG(1);
13752
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -080013753 if (hdd_is_ssr_required())
13754 {
13755 /* WDI timeout had happened during load, so SSR is needed here */
13756 subsystem_restart("wcnss");
13757 msleep(5000);
13758 }
13759 hdd_set_ssr_required (VOS_FALSE);
13760
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -080013761 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -070013762
13763success:
13764 EXIT();
13765 return 0;
13766}
13767
13768/**---------------------------------------------------------------------------
13769
Jeff Johnson32d95a32012-09-10 13:15:23 -070013770 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -070013771
Jeff Johnson32d95a32012-09-10 13:15:23 -070013772 This is the driver entry point - called in different timeline depending
13773 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -070013774
13775 \param - None
13776
13777 \return - 0 for success, non zero for failure
13778
13779 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -070013780static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -070013781{
13782 VOS_STATUS status;
13783 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -070013784 struct device *dev = NULL;
13785 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -070013786#ifdef HAVE_WCNSS_CAL_DOWNLOAD
13787 int max_retries = 0;
13788#endif
Siddharth Bhalc7e79b62014-10-10 22:37:38 +053013789#ifdef HAVE_CBC_DONE
13790 int max_cbc_retries = 0;
13791#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070013792
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +053013793#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
13794 wlan_logging_sock_init_svc();
13795#endif
13796
Jeff Johnson295189b2012-06-20 16:38:30 -070013797 ENTER();
13798
Sushant Kaushik83392fa2015-05-05 17:44:40 +053013799 vos_wake_lock_init(&wlan_wake_lock, "wlan");
Jeff Johnson295189b2012-06-20 16:38:30 -070013800
13801 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
13802 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
13803
Jeff Johnson295189b2012-06-20 16:38:30 -070013804#ifdef ANI_BUS_TYPE_PCI
13805
13806 dev = wcnss_wlan_get_device();
13807
13808#endif // ANI_BUS_TYPE_PCI
13809
13810#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -070013811
13812#ifdef HAVE_WCNSS_CAL_DOWNLOAD
13813 /* wait until WCNSS driver downloads NV */
Ravi Kumar Bokka7a139e62016-11-17 21:32:55 +053013814 while (!wcnss_device_ready() && 10 >= ++max_retries) {
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -070013815 msleep(1000);
13816 }
Siddharth Bhalc7e79b62014-10-10 22:37:38 +053013817
Ravi Kumar Bokka7a139e62016-11-17 21:32:55 +053013818 if (max_retries >= 10) {
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -070013819 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
Sushant Kaushik83392fa2015-05-05 17:44:40 +053013820 vos_wake_lock_destroy(&wlan_wake_lock);
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +053013821#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
13822 wlan_logging_sock_deinit_svc();
13823#endif
13824
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -070013825 return -ENODEV;
13826 }
13827#endif
13828
Siddharth Bhalc7e79b62014-10-10 22:37:38 +053013829#ifdef HAVE_CBC_DONE
13830 while (!wcnss_cbc_complete() && 10 >= ++max_cbc_retries) {
13831 msleep(1000);
13832 }
13833 if (max_cbc_retries >= 10) {
13834 hddLog(VOS_TRACE_LEVEL_FATAL, "%s:CBC not completed", __func__);
13835 }
13836#endif
13837
Jeff Johnson295189b2012-06-20 16:38:30 -070013838 dev = wcnss_wlan_get_device();
13839#endif // ANI_BUS_TYPE_PLATFORM
13840
13841
13842 do {
13843 if (NULL == dev) {
13844 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
13845 ret_status = -1;
13846 break;
13847 }
13848
Jeff Johnson295189b2012-06-20 16:38:30 -070013849#ifdef TIMER_MANAGER
13850 vos_timer_manager_init();
13851#endif
13852
13853 /* Preopen VOSS so that it is ready to start at least SAL */
13854 status = vos_preOpen(&pVosContext);
13855
13856 if (!VOS_IS_STATUS_SUCCESS(status))
13857 {
13858 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
13859 ret_status = -1;
13860 break;
13861 }
13862
Sushant Kaushik02beb352015-06-04 15:15:01 +053013863 hddTraceInit();
Padma, Santhosh Kumar9093b202015-07-21 15:37:38 +053013864 hdd_register_debug_callback();
13865
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070013866#ifndef MODULE
13867 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
13868 */
13869 hdd_set_conparam((v_UINT_t)con_mode);
13870#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070013871
13872 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -080013873 if (hdd_wlan_startup(dev))
13874 {
Jeff Johnson295189b2012-06-20 16:38:30 -070013875 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -080013876 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -070013877 vos_preClose( &pVosContext );
13878 ret_status = -1;
13879 break;
13880 }
13881
Jeff Johnson295189b2012-06-20 16:38:30 -070013882 } while (0);
13883
13884 if (0 != ret_status)
13885 {
Jeff Johnson295189b2012-06-20 16:38:30 -070013886#ifdef TIMER_MANAGER
13887 vos_timer_exit();
13888#endif
13889#ifdef MEMORY_DEBUG
13890 vos_mem_exit();
13891#endif
Sushant Kaushik83392fa2015-05-05 17:44:40 +053013892 vos_wake_lock_destroy(&wlan_wake_lock);
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +053013893#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
13894 wlan_logging_sock_deinit_svc();
13895#endif
13896
Jeff Johnson295189b2012-06-20 16:38:30 -070013897 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
13898 }
13899 else
13900 {
13901 //Send WLAN UP indication to Nlink Service
13902 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
13903
13904 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Jeff Johnson295189b2012-06-20 16:38:30 -070013905 }
13906
13907 EXIT();
13908
13909 return ret_status;
13910}
13911
Jeff Johnson32d95a32012-09-10 13:15:23 -070013912/**---------------------------------------------------------------------------
13913
13914 \brief hdd_module_init() - Init Function
13915
13916 This is the driver entry point (invoked when module is loaded using insmod)
13917
13918 \param - None
13919
13920 \return - 0 for success, non zero for failure
13921
13922 --------------------------------------------------------------------------*/
13923#ifdef MODULE
13924static int __init hdd_module_init ( void)
13925{
13926 return hdd_driver_init();
13927}
Jeff Johnson32d95a32012-09-10 13:15:23 -070013928#else /* #ifdef MODULE */
13929static int __init hdd_module_init ( void)
13930{
13931 /* Driver initialization is delayed to fwpath_changed_handler */
13932 return 0;
13933}
Jeff Johnson32d95a32012-09-10 13:15:23 -070013934#endif /* #ifdef MODULE */
13935
Jeff Johnson295189b2012-06-20 16:38:30 -070013936
13937/**---------------------------------------------------------------------------
13938
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070013939 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -070013940
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070013941 This is the driver exit point (invoked when module is unloaded using rmmod
13942 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -070013943
13944 \param - None
13945
13946 \return - None
13947
13948 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070013949static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -070013950{
13951 hdd_context_t *pHddCtx = NULL;
13952 v_CONTEXT_t pVosContext = NULL;
Agarwal Ashish5e414792014-06-08 15:25:23 +053013953 v_REGDOMAIN_t regId;
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +053013954 unsigned long rc = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -070013955
13956 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
13957
13958 //Get the global vos context
13959 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
13960
13961 if(!pVosContext)
13962 {
13963 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
13964 goto done;
13965 }
13966
13967 //Get the HDD context.
13968 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
13969
13970 if(!pHddCtx)
13971 {
13972 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
13973 }
Katya Nigame7b69a82015-04-28 15:24:06 +053013974 else if (VOS_MONITOR_MODE == hdd_get_conparam())
13975 {
13976 hddLog(VOS_TRACE_LEVEL_INFO,"%s: MONITOR MODE",__func__);
13977 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_UNLOAD_IN_PROGRESS;
13978 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
13979 hdd_wlan_exit(pHddCtx);
13980 vos_preClose( &pVosContext );
13981 goto done;
13982 }
Jeff Johnson295189b2012-06-20 16:38:30 -070013983 else
13984 {
Siddharth Bhal2e5871b2015-03-24 16:20:51 +053013985 /* We wait for active entry threads to exit from driver
13986 * by waiting until rtnl_lock is available.
13987 */
13988 rtnl_lock();
13989 rtnl_unlock();
13990
Siddharth Bhal3c29dca2015-02-19 00:41:40 +053013991 INIT_COMPLETION(pHddCtx->ssr_comp_var);
13992 if ((pHddCtx->isLogpInProgress) && (FALSE ==
13993 vos_is_wlan_in_badState(VOS_MODULE_ID_HDD, NULL)))
13994 {
Siddharth Bhala204f572015-01-17 02:03:36 +053013995 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Siddharth Bhal3c29dca2015-02-19 00:41:40 +053013996 "%s:SSR in Progress; block rmmod !!!", __func__);
Siddharth Bhala204f572015-01-17 02:03:36 +053013997 rc = wait_for_completion_timeout(&pHddCtx->ssr_comp_var,
13998 msecs_to_jiffies(30000));
13999 if(!rc)
14000 {
14001 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
14002 "%s:SSR timedout, fatal error", __func__);
14003 VOS_BUG(0);
14004 }
14005 }
14006
Siddharth Bhal3c29dca2015-02-19 00:41:40 +053014007 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_UNLOAD_IN_PROGRESS;
14008 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
Jeff Johnson295189b2012-06-20 16:38:30 -070014009
c_hpothu8adb97b2014-12-08 19:38:20 +053014010 /* Driver Need to send country code 00 in below condition
14011 * 1) If gCountryCodePriority is set to 1; and last country
14012 * code set is through 11d. This needs to be done in case
14013 * when NV country code is 00.
14014 * This Needs to be done as when kernel store last country
14015 * code and if stored country code is not through 11d,
14016 * in sme_HandleChangeCountryCodeByUser we will disable 11d
14017 * in next load/unload as soon as we get any country through
14018 * 11d. In sme_HandleChangeCountryCodeByUser
14019 * pMsg->countryCode will be last countryCode and
14020 * pMac->scan.countryCode11d will be country through 11d so
14021 * due to mismatch driver will disable 11d.
14022 *
14023 */
Agarwal Ashish8db39882014-07-30 21:56:07 +053014024
c_hpothu8adb97b2014-12-08 19:38:20 +053014025 if ((eANI_BOOLEAN_TRUE == sme_Is11dCountrycode(pHddCtx->hHal) &&
Agarwal Ashish8dcd2862014-07-25 11:58:52 +053014026 pHddCtx->cfg_ini->fSupplicantCountryCodeHasPriority &&
Abhishek Singh2a705962014-10-30 14:47:28 +053014027 sme_Is11dSupported(pHddCtx->hHal)))
c_hpothu8adb97b2014-12-08 19:38:20 +053014028 {
14029 hddLog(VOS_TRACE_LEVEL_INFO,
Agarwal Ashish8dcd2862014-07-25 11:58:52 +053014030 FL("CountryCode 00 is being set while unloading driver"));
c_hpothu8adb97b2014-12-08 19:38:20 +053014031 vos_nv_getRegDomainFromCountryCode(&regId , "00", COUNTRY_USER);
14032 }
Agarwal Ashish5e414792014-06-08 15:25:23 +053014033
c_hpothu8adb97b2014-12-08 19:38:20 +053014034 //Do all the cleanup before deregistering the driver
14035 hdd_wlan_exit(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -070014036 }
14037
Jeff Johnson295189b2012-06-20 16:38:30 -070014038 vos_preClose( &pVosContext );
14039
14040#ifdef TIMER_MANAGER
14041 vos_timer_exit();
14042#endif
14043#ifdef MEMORY_DEBUG
14044 vos_mem_exit();
14045#endif
14046
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +053014047#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
14048 wlan_logging_sock_deinit_svc();
14049#endif
14050
Jeff Johnson295189b2012-06-20 16:38:30 -070014051done:
Sushant Kaushik83392fa2015-05-05 17:44:40 +053014052 vos_wake_lock_destroy(&wlan_wake_lock);
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +053014053
Jeff Johnson295189b2012-06-20 16:38:30 -070014054 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
14055}
14056
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070014057/**---------------------------------------------------------------------------
14058
14059 \brief hdd_module_exit() - Exit function
14060
14061 This is the driver exit point (invoked when module is unloaded using rmmod)
14062
14063 \param - None
14064
14065 \return - None
14066
14067 --------------------------------------------------------------------------*/
14068static void __exit hdd_module_exit(void)
14069{
14070 hdd_driver_exit();
14071}
14072
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070014073#ifdef MODULE
14074static int fwpath_changed_handler(const char *kmessage,
14075 struct kernel_param *kp)
14076{
Jeff Johnson76052702013-04-16 13:55:05 -070014077 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070014078}
14079
14080static int con_mode_handler(const char *kmessage,
14081 struct kernel_param *kp)
14082{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -070014083 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070014084}
14085#else /* #ifdef MODULE */
14086/**---------------------------------------------------------------------------
14087
Jeff Johnson76052702013-04-16 13:55:05 -070014088 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070014089
Jeff Johnson76052702013-04-16 13:55:05 -070014090 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070014091 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -070014092 - invoked when module parameter fwpath is modified from userspace to signal
14093 initializing the WLAN driver or when con_mode is modified from userspace
14094 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070014095
14096 \return - 0 for success, non zero for failure
14097
14098 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -070014099static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070014100{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -070014101 int ret_status;
14102
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070014103 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -070014104 ret_status = hdd_driver_init();
14105 wlan_hdd_inited = ret_status ? 0 : 1;
14106 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070014107 }
14108
14109 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -070014110
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070014111 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -070014112
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -070014113 ret_status = hdd_driver_init();
14114 wlan_hdd_inited = ret_status ? 0 : 1;
14115 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070014116}
14117
Jeff Johnson295189b2012-06-20 16:38:30 -070014118/**---------------------------------------------------------------------------
14119
Jeff Johnson76052702013-04-16 13:55:05 -070014120 \brief fwpath_changed_handler() - Handler Function
14121
14122 Handle changes to the fwpath parameter
14123
14124 \return - 0 for success, non zero for failure
14125
14126 --------------------------------------------------------------------------*/
14127static int fwpath_changed_handler(const char *kmessage,
14128 struct kernel_param *kp)
14129{
14130 int ret;
14131
14132 ret = param_set_copystring(kmessage, kp);
14133 if (0 == ret)
14134 ret = kickstart_driver();
14135 return ret;
14136}
14137
14138/**---------------------------------------------------------------------------
14139
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070014140 \brief con_mode_handler() -
14141
14142 Handler function for module param con_mode when it is changed by userspace
14143 Dynamically linked - do nothing
14144 Statically linked - exit and init driver, as in rmmod and insmod
14145
Jeff Johnson76052702013-04-16 13:55:05 -070014146 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070014147
Jeff Johnson76052702013-04-16 13:55:05 -070014148 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070014149
14150 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -070014151static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070014152{
Jeff Johnson76052702013-04-16 13:55:05 -070014153 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070014154
Jeff Johnson76052702013-04-16 13:55:05 -070014155 ret = param_set_int(kmessage, kp);
14156 if (0 == ret)
14157 ret = kickstart_driver();
14158 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070014159}
14160#endif /* #ifdef MODULE */
14161
14162/**---------------------------------------------------------------------------
14163
Jeff Johnson295189b2012-06-20 16:38:30 -070014164 \brief hdd_get_conparam() -
14165
14166 This is the driver exit point (invoked when module is unloaded using rmmod)
14167
14168 \param - None
14169
14170 \return - tVOS_CON_MODE
14171
14172 --------------------------------------------------------------------------*/
14173tVOS_CON_MODE hdd_get_conparam ( void )
14174{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070014175#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -070014176 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070014177#else
14178 return (tVOS_CON_MODE)curr_con_mode;
14179#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070014180}
14181void hdd_set_conparam ( v_UINT_t newParam )
14182{
14183 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070014184#ifndef MODULE
14185 curr_con_mode = con_mode;
14186#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070014187}
14188/**---------------------------------------------------------------------------
14189
14190 \brief hdd_softap_sta_deauth() - function
14191
14192 This to take counter measure to handle deauth req from HDD
14193
14194 \param - pAdapter - Pointer to the HDD
14195
14196 \param - enable - boolean value
14197
14198 \return - None
14199
14200 --------------------------------------------------------------------------*/
14201
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +053014202VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter,
14203 struct tagCsrDelStaParams *pDelStaParams)
Jeff Johnson295189b2012-06-20 16:38:30 -070014204{
Jeff Johnson295189b2012-06-20 16:38:30 -070014205 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -080014206 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Hanumanth Reddy Pothula57323632017-12-06 17:55:09 +053014207 struct hdd_cache_sta_info *cache_sta_info;
14208 ptSapContext pSapCtx = VOS_GET_SAP_CB(pVosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -070014209
14210 ENTER();
14211
Jeff Johnsonc135a9a2017-09-19 08:37:24 -070014212 hddLog(LOG1, "hdd_softap_sta_deauth:(%pK, false)",
Rajesh Chauhan18488fc2013-08-22 10:15:03 -070014213 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -070014214
Hanumanth Reddy Pothula57323632017-12-06 17:55:09 +053014215 if (!pSapCtx) {
14216 hddLog(LOGE, "sap context is NULL");
14217 return vosStatus;
14218 }
14219
14220 cache_sta_info = hdd_get_cache_stainfo(pSapCtx->cache_sta_info,
14221 pDelStaParams->peerMacAddr);
14222 if (cache_sta_info) {
14223 cache_sta_info->reason_code = pDelStaParams->reason_code;
14224 cache_sta_info->rx_rate =
14225 wlan_tl_get_sta_rx_rate(pVosContext, cache_sta_info->ucSTAId);
14226 WLANTL_GetSAPStaRSSi(pVosContext, cache_sta_info->ucSTAId,
14227 &cache_sta_info->rssi);
14228 }
14229
Jeff Johnson295189b2012-06-20 16:38:30 -070014230 //Ignore request to deauth bcmc station
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +053014231 if (pDelStaParams->peerMacAddr[0] & 0x1)
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -080014232 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -070014233
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +053014234 vosStatus = WLANSAP_DeauthSta(pVosContext, pDelStaParams);
Jeff Johnson295189b2012-06-20 16:38:30 -070014235
14236 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -080014237 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -070014238}
14239
14240/**---------------------------------------------------------------------------
14241
Rashmi Ramanna1f0948d2014-08-28 15:33:48 +053014242 \brief hdd_del_all_sta() - function
14243
14244 This function removes all the stations associated on stopping AP/P2P GO.
14245
14246 \param - pAdapter - Pointer to the HDD
14247
14248 \return - None
14249
14250 --------------------------------------------------------------------------*/
14251
14252int hdd_del_all_sta(hdd_adapter_t *pAdapter)
14253{
14254 v_U16_t i;
14255 VOS_STATUS vos_status;
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +053014256 v_CONTEXT_t pVosContext = ( WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
14257 ptSapContext pSapCtx = NULL;
14258 pSapCtx = VOS_GET_SAP_CB(pVosContext);
14259 if(pSapCtx == NULL){
14260 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
14261 FL("psapCtx is NULL"));
14262 return 1;
14263 }
Rashmi Ramanna1f0948d2014-08-28 15:33:48 +053014264 ENTER();
14265
14266 hddLog(VOS_TRACE_LEVEL_INFO,
14267 "%s: Delete all STAs associated.",__func__);
14268 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
14269 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
14270 )
14271 {
14272 for(i = 0; i < WLAN_MAX_STA_COUNT; i++)
14273 {
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +053014274 if ((pSapCtx->aStaInfo[i].isUsed) &&
14275 (!pSapCtx->aStaInfo[i].isDeauthInProgress))
Rashmi Ramanna1f0948d2014-08-28 15:33:48 +053014276 {
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +053014277 struct tagCsrDelStaParams delStaParams;
14278
14279 WLANSAP_PopulateDelStaParams(
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +053014280 pSapCtx->aStaInfo[i].macAddrSTA.bytes,
Sushant Kaushik4cd28f62014-12-26 14:23:50 +053014281 eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
14282 SIR_MAC_MGMT_DEAUTH >> 4,
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +053014283 &delStaParams);
14284 vos_status = hdd_softap_sta_deauth(pAdapter, &delStaParams);
Rashmi Ramanna1f0948d2014-08-28 15:33:48 +053014285 if (VOS_IS_STATUS_SUCCESS(vos_status))
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +053014286 pSapCtx->aStaInfo[i].isDeauthInProgress = TRUE;
Rashmi Ramanna1f0948d2014-08-28 15:33:48 +053014287 }
14288 }
14289 }
14290
14291 EXIT();
14292 return 0;
14293}
14294
14295/**---------------------------------------------------------------------------
14296
Jeff Johnson295189b2012-06-20 16:38:30 -070014297 \brief hdd_softap_sta_disassoc() - function
14298
14299 This to take counter measure to handle deauth req from HDD
14300
14301 \param - pAdapter - Pointer to the HDD
14302
14303 \param - enable - boolean value
14304
14305 \return - None
14306
14307 --------------------------------------------------------------------------*/
14308
14309void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
14310{
Hanumanth Reddy Pothula57323632017-12-06 17:55:09 +053014311 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
14312 struct hdd_cache_sta_info *cache_sta_info;
14313 ptSapContext pSapCtx = VOS_GET_SAP_CB(pVosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -070014314
14315 ENTER();
14316
Jeff Johnsonc135a9a2017-09-19 08:37:24 -070014317 hddLog( LOGE, "hdd_softap_sta_disassoc:(%pK, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -070014318
Hanumanth Reddy Pothula57323632017-12-06 17:55:09 +053014319 if (!pSapCtx) {
14320 hddLog(LOGE, "sap context is NULL");
14321 return ;
14322 }
14323
Jeff Johnson295189b2012-06-20 16:38:30 -070014324 //Ignore request to disassoc bcmc station
14325 if( pDestMacAddress[0] & 0x1 )
14326 return;
14327
Hanumanth Reddy Pothula57323632017-12-06 17:55:09 +053014328 cache_sta_info = hdd_get_cache_stainfo(pSapCtx->cache_sta_info,
14329 pDestMacAddress);
14330 if (cache_sta_info) {
14331 cache_sta_info->reason_code = eSIR_MAC_DEAUTH_LEAVING_BSS_REASON;
14332 cache_sta_info->rx_rate =
14333 wlan_tl_get_sta_rx_rate(pVosContext, cache_sta_info->ucSTAId);
14334 WLANTL_GetSAPStaRSSi(pVosContext, cache_sta_info->ucSTAId,
14335 &cache_sta_info->rssi);
14336 }
14337
Jeff Johnson295189b2012-06-20 16:38:30 -070014338 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
14339}
14340
14341void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
14342{
14343 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
14344
14345 ENTER();
14346
Jeff Johnsonc135a9a2017-09-19 08:37:24 -070014347 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%pK, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -070014348
14349 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
14350}
14351
Jeff Johnson295189b2012-06-20 16:38:30 -070014352/**---------------------------------------------------------------------------
14353 *
14354 * \brief hdd_get__concurrency_mode() -
14355 *
14356 *
14357 * \param - None
14358 *
14359 * \return - CONCURRENCY MODE
14360 *
14361 * --------------------------------------------------------------------------*/
14362tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
14363{
14364 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
14365 hdd_context_t *pHddCtx;
14366
14367 if (NULL != pVosContext)
14368 {
14369 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
14370 if (NULL != pHddCtx)
14371 {
14372 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
14373 }
14374 }
14375
14376 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070014377 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -070014378 return VOS_STA;
14379}
Sushant Kaushikabb7ee62014-07-18 16:20:12 +053014380v_BOOL_t
14381wlan_hdd_is_GO_power_collapse_allowed (hdd_context_t* pHddCtx)
14382{
14383 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -070014384
Sushant Kaushikabb7ee62014-07-18 16:20:12 +053014385 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_GO);
14386 if (pAdapter == NULL)
14387 {
14388 hddLog(VOS_TRACE_LEVEL_INFO,
14389 FL("GO doesn't exist"));
14390 return TRUE;
14391 }
14392 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
14393 {
14394 hddLog(VOS_TRACE_LEVEL_INFO,
14395 FL("GO started"));
14396 return TRUE;
14397 }
14398 else
14399 /* wait till GO changes its interface to p2p device */
14400 hddLog(VOS_TRACE_LEVEL_INFO,
14401 FL("Del_bss called, avoid apps suspend"));
14402 return FALSE;
14403
14404}
Jeff Johnson295189b2012-06-20 16:38:30 -070014405/* Decide whether to allow/not the apps power collapse.
14406 * Allow apps power collapse if we are in connected state.
14407 * if not, allow only if we are in IMPS */
14408v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
14409{
14410 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -080014411 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -080014412 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -070014413 hdd_config_t *pConfig = pHddCtx->cfg_ini;
14414 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
14415 hdd_adapter_t *pAdapter = NULL;
14416 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -080014417 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -070014418
Jeff Johnson295189b2012-06-20 16:38:30 -070014419 if (VOS_STA_SAP_MODE == hdd_get_conparam())
14420 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -070014421
Yathish9f22e662012-12-10 14:21:35 -080014422 concurrent_state = hdd_get_concurrency_mode();
14423
Sushant Kaushikabb7ee62014-07-18 16:20:12 +053014424 if ((concurrent_state == (VOS_STA | VOS_P2P_GO)) &&
14425 !(wlan_hdd_is_GO_power_collapse_allowed(pHddCtx)))
14426 return FALSE;
Yathish9f22e662012-12-10 14:21:35 -080014427#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
Sushant Kaushikabb7ee62014-07-18 16:20:12 +053014428
Yathish9f22e662012-12-10 14:21:35 -080014429 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
Sushant Kaushikabb7ee62014-07-18 16:20:12 +053014430 (concurrent_state == (VOS_STA | VOS_P2P_GO)))&&
Yathish9f22e662012-12-10 14:21:35 -080014431 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
14432 return TRUE;
14433#endif
14434
Jeff Johnson295189b2012-06-20 16:38:30 -070014435 /*loop through all adapters. TBD fix for Concurrency */
14436 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
14437 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
14438 {
14439 pAdapter = pAdapterNode->pAdapter;
14440 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
14441 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
14442 {
Srikant Kuppafef66a72013-01-30 17:32:44 -080014443 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
c_hpothu4e8faac2014-05-16 17:38:44 +053014444 && (pmcState != IMPS && pmcState != BMPS && pmcState != UAPSD
c_hpothu1c6957d2015-01-06 18:19:47 +053014445 && pmcState != STOPPED && pmcState != STANDBY &&
14446 pmcState != WOWL)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -080014447 (eANI_BOOLEAN_TRUE == scanRspPending) ||
14448 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -070014449 {
Mukul Sharma4be88422015-03-09 20:29:07 +053014450 if(pmcState == FULL_POWER &&
14451 sme_IsCoexScoIndicationSet(pHddCtx->hHal))
14452 {
14453 /*
14454 * When SCO indication comes from Coex module , host will
14455 * enter in to full power mode, but this should not prevent
14456 * apps processor power collapse.
14457 */
14458 hddLog(LOG1,
14459 FL("Allow apps power collapse"
14460 "even when sco indication is set"));
14461 return TRUE;
14462 }
Srikant Kuppafef66a72013-01-30 17:32:44 -080014463 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Deepthi Gowri03a979f2016-11-03 15:20:19 +053014464 "pmcState = %d scanRspPending = %d "
14465 "inMiddleOfRoaming = %d connected = %d",
14466 __func__, pmcState, scanRspPending,
14467 inMiddleOfRoaming, hdd_connIsConnected(
14468 WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )));
14469 wlan_hdd_get_tdls_stats(pAdapter);
14470 return FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -070014471 }
14472 }
14473 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
14474 pAdapterNode = pNext;
14475 }
14476 return TRUE;
14477}
14478
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -080014479/* Decides whether to send suspend notification to Riva
14480 * if any adapter is in BMPS; then it is required */
14481v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
14482{
14483 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
14484 hdd_config_t *pConfig = pHddCtx->cfg_ini;
14485
14486 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
14487 {
14488 return TRUE;
14489 }
14490 return FALSE;
14491}
14492
Jeff Johnson295189b2012-06-20 16:38:30 -070014493void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
14494{
14495 switch(mode)
14496 {
Chilam Ngc4244af2013-04-01 15:37:32 -070014497 case VOS_STA_MODE:
14498 case VOS_P2P_CLIENT_MODE:
14499 case VOS_P2P_GO_MODE:
14500 case VOS_STA_SAP_MODE:
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +053014501 case VOS_MONITOR_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -070014502 pHddCtx->concurrency_mode |= (1 << mode);
Agarwal Ashish51325b52014-06-16 16:50:49 +053014503 pHddCtx->no_of_open_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -070014504 break;
14505 default:
14506 break;
Jeff Johnson295189b2012-06-20 16:38:30 -070014507 }
Agarwal Ashish51325b52014-06-16 16:50:49 +053014508 hddLog(VOS_TRACE_LEVEL_INFO, FL("concurrency_mode = 0x%x "
14509 "Number of open sessions for mode %d = %d"),
14510 pHddCtx->concurrency_mode, mode,
14511 pHddCtx->no_of_open_sessions[mode]);
Jeff Johnson295189b2012-06-20 16:38:30 -070014512}
14513
14514
14515void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
14516{
14517 switch(mode)
14518 {
Chilam Ngc4244af2013-04-01 15:37:32 -070014519 case VOS_STA_MODE:
14520 case VOS_P2P_CLIENT_MODE:
14521 case VOS_P2P_GO_MODE:
14522 case VOS_STA_SAP_MODE:
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +053014523 case VOS_MONITOR_MODE:
Agarwal Ashish51325b52014-06-16 16:50:49 +053014524 pHddCtx->no_of_open_sessions[mode]--;
14525 if (!(pHddCtx->no_of_open_sessions[mode]))
14526 pHddCtx->concurrency_mode &= (~(1 << mode));
Jeff Johnson295189b2012-06-20 16:38:30 -070014527 break;
14528 default:
14529 break;
14530 }
Agarwal Ashish51325b52014-06-16 16:50:49 +053014531 hddLog(VOS_TRACE_LEVEL_INFO, FL("concurrency_mode = 0x%x "
14532 "Number of open sessions for mode %d = %d"),
14533 pHddCtx->concurrency_mode, mode, pHddCtx->no_of_open_sessions[mode]);
14534
14535}
14536/**---------------------------------------------------------------------------
14537 *
14538 * \brief wlan_hdd_incr_active_session()
14539 *
14540 * This function increments the number of active sessions
14541 * maintained per device mode
14542 * Incase of STA/P2P CLI/IBSS upon connection indication it is incremented
14543 * Incase of SAP/P2P GO upon bss start it is incremented
14544 *
14545 * \param pHddCtx - HDD Context
14546 * \param mode - device mode
14547 *
14548 * \return - None
14549 *
14550 * --------------------------------------------------------------------------*/
14551void wlan_hdd_incr_active_session(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
14552{
14553 switch (mode) {
14554 case VOS_STA_MODE:
14555 case VOS_P2P_CLIENT_MODE:
14556 case VOS_P2P_GO_MODE:
14557 case VOS_STA_SAP_MODE:
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +053014558 case VOS_MONITOR_MODE:
Agarwal Ashish51325b52014-06-16 16:50:49 +053014559 pHddCtx->no_of_active_sessions[mode]++;
14560 break;
14561 default:
14562 hddLog(VOS_TRACE_LEVEL_INFO, FL("Not Expected Mode %d"), mode);
14563 break;
14564 }
14565 hddLog(VOS_TRACE_LEVEL_INFO, FL("No.# of active sessions for mode %d = %d"),
14566 mode,
14567 pHddCtx->no_of_active_sessions[mode]);
14568}
14569
14570/**---------------------------------------------------------------------------
14571 *
14572 * \brief wlan_hdd_decr_active_session()
14573 *
14574 * This function decrements the number of active sessions
14575 * maintained per device mode
14576 * Incase of STA/P2P CLI/IBSS upon disconnection it is decremented
14577 * Incase of SAP/P2P GO upon bss stop it is decremented
14578 *
14579 * \param pHddCtx - HDD Context
14580 * \param mode - device mode
14581 *
14582 * \return - None
14583 *
14584 * --------------------------------------------------------------------------*/
14585void wlan_hdd_decr_active_session(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
14586{
Bhargav Shahd0715912015-10-01 18:17:37 +053014587
Agarwal Ashish51325b52014-06-16 16:50:49 +053014588 switch (mode) {
14589 case VOS_STA_MODE:
14590 case VOS_P2P_CLIENT_MODE:
14591 case VOS_P2P_GO_MODE:
14592 case VOS_STA_SAP_MODE:
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +053014593 case VOS_MONITOR_MODE:
Agarwal Ashish5325f522014-08-06 00:58:44 +053014594 if (pHddCtx->no_of_active_sessions[mode] > 0)
14595 pHddCtx->no_of_active_sessions[mode]--;
14596 else
14597 hddLog(VOS_TRACE_LEVEL_INFO, FL(" No.# of Active sessions"
14598 "is already Zero"));
Agarwal Ashish51325b52014-06-16 16:50:49 +053014599 break;
14600 default:
14601 hddLog(VOS_TRACE_LEVEL_INFO, FL("Not Expected Mode %d"), mode);
14602 break;
14603 }
14604 hddLog(VOS_TRACE_LEVEL_INFO, FL("No.# of active sessions for mode %d = %d"),
14605 mode,
14606 pHddCtx->no_of_active_sessions[mode]);
Jeff Johnson295189b2012-06-20 16:38:30 -070014607}
14608
Jeff Johnsone7245742012-09-05 17:12:55 -070014609/**---------------------------------------------------------------------------
14610 *
14611 * \brief wlan_hdd_restart_init
14612 *
14613 * This function initalizes restart timer/flag. An internal function.
14614 *
14615 * \param - pHddCtx
14616 *
14617 * \return - None
14618 *
14619 * --------------------------------------------------------------------------*/
14620
14621static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
14622{
14623 /* Initialize */
14624 pHddCtx->hdd_restart_retries = 0;
14625 atomic_set(&pHddCtx->isRestartInProgress, 0);
14626 vos_timer_init(&pHddCtx->hdd_restart_timer,
14627 VOS_TIMER_TYPE_SW,
14628 wlan_hdd_restart_timer_cb,
14629 pHddCtx);
14630}
14631/**---------------------------------------------------------------------------
14632 *
14633 * \brief wlan_hdd_restart_deinit
14634 *
14635 * This function cleans up the resources used. An internal function.
14636 *
14637 * \param - pHddCtx
14638 *
14639 * \return - None
14640 *
14641 * --------------------------------------------------------------------------*/
14642
14643static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
14644{
14645
14646 VOS_STATUS vos_status;
14647 /* Block any further calls */
14648 atomic_set(&pHddCtx->isRestartInProgress, 1);
14649 /* Cleanup */
14650 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
14651 if (!VOS_IS_STATUS_SUCCESS(vos_status))
c_hpothu6ff1c3c2013-10-01 19:01:57 +053014652 hddLog(LOGE, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -070014653 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
14654 if (!VOS_IS_STATUS_SUCCESS(vos_status))
c_hpothu6ff1c3c2013-10-01 19:01:57 +053014655 hddLog(LOGE, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -070014656
14657}
14658
14659/**---------------------------------------------------------------------------
14660 *
14661 * \brief wlan_hdd_framework_restart
14662 *
14663 * This function uses a cfg80211 API to start a framework initiated WLAN
14664 * driver module unload/load.
14665 *
14666 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
14667 *
14668 *
14669 * \param - pHddCtx
14670 *
14671 * \return - VOS_STATUS_SUCCESS: Success
14672 * VOS_STATUS_E_EMPTY: Adapter is Empty
14673 * VOS_STATUS_E_NOMEM: No memory
14674
14675 * --------------------------------------------------------------------------*/
14676
14677static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
14678{
14679 VOS_STATUS status = VOS_STATUS_SUCCESS;
14680 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -070014681 int len = (sizeof (struct ieee80211_mgmt));
14682 struct ieee80211_mgmt *mgmt = NULL;
14683
14684 /* Prepare the DEAUTH managment frame with reason code */
14685 mgmt = kzalloc(len, GFP_KERNEL);
14686 if(mgmt == NULL)
14687 {
14688 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
14689 "%s: memory allocation failed (%d bytes)", __func__, len);
14690 return VOS_STATUS_E_NOMEM;
14691 }
14692 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -070014693
14694 /* Iterate over all adapters/devices */
14695 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Hanumantha Reddy Pothulada0fe362015-02-27 18:37:03 +053014696 if ((NULL == pAdapterNode) || (VOS_STATUS_SUCCESS != status))
14697 {
14698 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnsonc135a9a2017-09-19 08:37:24 -070014699 FL("fail to get adapter: %pK %d"), pAdapterNode, status);
Hanumantha Reddy Pothulada0fe362015-02-27 18:37:03 +053014700 goto end;
14701 }
14702
Jeff Johnsone7245742012-09-05 17:12:55 -070014703 do
14704 {
Hanumantha Reddy Pothulada0fe362015-02-27 18:37:03 +053014705 if(pAdapterNode->pAdapter &&
14706 WLAN_HDD_ADAPTER_MAGIC == pAdapterNode->pAdapter->magic)
Jeff Johnsone7245742012-09-05 17:12:55 -070014707 {
14708 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
14709 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
14710 pAdapterNode->pAdapter->dev->name,
14711 pAdapterNode->pAdapter->device_mode,
14712 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -070014713 /*
14714 * CFG80211 event to restart the driver
14715 *
14716 * 'cfg80211_send_unprot_deauth' sends a
14717 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
14718 * of SME(Linux Kernel) state machine.
14719 *
14720 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
14721 * the driver.
14722 *
14723 */
Abhishek Singh00b71972016-01-07 10:51:04 +053014724
Anand N Sunkade9adb1b2015-07-29 09:56:45 +053014725#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
14726 cfg80211_rx_unprot_mlme_mgmt(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len);
14727#else
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -070014728 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Anand N Sunkade9adb1b2015-07-29 09:56:45 +053014729#endif
Jeff Johnsone7245742012-09-05 17:12:55 -070014730 }
14731 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
14732 pAdapterNode = pNext;
14733 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
14734
Hanumantha Reddy Pothulada0fe362015-02-27 18:37:03 +053014735 end:
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -070014736 /* Free the allocated management frame */
14737 kfree(mgmt);
14738
Jeff Johnsone7245742012-09-05 17:12:55 -070014739 /* Retry until we unload or reach max count */
14740 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
14741 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
14742
14743 return status;
14744
14745}
14746/**---------------------------------------------------------------------------
14747 *
14748 * \brief wlan_hdd_restart_timer_cb
14749 *
14750 * Restart timer callback. An internal function.
14751 *
14752 * \param - User data:
14753 *
14754 * \return - None
14755 *
14756 * --------------------------------------------------------------------------*/
14757
14758void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
14759{
14760 hdd_context_t *pHddCtx = usrDataForCallback;
14761 wlan_hdd_framework_restart(pHddCtx);
14762 return;
14763
14764}
14765
14766
14767/**---------------------------------------------------------------------------
14768 *
14769 * \brief wlan_hdd_restart_driver
14770 *
14771 * This function sends an event to supplicant to restart the WLAN driver.
14772 *
14773 * This function is called from vos_wlanRestart.
14774 *
14775 * \param - pHddCtx
14776 *
14777 * \return - VOS_STATUS_SUCCESS: Success
14778 * VOS_STATUS_E_EMPTY: Adapter is Empty
14779 * VOS_STATUS_E_ALREADY: Request already in progress
14780
14781 * --------------------------------------------------------------------------*/
14782VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
14783{
14784 VOS_STATUS status = VOS_STATUS_SUCCESS;
14785
14786 /* A tight check to make sure reentrancy */
14787 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
14788 {
Mihir Shetefd528652014-06-23 19:07:50 +053014789 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnsone7245742012-09-05 17:12:55 -070014790 "%s: WLAN restart is already in progress", __func__);
14791
14792 return VOS_STATUS_E_ALREADY;
14793 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -070014794 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -080014795#ifdef HAVE_WCNSS_RESET_INTR
Siddharth Bhal864e7e82015-04-07 20:07:24 +053014796 wcnss_reset_fiq(TRUE);
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -070014797#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -070014798
Jeff Johnsone7245742012-09-05 17:12:55 -070014799 return status;
14800}
14801
Bhargav Shahd0715912015-10-01 18:17:37 +053014802/**
14803 * hdd_get_total_sessions() - provide total number of active sessions
14804 * @pHddCtx: Valid Global HDD context pointer
14805 *
14806 * This function iterates through pAdaptors and find the number of all active
14807 * sessions. This active sessions includes connected sta, p2p client and number
14808 * of client connected to sap/p2p go.
14809 *
14810 * Return: Total number of active sessions.
14811 */
14812v_U8_t hdd_get_total_sessions(hdd_context_t *pHddCtx)
14813{
14814 v_U8_t active_session = 0;
14815 hdd_station_ctx_t *pHddStaCtx;
14816 hdd_adapter_list_node_t *pAdapterNode, *pNext;
14817 hdd_adapter_t *pAdapter;
14818 VOS_STATUS status;
14819
14820 status = hdd_get_front_adapter(pHddCtx, &pAdapterNode);
14821 while (NULL != pAdapterNode && VOS_STATUS_SUCCESS == status) {
14822 pAdapter = pAdapterNode->pAdapter;
14823 switch (pAdapter->device_mode) {
14824 case VOS_STA_MODE:
14825 case VOS_P2P_CLIENT_MODE:
14826 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14827 if(eConnectionState_Associated == pHddStaCtx->conn_info.connState)
14828 active_session += 1;
14829 break;
14830 case VOS_STA_SAP_MODE:
14831 case VOS_P2P_GO_MODE:
14832 active_session += hdd_softap_get_connected_sta(pAdapter);
14833 break;
14834 default:
14835 break;
14836 }
14837
14838 status = hdd_get_next_adapter(pHddCtx, pAdapterNode, &pNext);
14839 pAdapterNode = pNext;
14840 }
14841
14842 return active_session;
14843}
14844
14845/**
14846 * hdd_set_delack_value() - Set delack value
14847 * @pHddCtx: Valid Global HDD context pointer
14848 * @next_rx_level: Value to set for delack
14849 *
14850 * This function compare present value and next value of delack. If the both
14851 * are diffrent then it sets next value .
14852 *
14853 * Return: void.
14854 */
14855void hdd_set_delack_value(hdd_context_t *pHddCtx, v_U32_t next_rx_level)
14856{
14857 if (pHddCtx->cur_rx_level != next_rx_level) {
14858 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_DEBUG,
14859 "%s: TCP DELACK trigger level %d",
14860 __func__, next_rx_level);
14861 mutex_lock(&pHddCtx->cur_rx_level_lock);
14862 pHddCtx->cur_rx_level = next_rx_level;
14863 mutex_unlock(&pHddCtx->cur_rx_level_lock);
14864 wlan_hdd_send_svc_nlink_msg(WLAN_SVC_WLAN_TP_IND, &next_rx_level,
14865 sizeof(next_rx_level));
14866 }
14867}
14868
14869/**
14870 * hdd_set_default_stop_delack_timer() - Start delack timer
14871 * @pHddCtx: Valid Global HDD context pointer
14872 *
14873 * This function stop delack timer and set delack value to default..
14874 *
14875 * Return: void.
14876 */
14877
14878void hdd_set_default_stop_delack_timer(hdd_context_t *pHddCtx)
14879{
14880 if (VOS_TIMER_STATE_RUNNING !=
14881 vos_timer_getCurrentState(&pHddCtx->delack_timer)) {
14882 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_DEBUG,
14883 "%s: Can not stop timer", __func__);
14884 return;
14885 }
14886
14887 vos_timer_stop(&pHddCtx->delack_timer);
14888 hdd_set_delack_value(pHddCtx, TP_IND_LOW);
14889}
14890
14891/**
14892 * hdd_start_delack_timer() - Start delack timer
14893 * @pHddCtx: Valid Global HDD context pointer
14894 *
14895 * This function starts the delack timer for tcpDelAckComputeInterval time
14896 * interval.The default timer value is 2 second.
14897 *
14898 * Return: void.
14899 */
14900void hdd_start_delack_timer(hdd_context_t *pHddCtx)
14901{
14902 if (VOS_TIMER_STATE_RUNNING ==
14903 vos_timer_getCurrentState(&pHddCtx->delack_timer)) {
14904 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_DEBUG,
14905 "%s: Timer is already running", __func__);
14906 return;
14907 }
14908
14909 vos_timer_start(&pHddCtx->delack_timer,
14910 pHddCtx->cfg_ini->tcpDelAckComputeInterval);
14911}
14912
14913/**
14914 * hdd_update_prev_rx_packet_count() - Update previous rx packet count
14915 * @pHddCtx: Valid Global HDD context pointer
14916 *
14917 * This function updates the prev_rx_packets count from the corresponding
14918 * pAdapter states. This prev_rx_packets will diffed with the packet count
14919 * at the end of delack timer. That can give number of RX packet is spacific
14920 * time.
14921 *
14922 * Return: void.
14923 */
14924void hdd_update_prev_rx_packet_count(hdd_context_t *pHddCtx)
14925{
14926 hdd_adapter_list_node_t *pAdapterNode, *pNext;
14927 hdd_adapter_t *pAdapter;
14928 VOS_STATUS status;
14929
14930 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
14931 while (NULL != pAdapterNode && VOS_STATUS_SUCCESS == status) {
14932 pAdapter = pAdapterNode->pAdapter;
14933 pAdapter->prev_rx_packets = pAdapter->stats.rx_packets;
14934 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
14935 pAdapterNode = pNext;
14936 }
14937}
14938
14939/**
14940 * hdd_manage_delack_timer() - start\stop delack timer
14941 * @pHddCtx: Valid Global HDD context pointer
14942 *
14943 * This function check the number of concerent session present, it starts the
14944 * delack timer if only one session is present.
14945 * In the case of BT_COEX and TDLS mode it blindly stop delack functionality.
14946 *
14947 * Return: void.
14948 */
14949void hdd_manage_delack_timer(hdd_context_t *pHddCtx)
14950{
14951 uint8_t sessions;
14952
14953 if (!pHddCtx->cfg_ini->enable_delack) {
14954 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_DEBUG,
14955 "%s: TCP DELACK is not enabled", __func__);
14956 return;
14957 }
14958
14959 /* Blindly stop timer of BTCOEX and TDLS Session is up */
14960 if (pHddCtx->mode != 0) {
14961 hdd_set_default_stop_delack_timer(pHddCtx);
14962 return;
14963 }
14964
14965 sessions = hdd_get_total_sessions(pHddCtx);
14966 if (sessions == 1) {
14967 hdd_update_prev_rx_packet_count(pHddCtx);
14968 hdd_start_delack_timer(pHddCtx);
14969 } else {
14970 hdd_set_default_stop_delack_timer(pHddCtx);
14971 }
14972}
14973
Mihir Shetee1093ba2014-01-21 20:13:32 +053014974/**---------------------------------------------------------------------------
14975 *
14976 * \brief wlan_hdd_init_channels
14977 *
14978 * This function is used to initialize the channel list in CSR
14979 *
14980 * This function is called from hdd_wlan_startup
14981 *
14982 * \param - pHddCtx: HDD context
14983 *
14984 * \return - VOS_STATUS_SUCCESS: Success
14985 * VOS_STATUS_E_FAULT: Failure reported by SME
14986
14987 * --------------------------------------------------------------------------*/
14988static VOS_STATUS wlan_hdd_init_channels(hdd_context_t *pHddCtx)
14989{
14990 eHalStatus status;
14991
14992 status = sme_InitChannels(pHddCtx->hHal);
14993 if (HAL_STATUS_SUCCESS(status))
14994 {
14995 return VOS_STATUS_SUCCESS;
14996 }
14997 else
14998 {
14999 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Channel initialization failed(%d)",
15000 __func__, status);
15001 return VOS_STATUS_E_FAULT;
15002 }
15003}
15004
Mihir Shete04206452014-11-20 17:50:58 +053015005#ifdef CONFIG_ENABLE_LINUX_REG
Agarwal Ashish6db9d532014-09-30 18:19:10 +053015006VOS_STATUS wlan_hdd_init_channels_for_cc(hdd_context_t *pHddCtx, driver_load_type init )
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053015007{
15008 eHalStatus status;
15009
Agarwal Ashish6db9d532014-09-30 18:19:10 +053015010 status = sme_InitChannelsForCC(pHddCtx->hHal, init);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053015011 if (HAL_STATUS_SUCCESS(status))
15012 {
15013 return VOS_STATUS_SUCCESS;
15014 }
15015 else
15016 {
15017 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Issue reg hint failed(%d)",
15018 __func__, status);
15019 return VOS_STATUS_E_FAULT;
15020 }
15021}
Mihir Shete04206452014-11-20 17:50:58 +053015022#endif
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -070015023/*
15024 * API to find if there is any STA or P2P-Client is connected
15025 */
15026VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
15027{
15028 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
15029}
Jeff Johnsone7245742012-09-05 17:12:55 -070015030
Mihir Shetee2ae82a2015-03-16 14:08:49 +053015031
15032/*
15033 * API to find if the firmware will send logs using DXE channel
15034 */
15035v_U8_t hdd_is_fw_logging_enabled(void)
15036{
15037 hdd_context_t *pHddCtx;
15038
15039 pHddCtx = vos_get_context(VOS_MODULE_ID_HDD,
15040 vos_get_global_context(VOS_MODULE_ID_HDD, NULL));
15041
Sachin Ahuja084313e2015-05-21 17:57:10 +053015042 return (pHddCtx && pHddCtx->cfg_ini->enableMgmtLogging);
Mihir Shetee2ae82a2015-03-16 14:08:49 +053015043}
15044
Agarwal Ashish57e84372014-12-05 18:26:53 +053015045/*
Mihir Shetebe94ebb2015-05-26 12:07:14 +053015046 * API to find if the firmware will send trace logs using DXE channel
15047 */
15048v_U8_t hdd_is_fw_ev_logging_enabled(void)
15049{
15050 hdd_context_t *pHddCtx;
15051
15052 pHddCtx = vos_get_context(VOS_MODULE_ID_HDD,
15053 vos_get_global_context(VOS_MODULE_ID_HDD, NULL));
15054
15055 return (pHddCtx && pHddCtx->cfg_ini->enableFWLogging);
15056}
15057/*
Agarwal Ashish57e84372014-12-05 18:26:53 +053015058 * API to find if there is any session connected
15059 */
15060VOS_STATUS hdd_is_any_session_connected(hdd_context_t *pHddCtx)
15061{
15062 return sme_is_any_session_connected(pHddCtx->hHal);
15063}
15064
15065
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053015066int wlan_hdd_scan_abort(hdd_adapter_t *pAdapter)
15067{
15068 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15069 hdd_scaninfo_t *pScanInfo = NULL;
Girish Gowli4bf7a632014-06-12 13:42:11 +053015070 long status = 0;
c_hpothua3d45d52015-01-05 14:11:17 +053015071 tSirAbortScanStatus abortScanStatus;
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053015072
15073 pScanInfo = &pHddCtx->scan_info;
Ratnam Rachuric7681132015-06-30 10:35:13 +053015074 INIT_COMPLETION(pScanInfo->abortscan_event_var);
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053015075 if (pScanInfo->mScanPending)
15076 {
c_hpothua3d45d52015-01-05 14:11:17 +053015077 abortScanStatus = hdd_abort_mac_scan(pHddCtx, pScanInfo->sessionId,
15078 eCSR_SCAN_ABORT_DEFAULT);
15079 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
15080 FL("abortScanStatus: %d"), abortScanStatus);
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053015081
c_hpothua3d45d52015-01-05 14:11:17 +053015082 /* If there is active scan command lets wait for the completion else
15083 * there is no need to wait as scan command might be in the SME pending
15084 * command list.
15085 */
15086 if (abortScanStatus == eSIR_ABORT_ACTIVE_SCAN_LIST_NOT_EMPTY)
15087 {
Mukul Sharmab392b642017-08-17 17:45:29 +053015088 status = wait_for_completion_timeout(
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053015089 &pScanInfo->abortscan_event_var,
15090 msecs_to_jiffies(5000));
c_hpothua3d45d52015-01-05 14:11:17 +053015091 if (0 >= status)
15092 {
15093 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Girish Gowli4bf7a632014-06-12 13:42:11 +053015094 "%s: Timeout or Interrupt occurred while waiting for abort"
15095 "scan, status- %ld", __func__, status);
c_hpothua3d45d52015-01-05 14:11:17 +053015096 return -ETIMEDOUT;
15097 }
15098 }
15099 else if (abortScanStatus == eSIR_ABORT_SCAN_FAILURE)
15100 {
15101 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
15102 FL("hdd_abort_mac_scan failed"));
15103 return -VOS_STATUS_E_FAILURE;
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053015104 }
15105 }
Girish Gowli4bf7a632014-06-12 13:42:11 +053015106 return 0;
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053015107}
15108
Abhishek Singh7d624e12015-11-30 14:29:27 +053015109/**
15110 * hdd_indicate_mgmt_frame() - Wrapper to indicate management frame to
15111 * user space
15112 * @frame_ind: Management frame data to be informed.
15113 *
15114 * This function is used to indicate management frame to
15115 * user space
15116 *
15117 * Return: None
15118 *
15119 */
15120void hdd_indicate_mgmt_frame(tSirSmeMgmtFrameInd *frame_ind)
15121{
15122 hdd_context_t *hdd_ctx = NULL;
15123 hdd_adapter_t *adapter = NULL;
15124 v_CONTEXT_t vos_context = NULL;
15125
15126 /* Get the global VOSS context.*/
15127 vos_context = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
15128 if (!vos_context) {
15129 hddLog(LOGE, FL("Global VOS context is Null"));
15130 return;
15131 }
15132 /* Get the HDD context.*/
15133 hdd_ctx =
15134 (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, vos_context );
15135
15136 if (0 != wlan_hdd_validate_context(hdd_ctx))
15137 {
15138 return;
15139 }
15140 adapter = hdd_get_adapter_by_sme_session_id(hdd_ctx,
15141 frame_ind->sessionId);
15142
15143 if ((NULL != adapter) &&
15144 (WLAN_HDD_ADAPTER_MAGIC == adapter->magic))
15145 __hdd_indicate_mgmt_frame(adapter,
15146 frame_ind->frameLen,
15147 frame_ind->frameBuf,
15148 frame_ind->frameType,
15149 frame_ind->rxChan,
15150 frame_ind->rxRssi);
15151 return;
15152
15153}
15154
c_hpothu225aa7c2014-10-22 17:45:13 +053015155VOS_STATUS wlan_hdd_cancel_remain_on_channel(hdd_context_t *pHddCtx)
15156{
15157 hdd_adapter_t *pAdapter;
15158 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
15159 VOS_STATUS vosStatus;
15160
15161 vosStatus = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
15162 while (NULL != pAdapterNode && VOS_STATUS_E_EMPTY != vosStatus)
15163 {
15164 pAdapter = pAdapterNode->pAdapter;
15165 if (NULL != pAdapter)
15166 {
15167 if (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode ||
15168 WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ||
15169 WLAN_HDD_P2P_GO == pAdapter->device_mode)
15170 {
15171 hddLog(LOG1, FL("abort ROC deviceMode: %d"),
15172 pAdapter->device_mode);
15173 if (VOS_STATUS_SUCCESS !=
15174 wlan_hdd_cancel_existing_remain_on_channel(pAdapter))
15175 {
15176 hddLog(LOGE, FL("failed to abort ROC"));
15177 return VOS_STATUS_E_FAILURE;
15178 }
15179 }
15180 }
15181 vosStatus = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
15182 pAdapterNode = pNext;
15183 }
15184 return VOS_STATUS_SUCCESS;
15185}
Mahesh A Saptasagard477b092015-02-06 15:12:16 +053015186
Mihir Shete0be28772015-02-17 18:42:14 +053015187hdd_remain_on_chan_ctx_t *hdd_get_remain_on_channel_ctx(hdd_context_t *pHddCtx)
15188{
15189 hdd_adapter_t *pAdapter;
15190 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
15191 hdd_cfg80211_state_t *cfgState;
15192 hdd_remain_on_chan_ctx_t *pRemainChanCtx = NULL;
15193 VOS_STATUS vosStatus;
15194
15195 vosStatus = hdd_get_front_adapter (pHddCtx, &pAdapterNode);
15196 while (NULL != pAdapterNode && VOS_STATUS_E_EMPTY != vosStatus)
15197 {
15198 pAdapter = pAdapterNode->pAdapter;
15199 if (NULL != pAdapter)
15200 {
15201 cfgState = WLAN_HDD_GET_CFG_STATE_PTR(pAdapter);
15202 pRemainChanCtx = cfgState->remain_on_chan_ctx;
15203 if (pRemainChanCtx)
15204 break;
15205 }
15206 vosStatus = hdd_get_next_adapter (pHddCtx, pAdapterNode, &pNext);
15207 pAdapterNode = pNext;
15208 }
15209 return pRemainChanCtx;
15210}
15211
Padma, Santhosh Kumar778d8382015-03-04 17:41:22 +053015212/**
15213 * wlan_hdd_handle_dfs_chan_scan () - handles disable/enable DFS channels
15214 *
15215 * @pHddCtx: HDD context within host driver
15216 * @dfsScanMode: dfsScanMode passed from ioctl
15217 *
15218 */
15219
15220VOS_STATUS wlan_hdd_handle_dfs_chan_scan(hdd_context_t *pHddCtx,
15221 tANI_U8 dfsScanMode)
15222{
15223 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
15224 hdd_adapter_t *pAdapter;
15225 VOS_STATUS vosStatus;
15226 hdd_station_ctx_t *pHddStaCtx;
15227 eHalStatus status = eHAL_STATUS_SUCCESS;
15228
15229 if(!pHddCtx)
15230 {
15231 hddLog(LOGE, FL("HDD context is Null"));
15232 return eHAL_STATUS_FAILURE;
15233 }
15234
15235 if (pHddCtx->scan_info.mScanPending)
15236 {
15237 hddLog(LOG1, FL("Aborting scan for sessionId: %d"),
15238 pHddCtx->scan_info.sessionId);
15239 hdd_abort_mac_scan(pHddCtx,
15240 pHddCtx->scan_info.sessionId,
15241 eCSR_SCAN_ABORT_DEFAULT);
15242 }
15243
15244 if (!dfsScanMode)
15245 {
15246 vosStatus = hdd_get_front_adapter( pHddCtx, &pAdapterNode);
15247 while ((NULL != pAdapterNode) &&
15248 (VOS_STATUS_SUCCESS == vosStatus))
15249 {
15250 pAdapter = pAdapterNode->pAdapter;
15251
15252 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
15253 {
15254 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
15255
15256 if(!pHddStaCtx)
15257 {
15258 hddLog(LOGE, FL("HDD STA context is Null"));
15259 return eHAL_STATUS_FAILURE;
15260 }
15261
15262 /* if STA is already connected on DFS channel,
15263 disconnect immediately*/
15264 if (hdd_connIsConnected(pHddStaCtx) &&
15265 (NV_CHANNEL_DFS ==
15266 vos_nv_getChannelEnabledState(
15267 pHddStaCtx->conn_info.operationChannel)))
15268 {
15269 status = sme_RoamDisconnect(pHddCtx->hHal,
15270 pAdapter->sessionId,
15271 eCSR_DISCONNECT_REASON_UNSPECIFIED);
15272 hddLog(LOG1, FL("Client connected on DFS channel %d,"
15273 "sme_RoamDisconnect returned with status: %d"
15274 "for sessionid: %d"), pHddStaCtx->conn_info.
15275 operationChannel, status, pAdapter->sessionId);
15276 }
15277 }
15278
15279 vosStatus = hdd_get_next_adapter(pHddCtx, pAdapterNode,
15280 &pNext);
15281 pAdapterNode = pNext;
15282 }
15283 }
15284
15285 sme_UpdateDFSScanMode(pHddCtx->hHal, dfsScanMode);
15286 sme_UpdateDFSRoamMode(pHddCtx->hHal,
15287 (dfsScanMode != DFS_CHNL_SCAN_DISABLED));
15288
15289 status = sme_HandleDFSChanScan(pHddCtx->hHal);
15290 if (!HAL_STATUS_SUCCESS(status))
15291 {
15292 hddLog(LOGE,
15293 FL("Failed in sme_HandleDFSChanScan (err=%d)"), status);
15294 return status;
15295 }
15296
15297 return status;
15298}
15299
Nirav Shah7e3c8132015-06-22 23:51:42 +053015300static int hdd_log2_ceil(unsigned value)
15301{
15302 /* need to switch to unsigned math so that negative values
15303 * will right-shift towards 0 instead of -1
15304 */
15305 unsigned tmp = value;
15306 int log2 = -1;
15307
15308 if (value == 0)
15309 return 0;
15310
15311 while (tmp) {
15312 log2++;
15313 tmp >>= 1;
15314 }
15315 if (1U << log2 != value)
15316 log2++;
15317
15318 return log2;
15319}
15320
15321/**
15322 * hdd_sta_id_hash_attach() - initialize sta id to macaddr hash
15323 * @pAdapter: adapter handle
15324 *
15325 * Return: vos status
15326 */
15327VOS_STATUS hdd_sta_id_hash_attach(hdd_adapter_t *pAdapter)
15328{
15329 int hash_elem, log2, i;
15330
15331 spin_lock_bh( &pAdapter->sta_hash_lock);
15332 if (pAdapter->is_sta_id_hash_initialized == VOS_TRUE) {
15333 spin_unlock_bh( &pAdapter->sta_hash_lock);
15334 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
15335 "%s: hash already attached for session id %d",
15336 __func__, pAdapter->sessionId);
15337 return VOS_STATUS_SUCCESS;
15338 }
15339 spin_unlock_bh( &pAdapter->sta_hash_lock);
15340
15341 hash_elem = WLAN_MAX_STA_COUNT;
15342 hash_elem *= HDD_STA_ID_HASH_MULTIPLIER;
15343 log2 = hdd_log2_ceil(hash_elem);
15344 hash_elem = 1 << log2;
15345
15346 pAdapter->sta_id_hash.mask = hash_elem - 1;
15347 pAdapter->sta_id_hash.idx_bits = log2;
15348 pAdapter->sta_id_hash.bins =
15349 vos_mem_malloc(hash_elem *sizeof(hdd_list_t));
15350 if (!pAdapter->sta_id_hash.bins) {
15351 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
15352 "%s: malloc failed for session %d",
15353 __func__, pAdapter->sessionId);
15354 return VOS_STATUS_E_NOMEM;
15355 }
15356
15357 for (i = 0; i < hash_elem; i++)
15358 hdd_list_init(&pAdapter->sta_id_hash.bins[i], WLAN_MAX_STA_COUNT);
15359
15360 spin_lock_bh( &pAdapter->sta_hash_lock);
15361 pAdapter->is_sta_id_hash_initialized = VOS_TRUE;
15362 spin_unlock_bh( &pAdapter->sta_hash_lock);
15363 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
15364 "%s: Station ID Hash attached for session id %d",
15365 __func__, pAdapter->sessionId);
15366
15367 return VOS_STATUS_SUCCESS;
15368}
15369
15370/**
15371 * hdd_sta_id_hash_detach() - deinit sta_id to macaddr hash
15372 * @pAdapter: adapter handle
15373 *
15374 * Return: vos status
15375 */
15376VOS_STATUS hdd_sta_id_hash_detach(hdd_adapter_t *pAdapter)
15377{
15378 int hash_elem, i;
15379 v_SIZE_t size;
15380
15381 spin_lock_bh( &pAdapter->sta_hash_lock);
15382 if (pAdapter->is_sta_id_hash_initialized != VOS_TRUE) {
15383 spin_unlock_bh( &pAdapter->sta_hash_lock);
15384 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
15385 "%s: hash not initialized for session id %d",
15386 __func__, pAdapter->sessionId);
15387 return VOS_STATUS_SUCCESS;
15388 }
15389
15390 pAdapter->is_sta_id_hash_initialized = VOS_FALSE;
15391 spin_unlock_bh( &pAdapter->sta_hash_lock);
15392
15393 hash_elem = 1 << pAdapter->sta_id_hash.idx_bits;
15394
15395 /* free all station info*/
15396 for (i = 0; i < hash_elem; i++) {
15397 hdd_list_size(&pAdapter->sta_id_hash.bins[i], &size);
15398 if (size != 0) {
15399 VOS_STATUS status;
15400 hdd_staid_hash_node_t *sta_info_node = NULL;
15401 hdd_staid_hash_node_t *next_node = NULL;
15402 status = hdd_list_peek_front ( &pAdapter->sta_id_hash.bins[i],
15403 (hdd_list_node_t**) &sta_info_node );
15404
15405 while ( NULL != sta_info_node && VOS_STATUS_SUCCESS == status )
15406 {
15407 status = hdd_list_remove_node( &pAdapter->sta_id_hash.bins[i],
15408 &sta_info_node->node);
15409 vos_mem_free(sta_info_node);
15410
15411 status = hdd_list_peek_next (&pAdapter->sta_id_hash.bins[i],
15412 (hdd_list_node_t*)sta_info_node,
15413 (hdd_list_node_t**)&next_node);
15414 sta_info_node = next_node;
15415 }
15416 }
15417 }
15418
15419 vos_mem_free(pAdapter->sta_id_hash.bins);
15420 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
15421 "%s: Station ID Hash detached for session id %d",
15422 __func__, pAdapter->sessionId);
15423 return VOS_STATUS_SUCCESS;
15424}
15425
15426/**
15427 * hdd_sta_id_hash_calculate_index() - derive index from macaddr
15428 * @pAdapter: adapter handle
15429 * @mac_addr_in: input mac address
15430 *
15431 * Return: index derived from mac address
15432 */
15433int hdd_sta_id_hash_calculate_index(hdd_adapter_t *pAdapter,
15434 v_MACADDR_t *mac_addr_in)
15435{
15436 uint16 index;
15437 struct hdd_align_mac_addr_t * mac_addr =
15438 (struct hdd_align_mac_addr_t *)mac_addr_in;
15439
15440 index = mac_addr->bytes_ab ^
15441 mac_addr->bytes_cd ^ mac_addr->bytes_ef;
15442 index ^= index >> pAdapter->sta_id_hash.idx_bits;
15443 index &= pAdapter->sta_id_hash.mask;
15444 return index;
15445}
15446
15447/**
15448 * hdd_sta_id_hash_add_entry() - add entry in hash
15449 * @pAdapter: adapter handle
15450 * @sta_id: station id
15451 * @mac_addr: mac address
15452 *
15453 * Return: vos status
15454 */
15455VOS_STATUS hdd_sta_id_hash_add_entry(hdd_adapter_t *pAdapter,
15456 v_U8_t sta_id, v_MACADDR_t *mac_addr)
15457{
15458 uint16 index;
15459 hdd_staid_hash_node_t *sta_info_node = NULL;
15460
Nirav Shah7e3c8132015-06-22 23:51:42 +053015461 index = hdd_sta_id_hash_calculate_index(pAdapter, mac_addr);
15462 sta_info_node = vos_mem_malloc(sizeof(hdd_staid_hash_node_t));
15463 if (!sta_info_node) {
Nirav Shah7e3c8132015-06-22 23:51:42 +053015464 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
15465 "%s: malloc failed", __func__);
15466 return VOS_STATUS_E_NOMEM;
15467 }
15468
15469 sta_info_node->sta_id = sta_id;
15470 vos_mem_copy(&sta_info_node->mac_addr, mac_addr, sizeof(v_MACADDR_t));
15471
Nirav Shah303ed5c2015-08-24 10:29:25 +053015472 spin_lock_bh( &pAdapter->sta_hash_lock);
15473 if (pAdapter->is_sta_id_hash_initialized != VOS_TRUE) {
15474 spin_unlock_bh( &pAdapter->sta_hash_lock);
15475 vos_mem_free(sta_info_node);
15476 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
15477 "%s: hash is not initialized for session id %d",
15478 __func__, pAdapter->sessionId);
15479 return VOS_STATUS_E_FAILURE;
15480 }
15481
Nirav Shah7e3c8132015-06-22 23:51:42 +053015482 hdd_list_insert_back ( &pAdapter->sta_id_hash.bins[index],
15483 (hdd_list_node_t*) sta_info_node );
15484 spin_unlock_bh( &pAdapter->sta_hash_lock);
15485 return VOS_STATUS_SUCCESS;
15486}
15487
15488/**
15489 * hdd_sta_id_hash_remove_entry() - remove entry from hash
15490 * @pAdapter: adapter handle
15491 * @sta_id: station id
15492 * @mac_addr: mac address
15493 *
15494 * Return: vos status
15495 */
15496VOS_STATUS hdd_sta_id_hash_remove_entry(hdd_adapter_t *pAdapter,
15497 v_U8_t sta_id, v_MACADDR_t *mac_addr)
15498{
15499 uint16 index;
15500 VOS_STATUS status;
15501 hdd_staid_hash_node_t *sta_info_node = NULL;
15502 hdd_staid_hash_node_t *next_node = NULL;
15503
15504 spin_lock_bh( &pAdapter->sta_hash_lock);
15505 if (pAdapter->is_sta_id_hash_initialized != VOS_TRUE) {
15506 spin_unlock_bh( &pAdapter->sta_hash_lock);
15507 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
15508 "%s: hash is not initialized for session id %d",
15509 __func__, pAdapter->sessionId);
15510 return VOS_STATUS_E_FAILURE;
15511 }
15512
15513 index = hdd_sta_id_hash_calculate_index(pAdapter, mac_addr);
15514 status = hdd_list_peek_front ( &pAdapter->sta_id_hash.bins[index],
15515 (hdd_list_node_t**) &sta_info_node );
15516
15517 while ( NULL != sta_info_node && VOS_STATUS_SUCCESS == status )
15518 {
15519 if (sta_info_node->sta_id == sta_id) {
15520 status = hdd_list_remove_node( &pAdapter->sta_id_hash.bins[index],
15521 &sta_info_node->node);
15522 vos_mem_free(sta_info_node);
15523 break;
15524 }
15525 status = hdd_list_peek_next (&pAdapter->sta_id_hash.bins[index],
15526 (hdd_list_node_t*)sta_info_node, (hdd_list_node_t**)&next_node);
15527 sta_info_node = next_node;
15528 }
15529 spin_unlock_bh( &pAdapter->sta_hash_lock);
15530 return status;
15531}
15532
15533/**
15534 * hdd_sta_id_find_from_mac_addr() - find sta id from mac address
15535 * @pAdapter: adapter handle
15536 * @mac_addr_in: mac address
15537 *
15538 * Return: station id
15539 */
15540int hdd_sta_id_find_from_mac_addr(hdd_adapter_t *pAdapter,
15541 v_MACADDR_t *mac_addr_in)
15542{
15543 uint8 is_found = 0;
15544 uint8 sta_id = HDD_WLAN_INVALID_STA_ID;
15545 uint16 index;
15546 VOS_STATUS status;
15547 hdd_staid_hash_node_t *sta_info_node = NULL;
15548 hdd_staid_hash_node_t *next_node = NULL;
15549
15550 spin_lock_bh( &pAdapter->sta_hash_lock);
15551 if (pAdapter->is_sta_id_hash_initialized != VOS_TRUE) {
15552 spin_unlock_bh( &pAdapter->sta_hash_lock);
Bhargav Shahce3b32c2015-08-10 12:29:24 +053015553 hddLog(VOS_TRACE_LEVEL_INFO,
Nirav Shah7e3c8132015-06-22 23:51:42 +053015554 FL("hash is not initialized for session id %d"),
15555 pAdapter->sessionId);
15556 return HDD_WLAN_INVALID_STA_ID;
15557 }
15558
15559 index = hdd_sta_id_hash_calculate_index(pAdapter, mac_addr_in);
15560 status = hdd_list_peek_front ( &pAdapter->sta_id_hash.bins[index],
15561 (hdd_list_node_t**) &sta_info_node );
15562
15563 while ( NULL != sta_info_node && VOS_STATUS_SUCCESS == status )
15564 {
15565 if (vos_mem_compare(&sta_info_node->mac_addr,
15566 mac_addr_in, sizeof(v_MACADDR_t))) {
15567 is_found = 1;
15568 sta_id = sta_info_node->sta_id;
15569 break;
15570 }
15571 status = hdd_list_peek_next (&pAdapter->sta_id_hash.bins[index],
15572 (hdd_list_node_t*)sta_info_node,
15573 (hdd_list_node_t**)&next_node);
15574 sta_info_node = next_node;
15575 }
15576 spin_unlock_bh( &pAdapter->sta_hash_lock);
15577 return sta_id;
15578}
15579
c_manjeecfd1efb2015-09-25 19:32:34 +053015580/*FW memory dump feature*/
15581/**
15582 * This structure hold information about the /proc file
15583 *
15584 */
15585static struct proc_dir_entry *proc_file, *proc_dir;
15586
15587/**
15588 * memdump_read() - perform read operation in memory dump proc file
15589 *
15590 * @file - handle for the proc file.
15591 * @buf - pointer to user space buffer.
15592 * @count - number of bytes to be read.
15593 * @pos - offset in the from buffer.
15594 *
15595 * This function performs read operation for the memory dump proc file.
15596 *
15597 * Return: number of bytes read on success, error code otherwise.
15598 */
15599static ssize_t memdump_read(struct file *file, char __user *buf,
15600 size_t count, loff_t *pos)
15601{
15602 int status;
15603 hdd_context_t *hdd_ctx = (hdd_context_t *)PDE_DATA(file_inode(file));
15604 size_t ret_count;
c_manjeef1495642015-10-13 18:35:01 +053015605 loff_t bytes_left;
c_manjeecfd1efb2015-09-25 19:32:34 +053015606 ENTER();
15607
15608 hddLog(LOG1, FL("Read req for size:%zu pos:%llu"), count, *pos);
15609 status = wlan_hdd_validate_context(hdd_ctx);
15610 if (0 != status) {
15611 return -EINVAL;
15612 }
15613
15614 if (!wlan_fwr_mem_dump_test_and_set_read_allowed_bit()) {
15615 hddLog(LOGE, FL("Current mem dump request timed out/failed"));
15616 return -EINVAL;
15617 }
15618
15619 /* run fs_read_handler in an atomic context*/
15620 vos_ssr_protect(__func__);
c_manjeef1495642015-10-13 18:35:01 +053015621 ret_count = wlan_fwr_mem_dump_fsread_handler( buf, count, pos, &bytes_left);
15622 if(bytes_left == 0)
c_manjeecfd1efb2015-09-25 19:32:34 +053015623 {
15624 /*Free the fwr mem dump buffer */
15625 wlan_free_fwr_mem_dump_buffer();
15626 wlan_set_fwr_mem_dump_state(FW_MEM_DUMP_IDLE);
c_manjeef1495642015-10-13 18:35:01 +053015627 ret_count=0;
c_manjeecfd1efb2015-09-25 19:32:34 +053015628 }
15629 /*if SSR/unload code is waiting for memdump_read to finish,signal it*/
15630 vos_ssr_unprotect(__func__);
15631 EXIT();
15632 return ret_count;
15633}
15634
15635/**
15636 * struct memdump_fops - file operations for memory dump feature
15637 * @read - read function for memory dump operation.
15638 *
15639 * This structure initialize the file operation handle for memory
15640 * dump feature
15641 */
15642static const struct file_operations memdump_fops = {
15643 read: memdump_read
15644};
15645
15646/*
15647* wlan_hdd_fw_mem_dump_cb : callback for Fw mem dump request
15648* To be passed by HDD to WDA and called upon receiving of response
15649* from firmware
15650* @fwMemDumpReqContext : memory dump request context
15651* @dump_rsp : dump response from HAL
15652* Returns none
15653*/
15654void wlan_hdd_fw_mem_dump_cb(void *fwMemDumpReqContext,
15655 tAniFwrDumpRsp *dump_rsp)
15656{
c_manjeef1495642015-10-13 18:35:01 +053015657 struct hdd_fw_mem_dump_req_ctx *pHddFwMemDumpCtx = (struct hdd_fw_mem_dump_req_ctx *)fwMemDumpReqContext;
c_manjeecfd1efb2015-09-25 19:32:34 +053015658
c_manjeef1495642015-10-13 18:35:01 +053015659 ENTER();
15660 spin_lock(&hdd_context_lock);
15661 if(!pHddFwMemDumpCtx || (FW_MEM_DUMP_MAGIC != pHddFwMemDumpCtx->magic)) {
15662 spin_unlock(&hdd_context_lock);
15663 return;
15664 }
15665 /* report the status to requesting function and free mem.*/
c_manjeecfd1efb2015-09-25 19:32:34 +053015666 if (dump_rsp->dump_status != eHAL_STATUS_SUCCESS) {
c_manjeef1495642015-10-13 18:35:01 +053015667 hddLog(LOGE, FL("fw dump request declined by fwr"));
15668 //set the request completion variable
15669 complete(&(pHddFwMemDumpCtx->req_completion));
c_manjeecfd1efb2015-09-25 19:32:34 +053015670 //Free the allocated fwr dump
15671 wlan_free_fwr_mem_dump_buffer();
15672 wlan_set_fwr_mem_dump_state(FW_MEM_DUMP_IDLE);
c_manjeecfd1efb2015-09-25 19:32:34 +053015673 }
c_manjeef1495642015-10-13 18:35:01 +053015674 else {
15675 hddLog(LOG1, FL("fw dump request accepted by fwr"));
15676 /* register the HDD callback which will be called by SVC */
15677 wlan_set_svc_fw_mem_dump_req_cb((void*)wlan_hdd_fw_mem_dump_req_cb,(void*)pHddFwMemDumpCtx);
15678 }
15679 spin_unlock(&hdd_context_lock);
c_manjeecfd1efb2015-09-25 19:32:34 +053015680 EXIT();
15681
15682}
15683
15684/**
15685 * memdump_procfs_remove() - Remove file/dir under procfs for memory dump
15686 *
15687 * This function removes file/dir under proc file system that was
15688 * processing firmware memory dump
15689 *
15690 * Return: None
15691 */
15692static void memdump_procfs_remove(void)
15693{
15694 remove_proc_entry(PROCFS_MEMDUMP_NAME, proc_dir);
15695 hddLog(LOG1 , FL("/proc/%s/%s removed\n"),
15696 PROCFS_MEMDUMP_DIR, PROCFS_MEMDUMP_NAME);
15697 remove_proc_entry(PROCFS_MEMDUMP_DIR, NULL);
15698 hddLog(LOG1 , FL("/proc/%s removed\n"), PROCFS_MEMDUMP_DIR);
15699}
15700
15701/**
15702 * memdump_procfs_init() - Initialize procfs for memory dump
15703 *
15704 * @vos_ctx - Global vos context.
15705 *
15706 * This function create file under proc file system to be used later for
15707 * processing firmware memory dump
15708 *
15709 * Return: 0 on success, error code otherwise.
15710 */
15711static int memdump_procfs_init(void *vos_ctx)
15712{
15713 hdd_context_t *hdd_ctx;
15714
15715 hdd_ctx = vos_get_context(VOS_MODULE_ID_HDD, vos_ctx);
15716 if (!hdd_ctx) {
15717 hddLog(LOGE , FL("Invalid HDD context"));
15718 return -EINVAL;
15719 }
15720
15721 proc_dir = proc_mkdir(PROCFS_MEMDUMP_DIR, NULL);
15722 if (proc_dir == NULL) {
15723 remove_proc_entry(PROCFS_MEMDUMP_DIR, NULL);
15724 hddLog(LOGE , FL("Error: Could not initialize /proc/%s"),
15725 PROCFS_MEMDUMP_DIR);
15726 return -ENOMEM;
15727 }
15728
15729 proc_file = proc_create_data(PROCFS_MEMDUMP_NAME,
15730 S_IRUSR | S_IWUSR, proc_dir,
15731 &memdump_fops, hdd_ctx);
15732 if (proc_file == NULL) {
15733 remove_proc_entry(PROCFS_MEMDUMP_NAME, proc_dir);
15734 hddLog(LOGE , FL("Error: Could not initialize /proc/%s"),
15735 PROCFS_MEMDUMP_NAME);
15736 return -ENOMEM;
15737 }
15738
15739 hddLog(LOG1 , FL("/proc/%s/%s created"),
15740 PROCFS_MEMDUMP_DIR, PROCFS_MEMDUMP_NAME);
15741
15742 return 0;
15743}
15744
15745/**
15746 * memdump_init() - Initialization function for memory dump feature
15747 *
15748 * This function creates proc file for memdump feature and registers
15749 * HDD callback function with SME.
15750 *
15751 * Return - 0 on success, error otherwise
15752 */
15753int memdump_init(void)
15754{
15755 hdd_context_t *hdd_ctx;
15756 void *vos_ctx;
15757 int status = 0;
15758
15759 vos_ctx = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
15760 if (!vos_ctx) {
15761 hddLog(LOGE, FL("Invalid VOS context"));
15762 return -EINVAL;
15763 }
15764
15765 hdd_ctx = vos_get_context(VOS_MODULE_ID_HDD, vos_ctx);
15766 if (!hdd_ctx) {
15767 hddLog(LOGE , FL("Invalid HDD context"));
15768 return -EINVAL;
15769 }
15770
15771 status = memdump_procfs_init(vos_ctx);
15772 if (status) {
15773 hddLog(LOGE , FL("Failed to create proc file"));
15774 return status;
15775 }
15776
15777 return 0;
15778}
15779
15780/**
15781 * memdump_deinit() - De initialize memdump feature
15782 *
15783 * This function removes proc file created for memdump feature.
15784 *
15785 * Return: None
15786 */
15787int memdump_deinit(void)
15788{
15789 hdd_context_t *hdd_ctx;
15790 void *vos_ctx;
15791
15792 vos_ctx = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
15793 if (!vos_ctx) {
15794 hddLog(LOGE, FL("Invalid VOS context"));
15795 return -EINVAL;
15796 }
15797
15798 hdd_ctx = vos_get_context(VOS_MODULE_ID_HDD, vos_ctx);
15799 if(!hdd_ctx) {
15800 hddLog(LOGE , FL("Invalid HDD context"));
15801 return -EINVAL;
15802 }
15803
15804 memdump_procfs_remove();
15805 return 0;
15806}
15807
15808/**
15809 * wlan_hdd_fw_mem_dump_req(pHddCtx) - common API(cfg80211/ioctl) for requesting fw mem dump to SME
15810 * Return: HAL status
15811 */
15812
15813int wlan_hdd_fw_mem_dump_req(hdd_context_t * pHddCtx)
15814{
15815 tAniFwrDumpReq fw_mem_dump_req={0};
c_manjeef1495642015-10-13 18:35:01 +053015816 struct hdd_fw_mem_dump_req_ctx fw_mem_dump_ctx;
c_manjeecfd1efb2015-09-25 19:32:34 +053015817 eHalStatus status = eHAL_STATUS_FAILURE;
Abhishek Singh4eca9822015-12-09 18:07:34 +053015818 int ret=0, result;
c_manjeecfd1efb2015-09-25 19:32:34 +053015819 ENTER();
c_manjeef1495642015-10-13 18:35:01 +053015820
c_manjeecfd1efb2015-09-25 19:32:34 +053015821 /*Check whether a dump request is already going on
15822 *Caution this function will free previously held memory if new dump request is allowed*/
15823 if (!wlan_fwr_mem_dump_test_and_set_write_allowed_bit()) {
15824 hddLog(LOGE, FL("Fw memdump already in progress"));
15825 return -EBUSY;
15826 }
15827 //Allocate memory for fw mem dump buffer
15828 ret = wlan_fwr_mem_dump_buffer_allocation();
15829 if(ret == -EFAULT)
15830 {
15831 hddLog(LOGE, FL("Fwr mem dump not supported by FW"));
15832 return ret;
15833 }
15834 if (0 != ret) {
15835 hddLog(LOGE, FL("Fwr mem Allocation failed"));
15836 return -ENOMEM;
15837 }
c_manjeef1495642015-10-13 18:35:01 +053015838 init_completion(&fw_mem_dump_ctx.req_completion);
15839 fw_mem_dump_ctx.magic = FW_MEM_DUMP_MAGIC;
15840 fw_mem_dump_ctx.status = false;
15841
c_manjeecfd1efb2015-09-25 19:32:34 +053015842 fw_mem_dump_req.fwMemDumpReqCallback = wlan_hdd_fw_mem_dump_cb;
c_manjeef1495642015-10-13 18:35:01 +053015843 fw_mem_dump_req.fwMemDumpReqContext = &fw_mem_dump_ctx;
c_manjeecfd1efb2015-09-25 19:32:34 +053015844 status = sme_FwMemDumpReq(pHddCtx->hHal, &fw_mem_dump_req);
15845 if(eHAL_STATUS_SUCCESS != status)
15846 {
15847 hddLog(VOS_TRACE_LEVEL_ERROR,
15848 "%s: fw_mem_dump_req failed ", __func__);
15849 wlan_free_fwr_mem_dump_buffer();
c_manjeef1495642015-10-13 18:35:01 +053015850 ret = -EFAULT;
15851 goto cleanup;
c_manjeecfd1efb2015-09-25 19:32:34 +053015852 }
c_manjeef1495642015-10-13 18:35:01 +053015853 /*wait for fw mem dump completion to send event to userspace*/
Abhishek Singh4eca9822015-12-09 18:07:34 +053015854 result =
15855 wait_for_completion_timeout(&fw_mem_dump_ctx.req_completion,
15856 msecs_to_jiffies(FW_MEM_DUMP_TIMEOUT_MS));
15857 if (0 >= result )
c_manjeef1495642015-10-13 18:35:01 +053015858 {
15859 hddLog(VOS_TRACE_LEVEL_ERROR,
Abhishek Singh4eca9822015-12-09 18:07:34 +053015860 "%s: fw_mem_dump_req timeout %d ", __func__,result);
15861 ret = -ETIMEDOUT;
c_manjeef1495642015-10-13 18:35:01 +053015862 }
15863cleanup:
15864 spin_lock(&hdd_context_lock);
15865 fw_mem_dump_ctx.magic = 0;
Abhishek Singh4eca9822015-12-09 18:07:34 +053015866 if(!ret && !fw_mem_dump_ctx.status)
15867 ret = -EFAULT;
c_manjeef1495642015-10-13 18:35:01 +053015868 spin_unlock(&hdd_context_lock);
c_manjeecfd1efb2015-09-25 19:32:34 +053015869
c_manjeef1495642015-10-13 18:35:01 +053015870 EXIT();
Abhishek Singh4eca9822015-12-09 18:07:34 +053015871 return ret;
c_manjeef1495642015-10-13 18:35:01 +053015872}
15873
15874/**
15875 * HDD callback which will be called by SVC to indicate mem dump completion.
15876 */
15877void wlan_hdd_fw_mem_dump_req_cb(struct hdd_fw_mem_dump_req_ctx* pHddFwMemDumpCtx)
15878{
15879 if (!pHddFwMemDumpCtx) {
15880 hddLog(VOS_TRACE_LEVEL_ERROR,
15881 "%s: HDD context not valid ", __func__);
15882 return;
15883 }
15884 spin_lock(&hdd_context_lock);
15885 /* check the req magic and set status */
15886 if (pHddFwMemDumpCtx->magic == FW_MEM_DUMP_MAGIC)
15887 {
15888 pHddFwMemDumpCtx->status = true;
15889 //signal the completion
15890 complete(&(pHddFwMemDumpCtx->req_completion));
15891 }
15892 else
15893 {
15894 hddLog(VOS_TRACE_LEVEL_ERROR,
15895 "%s: fw mem dump request possible timeout ", __func__);
15896 }
15897 spin_unlock(&hdd_context_lock);
c_manjeecfd1efb2015-09-25 19:32:34 +053015898}
15899
Mahesh A Saptasagar67ab9222015-10-21 15:38:41 +053015900void hdd_initialize_adapter_common(hdd_adapter_t *pAdapter)
15901{
15902 if (NULL == pAdapter)
15903 {
15904 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: pAdapter is NULL ", __func__);
15905 return;
15906 }
15907 init_completion(&pAdapter->session_open_comp_var);
15908 init_completion(&pAdapter->session_close_comp_var);
15909 init_completion(&pAdapter->disconnect_comp_var);
15910 init_completion(&pAdapter->linkup_event_var);
15911 init_completion(&pAdapter->cancel_rem_on_chan_var);
15912 init_completion(&pAdapter->rem_on_chan_ready_event);
15913 init_completion(&pAdapter->pno_comp_var);
15914#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
15915 init_completion(&pAdapter->offchannel_tx_event);
15916#endif
15917 init_completion(&pAdapter->tx_action_cnf_event);
15918#ifdef FEATURE_WLAN_TDLS
15919 init_completion(&pAdapter->tdls_add_station_comp);
15920 init_completion(&pAdapter->tdls_del_station_comp);
15921 init_completion(&pAdapter->tdls_mgmt_comp);
15922 init_completion(&pAdapter->tdls_link_establish_req_comp);
15923#endif
15924
15925#ifdef WLAN_FEATURE_RMC
15926 init_completion(&pAdapter->ibss_peer_info_comp);
15927#endif /* WLAN_FEATURE_RMC */
15928 init_completion(&pAdapter->ula_complete);
15929 init_completion(&pAdapter->change_country_code);
15930
15931#ifdef FEATURE_WLAN_BATCH_SCAN
15932 init_completion(&pAdapter->hdd_set_batch_scan_req_var);
15933 init_completion(&pAdapter->hdd_get_batch_scan_req_var);
15934#endif
Kapil Gupta2b44acb2016-12-30 16:49:51 +053015935 init_completion(&pAdapter->wlan_suspend_comp_var);
Mahesh A Saptasagar67ab9222015-10-21 15:38:41 +053015936
15937 return;
15938}
c_manjeecfd1efb2015-09-25 19:32:34 +053015939
Anurag Chouhan0b29de02016-12-16 13:18:40 +053015940#ifdef MDNS_OFFLOAD
15941
15942/**
15943 * hdd_mdns_enable_offload_done() - mdns enable offload response api
15944 * @padapter: holds adapter
15945 * @status: response status
15946 *
15947 * Return - None
15948 */
15949void hdd_mdns_enable_offload_done(void *padapter, VOS_STATUS status)
15950{
15951 hdd_adapter_t* adapter = (hdd_adapter_t*) padapter;
15952
15953 ENTER();
15954
15955 if (NULL == adapter)
15956 {
15957 hddLog(VOS_TRACE_LEVEL_ERROR,
15958 "%s: adapter is NULL",__func__);
15959 return;
15960 }
15961
15962 adapter->mdns_status.mdns_enable_status = status;
15963 vos_event_set(&adapter->mdns_status.vos_event);
15964 return;
15965}
15966
15967/**
15968 * hdd_mdns_fqdn_offload_done() - mdns fqdn offload response api
15969 * @padapter: holds adapter
15970 * @status: responce status
15971 *
15972 * Return - None
15973 */
15974void hdd_mdns_fqdn_offload_done(void *padapter, VOS_STATUS status)
15975{
15976 hdd_adapter_t* adapter = (hdd_adapter_t*) padapter;
15977
15978 ENTER();
15979
15980 if (NULL == adapter)
15981 {
15982 hddLog(VOS_TRACE_LEVEL_ERROR,
15983 "%s: adapter is NULL",__func__);
15984 return;
15985 }
15986
15987 adapter->mdns_status.mdns_fqdn_status = status;
15988 return;
15989}
15990
15991/**
15992 * hdd_mdns_resp_offload_done() - mdns resp offload response api
15993 * @padapter: holds adapter
15994 * @status: responce status
15995 *
15996 * Return - None
15997 */
15998void hdd_mdns_resp_offload_done(void *padapter, VOS_STATUS status)
15999{
16000 hdd_adapter_t* adapter = (hdd_adapter_t*) padapter;
16001
16002 ENTER();
16003
16004 if (NULL == adapter)
16005 {
16006 hddLog(VOS_TRACE_LEVEL_ERROR,
16007 "%s: adapter is NULL",__func__);
16008 return;
16009 }
16010
16011 adapter->mdns_status.mdns_resp_status = status;
16012 return;
16013}
16014
16015/**
16016 * wlan_hdd_mdns_process_response_dname() - Process mDNS domain name
16017 * @response: Pointer to a struct hdd_mdns_resp_info
16018 * @resp_info: Pointer to a struct tSirMDNSResponseInfo
16019 *
16020 * This function will pack the whole domain name without compression. It will
16021 * add the leading len for each field and add zero length octet to terminate
16022 * the domain name.
16023 *
16024 * Return: Return boolean. TRUE for success, FALSE for fail.
16025 */
16026static bool
16027wlan_hdd_mdns_process_response_dname(struct hdd_mdns_resp_info *response,
16028 sir_mdns_resp_info resp_info)
16029{
16030 uint8_t num;
16031 uint16_t idx;
16032 uint8_t len = 0;
16033
16034 if ((response == NULL) || (response->data == NULL) ||
16035 (response->offset == NULL)) {
16036 hddLog(LOGE, FL("Either data or offset in response is NULL!"));
16037 return FALSE;
16038 }
16039
16040 if ((resp_info == NULL) ||
16041 (resp_info->resp_len >= MAX_MDNS_RESP_LEN)) {
16042 hddLog(LOGE, FL("resp_len exceeds %d!"), MAX_MDNS_RESP_LEN);
16043 return FALSE;
16044 }
16045
16046 for (num = 0; num < response->num_entries; num++) {
16047 response->offset[num] =
16048 resp_info->resp_len + MDNS_HEADER_LEN;
16049 idx = num * MAX_LEN_DOMAINNAME_FIELD;
16050 len = strlen((char *)&response->data[idx]);
16051 if ((resp_info->resp_len + len + 1) >= MAX_MDNS_RESP_LEN) {
16052 hddLog(LOGE, FL("resp_len exceeds %d!"),
16053 MAX_MDNS_RESP_LEN);
16054 return FALSE;
16055 }
16056 resp_info->resp_data[resp_info->resp_len] = len;
16057 resp_info->resp_len++;
16058 vos_mem_copy(&resp_info->resp_data[resp_info->resp_len],
16059 &response->data[idx], len);
16060 resp_info->resp_len += len;
16061 }
16062
16063 /* The domain name terminates with the zero length octet */
16064 if (num == response->num_entries) {
16065 if (resp_info->resp_len >= MAX_MDNS_RESP_LEN) {
16066 hddLog(LOGE, FL("resp_len exceeds %d!"),
16067 MAX_MDNS_RESP_LEN);
16068 return FALSE;
16069 }
16070 resp_info->resp_data[resp_info->resp_len] = 0;
16071 resp_info->resp_len++;
16072 }
16073
16074 return TRUE;
16075}
16076
16077/**
16078 * wlan_hdd_mdns_format_response_u16() - Form uint16_t response data
16079 * @value: The uint16_t value is formed to the struct tSirMDNSResponseInfo
16080 * @resp_info: Pointer to a struct tSirMDNSResponseInfo
16081 *
16082 * Return: None
16083 */
16084static void wlan_hdd_mdns_format_response_u16(uint16_t value,
16085 sir_mdns_resp_info resp_info)
16086{
16087 uint8_t val_u8;
16088
16089 if ((resp_info == NULL) || (resp_info->resp_data == NULL))
16090 return;
16091 val_u8 = (value & 0xff00) >> 8;
16092 resp_info->resp_data[resp_info->resp_len++] = val_u8;
16093 val_u8 = value & 0xff;
16094 resp_info->resp_data[resp_info->resp_len++] = val_u8;
16095}
16096
16097/**
16098 * wlan_hdd_mdns_format_response_u32() - Form uint32_t response data
16099 * @value: The uint32_t value is formed to the struct tSirMDNSResponseInfo
16100 * @resp_info: Pointer to a struct tSirMDNSResponseInfo
16101 *
16102 * Return: None
16103 */
16104static void wlan_hdd_mdns_format_response_u32(uint32_t value,
16105 sir_mdns_resp_info resp_info)
16106{
16107 uint8_t val_u8;
16108
16109 if ((resp_info == NULL) || (resp_info->resp_data == NULL))
16110 return;
16111 val_u8 = (value & 0xff000000) >> 24;
16112 resp_info->resp_data[resp_info->resp_len++] = val_u8;
16113 val_u8 = (value & 0xff0000) >> 16;
16114 resp_info->resp_data[resp_info->resp_len++] = val_u8;
16115 val_u8 = (value & 0xff00) >> 8;
16116 resp_info->resp_data[resp_info->resp_len++] = val_u8;
16117 val_u8 = value & 0xff;
16118 resp_info->resp_data[resp_info->resp_len++] = val_u8;
16119}
16120
16121/**
16122 * wlan_hdd_mdns_process_response_misc() - Process misc info in mDNS response
16123 * @resp_type: Response type for mDNS
16124 * @resp_info: Pointer to a struct tSirMDNSResponseInfo
16125 *
16126 * This function will pack the response type, class and TTL (Time To Live).
16127 *
16128 * Return: Return boolean. TRUE for success, FALSE for fail.
16129 */
16130static bool wlan_hdd_mdns_process_response_misc(uint16_t resp_type,
16131 sir_mdns_resp_info resp_info)
16132{
16133 uint16_t len;
16134
16135 if (resp_info == NULL) {
16136 hddLog(LOGE, FL("resp_info is NULL!"));
16137 return FALSE;
16138 }
16139
16140 len = resp_info->resp_len + (2 * sizeof(uint16_t) + sizeof(uint32_t));
16141 if (len >= MAX_MDNS_RESP_LEN) {
16142 hddLog(LOGE, FL("resp_len exceeds %d!"), MAX_MDNS_RESP_LEN);
16143 return FALSE;
16144 }
16145
16146 /* Fill Type, Class, TTL */
16147 wlan_hdd_mdns_format_response_u16(resp_type, resp_info);
16148 wlan_hdd_mdns_format_response_u16(MDNS_CLASS, resp_info);
16149 wlan_hdd_mdns_format_response_u32(MDNS_TTL, resp_info);
16150
16151 return TRUE;
16152}
16153
16154/**
16155 * wlan_hdd_mdns_compress_data() - Compress the domain name in mDNS response
16156 * @resp_info: Pointer to a struct tSirMDNSResponseInfo
16157 * @response_dst: The response which domain name is compressed.
16158 * @response_src: The response which domain name is matched with response_dst.
16159 * Its offset is used for data compression.
16160 * @num_matched: The number of matched entries between response_dst and
16161 * response_src
16162 *
16163 * This function will form the different fields of domain name in response_dst
16164 * if any. Then use the offset of the matched domain name in response_src to
16165 * compress the matched domain name.
16166 *
16167 * Return: Return boolean. TRUE for success, FALSE for fail.
16168 */
16169static bool
16170wlan_hdd_mdns_compress_data(sir_mdns_resp_info resp_info,
16171 struct hdd_mdns_resp_info *response_dst,
16172 struct hdd_mdns_resp_info *response_src,
16173 uint8_t num_matched)
16174{
16175 uint8_t num, num_diff;
16176 uint16_t value, idx;
16177 uint8_t len = 0;
16178
16179 if ((response_src == NULL) || (response_dst == NULL) ||
16180 (resp_info == NULL)) {
16181 hddLog(LOGE, FL("response info is NULL!"));
16182 return FALSE;
16183 }
16184
16185 if (response_dst->num_entries < num_matched) {
16186 hddLog(LOGE, FL("num_entries is less than num_matched!"));
16187 return FALSE;
16188 }
16189
16190 if (resp_info->resp_len >= MAX_MDNS_RESP_LEN) {
16191 hddLog(LOGE, FL("resp_len exceeds %d!"), MAX_MDNS_RESP_LEN);
16192 return FALSE;
16193 }
16194
16195 num_diff = response_dst->num_entries - num_matched;
16196 if ((num_diff > 0) && (response_dst->data == NULL)) {
16197 hddLog(LOGE, FL("response_dst->data is NULL!"));
16198 return FALSE;
16199 }
16200
16201 /*
16202 * Handle the unmatched string at the beginning
16203 * Store the length of octets and the octets
16204 */
16205 for (num = 0; num < num_diff; num++) {
16206 response_dst->offset[num] =
16207 resp_info->resp_len + MDNS_HEADER_LEN;
16208 idx = num * MAX_LEN_DOMAINNAME_FIELD;
16209 len = strlen((char *)&response_dst->data[idx]);
16210 if ((resp_info->resp_len + len + 1) >= MAX_MDNS_RESP_LEN) {
16211 hddLog(LOGE, FL("resp_len exceeds %d!"),
16212 MAX_MDNS_RESP_LEN);
16213 return FALSE;
16214 }
16215 resp_info->resp_data[resp_info->resp_len] = len;
16216 resp_info->resp_len++;
16217 vos_mem_copy(&resp_info->resp_data[resp_info->resp_len],
16218 &response_dst->data[idx], len);
16219 resp_info->resp_len += len;
16220 }
16221 /*
16222 * Handle the matched string from the end
16223 * Just keep the offset and mask the leading two bit
16224 */
16225 if (response_src->num_entries >= num_matched) {
16226 num_diff = response_src->num_entries - num_matched;
16227 value = response_src->offset[num_diff];
16228 if (value > 0) {
16229 value |= 0xc000;
16230 if ((resp_info->resp_len + sizeof(uint16_t)) >=
16231 MAX_MDNS_RESP_LEN) {
16232 hddLog(LOGE, FL("resp_len exceeds %d!"),
16233 MAX_MDNS_RESP_LEN);
16234 return FALSE;
16235 }
16236 wlan_hdd_mdns_format_response_u16(value, resp_info);
16237 return TRUE;
16238 }
16239 }
16240 return FALSE;
16241}
16242
16243/**
16244 * wlan_hdd_mdns_reset_response() - Reset the response info
16245 * @response: The response which info is reset.
16246 *
16247 * Return: None
16248 */
16249static void wlan_hdd_mdns_reset_response(struct hdd_mdns_resp_info *response)
16250{
16251 if (response == NULL)
16252 return;
16253 response->num_entries = 0;
16254 response->data = NULL;
16255 response->offset = NULL;
16256}
16257
16258/**
16259 * wlan_hdd_mdns_init_response() - Initialize the response info
16260 * @response: The response which info is initiatized.
16261 * @resp_dname: The domain name string which might be tokenized.
16262 *
16263 * This function will allocate the memory for both response->data and
16264 * response->offset. Besides, it will also tokenize the domain name to some
16265 * entries and fill response->num_entries with the num of entries.
16266 *
16267 * Return: Return boolean. TRUE for success, FALSE for fail.
16268 */
16269static bool wlan_hdd_mdns_init_response(struct hdd_mdns_resp_info *response,
16270 uint8_t *resp_dname, char separator)
16271{
16272 uint16_t size;
16273
16274 if ((resp_dname == NULL) || (response == NULL)) {
16275 hddLog(LOGE, FL("resp_dname or response is NULL!"));
16276 return FALSE;
16277 }
16278
16279 size = MAX_NUM_FIELD_DOMAINNAME * MAX_LEN_DOMAINNAME_FIELD;
16280 response->data = vos_mem_malloc(size);
16281 if (response->data) {
16282 vos_mem_zero(response->data, size);
16283 if (VOS_STATUS_SUCCESS !=
16284 hdd_string_to_string_array((char *)resp_dname,
16285 response->data,
16286 separator,
16287 &response->num_entries,
16288 MAX_NUM_FIELD_DOMAINNAME,
16289 MAX_LEN_DOMAINNAME_FIELD)) {
16290 hddLog(LOGE, FL("hdd_string_to_string_array fail!"));
16291 goto err_init_resp;
16292 }
16293
16294 if ((response->num_entries > 0) &&
16295 (strlen((char *)&response->data[0]) > 0)) {
16296 size = sizeof(uint16_t) * response->num_entries;
16297 response->offset = vos_mem_malloc(size);
16298 if (response->offset) {
16299 vos_mem_zero(response->offset, size);
16300 return TRUE;
16301 }
16302 }
16303 }
16304
16305err_init_resp:
16306 if (response->data)
16307 vos_mem_free(response->data);
16308 wlan_hdd_mdns_reset_response(response);
16309 return FALSE;
16310}
16311
16312/**
16313 * wlan_hdd_mdns_find_entries_from_end() - Find the matched entries
16314 * @response1: The response info is used to be compared.
16315 * @response2: The response info is used to be compared.
16316 *
16317 * This function will find the matched entries from the end.
16318 *
16319 * Return: Return the number of the matched entries.
16320 */
16321static uint8_t
16322wlan_hdd_mdns_find_entries_from_end(struct hdd_mdns_resp_info *response1,
16323 struct hdd_mdns_resp_info *response2)
16324{
16325 uint8_t min, len1, i;
16326 uint16_t num1, num2;
16327 uint8_t num_matched = 0;
16328
16329 min = VOS_MIN(response1->num_entries, response2->num_entries);
16330
16331 for (i = 1; i <= min; i++) {
16332 num1 = (response1->num_entries - i);
16333 num1 *= MAX_LEN_DOMAINNAME_FIELD;
16334 num2 = (response2->num_entries - i);
16335 num2 *= MAX_LEN_DOMAINNAME_FIELD;
16336 len1 = strlen((char *)&response1->data[num1]);
16337
16338 if ((len1 == 0) ||
16339 (len1 != strlen((char *)&response2->data[num2])))
16340 break;
16341 if (memcmp(&response1->data[num1],
16342 &response2->data[num2], len1))
16343 break;
16344 else
16345 num_matched++;
16346 }
16347
16348 return num_matched;
16349}
16350
16351/**
16352 * wlan_hdd_mdns_find_max() - Find the maximum number of the matched entries
16353 * @matchedlist: Pointer to the array of struct hdd_mdns_resp_matched
16354 * @numlist: The number of the elements in the array matchedlist.
16355 *
16356 * Find the max number of the matched entries among the array matchedlist.
16357 *
16358 * Return: None
16359 */
16360static void wlan_hdd_mdns_find_max(struct hdd_mdns_resp_matched *matchedlist,
16361 uint8_t numlist)
16362{
16363 int j;
16364 struct hdd_mdns_resp_matched tmp;
16365
16366 /* At least two values are used for sorting */
16367 if ((numlist < 2) || (matchedlist == NULL)) {
16368 hddLog(LOGE, FL("At least two values are used for sorting!"));
16369 return;
16370 }
16371
16372 for (j = 0; j < numlist-1; j++) {
16373 if (matchedlist[j].num_matched >
16374 matchedlist[j+1].num_matched) {
16375 vos_mem_copy(&tmp, &matchedlist[j],
16376 sizeof(struct hdd_mdns_resp_matched));
16377 vos_mem_copy(&matchedlist[j], &matchedlist[j+1],
16378 sizeof(struct hdd_mdns_resp_matched));
16379 vos_mem_copy(&matchedlist[j+1], &tmp,
16380 sizeof(struct hdd_mdns_resp_matched));
16381 }
16382 }
16383}
16384
16385/**
16386 * wlan_hdd_mdns_pack_response_type_a() - Pack Type A response
16387 * @ini_config: Pointer to the struct hdd_config_t
16388 * @resp_info: Pointer to the struct tSirMDNSResponseInfo
16389 * @resptype_a: Pointer to the struct hdd_mdns_resp_info of Type A
16390 *
16391 * Type A response include QName, response type, class, TTL and Ipv4.
16392 *
16393 * Return: Return boolean. TRUE for success, FALSE for fail.
16394 */
16395static bool
16396wlan_hdd_mdns_pack_response_type_a(hdd_config_t *ini_config,
16397 sir_mdns_resp_info resp_info,
16398 struct hdd_mdns_resp_info *resptype_a)
16399{
16400 uint16_t value;
16401 uint32_t len;
16402
16403 ENTER();
16404 if ((ini_config == NULL) || (resp_info == NULL) ||
16405 (resptype_a == NULL)) {
16406 hddLog(LOGE, FL("ini_config or response info is NULL!"));
16407 return FALSE;
16408 }
16409
16410 /* No Type A response */
16411 if (strlen((char *)ini_config->mdns_resp_type_a) <= 0)
16412 return TRUE;
16413
16414 /* Wrong response is assigned, just ignore this response */
16415 if (!wlan_hdd_mdns_init_response(resptype_a,
16416 ini_config->mdns_resp_type_a, '.'))
16417 return TRUE;
16418
16419 /* Process response domain name */
16420 if (!wlan_hdd_mdns_process_response_dname(resptype_a, resp_info)) {
16421 hddLog(LOGE, FL("Fail to process mDNS response (%d)!"),
16422 MDNS_TYPE_A);
16423 return FALSE;
16424 }
16425
16426 /* Process response Type, Class, TTL */
16427 if (!wlan_hdd_mdns_process_response_misc(MDNS_TYPE_A, resp_info)) {
16428 hddLog(LOGE, FL("Fail to process mDNS misc response (%d)!"),
16429 MDNS_TYPE_A);
16430 return FALSE;
16431 }
16432
16433 /* Process response RDLength, RData */
16434 len = sizeof(uint16_t) + sizeof(uint32_t);
16435 len += resp_info->resp_len;
16436 if (len >= MAX_MDNS_RESP_LEN) {
16437 hddLog(LOGE, FL("resp_len exceeds %d!"), MAX_MDNS_RESP_LEN);
16438 return FALSE;
16439 }
16440 value = sizeof(uint32_t);
16441 wlan_hdd_mdns_format_response_u16(value, resp_info);
16442 wlan_hdd_mdns_format_response_u32(ini_config->mdns_resp_type_a_ipv4,
16443 resp_info);
16444
16445 EXIT();
16446 return TRUE;
16447}
16448
16449/**
16450 * wlan_hdd_mdns_pack_response_type_txt() - Pack Type Txt response
16451 * @ini_config: Pointer to the struct hdd_config_t
16452 * @resp_info: Pointer to the struct tSirMDNSResponseInfo
16453 * @resptype_txt: Pointer to the struct hdd_mdns_resp_info of Type txt
16454 * @resptype_a: Pointer to the struct hdd_mdns_resp_info of Type A
16455 *
16456 * Type Txt response include QName, response type, class, TTL and text content.
16457 * Also, it will find the matched QName from resptype_A and compress the data.
16458 *
16459 * Return: Return boolean. TRUE for success, FALSE for fail.
16460 */
16461static bool
16462wlan_hdd_mdns_pack_response_type_txt(hdd_config_t *ini_config,
16463 sir_mdns_resp_info resp_info,
16464 struct hdd_mdns_resp_info *resptype_txt,
16465 struct hdd_mdns_resp_info *resptype_a)
16466{
16467 uint8_t num_matched;
16468 uint8_t num;
16469 uint16_t idx;
16470 uint16_t value = 0;
16471 uint32_t len;
16472 uint32_t total_len;
16473 bool status;
16474 struct hdd_mdns_resp_info resptype_content;
16475
16476 ENTER();
16477
16478 if ((ini_config == NULL) || (resp_info == NULL) ||
16479 (resptype_txt == NULL)) {
16480 hddLog(LOGE, FL("ini_config or response info is NULL!"));
16481 return FALSE;
16482 }
16483
16484 /* No Type Txt response */
16485 if (strlen((char *)ini_config->mdns_resp_type_txt) <= 0)
16486 return TRUE;
16487
16488 /* Wrong response is assigned, just ignore this response */
16489 if (!wlan_hdd_mdns_init_response(resptype_txt,
16490 ini_config->mdns_resp_type_txt, '.'))
16491 return TRUE;
16492
16493 /*
16494 * For data compression
16495 * Check if any strings are matched with Type A response
16496 */
16497 if (resptype_a && (resptype_a->num_entries > 0)) {
16498 num_matched = wlan_hdd_mdns_find_entries_from_end(resptype_txt,
16499 resptype_a);
16500 if (num_matched > 0) {
16501 if (!wlan_hdd_mdns_compress_data(resp_info,
16502 resptype_txt, resptype_a, num_matched)) {
16503 hddLog(LOGE, FL("Fail to compress mDNS "
16504 "response (%d)!"), MDNS_TYPE_TXT);
16505 return FALSE;
16506 }
16507 } else {
16508 /*
16509 * num_matched is zero. Error!
16510 * At least ".local" is needed.
16511 */
16512 hddLog(LOGE, FL("No matched string! Fail to pack mDNS "
16513 "response (%d)!"), MDNS_TYPE_TXT);
16514 return FALSE;
16515 }
16516 } else {
16517 /* no TypeA response, so show the whole data */
16518 if (!wlan_hdd_mdns_process_response_dname(resptype_txt,
16519 resp_info)) {
16520 hddLog(LOGE, FL("Fail to process mDNS response (%d)!"),
16521 MDNS_TYPE_TXT);
16522 return FALSE;
16523 }
16524 }
16525
16526 /* Process response Type, Class, TTL */
16527 if (!wlan_hdd_mdns_process_response_misc(MDNS_TYPE_TXT, resp_info)) {
16528 hddLog(LOGE, FL("Fail to process mDNS misc response (%d)!"),
16529 MDNS_TYPE_TXT);
16530 return FALSE;
16531 }
16532
16533 /*
16534 * Process response RDLength, RData.
16535 * TypeTxt RData include len.
16536 */
16537 status = wlan_hdd_mdns_init_response(&resptype_content,
16538 ini_config->mdns_resp_type_txt_content,
16539 '/');
16540 if (status == FALSE) {
16541 hddLog(LOGE, FL("wlan_hdd_mdns_init_response FAIL"));
16542 return FALSE;
16543 }
16544
16545 for (num = 0; num < resptype_content.num_entries; num++) {
16546 idx = num * MAX_LEN_DOMAINNAME_FIELD;
16547 value += strlen((char *)&resptype_content.data[idx]);
16548 }
16549
16550 /* content len is uint16_t */
16551 total_len = sizeof(uint16_t);
16552 total_len += resp_info->resp_len + value +
16553 resptype_content.num_entries;
16554
16555 if (total_len >= MAX_MDNS_RESP_LEN) {
16556 hddLog(LOGE, FL("resp_len exceeds %d!"), MAX_MDNS_RESP_LEN);
16557 return FALSE;
16558 }
16559 wlan_hdd_mdns_format_response_u16(value + resptype_content.num_entries,
16560 resp_info);
16561
16562 for (num = 0; num < resptype_content.num_entries; num++) {
16563 idx = num * MAX_LEN_DOMAINNAME_FIELD;
16564 len = strlen((char *)&resptype_content.data[idx]);
16565 resp_info->resp_data[resp_info->resp_len] = len;
16566 resp_info->resp_len++;
16567
16568 vos_mem_copy(&resp_info->resp_data[resp_info->resp_len],
16569 &resptype_content.data[idx], len);
16570
16571 resp_info->resp_len += len;
16572 hddLog(LOG1, FL("index = %d, len = %d, str = %s"),
16573 num, len, &resptype_content.data[idx]);
16574 }
16575
16576 EXIT();
16577 return TRUE;
16578}
16579
16580/**
16581 * wlan_hdd_mdns_pack_response_type_ptr_dname() - Pack Type PTR domain name
16582 * @ini_config: Pointer to the struct hdd_config_t
16583 * @resp_info: Pointer to the struct tSirMDNSResponseInfo
16584 * @resptype_ptr_dn: Pointer to the struct hdd_mdns_resp_info of Type Ptr
16585 * domain name
16586 * @resptype_ptr: Pointer to the struct hdd_mdns_resp_info of Type Ptr
16587 * @resptype_txt: Pointer to the struct hdd_mdns_resp_info of Type Txt
16588 * @resptype_a: Pointer to the struct hdd_mdns_resp_info of Type A
16589 *
16590 * The Type Ptr response include Type PTR domain name in its data field.
16591 * Also, it will find the matched QName from the existing resptype_ptr,
16592 * resptype_txt, resptype_a and then compress the data.
16593 *
16594 * Return: Return boolean. TRUE for success, FALSE for fail.
16595 */
16596static bool
16597wlan_hdd_mdns_pack_response_type_ptr_dname(hdd_config_t *ini_config,
16598 sir_mdns_resp_info resp_info,
16599 struct hdd_mdns_resp_info *resptype_ptr_dn,
16600 struct hdd_mdns_resp_info *resptype_ptr,
16601 struct hdd_mdns_resp_info *resptype_txt,
16602 struct hdd_mdns_resp_info *resptype_a)
16603{
16604 uint8_t num_matched, numlist, size;
16605 struct hdd_mdns_resp_matched matchedlist[MAX_MDNS_RESP_TYPE-1];
16606 struct hdd_mdns_resp_info *resp;
16607
16608 if ((ini_config == NULL) || (resp_info == NULL) ||
16609 (resptype_ptr == NULL) || (resptype_ptr_dn == NULL)) {
16610 hddLog(LOGE, FL("ini_config or response info is NULL!"));
16611 return FALSE;
16612 }
16613
16614 /* No Type Ptr domain name response */
16615 if (strlen((char *)ini_config->mdns_resp_type_ptr_dname) <= 0)
16616 return TRUE;
16617
16618 /* Wrong response is assigned, just ignore this response */
16619 if (!wlan_hdd_mdns_init_response(resptype_ptr_dn,
16620 ini_config->mdns_resp_type_ptr_dname, '.'))
16621 return TRUE;
16622
16623 /*
16624 * For data compression
16625 * Check if any strings are matched with previous
16626 * response.
16627 */
16628 numlist = 0;
16629 size = (MAX_MDNS_RESP_TYPE-1);
16630 size *= sizeof(struct hdd_mdns_resp_matched);
16631 vos_mem_zero(matchedlist, size);
16632 num_matched = wlan_hdd_mdns_find_entries_from_end(resptype_ptr_dn,
16633 resptype_ptr);
16634 if (num_matched > 0) {
16635 matchedlist[numlist].num_matched = num_matched;
16636 matchedlist[numlist].type = MDNS_TYPE_PTR;
16637 numlist++;
16638 }
16639 if (resptype_txt && (resptype_txt->num_entries > 0)) {
16640 num_matched = wlan_hdd_mdns_find_entries_from_end(
16641 resptype_ptr_dn, resptype_txt);
16642 if (num_matched > 0) {
16643 matchedlist[numlist].num_matched = num_matched;
16644 matchedlist[numlist].type = MDNS_TYPE_TXT;
16645 numlist++;
16646 }
16647 }
16648 if (resptype_a && (resptype_a->num_entries > 0)) {
16649 num_matched = wlan_hdd_mdns_find_entries_from_end(
16650 resptype_ptr_dn,resptype_a);
16651 if (num_matched > 0) {
16652 matchedlist[numlist].num_matched = num_matched;
16653 matchedlist[numlist].type = MDNS_TYPE_A;
16654 numlist++;
16655 }
16656 }
16657 if (numlist > 0) {
16658 if (numlist > 1)
16659 wlan_hdd_mdns_find_max(matchedlist, numlist);
16660 resp = NULL;
16661 switch (matchedlist[numlist-1].type) {
16662 case MDNS_TYPE_A:
16663 resp = resptype_a;
16664 break;
16665 case MDNS_TYPE_TXT:
16666 resp = resptype_txt;
16667 break;
16668 case MDNS_TYPE_PTR:
16669 resp = resptype_ptr;
16670 break;
16671 default:
16672 hddLog(LOGE, FL("Fail to compress mDNS response "
16673 "(%d)!"), MDNS_TYPE_PTR_DNAME);
16674 return FALSE;
16675 }
16676 num_matched = matchedlist[numlist-1].num_matched;
16677 if (!wlan_hdd_mdns_compress_data(resp_info, resptype_ptr_dn,
16678 resp, num_matched)) {
16679 hddLog(LOGE, FL("Fail to compress mDNS response "
16680 "(%d)!"), MDNS_TYPE_PTR_DNAME);
16681 return FALSE;
16682 }
16683 } else {
16684 /* num = 0 -> no matched string */
16685 if (!wlan_hdd_mdns_process_response_dname(resptype_ptr_dn,
16686 resp_info)) {
16687 hddLog(LOGE, FL("Fail to process mDNS response (%d)!"),
16688 MDNS_TYPE_PTR_DNAME);
16689 return FALSE;
16690 }
16691 }
16692
16693 return TRUE;
16694}
16695
16696/**
16697 * wlan_hdd_mdns_pack_response_type_ptr() - Pack Type PTR response
16698 * @ini_config: Pointer to the struct hdd_config_t
16699 * @resp_info: Pointer to the struct tSirMDNSResponseInfo
16700 * @resptype_ptr: Pointer to the struct hdd_mdns_resp_info of Type Ptr
16701 * @resptype_ptr_dn: Pointer to the struct hdd_mdns_resp_info of Type Ptr
16702 * domain name
16703 * @resptype_txt: Pointer to the struct hdd_mdns_resp_info of Type Txt
16704 * @resptype_a: Pointer to the struct hdd_mdns_resp_info of Type A
16705 *
16706 * The Type Ptr response include QName, response type, class, TTL and
16707 * Type PTR domain name. Also, it will find the matched QName from the
16708 * existing resptype_txt, resptype_a and then compress the data.
16709 *
16710 * Return: Return boolean. TRUE for success, FALSE for fail.
16711 */
16712static bool
16713wlan_hdd_mdns_pack_response_type_ptr(hdd_config_t *ini_config,
16714 sir_mdns_resp_info resp_info,
16715 struct hdd_mdns_resp_info *resptype_ptr,
16716 struct hdd_mdns_resp_info *resptype_ptr_dn,
16717 struct hdd_mdns_resp_info *resptype_txt,
16718 struct hdd_mdns_resp_info *resptype_a)
16719{
16720 uint8_t num_matched, num_matched1;
16721 uint16_t value;
16722 uint8_t val_u8;
16723 uint32_t offset_data_len, len;
16724
16725 ENTER();
16726 if ((ini_config == NULL) || (resp_info == NULL) ||
16727 (resptype_ptr == NULL) || (resptype_ptr_dn == NULL)) {
16728 hddLog(LOGE, FL("ini_config or response info is NULL!"));
16729 return FALSE;
16730 }
16731
16732 /* No Type Ptr response */
16733 if (strlen((char *)ini_config->mdns_resp_type_ptr) <= 0)
16734 return TRUE;
16735
16736 /* Wrong response is assigned, just ignore this response */
16737 if (!wlan_hdd_mdns_init_response(resptype_ptr,
16738 ini_config->mdns_resp_type_ptr, '.'))
16739 return TRUE;
16740
16741 /*
16742 * For data compression
16743 * Check if any strings are matched with Type A response
16744 */
16745 num_matched = 0;
16746 num_matched1 = 0;
16747 if (resptype_a && (resptype_a->num_entries > 0)) {
16748 num_matched = wlan_hdd_mdns_find_entries_from_end(resptype_ptr,
16749 resptype_a);
16750 }
16751 if (resptype_txt && (resptype_txt->num_entries > 0)) {
16752 num_matched1 = wlan_hdd_mdns_find_entries_from_end(
16753 resptype_ptr, resptype_txt);
16754 }
16755 if ((num_matched != num_matched1) ||
16756 ((num_matched > 0) && (num_matched1 > 0))) {
16757 if (num_matched >= num_matched1) {
16758 if (!wlan_hdd_mdns_compress_data(resp_info,
16759 resptype_ptr, resptype_a, num_matched)) {
16760 hddLog(LOGE, FL("Fail to compress mDNS "
16761 "response (%d)!"), MDNS_TYPE_PTR);
16762 return FALSE;
16763 }
16764 } else {
16765 /* num_matched is less than num_matched1 */
16766 if (!wlan_hdd_mdns_compress_data(resp_info,
16767 resptype_ptr, resptype_txt, num_matched1)) {
16768 hddLog(LOGE, FL("Fail to compress mDNS "
16769 "response (%d)!"), MDNS_TYPE_PTR);
16770 return FALSE;
16771 }
16772 }
16773 } else {
16774 /*
16775 * Both num_matched and num_matched1 are zero.
16776 * no TypeA & TypeTxt
16777 */
16778 if (!wlan_hdd_mdns_process_response_dname(resptype_ptr,
16779 resp_info)) {
16780 hddLog(LOGE, FL("Fail to process mDNS response (%d)!"),
16781 MDNS_TYPE_PTR);
16782 return FALSE;
16783 }
16784 }
16785
16786 /* Process response Type, Class, TTL */
16787 if (!wlan_hdd_mdns_process_response_misc(MDNS_TYPE_PTR, resp_info)) {
16788 hddLog(LOGE, FL("Fail to process mDNS misc response (%d)!"),
16789 MDNS_TYPE_PTR);
16790 return FALSE;
16791 }
16792
16793 /*
16794 * Process response RDLength, RData (Ptr domain name)
16795 * Save the offset of RData length
16796 */
16797 offset_data_len = resp_info->resp_len;
16798 resp_info->resp_len += sizeof(uint16_t);
16799
16800 if (!wlan_hdd_mdns_pack_response_type_ptr_dname(ini_config, resp_info,
16801 resptype_ptr_dn, resptype_ptr,
16802 resptype_txt, resptype_a)) {
16803 return FALSE;
16804 }
16805 /* Set the RData length */
16806 len = offset_data_len + sizeof(uint16_t);
16807 if ((resptype_ptr_dn->num_entries > 0) &&
16808 (resp_info->resp_len > len)) {
16809 value = resp_info->resp_len - len;
16810 val_u8 = (value & 0xff00) >> 8;
16811 resp_info->resp_data[offset_data_len] = val_u8;
16812 val_u8 = value & 0xff;
16813 resp_info->resp_data[offset_data_len+1] = val_u8;
16814 } else {
16815 hddLog(LOGE, FL("Fail to process mDNS response (%d)!"),
16816 MDNS_TYPE_PTR);
16817 return FALSE;
16818 }
16819
16820 EXIT();
16821 return TRUE;
16822}
16823
16824/**
16825 * wlan_hdd_mdns_pack_response_type_srv_target()- Pack Type Service Target
16826 * @ini_config: Pointer to the struct hdd_config_t
16827 * @resp_info: Pointer to the struct tSirMDNSResponseInfo
16828 * @resptype_srv_tgt: Pointer to the struct hdd_mdns_resp_info of Type Srv
16829 * target
16830 * @resptype_srv: Pointer to the struct hdd_mdns_resp_info of Type Srv
16831 * @resptype_ptr: Pointer to the struct hdd_mdns_resp_info of Type Ptr
16832 * @resptype_ptr_dn: Pointer to the struct hdd_mdns_resp_info of Type Ptr
16833 * domain name
16834 * @resptype_txt: Pointer to the struct hdd_mdns_resp_info of Type Txt
16835 * @resptype_a: Pointer to the struct hdd_mdns_resp_info of Type A
16836 *
16837 * The Type service target is one of the data field in the Type SRV response.
16838 * Also, it will find the matched QName from the existing resptype_srv,
16839 * resptype_ptr, resptype_ptr_dn, resptype_txt, resptype_a and then compress
16840 * the data.
16841 *
16842 * Return: Return boolean. TRUE for success, FALSE for fail.
16843 */
16844static bool
16845wlan_hdd_mdns_pack_response_type_srv_target(hdd_config_t *ini_config,
16846 sir_mdns_resp_info resp_info,
16847 struct hdd_mdns_resp_info *resptype_srv_tgt,
16848 struct hdd_mdns_resp_info *resptype_srv,
16849 struct hdd_mdns_resp_info *resptype_ptr,
16850 struct hdd_mdns_resp_info *resptype_ptr_dn,
16851 struct hdd_mdns_resp_info *resptype_txt,
16852 struct hdd_mdns_resp_info *resptype_a)
16853{
16854 uint8_t num_matched, num, size;
16855 struct hdd_mdns_resp_matched matchedlist[MAX_MDNS_RESP_TYPE-1];
16856 struct hdd_mdns_resp_info *resp;
16857
16858 if ((ini_config == NULL) || (resp_info == NULL) ||
16859 (resptype_srv == NULL) || (resptype_srv_tgt == NULL)) {
16860 hddLog(LOGE, FL("ini_config or response info is NULL!"));
16861 return FALSE;
16862 }
16863
16864 /* No Type Srv Target response */
16865 if (strlen((char *)ini_config->mdns_resp_type_srv_target) <= 0)
16866 return TRUE;
16867
16868 /* Wrong response is assigned, just ignore this response */
16869 if (!wlan_hdd_mdns_init_response(resptype_srv_tgt,
16870 ini_config->mdns_resp_type_srv_target, '.'))
16871 return TRUE;
16872
16873 /*
16874 * For data compression
16875 * Check if any strings are matched with previous response.
16876 */
16877 num = 0;
16878 size = (MAX_MDNS_RESP_TYPE-1);
16879 size *= sizeof(struct hdd_mdns_resp_matched);
16880 vos_mem_zero(matchedlist, size);
16881 num_matched = wlan_hdd_mdns_find_entries_from_end(resptype_srv_tgt,
16882 resptype_srv);
16883 if (num_matched > 0) {
16884 matchedlist[num].num_matched = num_matched;
16885 matchedlist[num].type = MDNS_TYPE_SRV;
16886 num++;
16887 }
16888 if (resptype_ptr && (resptype_ptr->num_entries > 0)) {
16889 if (resptype_ptr_dn && (resptype_ptr_dn->num_entries > 0)) {
16890 num_matched = wlan_hdd_mdns_find_entries_from_end(
16891 resptype_srv_tgt, resptype_ptr_dn);
16892 if (num_matched > 0) {
16893 matchedlist[num].num_matched = num_matched;
16894 matchedlist[num].type = MDNS_TYPE_PTR_DNAME;
16895 num++;
16896 }
16897 }
16898 num_matched = wlan_hdd_mdns_find_entries_from_end(
16899 resptype_srv_tgt, resptype_ptr);
16900 if (num_matched > 0) {
16901 matchedlist[num].num_matched = num_matched;
16902 matchedlist[num].type = MDNS_TYPE_PTR;
16903 num++;
16904 }
16905 }
16906 if (resptype_txt && (resptype_txt->num_entries > 0)) {
16907 num_matched = wlan_hdd_mdns_find_entries_from_end(
16908 resptype_srv_tgt, resptype_txt);
16909 if (num_matched > 0) {
16910 matchedlist[num].num_matched = num_matched;
16911 matchedlist[num].type = MDNS_TYPE_TXT;
16912 num++;
16913 }
16914 }
16915 if (resptype_a && (resptype_a->num_entries > 0)) {
16916 num_matched = wlan_hdd_mdns_find_entries_from_end(
16917 resptype_srv_tgt, resptype_a);
16918 if (num_matched > 0) {
16919 matchedlist[num].num_matched = num_matched;
16920 matchedlist[num].type = MDNS_TYPE_A;
16921 num++;
16922 }
16923 }
16924 if (num > 0) {
16925 if (num > 1)
16926 wlan_hdd_mdns_find_max(matchedlist, num);
16927 resp = NULL;
16928 switch (matchedlist[num-1].type) {
16929 case MDNS_TYPE_A:
16930 resp = resptype_a;
16931 break;
16932 case MDNS_TYPE_TXT:
16933 resp = resptype_txt;
16934 break;
16935 case MDNS_TYPE_PTR:
16936 resp = resptype_ptr;
16937 break;
16938 case MDNS_TYPE_PTR_DNAME:
16939 resp = resptype_ptr_dn;
16940 break;
16941 case MDNS_TYPE_SRV:
16942 resp = resptype_srv;
16943 break;
16944 default:
16945 hddLog(LOGE, FL("Fail to compress mDNS response "
16946 "(%d)!"), MDNS_TYPE_SRV_TARGET);
16947 return FALSE;
16948 }
16949 num_matched = matchedlist[num-1].num_matched;
16950 if (!wlan_hdd_mdns_compress_data(resp_info, resptype_srv_tgt,
16951 resp, num_matched)) {
16952 hddLog(LOGE, FL("Fail to compress mDNS response "
16953 "(%d)!"), MDNS_TYPE_SRV_TARGET);
16954 return FALSE;
16955 }
16956 } else {
16957 /* num = 0 -> no matched string */
16958 if (!wlan_hdd_mdns_process_response_dname(resptype_srv_tgt,
16959 resp_info)) {
16960 hddLog(LOGE, FL("Fail to process mDNS response (%d)!"),
16961 MDNS_TYPE_SRV_TARGET);
16962 return FALSE;
16963 }
16964 }
16965
16966 return TRUE;
16967}
16968
16969/**
16970 * wlan_hdd_mdns_pack_response_type_srv()- Pack Type Service response
16971 * @ini_config: Pointer to the struct hdd_config_t
16972 * @resp_info: Pointer to the struct tSirMDNSResponseInfo
16973 * @resptype_srv: Pointer to the struct hdd_mdns_resp_info of Type Srv
16974 * @resptype_srv_tgt: Pointer to the struct hdd_mdns_resp_info of Type Srv
16975 * target
16976 * @resptype_ptr: Pointer to the struct hdd_mdns_resp_info of Type Ptr
16977 * @resptype_ptr_dn: Pointer to the struct hdd_mdns_resp_info of Type Ptr
16978 * domain name
16979 * @resptype_txt: Pointer to the struct hdd_mdns_resp_info of Type Txt
16980 * @resptype_a: Pointer to the struct hdd_mdns_resp_info of Type A
16981 *
16982 * The Type SRV (Service) response include QName, response type, class, TTL
16983 * and four kinds of data fields. Also, it will find the matched QName from
16984 * the existing resptype_ptr, resptype_ptr_dn, resptype_txt, resptype_a and
16985 * then compress the data.
16986 *
16987 * Return: Return boolean. TRUE for success, FALSE for fail.
16988 */
16989static bool
16990wlan_hdd_mdns_pack_response_type_srv(hdd_config_t *ini_config,
16991 sir_mdns_resp_info resp_info,
16992 struct hdd_mdns_resp_info *resptype_srv,
16993 struct hdd_mdns_resp_info *resptype_srv_tgt,
16994 struct hdd_mdns_resp_info *resptype_ptr,
16995 struct hdd_mdns_resp_info *resptype_ptr_dn,
16996 struct hdd_mdns_resp_info *resptype_txt,
16997 struct hdd_mdns_resp_info *resptype_a)
16998{
16999 uint8_t num_matched, num, size;
17000 uint16_t value;
17001 uint8_t val_u8;
17002 uint32_t offset_data_len, len;
17003 struct hdd_mdns_resp_info *resp;
17004 struct hdd_mdns_resp_matched matchedlist[MAX_MDNS_RESP_TYPE-1];
17005
17006 ENTER();
17007
17008 if ((ini_config == NULL) || (resp_info == NULL) ||
17009 (resptype_srv == NULL) || (resptype_srv_tgt == NULL)) {
17010 hddLog(LOGE, FL("ini_config or response info is NULL!"));
17011 return FALSE;
17012 }
17013
17014 /* No Type Srv response */
17015 if (strlen((char *)ini_config->mdns_resp_type_srv) <= 0)
17016 return TRUE;
17017
17018 /* Wrong response is assigned, just ignore this response */
17019 if (!wlan_hdd_mdns_init_response(resptype_srv,
17020 ini_config->mdns_resp_type_srv, '.'))
17021 return TRUE;
17022
17023 /*
17024 * For data compression
17025 * Check if any strings are matched with Type A response
17026 */
17027 num = 0;
17028 size = (MAX_MDNS_RESP_TYPE-1);
17029 size *= sizeof(struct hdd_mdns_resp_matched);
17030 vos_mem_zero(matchedlist, size);
17031 if (resptype_ptr && (resptype_ptr->num_entries > 0)) {
17032 if (resptype_ptr_dn && (resptype_ptr_dn->num_entries > 0)) {
17033 num_matched = wlan_hdd_mdns_find_entries_from_end(
17034 resptype_srv,
17035 resptype_ptr_dn);
17036 if (num_matched > 0) {
17037 matchedlist[num].num_matched = num_matched;
17038 matchedlist[num].type = MDNS_TYPE_PTR_DNAME;
17039 num++;
17040 }
17041 }
17042 num_matched = wlan_hdd_mdns_find_entries_from_end(resptype_srv,
17043 resptype_ptr);
17044 if (num_matched > 0) {
17045 matchedlist[num].num_matched = num_matched;
17046 matchedlist[num].type = MDNS_TYPE_PTR;
17047 num++;
17048 }
17049 }
17050 if (resptype_txt && (resptype_txt->num_entries > 0)) {
17051 num_matched = wlan_hdd_mdns_find_entries_from_end(resptype_srv,
17052 resptype_txt);
17053 if (num_matched > 0) {
17054 matchedlist[num].num_matched =num_matched;
17055 matchedlist[num].type = MDNS_TYPE_TXT;
17056 num++;
17057 }
17058 }
17059 if (resptype_a && (resptype_a->num_entries > 0)) {
17060 num_matched = wlan_hdd_mdns_find_entries_from_end(resptype_srv,
17061 resptype_a);
17062 if (num_matched > 0) {
17063 matchedlist[num].num_matched = num_matched;
17064 matchedlist[num].type = MDNS_TYPE_A;
17065 num++;
17066 }
17067 }
17068 if (num > 0) {
17069 if (num > 1)
17070 wlan_hdd_mdns_find_max(matchedlist, num);
17071 resp = NULL;
17072 switch (matchedlist[num-1].type) {
17073 case MDNS_TYPE_A:
17074 resp = resptype_a;
17075 break;
17076 case MDNS_TYPE_TXT:
17077 resp = resptype_txt;
17078 break;
17079 case MDNS_TYPE_PTR:
17080 resp = resptype_ptr;
17081 break;
17082 case MDNS_TYPE_PTR_DNAME:
17083 resp = resptype_ptr_dn;
17084 break;
17085 default:
17086 hddLog(LOGE, FL("Fail to compress mDNS response "
17087 "(%d)!"), MDNS_TYPE_SRV);
17088 return FALSE;
17089 }
17090 num_matched = matchedlist[num-1].num_matched;
17091 if (!wlan_hdd_mdns_compress_data(resp_info, resptype_srv,
17092 resp, num_matched)) {
17093 hddLog(LOGE, FL("Fail to compress mDNS response "
17094 "(%d)!"), MDNS_TYPE_SRV);
17095 return FALSE;
17096 }
17097 } else {
17098 /* num = 0 -> no matched string */
17099 if (!wlan_hdd_mdns_process_response_dname(resptype_srv,
17100 resp_info)) {
17101 hddLog(LOGE, FL("Fail to process mDNS response (%d)!"),
17102 MDNS_TYPE_SRV);
17103 return FALSE;
17104 }
17105 }
17106
17107 /* Process response Type, Class, TTL */
17108 if (!wlan_hdd_mdns_process_response_misc(MDNS_TYPE_SRV, resp_info)) {
17109 hddLog(LOGE, FL("Fail to process mDNS misc response (%d)!"),
17110 MDNS_TYPE_SRV);
17111 return FALSE;
17112 }
17113
17114 /*
17115 * Process response RDLength, RData (Srv target name)
17116 * Save the offset of RData length
17117 */
17118 offset_data_len = resp_info->resp_len;
17119 resp_info->resp_len += sizeof(uint16_t);
17120
17121 len = resp_info->resp_len + (3 * sizeof(uint16_t));
17122 if (len >= MAX_MDNS_RESP_LEN) {
17123 hddLog(LOGE, FL("resp_len exceeds %d!"), MAX_MDNS_RESP_LEN);
17124 return FALSE;
17125 }
17126
17127 /* set Srv Priority */
17128 value = ini_config->mdns_resp_type_srv_priority;
17129 wlan_hdd_mdns_format_response_u16(value, resp_info);
17130 /* set Srv Weight */
17131 value = ini_config->mdns_resp_type_srv_weight;
17132 wlan_hdd_mdns_format_response_u16(value, resp_info);
17133 /* set Srv Port */
17134 value = ini_config->mdns_resp_type_srv_port;
17135 wlan_hdd_mdns_format_response_u16(value, resp_info);
17136
17137 if (!wlan_hdd_mdns_pack_response_type_srv_target(ini_config, resp_info,
17138 resptype_srv_tgt, resptype_srv,
17139 resptype_ptr, resptype_ptr_dn,
17140 resptype_txt, resptype_a)) {
17141 return FALSE;
17142 }
17143 /* Set the RData length */
17144 len = offset_data_len + sizeof(uint16_t);
17145 if ((resptype_srv_tgt->num_entries > 0) &&
17146 (resp_info->resp_len > len)) {
17147 value = resp_info->resp_len - len;
17148 val_u8 = (value & 0xff00) >> 8;
17149 resp_info->resp_data[offset_data_len] = val_u8;
17150 val_u8 = value & 0xff;
17151 resp_info->resp_data[offset_data_len+1] = val_u8;
17152 } else {
17153 hddLog(LOGE, FL("Fail to process mDNS response (%d)!"),
17154 MDNS_TYPE_SRV);
17155 return FALSE;
17156 }
17157
17158 EXIT();
17159 return TRUE;
17160}
17161
17162/**
17163 * wlan_hdd_mdns_free_mem() - Free the allocated memory
17164 * @response: Pointer to the struct hdd_mdns_resp_info
17165 *
17166 * Return: None
17167 */
17168static void wlan_hdd_mdns_free_mem(struct hdd_mdns_resp_info *response)
17169{
17170 if (response && response->data)
17171 vos_mem_free(response->data);
17172 if (response && response->offset)
17173 vos_mem_free(response->offset);
17174}
17175
17176/**
17177 * wlan_hdd_mdns_pack_response() - Pack mDNS response
17178 * @ini_config: Pointer to the struct hdd_config_t
17179 * @resp_info: Pointer to the struct tSirMDNSResponseInfo
17180 *
17181 * This function will pack four types of responses (Type A, Type Txt, Type Ptr
17182 * and Type Service). Each response contains QName, response type, class, TTL
17183 * and data fields.
17184 *
17185 * Return: Return boolean. TRUE for success, FALSE for fail.
17186 */
17187static bool wlan_hdd_mdns_pack_response(hdd_config_t *ini_config,
17188 sir_mdns_resp_info resp_info)
17189{
17190 struct hdd_mdns_resp_info resptype_a, resptype_txt;
17191 struct hdd_mdns_resp_info resptype_ptr, resptype_ptr_dn;
17192 struct hdd_mdns_resp_info resptype_srv, resptype_srv_tgt;
17193 uint32_t num_res_records = 0;
17194 bool status = FALSE;
17195
17196 ENTER();
17197
17198 wlan_hdd_mdns_reset_response(&resptype_a);
17199 wlan_hdd_mdns_reset_response(&resptype_txt);
17200 wlan_hdd_mdns_reset_response(&resptype_ptr);
17201 wlan_hdd_mdns_reset_response(&resptype_ptr_dn);
17202 wlan_hdd_mdns_reset_response(&resptype_srv);
17203 wlan_hdd_mdns_reset_response(&resptype_srv_tgt);
17204
17205 resp_info->resp_len = 0;
17206
17207 /* Process Type A response */
17208 if (!wlan_hdd_mdns_pack_response_type_a(ini_config, resp_info,
17209 &resptype_a))
17210 goto err_resptype_a;
17211
17212 if ((resptype_a.num_entries > 0) &&
17213 (strlen((char *)&resptype_a.data[0]) > 0))
17214 num_res_records++;
17215
17216 /* Process Type TXT response */
17217 if (!wlan_hdd_mdns_pack_response_type_txt(ini_config, resp_info,
17218 &resptype_txt, &resptype_a))
17219 goto err_resptype_txt;
17220
17221 if ((resptype_txt.num_entries > 0) &&
17222 (strlen((char *)&resptype_txt.data[0]) > 0))
17223 num_res_records++;
17224
17225 /* Process Type PTR response */
17226 if (!wlan_hdd_mdns_pack_response_type_ptr(ini_config, resp_info,
17227 &resptype_ptr, &resptype_ptr_dn,
17228 &resptype_txt, &resptype_a))
17229 goto err_resptype_ptr;
17230
17231 if ((resptype_ptr.num_entries > 0) &&
17232 (strlen((char *)&resptype_ptr.data[0]) > 0))
17233 num_res_records++;
17234
17235 /* Process Type SRV response */
17236 if (!wlan_hdd_mdns_pack_response_type_srv(ini_config, resp_info,
17237 &resptype_srv, &resptype_srv_tgt,
17238 &resptype_ptr, &resptype_ptr_dn,
17239 &resptype_txt, &resptype_a))
17240 goto err_resptype_srv;
17241
17242 if ((resptype_srv.num_entries > 0) &&
17243 (strlen((char *)&resptype_srv.data[0]) > 0))
17244 num_res_records++;
17245
17246 resp_info->resourceRecord_count = num_res_records;
17247 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
17248 "%s: Pack mDNS response data successfully!", __func__);
17249 status = TRUE;
17250
17251err_resptype_srv:
17252 wlan_hdd_mdns_free_mem(&resptype_srv);
17253 wlan_hdd_mdns_free_mem(&resptype_srv_tgt);
17254
17255err_resptype_ptr:
17256 wlan_hdd_mdns_free_mem(&resptype_ptr);
17257 wlan_hdd_mdns_free_mem(&resptype_ptr_dn);
17258
17259err_resptype_txt:
17260 wlan_hdd_mdns_free_mem(&resptype_txt);
17261
17262err_resptype_a:
17263 wlan_hdd_mdns_free_mem(&resptype_a);
17264
17265 EXIT();
17266 return status;
17267}
17268
17269/**
17270 * wlan_hdd_set_mdns_offload() - Enable mDNS offload
17271 * @hostapd_adapter: Pointer to the struct hdd_adapter_t
17272 *
17273 * This function will set FQDN/unique FQDN (full qualified domain name)
17274 * and the mDNS response. Then send them to SME.
17275 *
17276 * Return: Return boolean. TRUE for success, FALSE for fail.
17277 */
17278bool wlan_hdd_set_mdns_offload(hdd_adapter_t *hostapd_adapter)
17279{
17280 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(hostapd_adapter);
17281 sir_mdns_offload_info mdns_offload_info;
17282 sir_mdns_fqdn_info mdns_fqdn_info;
17283 sir_mdns_resp_info mdns_resp_info;
17284 uint32_t fqdn_len, ufqdn_len;
17285
17286 ENTER();
17287
17288 /* 1. Prepare the MDNS fqdn request to send to SME */
17289 fqdn_len = strlen(hdd_ctx->cfg_ini->mdns_fqdn);
17290 ufqdn_len = strlen(hdd_ctx->cfg_ini->mdns_uniquefqdn);
17291 if ((fqdn_len == 0) && (ufqdn_len == 0)) {
17292 hddLog(LOGE, FL("No mDNS FQDN or UFQDN is assigned fqdn_len %d,"
17293 "ufqdn_len %d!"), fqdn_len, ufqdn_len);
17294 return FALSE;
17295 }
17296
17297 mdns_fqdn_info = vos_mem_malloc(sizeof(*mdns_fqdn_info));
17298 if (NULL == mdns_fqdn_info) {
17299 hddLog(LOGE, FL("could not allocate tSirMDNSFqdnInfo!"));
17300 return FALSE;
17301 }
17302 /* MDNS fqdn request */
17303 if (fqdn_len > 0) {
17304 vos_mem_zero(mdns_fqdn_info, sizeof(*mdns_fqdn_info));
17305 mdns_fqdn_info->bss_idx = hostapd_adapter->sessionId;
17306 mdns_fqdn_info->fqdn_type = MDNS_FQDN_TYPE_GENERAL;
17307 mdns_fqdn_info->fqdn_len = fqdn_len;
17308 mdns_fqdn_info->mdns_fqdn_callback = hdd_mdns_fqdn_offload_done;
17309 mdns_fqdn_info->mdns_fqdn_cb_context = hostapd_adapter;
17310 vos_mem_copy(mdns_fqdn_info->fqdn_data,
17311 hdd_ctx->cfg_ini->mdns_fqdn,
17312 mdns_fqdn_info->fqdn_len);
17313
17314 if (eHAL_STATUS_SUCCESS !=
17315 sme_set_mdns_fqdn(hdd_ctx->hHal, mdns_fqdn_info)) {
17316 hddLog(LOGE, FL("sme_set_mdns_fqdn fail!"));
17317 vos_mem_free(mdns_fqdn_info);
17318 return FALSE;
17319 }
17320 }
17321 /* MDNS unique fqdn request */
17322 if (ufqdn_len > 0) {
17323 vos_mem_zero(mdns_fqdn_info, sizeof(*mdns_fqdn_info));
17324 mdns_fqdn_info->bss_idx = hostapd_adapter->sessionId;
17325 mdns_fqdn_info->fqdn_type = MDNS_FQDN_TYPE_UNIQUE;
17326 mdns_fqdn_info->fqdn_len = ufqdn_len;
17327 mdns_fqdn_info->mdns_fqdn_callback = hdd_mdns_fqdn_offload_done;
17328 mdns_fqdn_info->mdns_fqdn_cb_context = hostapd_adapter;
17329 vos_mem_copy(mdns_fqdn_info->fqdn_data,
17330 hdd_ctx->cfg_ini->mdns_uniquefqdn,
17331 mdns_fqdn_info->fqdn_len);
17332 if (eHAL_STATUS_SUCCESS !=
17333 sme_set_mdns_fqdn(hdd_ctx->hHal, mdns_fqdn_info)) {
17334 hddLog(LOGE, FL("sme_set_mdns_fqdn fail!"));
17335 vos_mem_free(mdns_fqdn_info);
17336 return FALSE;
17337 }
17338 }
17339 vos_mem_free(mdns_fqdn_info);
17340
17341 /* 2. Prepare the MDNS response request to send to SME */
17342 mdns_resp_info = vos_mem_malloc(sizeof(*mdns_resp_info));
17343 if (NULL == mdns_resp_info) {
17344 hddLog(LOGE, FL("could not allocate tSirMDNSResponseInfo!"));
17345 return FALSE;
17346 }
17347
17348 vos_mem_zero(mdns_resp_info, sizeof(*mdns_resp_info));
17349 mdns_resp_info->bss_idx = hostapd_adapter->sessionId;
17350 mdns_resp_info->mdns_resp_callback = hdd_mdns_resp_offload_done;
17351 mdns_resp_info->mdns_resp_cb_context = hostapd_adapter;
17352 if (!wlan_hdd_mdns_pack_response(hdd_ctx->cfg_ini, mdns_resp_info)) {
17353 hddLog(LOGE, FL("wlan_hdd_pack_mdns_response fail!"));
17354 vos_mem_free(mdns_resp_info);
17355 return FALSE;
17356 }
17357 if (eHAL_STATUS_SUCCESS !=
17358 sme_set_mdns_resp(hdd_ctx->hHal, mdns_resp_info)) {
17359 hddLog(LOGE, FL("sme_set_mdns_resp fail!"));
17360 vos_mem_free(mdns_resp_info);
17361 return FALSE;
17362 }
17363 vos_mem_free(mdns_resp_info);
17364
17365 /* 3. Prepare the MDNS Enable request to send to SME */
17366 mdns_offload_info = vos_mem_malloc(sizeof(*mdns_offload_info));
17367 if (NULL == mdns_offload_info) {
17368 hddLog(LOGE, FL("could not allocate tSirMDNSOffloadInfo!"));
17369 return FALSE;
17370 }
17371
17372 vos_mem_zero(mdns_offload_info, sizeof(*mdns_offload_info));
17373
17374 mdns_offload_info->bss_idx = hostapd_adapter->sessionId;
17375 mdns_offload_info->enable = hdd_ctx->cfg_ini->enable_mdns_offload;
17376 mdns_offload_info->mdns_enable_callback = hdd_mdns_enable_offload_done;
17377 mdns_offload_info->mdns_enable_cb_context = hostapd_adapter;
17378 if (eHAL_STATUS_SUCCESS !=
17379 sme_set_mdns_offload(hdd_ctx->hHal, mdns_offload_info)) {
17380 hddLog(LOGE, FL("sme_set_mdns_offload fail!"));
17381 vos_mem_free(mdns_offload_info);
17382 return FALSE;
17383 }
17384
17385 vos_mem_free(mdns_offload_info);
17386 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
17387 "%s: enable mDNS offload successfully!", __func__);
17388 return TRUE;
17389}
Manjeet Singh3ed79242017-01-11 19:04:32 +053017390
17391
Anurag Chouhan0b29de02016-12-16 13:18:40 +053017392#endif /* MDNS_OFFLOAD */
c_manjeecfd1efb2015-09-25 19:32:34 +053017393
Hanumanth Reddy Pothulad864f312017-01-18 16:16:08 +053017394/**
17395 * wlan_hdd_start_sap() - This function starts bss of SAP.
17396 * @ap_adapter: SAP adapter
17397 *
17398 * This function will process the starting of sap adapter.
17399 *
17400 * Return: void.
17401 */
17402void wlan_hdd_start_sap(hdd_adapter_t *ap_adapter)
17403{
17404 hdd_ap_ctx_t *hdd_ap_ctx;
17405 hdd_hostapd_state_t *hostapd_state;
17406 VOS_STATUS vos_status;
17407 hdd_context_t *hdd_ctx;
17408 tsap_Config_t *pConfig;
17409
17410 if (NULL == ap_adapter) {
17411 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
17412 FL("ap_adapter is NULL here"));
17413 return;
17414 }
17415
17416 hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter);
17417 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
17418 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
17419 pConfig = &ap_adapter->sessionCtx.ap.sapConfig;
17420
17421 mutex_lock(&hdd_ctx->sap_lock);
17422 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags))
17423 goto end;
17424
17425 if (0 != wlan_hdd_cfg80211_update_apies(ap_adapter)) {
17426 hddLog(LOGE, FL("SAP Not able to set AP IEs"));
17427 goto end;
17428 }
17429
17430 vos_event_reset(&hostapd_state->vosEvent);
17431 if (WLANSAP_StartBss(hdd_ctx->pvosContext, hdd_hostapd_SAPEventCB,
17432 &hdd_ap_ctx->sapConfig, (v_PVOID_t)ap_adapter->dev)
17433 != VOS_STATUS_SUCCESS) {
17434 goto end;
17435 }
17436
17437 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
17438 FL("Waiting for SAP to start"));
17439 vos_status = vos_wait_single_event(&hostapd_state->vosEvent, 10000);
17440 if (!VOS_IS_STATUS_SUCCESS(vos_status)) {
17441 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
17442 FL("SAP Start failed"));
17443 goto end;
17444 }
17445 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
17446 FL("SAP Start Success"));
17447 set_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
17448
17449 wlan_hdd_incr_active_session(hdd_ctx, ap_adapter->device_mode);
17450 hostapd_state->bCommit = TRUE;
17451
17452end:
17453 mutex_unlock(&hdd_ctx->sap_lock);
17454 return;
17455}
17456
Manjeet Singh3ed79242017-01-11 19:04:32 +053017457#ifdef WLAN_FEATURE_TSF
17458
17459/**
17460 * hdd_tsf_cb() - handle tsf request callback
17461 *
17462 * @pcb_cxt: pointer to the hdd_contex
17463 * @ptsf: pointer to struct stsf
17464 *
17465 * Based on the request sent .
17466 *
17467 * Return: Describe the execute result of this routine
17468 */
17469static int hdd_tsf_cb(void *pcb_ctx, struct stsf *ptsf)
17470{
17471 hdd_context_t *hddctx;
17472 int status;
17473 hdd_adapter_t* adapter = (hdd_adapter_t*)pcb_ctx;
17474
17475 if (pcb_ctx == NULL || ptsf == NULL) {
17476 hddLog(VOS_TRACE_LEVEL_ERROR,
17477 FL("HDD context is not valid"));
17478 return -EINVAL;
17479 }
17480
17481 hddctx = (hdd_context_t *)pcb_ctx;
17482 status = wlan_hdd_validate_context(hddctx);
17483 if (0 != status)
17484 return -EINVAL;
17485
17486 if (NULL == adapter) {
17487 hddLog(VOS_TRACE_LEVEL_ERROR,
17488 FL("failed to find adapter"));
17489 return -EINVAL;
17490 }
17491
17492 hddLog(VOS_TRACE_LEVEL_INFO,
17493 FL("tsf cb handle event, device_mode is %d"),
17494 adapter->device_mode);
17495
17496 /* copy the return value to hdd_tsf_ctx in adapter*/
17497 if (ptsf->tsf_req_status) {
17498
17499 vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
17500 adapter->tsf_cap_ctx.tsf_get_state = TSF_NOT_RETURNED_BY_FW;
17501 adapter->tsf_cap_ctx.tsf_capture_state = TSF_IDLE;
17502 vos_event_set (&adapter->tsf_cap_ctx.tsf_capture_done_event);
17503 vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
17504
17505 hddLog(VOS_TRACE_LEVEL_ERROR, FL("tsf req failure :%d"),
17506 ptsf->tsf_req_status);
17507 return ptsf->tsf_req_status;
17508 }
17509 /* If this is a get request.Store the tsf values in adapter. */
17510 if (!ptsf->set_tsf_req) {
17511 vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
17512 adapter->tsf_cap_ctx.tsf_low = ptsf->tsf_low;
17513 adapter->tsf_cap_ctx.tsf_high = ptsf->tsf_high;
17514 adapter->tsf_cap_ctx.tsf_get_state = TSF_RETURN;
17515 adapter->tsf_cap_ctx.tsf_capture_state = TSF_IDLE;
17516 vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
17517
17518 hddLog(VOS_TRACE_LEVEL_INFO,
17519 FL("hdd_get_tsf_cb sta=%u, tsf_low=%u, tsf_high=%u"),
17520 adapter->sessionId, ptsf->tsf_low, ptsf->tsf_high);
17521 }
17522 else {
17523 vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
17524 adapter->tsf_cap_ctx.tsf_capture_state = TSF_CAP_STATE;
17525 adapter->tsf_cap_ctx.tsf_get_state = TSF_CURRENT_IN_CAP_STATE;
17526 vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
17527 }
17528 vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
17529 vos_event_set (&adapter->tsf_cap_ctx.tsf_capture_done_event);
17530 vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
17531
17532 /* free allocated mem */
17533 vos_mem_free(ptsf);
17534
17535 return 0;
17536}
17537
17538/**
17539 * hdd_capture_tsf() - capture tsf
17540 *
17541 * @adapter: pointer to adapter
17542 * @buf: pointer to upper layer buf
17543 * @len : the length of buf
17544 *
17545 * This function returns tsf value to uplayer.
17546 *
17547 * Return: Describe the execute result of this routine
17548 */
17549int hdd_capture_tsf(hdd_adapter_t *adapter, uint32_t *buf, int len)
17550{
17551 int ret = 0;
17552 hdd_station_ctx_t *hdd_sta_ctx;
17553 hdd_context_t *hdd_ctx;
17554 tSirCapTsfParams cap_tsf_params;
17555 VOS_STATUS status;
17556
17557 if (adapter == NULL || buf == NULL) {
17558 hddLog(VOS_TRACE_LEVEL_ERROR,
17559 FL("invalid pointer"));
17560 return -EINVAL;
17561 }
17562 if (len != 1)
17563 return -EINVAL;
17564
17565 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
17566
17567 if (wlan_hdd_validate_context(hdd_ctx)) {
17568 hddLog(VOS_TRACE_LEVEL_ERROR,
17569 FL("invalid hdd ctx"));
17570 return -EINVAL;
17571 }
17572 if (adapter->device_mode == WLAN_HDD_INFRA_STATION ||
17573 adapter->device_mode == WLAN_HDD_P2P_CLIENT) {
17574 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
17575 if (hdd_sta_ctx->conn_info.connState !=
17576 eConnectionState_Associated) {
17577
17578 hddLog(VOS_TRACE_LEVEL_INFO,
17579 FL("failed to cap tsf, not connect with ap"));
17580 buf[0] = TSF_STA_NOT_CONNECTED_NO_TSF;
17581 return ret;
17582 }
17583 }
17584 if ((adapter->device_mode == WLAN_HDD_SOFTAP ||
17585 adapter->device_mode == WLAN_HDD_P2P_GO) &&
17586 !(test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags))) {
17587 hddLog(VOS_TRACE_LEVEL_INFO,
17588 FL("Soft AP / P2p GO not beaconing"));
17589 buf[0] = TSF_SAP_NOT_STARTED_NO_TSF;
17590 return ret;
17591 }
17592 if (adapter->tsf_cap_ctx.tsf_capture_state == TSF_CAP_STATE) {
17593 hddLog(VOS_TRACE_LEVEL_INFO,
17594 FL("current in capture state, pls reset"));
17595 buf[0] = TSF_CURRENT_IN_CAP_STATE;
17596 } else {
17597 hddLog(VOS_TRACE_LEVEL_INFO, FL("ioctl issue cap tsf cmd"));
17598 buf[0] = TSF_RETURN;
17599 cap_tsf_params.session_id = adapter->sessionId;
17600 cap_tsf_params.tsf_rsp_cb_func = hdd_tsf_cb;
17601 cap_tsf_params.tsf_rsp_cb_ctx = adapter;
17602
17603 vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
17604 adapter->tsf_cap_ctx.tsf_capture_state = TSF_CAP_STATE;
17605 adapter->tsf_cap_ctx.tsf_get_state = TSF_CURRENT_IN_CAP_STATE;
17606 vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
17607
17608 ret = sme_capture_tsf_req(hdd_ctx->hHal, cap_tsf_params);
17609
17610 if (ret != VOS_STATUS_SUCCESS) {
17611 hddLog(VOS_TRACE_LEVEL_ERROR, FL("capture fail"));
17612 buf[0] = TSF_CAPTURE_FAIL;
17613 vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
17614 adapter->tsf_cap_ctx.tsf_capture_state = TSF_IDLE;
17615 vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
17616 return -EINVAL;
17617 }
17618 /* wait till we get a response from fw */
17619 status = vos_wait_single_event(&adapter->tsf_cap_ctx.
17620 tsf_capture_done_event,
17621 HDD_TSF_CAP_REQ_TIMEOUT);
17622
17623 if (!VOS_IS_STATUS_SUCCESS(status)) {
17624 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
17625 ("capture tsf vos wait for single_event failed!! %d"),
17626 adapter->tsf_cap_ctx.tsf_get_state);
17627
17628 vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
17629 adapter->tsf_cap_ctx.tsf_capture_state = TSF_IDLE;
17630 vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
17631
17632 return -EINVAL;
17633 }
17634 }
17635 buf[0] = TSF_RETURN;
17636 hddLog(VOS_TRACE_LEVEL_INFO,
17637 FL("ioctl return cap tsf cmd, ret = %d"), ret);
17638 return ret;
17639}
17640
17641/**
17642 * hdd_indicate_tsf() - return tsf to uplayer
17643 *
17644 * @adapter: pointer to adapter
17645 * @buf: pointer to uplayer buf
17646 * @len : the length of buf
17647 *
17648 * This function returns tsf value to uplayer.
17649 *
17650 * Return: Describe the execute result of this routine
17651 */
17652int hdd_indicate_tsf(hdd_adapter_t *adapter, uint32_t *buf, int len)
17653{
17654 int ret = 0;
17655 hdd_station_ctx_t *hdd_sta_ctx;
17656 hdd_context_t *hdd_ctx;
17657 tSirCapTsfParams cap_tsf_params;
17658 VOS_STATUS status;
17659
17660 if (adapter == NULL || buf == NULL) {
17661 hddLog(VOS_TRACE_LEVEL_ERROR,
17662 FL("invalid pointer"));
17663 return -EINVAL;
17664 }
17665 if (len != 3)
17666 return -EINVAL;
17667
17668 buf [1] = 0;
17669 buf [2] = 0;
17670 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
17671
17672 if (wlan_hdd_validate_context(hdd_ctx)) {
17673 hddLog(VOS_TRACE_LEVEL_ERROR,
17674 FL("invalid hdd ctx"));
17675 return -EINVAL;
17676 }
17677 if (adapter->device_mode == WLAN_HDD_INFRA_STATION ||
17678 adapter->device_mode == WLAN_HDD_P2P_CLIENT) {
17679 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
17680 if (hdd_sta_ctx->conn_info.connState !=
17681 eConnectionState_Associated) {
17682
17683 hddLog(VOS_TRACE_LEVEL_INFO,
17684 FL("failed to cap tsf, not connect with ap"));
17685 buf[0] = TSF_STA_NOT_CONNECTED_NO_TSF;
17686 return ret;
17687 }
17688 }
17689 if ((adapter->device_mode == WLAN_HDD_SOFTAP ||
17690 adapter->device_mode == WLAN_HDD_P2P_GO) &&
17691 !(test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags))) {
17692 hddLog(VOS_TRACE_LEVEL_INFO,
17693 FL("Soft AP / P2p GO not beaconing"));
17694 buf[0] = TSF_SAP_NOT_STARTED_NO_TSF;
17695 return ret;
17696 }
17697
17698 if (adapter->tsf_cap_ctx.tsf_capture_state != TSF_CAP_STATE ||
17699 adapter->tsf_cap_ctx.tsf_get_state != TSF_CURRENT_IN_CAP_STATE ) {
17700 hddLog(VOS_TRACE_LEVEL_INFO,
17701 FL("Not in capture state,Enter capture state first"));
17702 buf[0] = TSF_GET_FAIL;
17703 } else {
17704 hddLog(VOS_TRACE_LEVEL_INFO, FL("ioctl issue cap tsf cmd"));
17705 cap_tsf_params.session_id = adapter->sessionId;
17706 cap_tsf_params.tsf_rsp_cb_func = hdd_tsf_cb;
17707 cap_tsf_params.tsf_rsp_cb_ctx = adapter;
17708
17709 ret = sme_get_tsf_req(hdd_ctx->hHal, cap_tsf_params);
17710
17711 if (ret != VOS_STATUS_SUCCESS) {
17712 hddLog(VOS_TRACE_LEVEL_ERROR, FL("capture fail"));
17713 buf[0] = TSF_CAPTURE_FAIL;
17714 vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
17715 adapter->tsf_cap_ctx.tsf_capture_state = TSF_IDLE;
17716 vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
17717 return -EINVAL;
17718 }
17719 /* wait till we get a response from fw */
17720 status = vos_wait_single_event(&adapter->tsf_cap_ctx.
17721 tsf_capture_done_event,
17722 HDD_TSF_GET_REQ_TIMEOUT);
17723
17724 if (!VOS_IS_STATUS_SUCCESS(status)) {
17725 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
17726 ("capture tsf vos wait for single_event failed!! %d"),
17727 status);
17728
17729 vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
17730 adapter->tsf_cap_ctx.tsf_capture_state = TSF_IDLE;
17731 vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
17732 return status;
17733 }
17734 buf[1] = adapter->tsf_cap_ctx.tsf_low;
17735 buf[2] = adapter->tsf_cap_ctx.tsf_high;
17736
17737 hddLog(VOS_TRACE_LEVEL_INFO,
17738 FL("get tsf cmd,status=%u, tsf_low=%u, tsf_high=%u"),
17739 buf[0], buf[1], buf[2]);
17740 }
17741 hddLog(VOS_TRACE_LEVEL_INFO,
17742 FL("ioctl return cap tsf cmd, ret = %d"), ret);
17743 return ret;
17744}
17745
17746void wlan_hdd_tsf_init(hdd_adapter_t *adapter)
17747{
17748
17749 if (adapter == NULL) {
17750 hddLog(VOS_TRACE_LEVEL_ERROR,
17751 FL("TSF init on a null adapter!"));
17752 return;
17753 }
17754
17755 adapter->tsf_cap_ctx.tsf_get_state = TSF_RETURN;
17756 adapter->tsf_cap_ctx.tsf_capture_state = TSF_IDLE;
17757 vos_event_init(&adapter->tsf_cap_ctx.tsf_capture_done_event);
17758 vos_spin_lock_init(&adapter->tsf_cap_ctx.tsf_lock);
17759 adapter->tsf_cap_ctx.tsf_high = 0;
17760 adapter->tsf_cap_ctx.tsf_low = 0;
17761}
17762
17763#endif
17764
Jeff Johnson295189b2012-06-20 16:38:30 -070017765//Register the module init/exit functions
17766module_init(hdd_module_init);
17767module_exit(hdd_module_exit);
17768
17769MODULE_LICENSE("Dual BSD/GPL");
17770MODULE_AUTHOR("Qualcomm Atheros, Inc.");
17771MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
17772
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070017773module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
17774 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -070017775
Jeff Johnson76052702013-04-16 13:55:05 -070017776module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -070017777 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Arif Hussain66559122013-11-21 10:11:40 -080017778
17779module_param(enable_dfs_chan_scan, int,
17780 S_IRUSR | S_IRGRP | S_IROTH);
17781
17782module_param(enable_11d, int,
17783 S_IRUSR | S_IRGRP | S_IROTH);
17784
17785module_param(country_code, charp,
17786 S_IRUSR | S_IRGRP | S_IROTH);