blob: 4fbd76158e4e8975769d8dfbdb55d50b77cdd4fd [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
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003203static int hdd_driver_command(hdd_adapter_t *pAdapter,
3204 hdd_priv_data_t *ppriv_data)
Jeff Johnson295189b2012-06-20 16:38:30 -07003205{
Jeff Johnson295189b2012-06-20 16:38:30 -07003206 hdd_priv_data_t priv_data;
3207 tANI_U8 *command = NULL;
Kaushik, Sushant96122442014-10-21 16:40:18 +05303208 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3209 hdd_scaninfo_t *pScanInfo = NULL;
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003210 int ret = 0;
Kaushik, Sushant96122442014-10-21 16:40:18 +05303211 int status;
Anand N Sunkade9adb1b2015-07-29 09:56:45 +05303212#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0))
3213 struct cfg80211_mgmt_tx_params params;
3214#endif
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05303215
3216 ENTER();
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003217 /*
3218 * Note that valid pointers are provided by caller
3219 */
Jeff Johnson295189b2012-06-20 16:38:30 -07003220
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003221 /* copy to local struct to avoid numerous changes to legacy code */
3222 priv_data = *ppriv_data;
Jeff Johnson295189b2012-06-20 16:38:30 -07003223
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003224 if (priv_data.total_len <= 0 ||
3225 priv_data.total_len > WLAN_PRIV_DATA_MAX_LEN)
Sameer Thalappil8ef3a0e2013-04-05 14:36:04 -07003226 {
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003227 hddLog(VOS_TRACE_LEVEL_WARN,
3228 "%s:invalid priv_data.total_len(%d)!!!", __func__,
3229 priv_data.total_len);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003230 ret = -EINVAL;
3231 goto exit;
3232 }
Kaushik, Sushant96122442014-10-21 16:40:18 +05303233 status = wlan_hdd_validate_context(pHddCtx);
3234 if (0 != status)
3235 {
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05303236 ret = -EINVAL;
3237 goto exit;
Kaushik, Sushant96122442014-10-21 16:40:18 +05303238 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003239 /* Allocate +1 for '\0' */
3240 command = kmalloc(priv_data.total_len + 1, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07003241 if (!command)
3242 {
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003243 hddLog(VOS_TRACE_LEVEL_ERROR,
3244 "%s: failed to allocate memory", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003245 ret = -ENOMEM;
3246 goto exit;
3247 }
3248
3249 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
3250 {
3251 ret = -EFAULT;
3252 goto exit;
3253 }
3254
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003255 /* Make sure the command is NUL-terminated */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003256 command[priv_data.total_len] = '\0';
3257
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003258 /* at one time the following block of code was conditional. braces
3259 * have been retained to avoid re-indenting the legacy code
3260 */
Jeff Johnson295189b2012-06-20 16:38:30 -07003261 {
3262 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
3263
3264 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07003265 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -07003266
3267 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
3268 {
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303269 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3270 TRACE_CODE_HDD_P2P_DEV_ADDR_IOCTL,
3271 pAdapter->sessionId, (unsigned)
3272 (*(pHddCtx->p2pDeviceAddress.bytes+2)<<24 |
3273 *(pHddCtx->p2pDeviceAddress.bytes+3)<<16 |
3274 *(pHddCtx->p2pDeviceAddress.bytes+4)<<8 |
3275 *(pHddCtx->p2pDeviceAddress.bytes+5))));
Jeff Johnson295189b2012-06-20 16:38:30 -07003276 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
3277 sizeof(tSirMacAddr)))
3278 {
3279 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Arif Hussain6d2a3322013-11-17 19:50:10 -08003280 "%s: failed to copy data to user buffer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003281 ret = -EFAULT;
3282 }
3283 }
Amar Singhal0974e402013-02-12 14:27:46 -08003284 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07003285 {
Amar Singhal0974e402013-02-12 14:27:46 -08003286 tANI_U8 *ptr = command ;
Srinivas Girigowdade697412013-02-14 16:31:48 -08003287
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05303288 ret = hdd_drv_cmd_validate(command, 7);
3289 if (ret)
3290 goto exit;
3291
Jeff Johnson295189b2012-06-20 16:38:30 -07003292 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -08003293
3294 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -07003295 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07003296 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -08003297 "%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 +05303298 if(VOS_FTM_MODE != hdd_get_conparam())
3299 {
3300 /* Change band request received */
3301 ret = hdd_setBand_helper(pAdapter->dev, ptr);
3302 if(ret < 0)
3303 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
3304 "%s: failed to set band ret=%d", __func__, ret);
3305 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08003306 }
Kiet Lamf040f472013-11-20 21:15:23 +05303307 else if(strncmp(command, "SETWMMPS", 8) == 0)
3308 {
3309 tANI_U8 *ptr = command;
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05303310
3311 ret = hdd_drv_cmd_validate(command, 8);
3312 if (ret)
3313 goto exit;
3314
Kiet Lamf040f472013-11-20 21:15:23 +05303315 ret = hdd_wmmps_helper(pAdapter, ptr);
3316 }
Agarwal Ashishef54a182014-12-16 15:07:31 +05303317
3318 else if(strncmp(command, "TDLSSCAN", 8) == 0)
3319 {
3320 tANI_U8 *ptr = command;
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05303321
3322 ret = hdd_drv_cmd_validate(command, 8);
3323 if (ret)
3324 goto exit;
3325
Agarwal Ashishef54a182014-12-16 15:07:31 +05303326 ret = hdd_set_tdls_scan_type(pAdapter, ptr);
3327 }
3328
Jeff Johnson32d95a32012-09-10 13:15:23 -07003329 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
3330 {
3331 char *country_code;
3332
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05303333 ret = hdd_drv_cmd_validate(command, 7);
3334 if (ret)
3335 goto exit;
3336
Jeff Johnson32d95a32012-09-10 13:15:23 -07003337 country_code = command + 8;
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07003338
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07003339 INIT_COMPLETION(pAdapter->change_country_code);
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07003340 hdd_checkandupdate_dfssetting(pAdapter, country_code);
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -07003341#ifndef CONFIG_ENABLE_LINUX_REG
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +05303342 hdd_checkandupdate_phymode(pAdapter, country_code);
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -07003343#endif
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07003344 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal,
3345 (void *)(tSmeChangeCountryCallback)
3346 wlan_hdd_change_country_code_callback,
Abhishek Singha306a442013-11-07 18:39:01 +05303347 country_code, pAdapter, pHddCtx->pvosContext, eSIR_TRUE, eSIR_TRUE);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07003348 if (eHAL_STATUS_SUCCESS == ret)
3349 {
3350 ret = wait_for_completion_interruptible_timeout(
3351 &pAdapter->change_country_code,
3352 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
3353 if (0 >= ret)
3354 {
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003355 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: SME while setting country code timed out %d",
c_hpothu6ff1c3c2013-10-01 19:01:57 +05303356 __func__, ret);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07003357 }
3358 }
3359 else
Jeff Johnson32d95a32012-09-10 13:15:23 -07003360 {
3361 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003362 "%s: SME Change Country code fail ret=%d", __func__, ret);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07003363 ret = -EINVAL;
Jeff Johnson32d95a32012-09-10 13:15:23 -07003364 }
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07003365
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07003366 }
3367 /*
3368 command should be a string having format
3369 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
3370 */
Amar Singhal0974e402013-02-12 14:27:46 -08003371 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07003372 {
Amar Singhal0974e402013-02-12 14:27:46 -08003373 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07003374
3375 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003376 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07003377
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -08003378 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -07003379 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -08003380 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
3381 {
3382 int suspend = 0;
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05303383 tANI_U8 *ptr;
3384
3385 ret = hdd_drv_cmd_validate(command, 14);
3386 if (ret)
3387 goto exit;
3388
3389 ptr = (tANI_U8*)command + 15;
Sameer Thalappil45931fb2013-02-01 11:18:05 -08003390
3391 suspend = *ptr - '0';
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303392 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3393 TRACE_CODE_HDD_SETSUSPENDMODE_IOCTL,
3394 pAdapter->sessionId, suspend));
Sameer Thalappil45931fb2013-02-01 11:18:05 -08003395 hdd_set_wlan_suspend_mode(suspend);
3396 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08003397#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
3398 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
3399 {
3400 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003401 tANI_S8 rssi = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08003402 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
3403 eHalStatus status = eHAL_STATUS_SUCCESS;
3404
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05303405 ret = hdd_drv_cmd_validate(command, 14);
3406 if (ret)
3407 goto exit;
3408
Srinivas Girigowdade697412013-02-14 16:31:48 -08003409 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
3410 value = value + 15;
3411
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003412 /* Convert the value from ascii to integer */
3413 ret = kstrtos8(value, 10, &rssi);
3414 if (ret < 0)
3415 {
3416 /* If the input value is greater than max value of datatype, then also
3417 kstrtou8 fails */
3418 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3419 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdafa7157d2013-10-31 10:14:22 -07003420 __func__,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003421 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
3422 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
3423 ret = -EINVAL;
3424 goto exit;
3425 }
3426
Srinivas Girigowdade697412013-02-14 16:31:48 -08003427 lookUpThreshold = abs(rssi);
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003428
Srinivas Girigowdade697412013-02-14 16:31:48 -08003429 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
3430 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
3431 {
3432 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3433 "Neighbor lookup threshold value %d is out of range"
3434 " (Min: %d Max: %d)", lookUpThreshold,
3435 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
3436 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
3437 ret = -EINVAL;
3438 goto exit;
3439 }
3440
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303441 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3442 TRACE_CODE_HDD_SETROAMTRIGGER_IOCTL,
3443 pAdapter->sessionId, lookUpThreshold));
Srinivas Girigowdade697412013-02-14 16:31:48 -08003444 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3445 "%s: Received Command to Set Roam trigger"
3446 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
3447
3448 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
3449 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
3450 if (eHAL_STATUS_SUCCESS != status)
3451 {
3452 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3453 "%s: Failed to set roam trigger, try again", __func__);
3454 ret = -EPERM;
3455 goto exit;
3456 }
3457
3458 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
mukul sharmad6e1fdd2014-06-23 19:19:09 +05303459 pHddCtx->cfg_ini->nNeighborReassocRssiThreshold = lookUpThreshold + 5;
Srinivas Girigowdade697412013-02-14 16:31:48 -08003460 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
3461 }
3462 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
3463 {
3464 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
3465 int rssi = (-1) * lookUpThreshold;
3466 char extra[32];
3467 tANI_U8 len = 0;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303468 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3469 TRACE_CODE_HDD_GETROAMTRIGGER_IOCTL,
3470 pAdapter->sessionId, lookUpThreshold));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003471 len = scnprintf(extra, sizeof(extra), "%s %d", command, rssi);
Srinivas Girigowda91719232015-07-13 15:10:10 +05303472 len = VOS_MIN(priv_data.total_len, len + 1);
3473 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdade697412013-02-14 16:31:48 -08003474 {
3475 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3476 "%s: failed to copy data to user buffer", __func__);
3477 ret = -EFAULT;
3478 goto exit;
3479 }
3480 }
3481 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
3482 {
3483 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003484 tANI_U8 roamScanPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003485 tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003486
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05303487 ret = hdd_drv_cmd_validate(command, 17);
3488 if (ret)
3489 goto exit;
3490
Srinivas Girigowdade697412013-02-14 16:31:48 -08003491 /* input refresh period is in terms of seconds */
3492 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
3493 value = value + 18;
3494 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003495 ret = kstrtou8(value, 10, &roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08003496 if (ret < 0)
3497 {
3498 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003499 kstrtou8 fails */
Srinivas Girigowdade697412013-02-14 16:31:48 -08003500 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003501 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdade697412013-02-14 16:31:48 -08003502 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07003503 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
3504 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08003505 ret = -EINVAL;
3506 goto exit;
3507 }
3508
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003509 if ((roamScanPeriod < (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000)) ||
3510 (roamScanPeriod > (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000)))
Srinivas Girigowdade697412013-02-14 16:31:48 -08003511 {
3512 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003513 "Roam scan period value %d is out of range"
3514 " (Min: %d Max: %d)", roamScanPeriod,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07003515 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
3516 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08003517 ret = -EINVAL;
3518 goto exit;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303519 }
3520 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3521 TRACE_CODE_HDD_SETROAMSCANPERIOD_IOCTL,
3522 pAdapter->sessionId, roamScanPeriod));
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003523 neighborEmptyScanRefreshPeriod = roamScanPeriod * 1000;
Srinivas Girigowdade697412013-02-14 16:31:48 -08003524
3525 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3526 "%s: Received Command to Set roam scan period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003527 " (Empty Scan refresh period) = %d", __func__, roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08003528
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003529 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod;
3530 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08003531 }
3532 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
3533 {
3534 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
3535 char extra[32];
3536 tANI_U8 len = 0;
3537
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303538 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3539 TRACE_CODE_HDD_GETROAMSCANPERIOD_IOCTL,
3540 pAdapter->sessionId, nEmptyScanRefreshPeriod));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003541 len = scnprintf(extra, sizeof(extra), "%s %d",
3542 "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08003543 /* Returned value is in units of seconds */
Ratnam Rachuria72ba112015-07-17 13:27:03 +05303544 len = VOS_MIN(priv_data.total_len, len + 1);
3545 if (copy_to_user(priv_data.buf, &extra, len)) {
Srinivas Girigowdade697412013-02-14 16:31:48 -08003546 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3547 "%s: failed to copy data to user buffer", __func__);
3548 ret = -EFAULT;
3549 goto exit;
3550 }
3551 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003552 else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0)
3553 {
3554 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003555 tANI_U8 roamScanRefreshPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003556 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003557
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05303558 ret = hdd_drv_cmd_validate(command, 24);
3559 if (ret)
3560 goto exit;
3561
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003562 /* input refresh period is in terms of seconds */
3563 /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */
3564 value = value + 25;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003565
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003566 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003567 ret = kstrtou8(value, 10, &roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003568 if (ret < 0)
3569 {
3570 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003571 kstrtou8 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003572 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003573 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003574 __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003575 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
3576 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
3577 ret = -EINVAL;
3578 goto exit;
3579 }
3580
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003581 if ((roamScanRefreshPeriod < (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000)) ||
3582 (roamScanRefreshPeriod > (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000)))
3583 {
3584 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3585 "Neighbor scan results refresh period value %d is out of range"
3586 " (Min: %d Max: %d)", roamScanRefreshPeriod,
3587 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
3588 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
3589 ret = -EINVAL;
3590 goto exit;
3591 }
3592 neighborScanRefreshPeriod = roamScanRefreshPeriod * 1000;
3593
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003594 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3595 "%s: Received Command to Set roam scan refresh period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003596 " (Scan refresh period) = %d", __func__, roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003597
3598 pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod;
3599 sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
3600 }
3601 else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0)
3602 {
3603 tANI_U16 value = sme_getNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
3604 char extra[32];
3605 tANI_U8 len = 0;
3606
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003607 len = scnprintf(extra, sizeof(extra), "%s %d",
3608 "GETROAMSCANREFRESHPERIOD", (value/1000));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003609 /* Returned value is in units of seconds */
Ratnam Rachuri2c9d6702015-07-17 13:25:16 +05303610 len = VOS_MIN(priv_data.total_len, len + 1);
3611 if (copy_to_user(priv_data.buf, &extra, len)) {
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003612 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3613 "%s: failed to copy data to user buffer", __func__);
3614 ret = -EFAULT;
3615 goto exit;
3616 }
3617 }
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07003618#ifdef FEATURE_WLAN_LFR
3619 /* SETROAMMODE */
3620 else if (strncmp(command, "SETROAMMODE", SIZE_OF_SETROAMMODE) == 0)
3621 {
3622 tANI_U8 *value = command;
3623 tANI_BOOLEAN roamMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
3624
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05303625 if (pHddCtx->concurrency_mode == VOS_STA_MON) {
3626 hddLog(LOGE,
3627 FL("Roaming is always disabled in STA + MON concurrency"));
3628 ret = -EINVAL;
3629 goto exit;
3630 }
3631
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05303632 ret = hdd_drv_cmd_validate(command, SIZE_OF_SETROAMMODE);
3633 if (ret)
3634 goto exit;
3635
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07003636 /* Move pointer to ahead of SETROAMMODE<delimiter> */
3637 value = value + SIZE_OF_SETROAMMODE + 1;
3638
3639 /* Convert the value from ascii to integer */
3640 ret = kstrtou8(value, SIZE_OF_SETROAMMODE, &roamMode);
3641 if (ret < 0)
3642 {
3643 /* If the input value is greater than max value of datatype, then also
3644 kstrtou8 fails */
3645 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3646 "%s: kstrtou8 failed range [%d - %d]", __func__,
3647 CFG_LFR_FEATURE_ENABLED_MIN,
3648 CFG_LFR_FEATURE_ENABLED_MAX);
3649 ret = -EINVAL;
3650 goto exit;
3651 }
3652 if ((roamMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
3653 (roamMode > CFG_LFR_FEATURE_ENABLED_MAX))
3654 {
3655 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3656 "Roam Mode value %d is out of range"
3657 " (Min: %d Max: %d)", roamMode,
3658 CFG_LFR_FEATURE_ENABLED_MIN,
3659 CFG_LFR_FEATURE_ENABLED_MAX);
3660 ret = -EINVAL;
3661 goto exit;
3662 }
3663
3664 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3665 "%s: Received Command to Set Roam Mode = %d", __func__, roamMode);
3666 /*
3667 * Note that
3668 * SETROAMMODE 0 is to enable LFR while
3669 * SETROAMMODE 1 is to disable LFR, but
3670 * NotifyIsFastRoamIniFeatureEnabled 0/1 is to enable/disable.
3671 * So, we have to invert the value to call sme_UpdateIsFastRoamIniFeatureEnabled.
3672 */
3673 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
3674 roamMode = CFG_LFR_FEATURE_ENABLED_MAX; /* Roam enable */
3675 else
3676 roamMode = CFG_LFR_FEATURE_ENABLED_MIN; /* Roam disable */
3677
3678 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = roamMode;
3679 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), roamMode);
3680 }
3681 /* GETROAMMODE */
Mahesh A Saptasagarec7d1092015-04-02 13:41:34 +05303682 else if (strncmp(command, "GETROAMMODE", SIZE_OF_GETROAMMODE) == 0)
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07003683 {
3684 tANI_BOOLEAN roamMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
3685 char extra[32];
3686 tANI_U8 len = 0;
3687
3688 /*
3689 * roamMode value shall be inverted because the sementics is different.
3690 */
3691 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
3692 roamMode = CFG_LFR_FEATURE_ENABLED_MAX;
3693 else
3694 roamMode = CFG_LFR_FEATURE_ENABLED_MIN;
3695
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003696 len = scnprintf(extra, sizeof(extra), "%s %d", command, roamMode);
Ratnam Rachuri28693eb2015-07-17 13:23:42 +05303697 len = VOS_MIN(priv_data.total_len, len + 1);
3698 if (copy_to_user(priv_data.buf, &extra, len)) {
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07003699 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3700 "%s: failed to copy data to user buffer", __func__);
3701 ret = -EFAULT;
3702 goto exit;
3703 }
3704 }
3705#endif
Srinivas Girigowdade697412013-02-14 16:31:48 -08003706#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003707#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -08003708 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
3709 {
3710 tANI_U8 *value = command;
3711 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
3712
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05303713 ret = hdd_drv_cmd_validate(command, 12);
3714 if (ret)
3715 goto exit;
3716
Srinivas Girigowdade697412013-02-14 16:31:48 -08003717 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
3718 value = value + 13;
3719 /* Convert the value from ascii to integer */
3720 ret = kstrtou8(value, 10, &roamRssiDiff);
3721 if (ret < 0)
3722 {
3723 /* If the input value is greater than max value of datatype, then also
3724 kstrtou8 fails */
3725 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3726 "%s: kstrtou8 failed range [%d - %d]", __func__,
3727 CFG_ROAM_RSSI_DIFF_MIN,
3728 CFG_ROAM_RSSI_DIFF_MAX);
3729 ret = -EINVAL;
3730 goto exit;
3731 }
3732
3733 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
3734 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
3735 {
3736 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3737 "Roam rssi diff value %d is out of range"
3738 " (Min: %d Max: %d)", roamRssiDiff,
3739 CFG_ROAM_RSSI_DIFF_MIN,
3740 CFG_ROAM_RSSI_DIFF_MAX);
3741 ret = -EINVAL;
3742 goto exit;
3743 }
3744
3745 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3746 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
3747
3748 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
3749 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
3750 }
Mahesh A Saptasagarec7d1092015-04-02 13:41:34 +05303751 else if (strncmp(command, "GETROAMDELTA", 12) == 0)
Srinivas Girigowdade697412013-02-14 16:31:48 -08003752 {
3753 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
3754 char extra[32];
3755 tANI_U8 len = 0;
3756
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303757 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3758 TRACE_CODE_HDD_GETROAMDELTA_IOCTL,
3759 pAdapter->sessionId, roamRssiDiff));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003760 len = scnprintf(extra, sizeof(extra), "%s %d",
3761 command, roamRssiDiff);
Ratnam Rachuri22a3b402015-07-17 13:21:49 +05303762 len = VOS_MIN(priv_data.total_len, len + 1);
3763 if (copy_to_user(priv_data.buf, &extra, len)) {
Srinivas Girigowdade697412013-02-14 16:31:48 -08003764 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3765 "%s: failed to copy data to user buffer", __func__);
3766 ret = -EFAULT;
3767 goto exit;
3768 }
3769 }
3770#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003771#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -08003772 else if (strncmp(command, "GETBAND", 7) == 0)
3773 {
3774 int band = -1;
3775 char extra[32];
3776 tANI_U8 len = 0;
3777 hdd_getBand_helper(pHddCtx, &band);
3778
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303779 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3780 TRACE_CODE_HDD_GETBAND_IOCTL,
3781 pAdapter->sessionId, band));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003782 len = scnprintf(extra, sizeof(extra), "%s %d", command, band);
Ratnam Rachuri52139592015-07-17 13:17:29 +05303783 len = VOS_MIN(priv_data.total_len, len + 1);
3784 if (copy_to_user(priv_data.buf, &extra, len)) {
Srinivas Girigowdade697412013-02-14 16:31:48 -08003785 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3786 "%s: failed to copy data to user buffer", __func__);
3787 ret = -EFAULT;
3788 goto exit;
3789 }
3790 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08003791 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
3792 {
3793 tANI_U8 *value = command;
3794 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
3795 tANI_U8 numChannels = 0;
3796 eHalStatus status = eHAL_STATUS_SUCCESS;
3797
3798 status = hdd_parse_channellist(value, ChannelList, &numChannels);
3799 if (eHAL_STATUS_SUCCESS != status)
3800 {
3801 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3802 "%s: Failed to parse channel list information", __func__);
3803 ret = -EINVAL;
3804 goto exit;
3805 }
3806
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303807 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3808 TRACE_CODE_HDD_SETROAMSCANCHANNELS_IOCTL,
3809 pAdapter->sessionId, numChannels));
Srinivas Girigowdade697412013-02-14 16:31:48 -08003810 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
3811 {
3812 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3813 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
3814 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
3815 ret = -EINVAL;
3816 goto exit;
3817 }
3818 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
3819 numChannels);
3820 if (eHAL_STATUS_SUCCESS != status)
3821 {
3822 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3823 "%s: Failed to update channel list information", __func__);
3824 ret = -EINVAL;
3825 goto exit;
3826 }
3827 }
3828 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
3829 {
3830 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
3831 tANI_U8 numChannels = 0;
Jeff Johnson51b67782013-04-05 12:35:41 -07003832 tANI_U8 j = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08003833 char extra[128] = {0};
Jeff Johnson51b67782013-04-05 12:35:41 -07003834 int len;
Srinivas Girigowdade697412013-02-14 16:31:48 -08003835
3836 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
3837 ChannelList, &numChannels ))
3838 {
3839 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3840 "%s: failed to get roam scan channel list", __func__);
3841 ret = -EFAULT;
3842 goto exit;
3843 }
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303844 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3845 TRACE_CODE_HDD_GETROAMSCANCHANNELS_IOCTL,
3846 pAdapter->sessionId, numChannels));
Srinivas Girigowdade697412013-02-14 16:31:48 -08003847 /* output channel list is of the format
3848 [Number of roam scan channels][Channel1][Channel2]... */
3849 /* copy the number of channels in the 0th index */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003850 len = scnprintf(extra, sizeof(extra), "%s %d", command, numChannels);
Sushant Kaushika08ca192015-09-16 15:52:04 +05303851 for (j = 0; (j < numChannels) && len <= sizeof(extra); j++)
Srinivas Girigowdade697412013-02-14 16:31:48 -08003852 {
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003853 len += scnprintf(extra + len, sizeof(extra) - len, " %d",
3854 ChannelList[j]);
Srinivas Girigowdade697412013-02-14 16:31:48 -08003855 }
3856
Sushant Kaushikc9b8be52015-07-15 16:41:27 +05303857 len = VOS_MIN(priv_data.total_len, len + 1);
3858 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdade697412013-02-14 16:31:48 -08003859 {
3860 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3861 "%s: failed to copy data to user buffer", __func__);
3862 ret = -EFAULT;
3863 goto exit;
3864 }
3865 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003866 else if (strncmp(command, "GETCCXMODE", 10) == 0)
3867 {
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003868 tANI_BOOLEAN eseMode = sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003869 char extra[32];
3870 tANI_U8 len = 0;
3871
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003872 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003873 then this operation is not permitted (return FAILURE) */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003874 if (eseMode &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003875 hdd_is_okc_mode_enabled(pHddCtx) &&
3876 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
3877 {
3878 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003879 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003880 " hence this operation is not permitted!", __func__);
3881 ret = -EPERM;
3882 goto exit;
3883 }
3884
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003885 len = scnprintf(extra, sizeof(extra), "%s %d",
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003886 "GETCCXMODE", eseMode);
Sushant Kaushikf8abd352015-07-15 16:37:49 +05303887 len = VOS_MIN(priv_data.total_len, len + 1);
3888 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003889 {
3890 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3891 "%s: failed to copy data to user buffer", __func__);
3892 ret = -EFAULT;
3893 goto exit;
3894 }
3895 }
3896 else if (strncmp(command, "GETOKCMODE", 10) == 0)
3897 {
3898 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
3899 char extra[32];
3900 tANI_U8 len = 0;
3901
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003902 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003903 then this operation is not permitted (return FAILURE) */
3904 if (okcMode &&
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003905 sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003906 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
3907 {
3908 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003909 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003910 " hence this operation is not permitted!", __func__);
3911 ret = -EPERM;
3912 goto exit;
3913 }
3914
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003915 len = scnprintf(extra, sizeof(extra), "%s %d",
3916 "GETOKCMODE", okcMode);
Sushant Kaushikbc2fb5c2015-07-15 16:43:16 +05303917 len = VOS_MIN(priv_data.total_len, len + 1);
3918 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003919 {
3920 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3921 "%s: failed to copy data to user buffer", __func__);
3922 ret = -EFAULT;
3923 goto exit;
3924 }
3925 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003926 else if (strncmp(command, "GETFASTROAM", 11) == 0)
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003927 {
3928 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
3929 char extra[32];
3930 tANI_U8 len = 0;
3931
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003932 len = scnprintf(extra, sizeof(extra), "%s %d",
3933 "GETFASTROAM", lfrMode);
Sushant Kaushik4da7ec92015-07-15 16:39:32 +05303934 len = VOS_MIN(priv_data.total_len, len + 1);
3935 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003936 {
3937 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3938 "%s: failed to copy data to user buffer", __func__);
3939 ret = -EFAULT;
3940 goto exit;
3941 }
3942 }
3943 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
3944 {
3945 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
3946 char extra[32];
3947 tANI_U8 len = 0;
3948
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003949 len = scnprintf(extra, sizeof(extra), "%s %d",
3950 "GETFASTTRANSITION", ft);
Sushant Kaushik231a4452015-07-15 16:23:56 +05303951 len = VOS_MIN(priv_data.total_len, len + 1);
3952 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003953 {
3954 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3955 "%s: failed to copy data to user buffer", __func__);
3956 ret = -EFAULT;
3957 goto exit;
3958 }
3959 }
3960 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
3961 {
3962 tANI_U8 *value = command;
3963 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
3964
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05303965 ret = hdd_drv_cmd_validate(command, 25);
3966 if (ret)
3967 goto exit;
3968
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003969 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
3970 value = value + 26;
3971 /* Convert the value from ascii to integer */
3972 ret = kstrtou8(value, 10, &minTime);
3973 if (ret < 0)
3974 {
3975 /* If the input value is greater than max value of datatype, then also
3976 kstrtou8 fails */
3977 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3978 "%s: kstrtou8 failed range [%d - %d]", __func__,
3979 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
3980 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
3981 ret = -EINVAL;
3982 goto exit;
3983 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003984 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
3985 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
3986 {
3987 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3988 "scan min channel time value %d is out of range"
3989 " (Min: %d Max: %d)", minTime,
3990 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
3991 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
3992 ret = -EINVAL;
3993 goto exit;
3994 }
3995
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303996 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3997 TRACE_CODE_HDD_SETROAMSCANCHANNELMINTIME_IOCTL,
3998 pAdapter->sessionId, minTime));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003999 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4000 "%s: Received Command to change channel min time = %d", __func__, minTime);
4001
4002 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
4003 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
4004 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004005 else if (strncmp(command, "SENDACTIONFRAME", 15) == 0)
4006 {
4007 tANI_U8 *value = command;
4008 tANI_U8 channel = 0;
4009 tANI_U8 dwellTime = 0;
4010 tANI_U8 bufLen = 0;
4011 tANI_U8 *buf = NULL;
4012 tSirMacAddr targetApBssid;
4013 eHalStatus status = eHAL_STATUS_SUCCESS;
4014 struct ieee80211_channel chan;
4015 tANI_U8 finalLen = 0;
4016 tANI_U8 *finalBuf = NULL;
4017 tANI_U8 temp = 0;
4018 u64 cookie;
4019 hdd_station_ctx_t *pHddStaCtx = NULL;
4020 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4021
4022 /* if not associated, no need to send action frame */
4023 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
4024 {
4025 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
4026 ret = -EINVAL;
4027 goto exit;
4028 }
4029
4030 status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel,
4031 &dwellTime, &buf, &bufLen);
4032 if (eHAL_STATUS_SUCCESS != status)
4033 {
4034 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4035 "%s: Failed to parse send action frame data", __func__);
4036 ret = -EINVAL;
4037 goto exit;
4038 }
4039
4040 /* if the target bssid is different from currently associated AP,
4041 then no need to send action frame */
4042 if (VOS_TRUE != vos_mem_compare(targetApBssid,
4043 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
4044 {
4045 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__);
4046 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07004047 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08004048 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004049 goto exit;
4050 }
4051
4052 /* if the channel number is different from operating channel then
4053 no need to send action frame */
4054 if (channel != pHddStaCtx->conn_info.operationChannel)
4055 {
4056 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4057 "%s: channel(%d) is different from operating channel(%d)",
4058 __func__, channel, pHddStaCtx->conn_info.operationChannel);
4059 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07004060 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08004061 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004062 goto exit;
4063 }
4064 chan.center_freq = sme_ChnToFreq(channel);
4065
4066 finalLen = bufLen + 24;
4067 finalBuf = vos_mem_malloc(finalLen);
4068 if (NULL == finalBuf)
4069 {
4070 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__);
4071 ret = -ENOMEM;
Jeff Johnson11c33152013-04-16 17:52:40 -07004072 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08004073 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004074 goto exit;
4075 }
4076 vos_mem_zero(finalBuf, finalLen);
4077
4078 /* Fill subtype */
4079 temp = SIR_MAC_MGMT_ACTION << 4;
4080 vos_mem_copy(finalBuf + 0, &temp, sizeof(temp));
4081
4082 /* Fill type */
4083 temp = SIR_MAC_MGMT_FRAME;
4084 vos_mem_copy(finalBuf + 2, &temp, sizeof(temp));
4085
4086 /* Fill destination address (bssid of the AP) */
4087 vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid));
4088
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07004089 /* Fill source address (STA mac address) */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004090 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
4091
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07004092 /* Fill BSSID (AP mac address) */
4093 vos_mem_copy(finalBuf + 16, targetApBssid, sizeof(targetApBssid));
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004094
4095 /* Fill received buffer from 24th address */
4096 vos_mem_copy(finalBuf + 24, buf, bufLen);
4097
Jeff Johnson11c33152013-04-16 17:52:40 -07004098 /* done with the parsed buffer */
4099 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08004100 buf = NULL;
Jeff Johnson11c33152013-04-16 17:52:40 -07004101
Anand N Sunkade9adb1b2015-07-29 09:56:45 +05304102#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0))
4103 params.chan = &chan;
4104 params.offchan = 0;
4105 params.wait = dwellTime;
4106 params.buf = finalBuf;
4107 params.len = finalLen;
4108 params.no_cck = 1;
4109 params.dont_wait_for_ack = 1;
4110 ret = wlan_hdd_mgmt_tx(NULL, &pAdapter->wdev, &params, &cookie);
4111#else
DARAM SUDHA39eede62014-02-12 11:16:40 +05304112 wlan_hdd_mgmt_tx( NULL,
Yue Maf49ba872013-08-19 12:04:25 -07004113#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
4114 &(pAdapter->wdev),
4115#else
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07004116 pAdapter->dev,
Yue Maf49ba872013-08-19 12:04:25 -07004117#endif
4118 &chan, 0,
4119#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
4120 NL80211_CHAN_HT20, 1,
4121#endif
4122 dwellTime, finalBuf, finalLen, 1,
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004123 1, &cookie );
Anand N Sunkade9adb1b2015-07-29 09:56:45 +05304124#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0)*/
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004125 vos_mem_free(finalBuf);
4126 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004127 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
4128 {
4129 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
4130 char extra[32];
4131 tANI_U8 len = 0;
4132
4133 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004134 len = scnprintf(extra, sizeof(extra), "%s %d",
4135 "GETROAMSCANCHANNELMINTIME", val);
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05304136 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
4137 TRACE_CODE_HDD_GETROAMSCANCHANNELMINTIME_IOCTL,
4138 pAdapter->sessionId, val));
Sushant Kaushikbb8c52c2015-07-15 16:36:23 +05304139 len = VOS_MIN(priv_data.total_len, len + 1);
4140 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004141 {
4142 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4143 "%s: failed to copy data to user buffer", __func__);
4144 ret = -EFAULT;
4145 goto exit;
4146 }
4147 }
4148 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
4149 {
4150 tANI_U8 *value = command;
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07004151 tANI_U16 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004152
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304153 ret = hdd_drv_cmd_validate(command, 18);
4154 if (ret)
4155 goto exit;
4156
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004157 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
4158 value = value + 19;
4159 /* Convert the value from ascii to integer */
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07004160 ret = kstrtou16(value, 10, &maxTime);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004161 if (ret < 0)
4162 {
4163 /* If the input value is greater than max value of datatype, then also
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07004164 kstrtou16 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004165 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07004166 "%s: kstrtou16 failed range [%d - %d]", __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004167 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
4168 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
4169 ret = -EINVAL;
4170 goto exit;
4171 }
4172
4173 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
4174 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
4175 {
4176 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4177 "lfr mode value %d is out of range"
4178 " (Min: %d Max: %d)", maxTime,
4179 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
4180 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
4181 ret = -EINVAL;
4182 goto exit;
4183 }
4184
4185 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4186 "%s: Received Command to change channel max time = %d", __func__, maxTime);
4187
4188 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
4189 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
4190 }
4191 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
4192 {
4193 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
4194 char extra[32];
4195 tANI_U8 len = 0;
4196
4197 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004198 len = scnprintf(extra, sizeof(extra), "%s %d",
4199 "GETSCANCHANNELTIME", val);
Ratheesh S Pacbfa932015-07-16 15:27:18 +05304200 len = VOS_MIN(priv_data.total_len, len + 1);
4201 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004202 {
4203 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4204 "%s: failed to copy data to user buffer", __func__);
4205 ret = -EFAULT;
4206 goto exit;
4207 }
4208 }
4209 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
4210 {
4211 tANI_U8 *value = command;
4212 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
4213
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304214 ret = hdd_drv_cmd_validate(command, 15);
4215 if (ret)
4216 goto exit;
4217
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004218 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
4219 value = value + 16;
4220 /* Convert the value from ascii to integer */
4221 ret = kstrtou16(value, 10, &val);
4222 if (ret < 0)
4223 {
4224 /* If the input value is greater than max value of datatype, then also
4225 kstrtou16 fails */
4226 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4227 "%s: kstrtou16 failed range [%d - %d]", __func__,
4228 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
4229 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
4230 ret = -EINVAL;
4231 goto exit;
4232 }
4233
4234 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
4235 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
4236 {
4237 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4238 "scan home time value %d is out of range"
4239 " (Min: %d Max: %d)", val,
4240 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
4241 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
4242 ret = -EINVAL;
4243 goto exit;
4244 }
4245
4246 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4247 "%s: Received Command to change scan home time = %d", __func__, val);
4248
4249 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
4250 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
4251 }
4252 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
4253 {
4254 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
4255 char extra[32];
4256 tANI_U8 len = 0;
4257
4258 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004259 len = scnprintf(extra, sizeof(extra), "%s %d",
4260 "GETSCANHOMETIME", val);
Ratheesh S P728d7c62015-07-16 15:38:58 +05304261 len = VOS_MIN(priv_data.total_len, len + 1);
4262 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004263 {
4264 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4265 "%s: failed to copy data to user buffer", __func__);
4266 ret = -EFAULT;
4267 goto exit;
4268 }
4269 }
4270 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
4271 {
4272 tANI_U8 *value = command;
4273 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
4274
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304275 ret = hdd_drv_cmd_validate(command, 16);
4276 if (ret)
4277 goto exit;
4278
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004279 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
4280 value = value + 17;
4281 /* Convert the value from ascii to integer */
4282 ret = kstrtou8(value, 10, &val);
4283 if (ret < 0)
4284 {
4285 /* If the input value is greater than max value of datatype, then also
4286 kstrtou8 fails */
4287 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4288 "%s: kstrtou8 failed range [%d - %d]", __func__,
4289 CFG_ROAM_INTRA_BAND_MIN,
4290 CFG_ROAM_INTRA_BAND_MAX);
4291 ret = -EINVAL;
4292 goto exit;
4293 }
4294
4295 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
4296 (val > CFG_ROAM_INTRA_BAND_MAX))
4297 {
4298 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4299 "intra band mode value %d is out of range"
4300 " (Min: %d Max: %d)", val,
4301 CFG_ROAM_INTRA_BAND_MIN,
4302 CFG_ROAM_INTRA_BAND_MAX);
4303 ret = -EINVAL;
4304 goto exit;
4305 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004306 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4307 "%s: Received Command to change intra band = %d", __func__, val);
4308
4309 pHddCtx->cfg_ini->nRoamIntraBand = val;
4310 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
4311 }
4312 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
4313 {
4314 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
4315 char extra[32];
4316 tANI_U8 len = 0;
4317
4318 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004319 len = scnprintf(extra, sizeof(extra), "%s %d",
4320 "GETROAMINTRABAND", val);
Ratheesh S P2dd2a3e2015-07-16 15:34:23 +05304321 len = VOS_MIN(priv_data.total_len, len + 1);
4322 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004323 {
4324 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4325 "%s: failed to copy data to user buffer", __func__);
4326 ret = -EFAULT;
4327 goto exit;
4328 }
4329 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004330 else if (strncmp(command, "SETSCANNPROBES", 14) == 0)
4331 {
4332 tANI_U8 *value = command;
4333 tANI_U8 nProbes = CFG_ROAM_SCAN_N_PROBES_DEFAULT;
4334
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304335 ret = hdd_drv_cmd_validate(command, 14);
4336 if (ret)
4337 goto exit;
4338
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004339 /* Move pointer to ahead of SETSCANNPROBES<delimiter> */
4340 value = value + 15;
4341 /* Convert the value from ascii to integer */
4342 ret = kstrtou8(value, 10, &nProbes);
4343 if (ret < 0)
4344 {
4345 /* If the input value is greater than max value of datatype, then also
4346 kstrtou8 fails */
4347 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4348 "%s: kstrtou8 failed range [%d - %d]", __func__,
4349 CFG_ROAM_SCAN_N_PROBES_MIN,
4350 CFG_ROAM_SCAN_N_PROBES_MAX);
4351 ret = -EINVAL;
4352 goto exit;
4353 }
4354
4355 if ((nProbes < CFG_ROAM_SCAN_N_PROBES_MIN) ||
4356 (nProbes > CFG_ROAM_SCAN_N_PROBES_MAX))
4357 {
4358 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4359 "NProbes value %d is out of range"
4360 " (Min: %d Max: %d)", nProbes,
4361 CFG_ROAM_SCAN_N_PROBES_MIN,
4362 CFG_ROAM_SCAN_N_PROBES_MAX);
4363 ret = -EINVAL;
4364 goto exit;
4365 }
4366
4367 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4368 "%s: Received Command to Set nProbes = %d", __func__, nProbes);
4369
4370 pHddCtx->cfg_ini->nProbes = nProbes;
4371 sme_UpdateRoamScanNProbes((tHalHandle)(pHddCtx->hHal), nProbes);
4372 }
Mahesh A Saptasagarec7d1092015-04-02 13:41:34 +05304373 else if (strncmp(command, "GETSCANNPROBES", 14) == 0)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004374 {
4375 tANI_U8 val = sme_getRoamScanNProbes((tHalHandle)(pHddCtx->hHal));
4376 char extra[32];
4377 tANI_U8 len = 0;
4378
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004379 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Ratnam Rachuri6da525d2015-08-07 13:55:54 +05304380 len = VOS_MIN(priv_data.total_len, len + 1);
4381 if (copy_to_user(priv_data.buf, &extra, len)) {
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004382 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4383 "%s: failed to copy data to user buffer", __func__);
4384 ret = -EFAULT;
4385 goto exit;
4386 }
4387 }
4388 else if (strncmp(command, "SETSCANHOMEAWAYTIME", 19) == 0)
4389 {
4390 tANI_U8 *value = command;
4391 tANI_U16 homeAwayTime = CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT;
4392
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304393 ret = hdd_drv_cmd_validate(command, 19);
4394 if (ret)
4395 goto exit;
4396
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004397 /* Move pointer to ahead of SETSCANHOMEAWAYTIME<delimiter> */
4398 /* input value is in units of msec */
4399 value = value + 20;
4400 /* Convert the value from ascii to integer */
4401 ret = kstrtou16(value, 10, &homeAwayTime);
4402 if (ret < 0)
4403 {
4404 /* If the input value is greater than max value of datatype, then also
4405 kstrtou8 fails */
4406 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4407 "%s: kstrtou8 failed range [%d - %d]", __func__,
4408 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
4409 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
4410 ret = -EINVAL;
4411 goto exit;
4412 }
4413
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004414 if ((homeAwayTime < CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN) ||
4415 (homeAwayTime > CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX))
4416 {
4417 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4418 "homeAwayTime value %d is out of range"
4419 " (Min: %d Max: %d)", homeAwayTime,
4420 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
4421 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
4422 ret = -EINVAL;
4423 goto exit;
4424 }
4425
4426 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4427 "%s: Received Command to Set scan away time = %d", __func__, homeAwayTime);
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07004428 if (pHddCtx->cfg_ini->nRoamScanHomeAwayTime != homeAwayTime)
4429 {
4430 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
4431 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_TRUE);
4432 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004433 }
Mahesh A Saptasagarec7d1092015-04-02 13:41:34 +05304434 else if (strncmp(command, "GETSCANHOMEAWAYTIME", 19) == 0)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004435 {
4436 tANI_U16 val = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
4437 char extra[32];
4438 tANI_U8 len = 0;
4439
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004440 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Ratnam Rachuri51a5ad12015-08-07 14:06:37 +05304441 len = VOS_MIN(priv_data.total_len, len + 1);
4442 if (copy_to_user(priv_data.buf, &extra, len)) {
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004443 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4444 "%s: failed to copy data to user buffer", __func__);
4445 ret = -EFAULT;
4446 goto exit;
4447 }
4448 }
4449 else if (strncmp(command, "REASSOC", 7) == 0)
4450 {
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304451 ret = hdd_drv_cmd_validate(command, 7);
4452 if (ret)
4453 goto exit;
4454
4455 ret = hdd_parse_reassoc(pAdapter, command, priv_data.total_len);
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05304456 if (!ret)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004457 goto exit;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004458 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07004459 else if (strncmp(command, "SETWESMODE", 10) == 0)
4460 {
4461 tANI_U8 *value = command;
4462 tANI_BOOLEAN wesMode = CFG_ENABLE_WES_MODE_NAME_DEFAULT;
4463
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304464 ret = hdd_drv_cmd_validate(command, 10);
4465 if (ret)
4466 goto exit;
4467
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07004468 /* Move pointer to ahead of SETWESMODE<delimiter> */
4469 value = value + 11;
4470 /* Convert the value from ascii to integer */
4471 ret = kstrtou8(value, 10, &wesMode);
4472 if (ret < 0)
4473 {
4474 /* If the input value is greater than max value of datatype, then also
4475 kstrtou8 fails */
4476 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4477 "%s: kstrtou8 failed range [%d - %d]", __func__,
4478 CFG_ENABLE_WES_MODE_NAME_MIN,
4479 CFG_ENABLE_WES_MODE_NAME_MAX);
4480 ret = -EINVAL;
4481 goto exit;
4482 }
4483
4484 if ((wesMode < CFG_ENABLE_WES_MODE_NAME_MIN) ||
4485 (wesMode > CFG_ENABLE_WES_MODE_NAME_MAX))
4486 {
4487 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4488 "WES Mode value %d is out of range"
4489 " (Min: %d Max: %d)", wesMode,
4490 CFG_ENABLE_WES_MODE_NAME_MIN,
4491 CFG_ENABLE_WES_MODE_NAME_MAX);
4492 ret = -EINVAL;
4493 goto exit;
4494 }
4495 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4496 "%s: Received Command to Set WES Mode rssi diff = %d", __func__, wesMode);
4497
4498 pHddCtx->cfg_ini->isWESModeEnabled = wesMode;
4499 sme_UpdateWESMode((tHalHandle)(pHddCtx->hHal), wesMode);
4500 }
Mahesh A Saptasagarec7d1092015-04-02 13:41:34 +05304501 else if (strncmp(command, "GETWESMODE", 10) == 0)
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07004502 {
4503 tANI_BOOLEAN wesMode = sme_GetWESMode((tHalHandle)(pHddCtx->hHal));
4504 char extra[32];
4505 tANI_U8 len = 0;
4506
Arif Hussain826d9412013-11-12 16:44:54 -08004507 len = scnprintf(extra, sizeof(extra), "%s %d", command, wesMode);
Ratnam Rachuri8fe90c62015-08-07 14:03:26 +05304508 len = VOS_MIN(priv_data.total_len, len + 1);
4509 if (copy_to_user(priv_data.buf, &extra, len)) {
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07004510 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4511 "%s: failed to copy data to user buffer", __func__);
4512 ret = -EFAULT;
4513 goto exit;
4514 }
4515 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004516#endif /* WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_ESE || FEATURE_WLAN_LFR */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004517#ifdef FEATURE_WLAN_LFR
4518 else if (strncmp(command, "SETFASTROAM", 11) == 0)
4519 {
4520 tANI_U8 *value = command;
4521 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
4522
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05304523 if (pHddCtx->concurrency_mode == VOS_STA_MON) {
4524 hddLog(LOGE,
4525 FL("Roaming is always disabled in STA + MON concurrency"));
4526 ret = -EINVAL;
4527 goto exit;
4528 }
4529
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304530 ret = hdd_drv_cmd_validate(command, 11);
4531 if (ret)
4532 goto exit;
4533
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004534 /* Move pointer to ahead of SETFASTROAM<delimiter> */
4535 value = value + 12;
4536 /* Convert the value from ascii to integer */
4537 ret = kstrtou8(value, 10, &lfrMode);
4538 if (ret < 0)
4539 {
4540 /* If the input value is greater than max value of datatype, then also
4541 kstrtou8 fails */
4542 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4543 "%s: kstrtou8 failed range [%d - %d]", __func__,
4544 CFG_LFR_FEATURE_ENABLED_MIN,
4545 CFG_LFR_FEATURE_ENABLED_MAX);
4546 ret = -EINVAL;
4547 goto exit;
4548 }
4549
4550 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
4551 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
4552 {
4553 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4554 "lfr mode value %d is out of range"
4555 " (Min: %d Max: %d)", lfrMode,
4556 CFG_LFR_FEATURE_ENABLED_MIN,
4557 CFG_LFR_FEATURE_ENABLED_MAX);
4558 ret = -EINVAL;
4559 goto exit;
4560 }
4561
4562 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4563 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
4564
4565 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
4566 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
4567 }
4568#endif
4569#ifdef WLAN_FEATURE_VOWIFI_11R
4570 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
4571 {
4572 tANI_U8 *value = command;
4573 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
4574
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304575 ret = hdd_drv_cmd_validate(command, 17);
4576 if (ret)
4577 goto exit;
4578
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004579 /* Move pointer to ahead of SETFASTROAM<delimiter> */
4580 value = value + 18;
4581 /* Convert the value from ascii to integer */
4582 ret = kstrtou8(value, 10, &ft);
4583 if (ret < 0)
4584 {
4585 /* If the input value is greater than max value of datatype, then also
4586 kstrtou8 fails */
4587 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4588 "%s: kstrtou8 failed range [%d - %d]", __func__,
4589 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
4590 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
4591 ret = -EINVAL;
4592 goto exit;
4593 }
4594
4595 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
4596 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
4597 {
4598 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4599 "ft mode value %d is out of range"
4600 " (Min: %d Max: %d)", ft,
4601 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
4602 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
4603 ret = -EINVAL;
4604 goto exit;
4605 }
4606
4607 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4608 "%s: Received Command to change ft mode = %d", __func__, ft);
4609
4610 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
4611 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
4612 }
Padma, Santhosh Kumar778d8382015-03-04 17:41:22 +05304613 else if (strncmp(command, "SETDFSSCANMODE", 14) == 0)
4614 {
4615 tANI_U8 *value = command;
4616 tANI_U8 dfsScanMode = DFS_CHNL_SCAN_ENABLED_NORMAL;
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05304617
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304618 ret = hdd_drv_cmd_validate(command, 14);
4619 if (ret)
4620 goto exit;
4621
Padma, Santhosh Kumar778d8382015-03-04 17:41:22 +05304622 /* Move pointer to ahead of SETDFSSCANMODE<delimiter> */
4623 value = value + 15;
4624 /* Convert the value from ascii to integer */
4625 ret = kstrtou8(value, 10, &dfsScanMode);
4626 if (ret < 0)
4627 {
4628 /* If the input value is greater than max value of
4629 datatype, then also kstrtou8 fails
4630 */
4631 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4632 "%s: kstrtou8 failed range [%d - %d]", __func__,
4633 CFG_ENABLE_DFS_CHNL_SCAN_MIN,
4634 CFG_ENABLE_DFS_CHNL_SCAN_MAX);
4635 ret = -EINVAL;
4636 goto exit;
4637 }
4638
4639 if ((dfsScanMode < CFG_ENABLE_DFS_CHNL_SCAN_MIN) ||
4640 (dfsScanMode > CFG_ENABLE_DFS_CHNL_SCAN_MAX))
4641 {
4642 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4643 "dfsScanMode value %d is out of range"
4644 " (Min: %d Max: %d)", dfsScanMode,
4645 CFG_ENABLE_DFS_CHNL_SCAN_MIN,
4646 CFG_ENABLE_DFS_CHNL_SCAN_MAX);
4647 ret = -EINVAL;
4648 goto exit;
4649 }
4650 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4651 "%s: Received Command to Set DFS Scan Mode = %d",
4652 __func__, dfsScanMode);
4653
4654 ret = wlan_hdd_handle_dfs_chan_scan(pHddCtx, dfsScanMode);
4655 }
4656 else if (strncmp(command, "GETDFSSCANMODE", 14) == 0)
4657 {
4658 tANI_U8 dfsScanMode = sme_GetDFSScanMode(pHddCtx->hHal);
4659 char extra[32];
4660 tANI_U8 len = 0;
4661
4662 len = scnprintf(extra, sizeof(extra), "%s %d", command, dfsScanMode);
Ratheesh S P767224e2015-07-16 15:35:51 +05304663 len = VOS_MIN(priv_data.total_len, len + 1);
4664 if (copy_to_user(priv_data.buf, &extra, len))
Padma, Santhosh Kumar778d8382015-03-04 17:41:22 +05304665 {
4666 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4667 "%s: failed to copy data to user buffer", __func__);
4668 ret = -EFAULT;
4669 goto exit;
4670 }
4671 }
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05304672 else if (strncmp(command, "FASTREASSOC", 11) == 0)
4673 {
Selvaraj, Sridhar3714c4d2016-06-22 15:19:12 +05304674 ret = wlan_hdd_handle_fastreassoc(pAdapter, command);
4675 if (!ret)
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05304676 goto exit;
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05304677 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004678#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004679#ifdef FEATURE_WLAN_ESE
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004680 else if (strncmp(command, "SETCCXMODE", 10) == 0)
4681 {
4682 tANI_U8 *value = command;
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004683 tANI_U8 eseMode = CFG_ESE_FEATURE_ENABLED_DEFAULT;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004684
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304685 ret = hdd_drv_cmd_validate(command, 10);
4686 if (ret)
4687 goto exit;
4688
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004689 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07004690 then this operation is not permitted (return FAILURE) */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004691 if (sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07004692 hdd_is_okc_mode_enabled(pHddCtx) &&
4693 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
4694 {
4695 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004696 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07004697 " hence this operation is not permitted!", __func__);
4698 ret = -EPERM;
4699 goto exit;
4700 }
4701
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004702 /* Move pointer to ahead of SETCCXMODE<delimiter> */
4703 value = value + 11;
4704 /* Convert the value from ascii to integer */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004705 ret = kstrtou8(value, 10, &eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004706 if (ret < 0)
4707 {
4708 /* If the input value is greater than max value of datatype, then also
4709 kstrtou8 fails */
4710 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4711 "%s: kstrtou8 failed range [%d - %d]", __func__,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004712 CFG_ESE_FEATURE_ENABLED_MIN,
4713 CFG_ESE_FEATURE_ENABLED_MAX);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004714 ret = -EINVAL;
4715 goto exit;
4716 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004717 if ((eseMode < CFG_ESE_FEATURE_ENABLED_MIN) ||
4718 (eseMode > CFG_ESE_FEATURE_ENABLED_MAX))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004719 {
4720 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004721 "Ese mode value %d is out of range"
4722 " (Min: %d Max: %d)", eseMode,
4723 CFG_ESE_FEATURE_ENABLED_MIN,
4724 CFG_ESE_FEATURE_ENABLED_MAX);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004725 ret = -EINVAL;
4726 goto exit;
4727 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004728 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004729 "%s: Received Command to change ese mode = %d", __func__, eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004730
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004731 pHddCtx->cfg_ini->isEseIniFeatureEnabled = eseMode;
4732 sme_UpdateIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal), eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004733 }
4734#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004735 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
4736 {
4737 tANI_U8 *value = command;
4738 tANI_BOOLEAN roamScanControl = 0;
4739
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304740 ret = hdd_drv_cmd_validate(command, 18);
4741 if (ret)
4742 goto exit;
4743
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004744 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
4745 value = value + 19;
4746 /* Convert the value from ascii to integer */
4747 ret = kstrtou8(value, 10, &roamScanControl);
4748 if (ret < 0)
4749 {
4750 /* If the input value is greater than max value of datatype, then also
4751 kstrtou8 fails */
4752 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4753 "%s: kstrtou8 failed ", __func__);
4754 ret = -EINVAL;
4755 goto exit;
4756 }
4757
4758 if (0 != roamScanControl)
4759 {
4760 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4761 "roam scan control invalid value = %d",
4762 roamScanControl);
4763 ret = -EINVAL;
4764 goto exit;
4765 }
4766 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4767 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
4768
4769 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
4770 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004771#ifdef FEATURE_WLAN_OKC
4772 else if (strncmp(command, "SETOKCMODE", 10) == 0)
4773 {
4774 tANI_U8 *value = command;
4775 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
4776
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304777 ret = hdd_drv_cmd_validate(command, 10);
4778 if (ret)
4779 goto exit;
4780
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004781 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07004782 then this operation is not permitted (return FAILURE) */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004783 if (sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07004784 hdd_is_okc_mode_enabled(pHddCtx) &&
4785 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
4786 {
4787 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004788 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07004789 " hence this operation is not permitted!", __func__);
4790 ret = -EPERM;
4791 goto exit;
4792 }
4793
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004794 /* Move pointer to ahead of SETOKCMODE<delimiter> */
4795 value = value + 11;
4796 /* Convert the value from ascii to integer */
4797 ret = kstrtou8(value, 10, &okcMode);
4798 if (ret < 0)
4799 {
4800 /* If the input value is greater than max value of datatype, then also
4801 kstrtou8 fails */
4802 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4803 "%s: kstrtou8 failed range [%d - %d]", __func__,
4804 CFG_OKC_FEATURE_ENABLED_MIN,
4805 CFG_OKC_FEATURE_ENABLED_MAX);
4806 ret = -EINVAL;
4807 goto exit;
4808 }
4809
4810 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
4811 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
4812 {
4813 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4814 "Okc mode value %d is out of range"
4815 " (Min: %d Max: %d)", okcMode,
4816 CFG_OKC_FEATURE_ENABLED_MIN,
4817 CFG_OKC_FEATURE_ENABLED_MAX);
4818 ret = -EINVAL;
4819 goto exit;
4820 }
4821
4822 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4823 "%s: Received Command to change okc mode = %d", __func__, okcMode);
4824
4825 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
4826 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07004827#endif /* FEATURE_WLAN_OKC */
Mahesh A Saptasagarec7d1092015-04-02 13:41:34 +05304828 else if (strncmp(command, "GETROAMSCANCONTROL", 18) == 0)
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004829 {
4830 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
4831 char extra[32];
4832 tANI_U8 len = 0;
4833
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004834 len = scnprintf(extra, sizeof(extra), "%s %d",
4835 command, roamScanControl);
Ratnam Rachuri083ada82015-08-07 14:01:05 +05304836 len = VOS_MIN(priv_data.total_len, len + 1);
4837 if (copy_to_user(priv_data.buf, &extra, len)) {
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004838 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4839 "%s: failed to copy data to user buffer", __func__);
4840 ret = -EFAULT;
4841 goto exit;
4842 }
4843 }
Gopichand Nakkala227c7f32013-06-26 22:44:57 +05304844#ifdef WLAN_FEATURE_PACKET_FILTERING
4845 else if (strncmp(command, "ENABLE_PKTFILTER_IPV6", 21) == 0)
4846 {
4847 tANI_U8 filterType = 0;
4848 tANI_U8 *value = command;
4849
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304850 ret = hdd_drv_cmd_validate(command, 21);
4851 if (ret)
4852 goto exit;
4853
Gopichand Nakkala227c7f32013-06-26 22:44:57 +05304854 /* Move pointer to ahead of ENABLE_PKTFILTER_IPV6<delimiter> */
4855 value = value + 22;
4856
4857 /* Convert the value from ascii to integer */
4858 ret = kstrtou8(value, 10, &filterType);
4859 if (ret < 0)
4860 {
4861 /* If the input value is greater than max value of datatype,
4862 * then also kstrtou8 fails
4863 */
4864 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4865 "%s: kstrtou8 failed range ", __func__);
4866 ret = -EINVAL;
4867 goto exit;
4868 }
4869
4870 if (filterType != 0 && filterType != 1)
4871 {
4872 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4873 "%s: Accepted Values are 0 and 1 ", __func__);
4874 ret = -EINVAL;
4875 goto exit;
4876 }
4877 wlan_hdd_setIPv6Filter(WLAN_HDD_GET_CTX(pAdapter), filterType,
4878 pAdapter->sessionId);
4879 }
4880#endif
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05304881 else if (strncmp(command, "BTCOEXMODE", 10) == 0 )
4882 {
Kiet Lamad161252014-07-22 11:23:32 -07004883 char *dhcpPhase;
Satyanarayana Dash1faea4f2014-09-22 16:21:04 +05304884 int ret;
4885
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304886 ret = hdd_drv_cmd_validate(command, 10);
4887 if (ret)
4888 goto exit;
4889
Kiet Lamad161252014-07-22 11:23:32 -07004890 dhcpPhase = command + 11;
4891 if ('1' == *dhcpPhase)
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05304892 {
Deepthi Gowribfd17132014-11-14 17:59:04 +05304893 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Kiet Lamad161252014-07-22 11:23:32 -07004894 FL("send DHCP START indication"));
c_hpothu9b781ba2013-12-30 20:57:45 +05304895
4896 pHddCtx->btCoexModeSet = TRUE;
Kiet Lamad161252014-07-22 11:23:32 -07004897
Satyanarayana Dash1faea4f2014-09-22 16:21:04 +05304898 ret = wlan_hdd_scan_abort(pAdapter);
4899 if (ret < 0)
4900 {
4901 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4902 FL("failed to abort existing scan %d"), ret);
4903 }
4904
Kiet Lamad161252014-07-22 11:23:32 -07004905 sme_DHCPStartInd(pHddCtx->hHal, pAdapter->device_mode,
4906 pAdapter->sessionId);
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05304907 }
Kiet Lamad161252014-07-22 11:23:32 -07004908 else if ('2' == *dhcpPhase)
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05304909 {
Deepthi Gowribfd17132014-11-14 17:59:04 +05304910 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Kiet Lamad161252014-07-22 11:23:32 -07004911 FL("send DHCP STOP indication"));
c_hpothu9b781ba2013-12-30 20:57:45 +05304912
4913 pHddCtx->btCoexModeSet = FALSE;
Kiet Lamad161252014-07-22 11:23:32 -07004914
4915 sme_DHCPStopInd(pHddCtx->hHal, pAdapter->device_mode,
4916 pAdapter->sessionId);
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05304917 }
4918 }
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07004919 else if (strncmp(command, "SCAN-ACTIVE", 11) == 0)
4920 {
Abhishek Singh58749d62016-02-03 15:27:20 +05304921 hddLog(LOG1,
4922 FL("making default scan to ACTIVE"));
c_hpothudbefd3e2014-04-28 15:59:47 +05304923 pHddCtx->scan_info.scan_mode = eSIR_ACTIVE_SCAN;
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07004924 }
4925 else if (strncmp(command, "SCAN-PASSIVE", 12) == 0)
4926 {
Abhishek Singh58749d62016-02-03 15:27:20 +05304927 hddLog(LOG1,
4928 FL("making default scan to PASSIVE"));
c_hpothudbefd3e2014-04-28 15:59:47 +05304929 pHddCtx->scan_info.scan_mode = eSIR_PASSIVE_SCAN;
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07004930 }
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05304931 else if (strncmp(command, "GETDWELLTIME", 12) == 0)
4932 {
4933 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
4934 char extra[32];
4935 tANI_U8 len = 0;
4936
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05304937 memset(extra, 0, sizeof(extra));
4938 ret = hdd_get_dwell_time(pCfg, command, extra, sizeof(extra), &len);
Ratnam Rachuri12d5d462015-08-07 14:10:23 +05304939 len = VOS_MIN(priv_data.total_len, len + 1);
4940 if (ret != 0 || copy_to_user(priv_data.buf, &extra, len)) {
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05304941 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4942 "%s: failed to copy data to user buffer", __func__);
4943 ret = -EFAULT;
4944 goto exit;
4945 }
4946 ret = len;
4947 }
4948 else if (strncmp(command, "SETDWELLTIME", 12) == 0)
4949 {
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05304950 ret = hdd_set_dwell_time(pAdapter, command);
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05304951 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07004952 else if ( strncasecmp(command, "MIRACAST", 8) == 0 )
4953 {
4954 tANI_U8 filterType = 0;
4955 tANI_U8 *value;
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304956
4957 ret = hdd_drv_cmd_validate(command, 8);
4958 if (ret)
4959 goto exit;
4960
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07004961 value = command + 9;
4962
4963 /* Convert the value from ascii to integer */
4964 ret = kstrtou8(value, 10, &filterType);
4965 if (ret < 0)
4966 {
4967 /* If the input value is greater than max value of datatype,
4968 * then also kstrtou8 fails
4969 */
4970 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4971 "%s: kstrtou8 failed range ", __func__);
4972 ret = -EINVAL;
4973 goto exit;
4974 }
4975 if ((filterType < WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL ) ||
4976 (filterType > WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL))
4977 {
4978 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4979 "%s: Accepted Values are 0 to 2. 0-Disabled, 1-Source,"
4980 " 2-Sink ", __func__);
4981 ret = -EINVAL;
4982 goto exit;
4983 }
4984 //Filtertype value should be either 0-Disabled, 1-Source, 2-sink
4985 pHddCtx->drvr_miracast = filterType;
Kaushik, Sushant96122442014-10-21 16:40:18 +05304986 pScanInfo = &pHddCtx->scan_info;
4987 if (filterType && pScanInfo != NULL &&
4988 pHddCtx->scan_info.mScanPending)
4989 {
4990 /*Miracast Session started. Abort Scan */
4991 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4992 "%s, Aborting Scan For Miracast",__func__);
4993 hdd_abort_mac_scan(pHddCtx, pScanInfo->sessionId,
4994 eCSR_SCAN_ABORT_DEFAULT);
4995 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07004996 hdd_tx_rx_pkt_cnt_stat_timer_handler(pHddCtx);
Ganesh Kondabattini8f6e3b32014-08-25 16:07:54 +05304997 sme_SetMiracastMode(pHddCtx->hHal, pHddCtx->drvr_miracast);
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07004998 }
Leo Chang614d2072013-08-22 14:59:44 -07004999 else if (strncmp(command, "SETMCRATE", 9) == 0)
5000 {
Leo Chang614d2072013-08-22 14:59:44 -07005001 tANI_U8 *value = command;
5002 int targetRate;
Leo Chang1f98cbd2013-10-17 15:03:52 -07005003 tSirRateUpdateInd *rateUpdate;
5004 eHalStatus status;
Leo Chang614d2072013-08-22 14:59:44 -07005005
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05305006 ret = hdd_drv_cmd_validate(command, 9);
5007 if (ret)
5008 goto exit;
5009
Leo Chang614d2072013-08-22 14:59:44 -07005010 /* Only valid for SAP mode */
5011 if (WLAN_HDD_SOFTAP != pAdapter->device_mode)
5012 {
5013 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5014 "%s: SAP mode is not running", __func__);
5015 ret = -EFAULT;
5016 goto exit;
5017 }
5018
5019 /* Move pointer to ahead of SETMCRATE<delimiter> */
5020 /* input value is in units of hundred kbps */
5021 value = value + 10;
5022 /* Convert the value from ascii to integer, decimal base */
5023 ret = kstrtouint(value, 10, &targetRate);
5024
Leo Chang1f98cbd2013-10-17 15:03:52 -07005025 rateUpdate = (tSirRateUpdateInd *)vos_mem_malloc(sizeof(tSirRateUpdateInd));
5026 if (NULL == rateUpdate)
Leo Chang614d2072013-08-22 14:59:44 -07005027 {
Leo Chang1f98cbd2013-10-17 15:03:52 -07005028 hddLog(VOS_TRACE_LEVEL_ERROR,
5029 "%s: SETMCRATE indication alloc fail", __func__);
5030 ret = -EFAULT;
5031 goto exit;
5032 }
5033 vos_mem_zero(rateUpdate, sizeof(tSirRateUpdateInd ));
5034
5035 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5036 "MC Target rate %d", targetRate);
5037 /* Ignore unicast */
5038 rateUpdate->ucastDataRate = -1;
5039 rateUpdate->mcastDataRate24GHz = targetRate;
5040 rateUpdate->mcastDataRate5GHz = targetRate;
5041 rateUpdate->mcastDataRate24GHzTxFlag = 0;
5042 rateUpdate->mcastDataRate5GHzTxFlag = 0;
5043 status = sme_SendRateUpdateInd(pHddCtx->hHal, rateUpdate);
5044 if (eHAL_STATUS_SUCCESS != status)
5045 {
5046 hddLog(VOS_TRACE_LEVEL_ERROR,
5047 "%s: SET_MC_RATE failed", __func__);
5048 vos_mem_free(rateUpdate);
5049 ret = -EFAULT;
5050 goto exit;
Leo Chang614d2072013-08-22 14:59:44 -07005051 }
5052 }
jge35567202017-06-21 16:39:38 +08005053 else if (strncmp(command, "MAXTXPOWER", 10) == 0)
5054 {
5055 int status;
5056 int txPower;
5057 eHalStatus smeStatus;
5058 tANI_U8 *value = command;
5059 tSirMacAddr bssid = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
5060 tSirMacAddr selfMac = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
5061
5062 status = hdd_parse_setmaxtxpower_command(value, &txPower);
5063 if (status)
5064 {
5065 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5066 "Invalid MAXTXPOWER command ");
5067 ret = -EINVAL;
5068 goto exit;
5069 }
5070
5071 hddLog(VOS_TRACE_LEVEL_INFO, "max tx power %d selfMac: "
5072 MAC_ADDRESS_STR " bssId: " MAC_ADDRESS_STR " ",
5073 txPower, MAC_ADDR_ARRAY(selfMac),
5074 MAC_ADDR_ARRAY(bssid));
5075 smeStatus = sme_SetMaxTxPower((tHalHandle)(pHddCtx->hHal),
5076 bssid, selfMac, txPower) ;
5077 if( smeStatus != eHAL_STATUS_SUCCESS )
5078 {
5079 hddLog(VOS_TRACE_LEVEL_ERROR, "%s:Set max tx power failed",
5080 __func__);
5081 ret = -EINVAL;
5082 goto exit;
5083 }
5084
5085 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Set max tx power success",
5086 __func__);
5087 }
Rajeev79dbe4c2013-10-05 11:03:42 +05305088#ifdef FEATURE_WLAN_BATCH_SCAN
Rajeev Kumar8b373292014-01-08 20:36:55 -08005089 else if (strncmp(command, "WLS_BATCHING", 12) == 0)
Rajeev79dbe4c2013-10-05 11:03:42 +05305090 {
Rajeev Kumar8b373292014-01-08 20:36:55 -08005091 ret = hdd_handle_batch_scan_ioctl(pAdapter, &priv_data, command);
Rajeev79dbe4c2013-10-05 11:03:42 +05305092 }
5093#endif
Abhishek Singh00b71972016-01-07 10:51:04 +05305094#ifdef WLAN_FEATURE_RMC
5095 else if ((strncasecmp(command, "SETIBSSBEACONOUIDATA", 20) == 0) &&
5096 (WLAN_HDD_IBSS == pAdapter->device_mode))
5097 {
5098 int i = 0;
5099 tANI_U8 *ibss_ie;
5100 tANI_U32 command_len;
5101 tANI_U8 *value = command;
5102 tHalHandle hHal = pHddCtx->hHal;
5103 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
5104 tANI_U32 ibss_ie_length;
5105 tANI_U32 len, present;
5106 tANI_U8 *addIE;
5107 tANI_U8 *addIEData;
5108
5109 hddLog(LOG1,
5110 FL(" received command %s"),((char *) value));
5111 /* validate argument of command */
5112 if (strlen(value) <= 21)
5113 {
5114 hddLog(LOGE,
5115 FL("No arguements in command length %zu"), strlen(value));
5116 ret = -EFAULT;
5117 goto exit;
5118 }
5119
5120 /* moving to arguments of commands */
5121 value = value + 21;
5122 command_len = strlen(value);
5123
5124 /* oui_data can't be less than 3 bytes */
5125 if (command_len <= (2 * WLAN_HDD_IBSS_MIN_OUI_DATA_LENGTH))
5126 {
5127 hddLog(LOGE,
5128 FL("Invalid SETIBSSBEACONOUIDATA command length %d"),
5129 command_len);
5130 ret = -EFAULT;
5131 goto exit;
5132 }
5133 ibss_ie = vos_mem_malloc(command_len);
5134 if (!ibss_ie) {
5135 hddLog(LOGE,
5136 FL("Could not allocate memory for command length %d"),
5137 command_len);
5138 ret = -ENOMEM;
5139 goto exit;
5140 }
5141 vos_mem_zero(ibss_ie, command_len);
5142
5143 ibss_ie_length = hdd_parse_set_ibss_oui_data_command(value, ibss_ie,
5144 command_len);
5145 if (ibss_ie_length < (2 * WLAN_HDD_IBSS_MIN_OUI_DATA_LENGTH)) {
5146 hddLog(LOGE, FL("Could not parse command %s return length %d"),
5147 value, ibss_ie_length);
5148 ret = -EFAULT;
5149 vos_mem_free(ibss_ie);
5150 goto exit;
5151 }
5152
5153 hddLog(LOG1, FL("ibss_ie length %d ibss_ie:"), ibss_ie_length);
5154 while (i < ibss_ie_length)
5155 hddLog(LOG1, FL("0x%x"), ibss_ie[i++]);
5156
5157 /* Populate Vendor IE in Beacon */
5158 if ((ccmCfgGetInt(hHal,
5159 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
5160 &present)) != eHAL_STATUS_SUCCESS)
5161 {
5162 hddLog(LOGE,
5163 FL("unable to ftch WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG"));
5164 ret = -EFAULT;
5165 vos_mem_free(ibss_ie);
5166 goto exit;
5167 }
5168
5169 addIE = vos_mem_malloc(WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN);
5170 if (!addIE) {
5171 hddLog(LOGE,
5172 FL("Could not allocate memory for command length %d"),
5173 command_len);
5174 vos_mem_free(ibss_ie);
5175 ret = -ENOMEM;
5176 goto exit;
5177 }
5178 vos_mem_zero(addIE, WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN);
5179
5180 if (present)
5181 {
5182 if ((wlan_cfgGetStrLen(pMac,
5183 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, &len)) != eSIR_SUCCESS)
5184 {
5185 hddLog(LOGE,
5186 FL("unable to fetch WNI_CFG_PROBE_RSP_BCN_ADDNIE_LEN"));
5187 ret = -EFAULT;
5188 vos_mem_free(ibss_ie);
5189 vos_mem_free(addIE);
5190 goto exit;
5191 }
5192
5193 if (len <= WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN && len &&
5194 ((len + ibss_ie_length) <=
5195 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN))
5196 {
5197 if ((ccmCfgGetStr(hHal,
5198 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, addIE, &len))
5199 != eHAL_STATUS_SUCCESS)
5200 {
5201 hddLog(LOGE,
5202 FL("unable to fetch WNI_PROBE_RSP_BCN_ADDNIE_DATA"));
5203 ret = -EFAULT;
5204 vos_mem_free(ibss_ie);
5205 vos_mem_free(addIE);
5206 goto exit;
5207 }
5208 else
5209 {
5210 /* Curruntly only WPA IE is added before Vendor IE
5211 * so we can blindly place the Vendor IE after WPA
5212 * IE. If no WPA IE found replace all with Vendor IE.
5213 */
5214 len = hdd_find_ibss_wpa_ie_pos(addIE, len);
5215 }
5216 }
5217 else
5218 {
5219 hddLog(LOGE,
5220 FL("IE len exceed limit len %d,ibss_ie_length %d "),
5221 len, ibss_ie_length);
5222 ret = -EFAULT;
5223 vos_mem_free(addIE);
5224 vos_mem_free(ibss_ie);
5225 goto exit;
5226 }
5227 }
5228 else {
5229 len = 0;
5230 }
5231
5232 vos_mem_copy (addIE + len , ibss_ie, ibss_ie_length);
5233 len += ibss_ie_length;
5234
5235 if (ccmCfgSetStr(hHal,
5236 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, addIE, len, NULL,
5237 eANI_BOOLEAN_FALSE) != eHAL_STATUS_SUCCESS)
5238 {
5239 hddLog(LOGE,
5240 FL("unable to set WNI_CFG_PRBE_RSP_BCN_ADDNIE_DATA"));
5241 ret = -EFAULT;
5242 vos_mem_free(ibss_ie);
5243 vos_mem_free(addIE);
5244 goto exit;
5245 }
5246 vos_mem_free(addIE);
5247 if (ccmCfgSetInt(hHal,
5248 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 1,NULL,
5249 eANI_BOOLEAN_FALSE) != eHAL_STATUS_SUCCESS)
5250 {
5251 hddLog(LOGE,
5252 FL("unble to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG"));
5253 ret = -EFAULT;
5254 vos_mem_free(ibss_ie);
5255 goto exit;
5256 }
5257
5258 /* Populate Vendor IE in probe resp */
5259 if ((ccmCfgGetInt(hHal,
5260 WNI_CFG_PROBE_RSP_ADDNIE_FLAG,
5261 &present)) != eHAL_STATUS_SUCCESS)
5262 {
5263 hddLog(LOGE,
5264 FL("unable to fetch WNI_CFG_PROBE_RSP_ADDNIE_FLAG"));
5265 ret = -EFAULT;
5266 vos_mem_free(ibss_ie);
5267 goto exit;
5268 }
5269
5270 addIEData = vos_mem_malloc(WNI_CFG_PROBE_RSP_ADDNIE_DATA1_LEN);
5271 if (!addIEData) {
5272 hddLog(LOGE,
5273 FL("Could not allocate memory for command length %d"),
5274 command_len);
5275 vos_mem_free(ibss_ie);
5276 ret = -ENOMEM;
5277 goto exit;
5278 }
5279 vos_mem_zero(addIEData, WNI_CFG_PROBE_RSP_ADDNIE_DATA1_LEN);
5280
5281 if (present) {
5282 if (eSIR_SUCCESS != wlan_cfgGetStrLen(pMac,
5283 WNI_CFG_PROBE_RSP_ADDNIE_DATA1, &len)) {
5284 hddLog(LOGE,
5285 FL("unable to fetch WNI_CFG_PROBE_RSP_ADDNIE_DATA1"));
5286 ret = -EFAULT;
5287 vos_mem_free(ibss_ie);
5288 vos_mem_free(addIEData);
5289 goto exit;
5290 }
5291 if (len < WNI_CFG_PROBE_RSP_ADDNIE_DATA1_LEN && len &&
5292 (ibss_ie_length + len) <=
5293 WNI_CFG_PROBE_RSP_ADDNIE_DATA1_LEN) {
5294
5295 if ((ccmCfgGetStr(hHal,
5296 WNI_CFG_PROBE_RSP_ADDNIE_DATA1, addIEData, &len))
5297 != eHAL_STATUS_SUCCESS) {
5298 hddLog(LOGE,
5299 FL("unable fetch WNI_CFG_PROBE_RSP_ADDNIE_DATA1"));
5300 ret = -EFAULT;
5301 vos_mem_free(ibss_ie);
5302 vos_mem_free(addIEData);
5303 goto exit;
5304 }
5305 else {
5306 /* Curruntly only WPA IE is added before Vendor IE
5307 * so we can blindly place the Vendor IE after WPA
5308 * IE. If no WPA IE found replace all with Vendor IE.
5309 */
5310 len = hdd_find_ibss_wpa_ie_pos(addIEData, len);
5311 }
5312 }
5313 else
5314 {
5315 hddLog(LOGE,
5316 FL("IE len exceed limit len %d,ibss_ie_length %d "),
5317 len, ibss_ie_length);
5318 ret = -EFAULT;
5319 vos_mem_free(addIEData);
5320 vos_mem_free(ibss_ie);
5321 goto exit;
5322 }
5323 } /* probe rsp ADD IE present */
5324 else {
5325 /* probe rsp add IE is not present */
5326 len = 0;
5327 }
5328
5329 vos_mem_copy(addIEData +len , ibss_ie, ibss_ie_length);
5330 len += ibss_ie_length;
5331
5332 vos_mem_free(ibss_ie);
5333
5334 if (ccmCfgSetStr(hHal,
5335 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,
5336 (tANI_U8*)(addIEData),
5337 len, NULL,
5338 eANI_BOOLEAN_FALSE)
5339 == eHAL_STATUS_FAILURE) {
5340 hddLog(LOGE,
5341 FL("unable to copy to WNI_CFG_PROBE_RSP_ADDNIE_DATA1"));
5342 ret = -EFAULT;
5343 vos_mem_free(addIEData);
5344 goto exit;
5345 }
5346 vos_mem_free(addIEData);
5347 if (ccmCfgSetInt(WLAN_HDD_GET_HAL_CTX(pAdapter),
5348 WNI_CFG_PROBE_RSP_ADDNIE_FLAG, 1,NULL,
5349 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
5350 {
5351 hddLog(LOGE,
5352 FL("unable to copy WNI_CFG_PROBE_RSP_ADDNIE_FLAG"));
5353 ret = -EFAULT;
5354 goto exit;
5355 }
5356 }
5357 else if (strncasecmp(command, "SETRMCENABLE", 12) == 0)
5358 {
5359 tANI_U8 *value = command;
5360 tANI_U8 ucRmcEnable = 0;
5361 int status;
5362
5363 if ((WLAN_HDD_IBSS != pAdapter->device_mode) &&
5364 (WLAN_HDD_SOFTAP != pAdapter->device_mode))
5365 {
5366 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5367 "Received SETRMCENABLE command in invalid mode %d "
5368 "SETRMCENABLE command is only allowed in IBSS or SOFTAP mode",
5369 pAdapter->device_mode);
5370 ret = -EINVAL;
5371 goto exit;
5372 }
5373
5374 status = hdd_parse_setrmcenable_command(value, &ucRmcEnable);
5375 if (status)
5376 {
5377 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5378 "Invalid SETRMCENABLE command ");
5379 ret = -EINVAL;
5380 goto exit;
5381 }
5382
5383 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5384 "%s: ucRmcEnable %d ", __func__, ucRmcEnable);
5385
5386 if (TRUE == ucRmcEnable)
5387 {
5388 status = sme_EnableRMC( (tHalHandle)(pHddCtx->hHal),
5389 pAdapter->sessionId );
5390 }
5391 else if(FALSE == ucRmcEnable)
5392 {
5393 status = sme_DisableRMC( (tHalHandle)(pHddCtx->hHal),
5394 pAdapter->sessionId );
5395 }
5396 else
5397 {
5398 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5399 "Invalid SETRMCENABLE command %d", ucRmcEnable);
5400 ret = -EINVAL;
5401 goto exit;
5402 }
5403
5404 if (VOS_STATUS_SUCCESS != status)
5405 {
5406 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5407 "%s: SETRMC %d failed status %d", __func__, ucRmcEnable,
5408 status);
5409 ret = -EINVAL;
5410 goto exit;
5411 }
5412 }
5413 else if (strncasecmp(command, "SETRMCACTIONPERIOD", 18) == 0)
5414 {
5415 tANI_U8 *value = command;
5416 tANI_U32 uActionPeriod = 0;
5417 int status;
5418
5419 if ((WLAN_HDD_IBSS != pAdapter->device_mode) &&
5420 (WLAN_HDD_SOFTAP != pAdapter->device_mode))
5421 {
5422 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5423 "Received SETRMC command in invalid mode %d "
5424 "SETRMC command is only allowed in IBSS or SOFTAP mode",
5425 pAdapter->device_mode);
5426 ret = -EINVAL;
5427 goto exit;
5428 }
5429
5430 status = hdd_parse_setrmcactionperiod_command(value, &uActionPeriod);
5431 if (status)
5432 {
5433 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5434 "Invalid SETRMCACTIONPERIOD command ");
5435 ret = -EINVAL;
5436 goto exit;
5437 }
5438
5439 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5440 "%s: uActionPeriod %d ", __func__, uActionPeriod);
5441
5442 if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY,
5443 uActionPeriod, NULL, eANI_BOOLEAN_FALSE))
5444 {
5445 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5446 "%s: Could not set SETRMCACTIONPERIOD %d", __func__, uActionPeriod);
5447 ret = -EINVAL;
5448 goto exit;
5449 }
5450
5451 }
5452 else if (strncasecmp(command, "GETIBSSPEERINFOALL", 18) == 0)
5453 {
5454 /* Peer Info All Command */
5455 int status = eHAL_STATUS_SUCCESS;
5456 hdd_station_ctx_t *pHddStaCtx = NULL;
5457 char *extra = NULL;
5458 int idx = 0, length = 0;
5459 v_MACADDR_t *macAddr;
5460 v_U32_t txRateMbps = 0, numOfBytestoPrint = 0;
5461
5462 if (WLAN_HDD_IBSS == pAdapter->device_mode)
5463 {
5464 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5465 }
5466 else
5467 {
5468 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5469 "%s: pAdapter is not valid for this device mode",
5470 __func__);
5471 ret = -EINVAL;
5472 goto exit;
5473 }
5474
5475 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5476 "%s: Received GETIBSSPEERINFOALL Command", __func__);
5477
5478
5479 /* Handle the command */
5480 status = hdd_cfg80211_get_ibss_peer_info_all(pAdapter);
5481 if (VOS_STATUS_SUCCESS == status)
5482 {
5483 /* The variable extra needed to be allocated on the heap since
5484 * amount of memory required to copy the data for 32 devices
5485 * exceeds the size of 1024 bytes of default stack size. On
5486 * 64 bit devices, the default max stack size of 2048 bytes
5487 */
5488 extra = kmalloc(WLAN_MAX_BUF_SIZE, GFP_KERNEL);
5489
5490 if (NULL == extra)
5491 {
5492 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5493 "%s:kmalloc failed", __func__);
5494 ret = -EINVAL;
5495 goto exit;
5496 }
5497
5498 /* Copy number of stations */
5499 length = scnprintf( extra, WLAN_MAX_BUF_SIZE, "%d ",
5500 pHddStaCtx->ibss_peer_info.numIBSSPeers);
5501 numOfBytestoPrint = length;
5502 for (idx = 0; idx < pHddStaCtx->ibss_peer_info.numIBSSPeers; idx++)
5503 {
5504 macAddr =
5505 hdd_wlan_get_ibss_mac_addr_from_staid(pAdapter,
5506 pHddStaCtx->ibss_peer_info.ibssPeerList[idx].staIdx);
5507 if (NULL != macAddr)
5508 {
5509 txRateMbps =
5510 ((pHddStaCtx->ibss_peer_info.ibssPeerList[idx].txRate)*500*1000)/1000000;
5511
5512 length += scnprintf( (extra + length), WLAN_MAX_BUF_SIZE - length,
5513 "%02x:%02x:%02x:%02x:%02x:%02x %d %d ",
5514 macAddr->bytes[0], macAddr->bytes[1], macAddr->bytes[2],
5515 macAddr->bytes[3], macAddr->bytes[4], macAddr->bytes[5],
5516 (int)txRateMbps,
5517 (int)pHddStaCtx->ibss_peer_info.ibssPeerList[idx].rssi);
5518 }
5519 else
5520 {
5521 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5522 "%s: MAC ADDR is NULL for staIdx: %d", __func__,
5523 pHddStaCtx->ibss_peer_info.ibssPeerList[idx].staIdx);
5524 }
5525
5526 /*
5527 * VOS_TRACE() macro has limitation of 512 bytes for the print
5528 * buffer. Hence printing the data in two chunks. The first chunk
5529 * will have the data for 16 devices and the second chunk will
5530 * have the rest.
5531 */
5532 if (idx < NUM_OF_STA_DATA_TO_PRINT)
5533 {
5534 numOfBytestoPrint = length;
5535 }
5536 }
5537
5538 /*
5539 * Copy the data back into buffer, if the data to copy is
5540 * morethan 512 bytes than we will split the data and do
5541 * it in two shots
5542 */
5543 if (copy_to_user(priv_data.buf, extra, numOfBytestoPrint))
5544 {
5545 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5546 "%s: Copy into user data buffer failed ", __func__);
5547 ret = -EFAULT;
5548 kfree(extra);
5549 goto exit;
5550 }
5551 priv_data.buf[numOfBytestoPrint] = '\0';
5552 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED,
5553 "%s", priv_data.buf);
5554
5555 if (length > numOfBytestoPrint)
5556 {
5557 if (copy_to_user(priv_data.buf + numOfBytestoPrint,
5558 extra + numOfBytestoPrint,
5559 length - numOfBytestoPrint + 1))
5560 {
5561 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5562 "%s: Copy into user data buffer failed ", __func__);
5563 ret = -EFAULT;
5564 kfree(extra);
5565 goto exit;
5566 }
5567 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED,
5568 "%s", &priv_data.buf[numOfBytestoPrint]);
5569 }
5570
5571 /* Free temporary buffer */
5572 kfree(extra);
5573 }
5574
5575 else
5576 {
5577 /* Command failed, log error */
5578 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5579 "%s: GETIBSSPEERINFOALL command failed with status code %d",
5580 __func__, status);
5581 ret = -EINVAL;
5582 goto exit;
5583 }
5584 ret = 0;
5585 }
5586 else if(strncasecmp(command, "GETIBSSPEERINFO", 15) == 0)
5587 {
5588 /* Peer Info <Peer Addr> command */
5589 tANI_U8 *value = command;
5590 VOS_STATUS status;
5591 hdd_station_ctx_t *pHddStaCtx = NULL;
5592 char extra[128] = { 0 };
5593 v_U32_t length = 0;
5594 v_U8_t staIdx = 0;
5595 v_U32_t txRateMbps = 0;
5596 v_MACADDR_t peerMacAddr;
5597
5598 if (WLAN_HDD_IBSS == pAdapter->device_mode)
5599 {
5600 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5601 }
5602 else
5603 {
5604 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5605 "%s: pAdapter is not valid for this device mode",
5606 __func__);
5607 ret = -EINVAL;
5608 goto exit;
5609 }
5610
5611 /* if there are no peers, no need to continue with the command */
5612 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5613 "%s: Received GETIBSSPEERINFO Command", __func__);
5614
5615 if (eConnectionState_IbssConnected != pHddStaCtx->conn_info.connState)
5616 {
5617 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5618 "%s:No IBSS Peers coalesced", __func__);
5619 ret = -EINVAL;
5620 goto exit;
5621 }
5622
5623 /* Parse the incoming command buffer */
5624 status = hdd_parse_get_ibss_peer_info(value, &peerMacAddr);
5625 if (VOS_STATUS_SUCCESS != status)
5626 {
5627 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5628 "%s: Invalid GETIBSSPEERINFO command", __func__);
5629 ret = -EINVAL;
5630 goto exit;
5631 }
5632
5633 /* Get station index for the peer mac address */
5634 hdd_Ibss_GetStaId(pHddStaCtx, &peerMacAddr, &staIdx);
5635
5636 if (staIdx > HDD_MAX_NUM_IBSS_STA)
5637 {
5638 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5639 "%s: Invalid StaIdx %d returned", __func__, staIdx);
5640 ret = -EINVAL;
5641 goto exit;
5642 }
5643
5644 /* Handle the command */
5645 status = hdd_cfg80211_get_ibss_peer_info(pAdapter, staIdx);
5646 if (VOS_STATUS_SUCCESS == status)
5647 {
5648 v_U32_t txRate = pHddStaCtx->ibss_peer_info.ibssPeerList[0].txRate;
5649 txRateMbps = (txRate * 500 * 1000)/1000000;
5650
5651 length = scnprintf( extra, sizeof(extra), "%d %d", (int)txRateMbps,
5652 (int)pHddStaCtx->ibss_peer_info.ibssPeerList[0].rssi);
5653
5654 /* Copy the data back into buffer */
5655 if (copy_to_user(priv_data.buf, &extra, length+ 1))
5656 {
5657 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5658 "%s: copy data to user buffer failed GETIBSSPEERINFO command",
5659 __func__);
5660 ret = -EFAULT;
5661 goto exit;
5662 }
5663 }
5664 else
5665 {
5666 /* Command failed, log error */
5667 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5668 "%s: GETIBSSPEERINFO command failed with status code %d",
5669 __func__, status);
5670 ret = -EINVAL;
5671 goto exit;
5672 }
5673
5674 /* Success ! */
5675 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED,
5676 "%s", priv_data.buf);
5677 ret = 0;
5678 }
5679 else if (strncasecmp(command, "SETRMCTXRATE", 12) == 0)
5680 {
5681 tANI_U8 *value = command;
5682 tANI_U32 uRate = 0;
5683 tTxrateinfoflags txFlags = 0;
5684 tSirRateUpdateInd *rateUpdateParams;
5685 int status;
5686
5687 if ((WLAN_HDD_IBSS != pAdapter->device_mode) &&
5688 (WLAN_HDD_SOFTAP != pAdapter->device_mode))
5689 {
5690 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5691 "Received SETRMCTXRATE command in invalid mode %d "
5692 "SETRMC command is only allowed in IBSS or SOFTAP mode",
5693 pAdapter->device_mode);
5694 ret = -EINVAL;
5695 goto exit;
5696 }
5697
5698 status = hdd_parse_setrmcrate_command(value, &uRate, &txFlags);
5699 if (status)
5700 {
5701 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5702 "Invalid SETRMCTXRATE command ");
5703 ret = -EINVAL;
5704 goto exit;
5705 }
5706
5707 rateUpdateParams = vos_mem_malloc(sizeof(tSirRateUpdateInd));
5708 if (NULL == rateUpdateParams)
5709 {
5710 ret = -EINVAL;
5711 goto exit;
5712 }
5713
5714 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5715 "%s: uRate %d ", __func__, uRate);
5716
5717 vos_mem_zero(rateUpdateParams, sizeof(tSirRateUpdateInd ));
5718
5719 /* -1 implies ignore this param */
5720 rateUpdateParams->ucastDataRate = -1;
5721
5722 /*
5723 * Fill the user specifieed RMC rate param
5724 * and the derived tx flags.
5725 */
5726 rateUpdateParams->rmcDataRate = uRate;
5727 rateUpdateParams->rmcDataRateTxFlag = txFlags;
5728
5729 status = sme_SendRateUpdateInd((tHalHandle)(pHddCtx->hHal), rateUpdateParams);
5730 }
5731 else if (strncasecmp(command, "SETIBSSTXFAILEVENT", 18) == 0 )
5732 {
5733 char *value;
5734 tANI_U8 tx_fail_count = 0;
5735 tANI_U16 pid = 0;
5736
5737 value = command;
5738
5739 ret = hdd_ParseIBSSTXFailEventParams(value, &tx_fail_count, &pid);
5740
5741 if (0 != ret)
5742 {
5743 hddLog(VOS_TRACE_LEVEL_INFO,
5744 "%s: Failed to parse SETIBSSTXFAILEVENT arguments",
5745 __func__);
5746 goto exit;
5747 }
5748
5749 hddLog(VOS_TRACE_LEVEL_INFO, "%s: tx_fail_cnt=%hhu, pid=%hu",
5750 __func__, tx_fail_count, pid);
5751
5752 if (0 == tx_fail_count)
5753 {
5754 // Disable TX Fail Indication
5755 if (eHAL_STATUS_SUCCESS ==
5756 sme_TXFailMonitorStartStopInd(pHddCtx->hHal,
5757 tx_fail_count,
5758 NULL))
5759 {
5760 cesium_pid = 0;
5761 }
5762 else
5763 {
5764 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5765 "%s: failed to disable TX Fail Event ", __func__);
5766 ret = -EINVAL;
5767 }
5768 }
5769 else
5770 {
5771 if (eHAL_STATUS_SUCCESS ==
5772 sme_TXFailMonitorStartStopInd(pHddCtx->hHal,
5773 tx_fail_count,
5774 (void*)hdd_tx_fail_ind_callback))
5775 {
5776 cesium_pid = pid;
5777 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5778 "%s: Registered Cesium pid %u", __func__,
5779 cesium_pid);
5780 }
5781 else
5782 {
5783 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5784 "%s: Failed to enable TX Fail Monitoring", __func__);
5785 ret = -EINVAL;
5786 }
5787 }
5788 }
5789
5790#endif /* WLAN_FEATURE_RMC */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08005791#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07005792 else if (strncmp(command, "SETCCXROAMSCANCHANNELS", 22) == 0)
5793 {
5794 tANI_U8 *value = command;
5795 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
5796 tANI_U8 numChannels = 0;
5797 eHalStatus status = eHAL_STATUS_SUCCESS;
5798
5799 status = hdd_parse_channellist(value, ChannelList, &numChannels);
5800 if (eHAL_STATUS_SUCCESS != status)
5801 {
5802 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5803 "%s: Failed to parse channel list information", __func__);
5804 ret = -EINVAL;
5805 goto exit;
5806 }
5807
5808 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
5809 {
5810 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5811 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
5812 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
5813 ret = -EINVAL;
5814 goto exit;
5815 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08005816 status = sme_SetEseRoamScanChannelList((tHalHandle)(pHddCtx->hHal),
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07005817 ChannelList,
5818 numChannels);
5819 if (eHAL_STATUS_SUCCESS != status)
5820 {
5821 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5822 "%s: Failed to update channel list information", __func__);
5823 ret = -EINVAL;
5824 goto exit;
5825 }
5826 }
5827 else if (strncmp(command, "GETTSMSTATS", 11) == 0)
5828 {
5829 tANI_U8 *value = command;
5830 char extra[128] = {0};
5831 int len = 0;
5832 tANI_U8 tid = 0;
5833 hdd_station_ctx_t *pHddStaCtx = NULL;
5834 tAniTrafStrmMetrics tsmMetrics;
5835 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5836
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05305837 ret = hdd_drv_cmd_validate(command, 11);
5838 if (ret)
5839 goto exit;
5840
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07005841 /* if not associated, return error */
5842 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
5843 {
5844 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:Not associated!",__func__);
5845 ret = -EINVAL;
5846 goto exit;
5847 }
5848
5849 /* Move pointer to ahead of GETTSMSTATS<delimiter> */
5850 value = value + 12;
5851 /* Convert the value from ascii to integer */
5852 ret = kstrtou8(value, 10, &tid);
5853 if (ret < 0)
5854 {
5855 /* If the input value is greater than max value of datatype, then also
5856 kstrtou8 fails */
5857 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5858 "%s: kstrtou8 failed range [%d - %d]", __func__,
5859 TID_MIN_VALUE,
5860 TID_MAX_VALUE);
5861 ret = -EINVAL;
5862 goto exit;
5863 }
5864
5865 if ((tid < TID_MIN_VALUE) || (tid > TID_MAX_VALUE))
5866 {
5867 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5868 "tid value %d is out of range"
5869 " (Min: %d Max: %d)", tid,
5870 TID_MIN_VALUE,
5871 TID_MAX_VALUE);
5872 ret = -EINVAL;
5873 goto exit;
5874 }
5875
5876 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5877 "%s: Received Command to get tsm stats tid = %d", __func__, tid);
5878
5879 if (VOS_STATUS_SUCCESS != hdd_get_tsm_stats(pAdapter, tid, &tsmMetrics))
5880 {
5881 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5882 "%s: failed to get tsm stats", __func__);
5883 ret = -EFAULT;
5884 goto exit;
5885 }
5886
5887 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5888 "UplinkPktQueueDly(%d)\n"
5889 "UplinkPktQueueDlyHist[0](%d)\n"
5890 "UplinkPktQueueDlyHist[1](%d)\n"
5891 "UplinkPktQueueDlyHist[2](%d)\n"
5892 "UplinkPktQueueDlyHist[3](%d)\n"
Arun Kumar Khandavallie8768212014-02-17 16:43:34 +05305893 "UplinkPktTxDly(%u)\n"
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07005894 "UplinkPktLoss(%d)\n"
5895 "UplinkPktCount(%d)\n"
5896 "RoamingCount(%d)\n"
5897 "RoamingDly(%d)", tsmMetrics.UplinkPktQueueDly,
5898 tsmMetrics.UplinkPktQueueDlyHist[0],
5899 tsmMetrics.UplinkPktQueueDlyHist[1],
5900 tsmMetrics.UplinkPktQueueDlyHist[2],
5901 tsmMetrics.UplinkPktQueueDlyHist[3],
5902 tsmMetrics.UplinkPktTxDly, tsmMetrics.UplinkPktLoss,
5903 tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount, tsmMetrics.RoamingDly);
5904
5905 /* Output TSM stats is of the format
5906 GETTSMSTATS [PktQueueDly] [PktQueueDlyHist[0]]:[PktQueueDlyHist[1]] ...[RoamingDly]
5907 eg., GETTSMSTATS 10 1:0:0:161 20 1 17 8 39800 */
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08005908 len = scnprintf(extra, sizeof(extra), "%s %d %d:%d:%d:%d %u %d %d %d %d", command,
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07005909 tsmMetrics.UplinkPktQueueDly, tsmMetrics.UplinkPktQueueDlyHist[0],
5910 tsmMetrics.UplinkPktQueueDlyHist[1], tsmMetrics.UplinkPktQueueDlyHist[2],
5911 tsmMetrics.UplinkPktQueueDlyHist[3], tsmMetrics.UplinkPktTxDly,
5912 tsmMetrics.UplinkPktLoss, tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount,
5913 tsmMetrics.RoamingDly);
5914
Ratnam Rachurid53009c2015-08-07 13:59:00 +05305915 len = VOS_MIN(priv_data.total_len, len + 1);
5916 if (copy_to_user(priv_data.buf, &extra, len)) {
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07005917 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5918 "%s: failed to copy data to user buffer", __func__);
5919 ret = -EFAULT;
5920 goto exit;
5921 }
5922 }
5923 else if (strncmp(command, "SETCCKMIE", 9) == 0)
5924 {
5925 tANI_U8 *value = command;
5926 tANI_U8 *cckmIe = NULL;
5927 tANI_U8 cckmIeLen = 0;
5928 eHalStatus status = eHAL_STATUS_SUCCESS;
5929
5930 status = hdd_parse_get_cckm_ie(value, &cckmIe, &cckmIeLen);
5931 if (eHAL_STATUS_SUCCESS != status)
5932 {
5933 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5934 "%s: Failed to parse cckm ie data", __func__);
5935 ret = -EINVAL;
5936 goto exit;
5937 }
5938
5939 if (cckmIeLen > DOT11F_IE_RSN_MAX_LEN)
5940 {
5941 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5942 "%s: CCKM Ie input length is more than max[%d]", __func__,
5943 DOT11F_IE_RSN_MAX_LEN);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08005944 vos_mem_free(cckmIe);
5945 cckmIe = NULL;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07005946 ret = -EINVAL;
5947 goto exit;
5948 }
5949 sme_SetCCKMIe((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, cckmIe, cckmIeLen);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08005950 vos_mem_free(cckmIe);
5951 cckmIe = NULL;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07005952 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08005953 else if (strncmp(command, "CCXBEACONREQ", 12) == 0)
5954 {
5955 tANI_U8 *value = command;
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08005956 tCsrEseBeaconReq eseBcnReq;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08005957 eHalStatus status = eHAL_STATUS_SUCCESS;
Srinivas Girigowda0c6d7fe2014-05-28 18:18:10 -07005958
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08005959 status = hdd_parse_ese_beacon_req(value, &eseBcnReq);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08005960 if (eHAL_STATUS_SUCCESS != status)
5961 {
5962 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08005963 "%s: Failed to parse ese beacon req", __func__);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08005964 ret = -EINVAL;
5965 goto exit;
5966 }
Srinivas Girigowda0c6d7fe2014-05-28 18:18:10 -07005967 if (!hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))) {
5968 hddLog(VOS_TRACE_LEVEL_INFO, FL("Not associated"));
5969 hdd_indicateEseBcnReportNoResults (pAdapter,
5970 eseBcnReq.bcnReq[0].measurementToken,
5971 0x02, //BIT(1) set for measurement done
5972 0); // no BSS
5973 goto exit;
5974 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08005975
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08005976 status = sme_SetEseBeaconRequest((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, &eseBcnReq);
5977 if (eHAL_STATUS_SUCCESS != status)
5978 {
5979 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5980 "%s: sme_SetEseBeaconRequest failed (%d)", __func__, status);
5981 ret = -EINVAL;
5982 goto exit;
5983 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08005984 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08005985#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
c_hpothu92367912014-05-01 15:18:17 +05305986 else if (strncmp(command, "GETBCNMISSRATE", 14) == 0)
5987 {
5988 eHalStatus status;
5989 char buf[32], len;
5990 long waitRet;
5991 bcnMissRateContext_t getBcnMissRateCtx;
5992
5993 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5994
5995 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
5996 {
5997 hddLog(VOS_TRACE_LEVEL_WARN,
5998 FL("GETBCNMISSRATE: STA is not in connected state"));
5999 ret = -1;
6000 goto exit;
6001 }
6002
6003 init_completion(&(getBcnMissRateCtx.completion));
6004 getBcnMissRateCtx.magic = BCN_MISS_RATE_CONTEXT_MAGIC;
6005
6006 status = sme_getBcnMissRate((tHalHandle)(pHddCtx->hHal),
6007 pAdapter->sessionId,
6008 (void *)getBcnMissRateCB,
6009 (void *)(&getBcnMissRateCtx));
6010 if( eHAL_STATUS_SUCCESS != status)
6011 {
6012 hddLog(VOS_TRACE_LEVEL_INFO,
6013 FL("GETBCNMISSRATE: fail to post WDA cmd"));
6014 ret = -EINVAL;
6015 goto exit;
6016 }
6017
6018 waitRet = wait_for_completion_interruptible_timeout
6019 (&getBcnMissRateCtx.completion, BCN_MISS_RATE_TIME);
6020 if(waitRet <= 0)
6021 {
6022 hddLog(VOS_TRACE_LEVEL_ERROR,
6023 FL("failed to wait on bcnMissRateComp %d"), ret);
6024
6025 //Make magic number to zero so that callback is not called.
6026 spin_lock(&hdd_context_lock);
6027 getBcnMissRateCtx.magic = 0x0;
6028 spin_unlock(&hdd_context_lock);
6029 ret = -EINVAL;
6030 goto exit;
6031 }
6032
6033 hddLog(VOS_TRACE_LEVEL_INFO,
6034 FL("GETBCNMISSRATE: bcnMissRate: %d"), gbcnMissRate);
6035
6036 len = snprintf(buf, sizeof(buf), "GETBCNMISSRATE %d", gbcnMissRate);
6037 if (copy_to_user(priv_data.buf, &buf, len + 1))
6038 {
6039 hddLog(VOS_TRACE_LEVEL_ERROR,
6040 "%s: failed to copy data to user buffer", __func__);
6041 ret = -EFAULT;
6042 goto exit;
6043 }
6044 ret = len;
6045 }
Atul Mittal87ec2422014-09-24 13:12:50 +05306046#ifdef FEATURE_WLAN_TDLS
6047 else if (strncmp(command, "TDLSSECONDARYCHANNELOFFSET", 26) == 0) {
6048 tANI_U8 *value = command;
6049 int set_value;
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05306050
6051 ret = hdd_drv_cmd_validate(command, 26);
6052 if (ret)
6053 goto exit;
6054
Atul Mittal87ec2422014-09-24 13:12:50 +05306055 /* Move pointer to ahead of TDLSOFFCH*/
6056 value += 26;
c_manjeebbc40212015-12-08 13:52:59 +05306057 if (!(sscanf(value, "%d", &set_value))) {
6058 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6059 FL("No input identified"));
6060 ret = -EINVAL;
6061 goto exit;
6062 }
6063
Atul Mittal87ec2422014-09-24 13:12:50 +05306064 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6065 "%s: Tdls offchannel offset:%d",
6066 __func__, set_value);
6067 ret = iw_set_tdlssecoffchanneloffset(pHddCtx, set_value);
6068 if (ret < 0)
6069 {
6070 ret = -EINVAL;
6071 goto exit;
6072 }
6073
6074 } else if (strncmp(command, "TDLSOFFCHANNELMODE", 18) == 0) {
6075 tANI_U8 *value = command;
6076 int set_value;
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05306077
6078 ret = hdd_drv_cmd_validate(command, 18);
6079 if (ret)
6080 goto exit;
6081
Atul Mittal87ec2422014-09-24 13:12:50 +05306082 /* Move pointer to ahead of tdlsoffchnmode*/
6083 value += 18;
c_manjee82323892015-12-08 12:40:34 +05306084 ret = sscanf(value, "%d", &set_value);
6085 if (ret != 1) {
6086 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6087 FL("No input identified"));
6088 ret = -EINVAL;
6089 goto exit;
6090 }
Atul Mittal87ec2422014-09-24 13:12:50 +05306091 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6092 "%s: Tdls offchannel mode:%d",
6093 __func__, set_value);
6094 ret = iw_set_tdlsoffchannelmode(pAdapter, set_value);
6095 if (ret < 0)
6096 {
6097 ret = -EINVAL;
6098 goto exit;
6099 }
6100 } else if (strncmp(command, "TDLSOFFCHANNEL", 14) == 0) {
6101 tANI_U8 *value = command;
6102 int set_value;
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05306103
6104 ret = hdd_drv_cmd_validate(command, 14);
6105 if (ret)
6106 goto exit;
6107
Atul Mittal87ec2422014-09-24 13:12:50 +05306108 /* Move pointer to ahead of TDLSOFFCH*/
6109 value += 14;
c_manjeef6ccaf52015-12-08 11:52:11 +05306110 ret = sscanf(value, "%d", &set_value);
6111 if (ret != 1) {
6112 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6113 "Wrong value is given for hdd_set_tdls_offchannel");
6114 ret = -EINVAL;
6115 goto exit;
6116 }
6117
Atul Mittal87ec2422014-09-24 13:12:50 +05306118 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6119 "%s: Tdls offchannel num: %d",
6120 __func__, set_value);
6121 ret = iw_set_tdlsoffchannel(pHddCtx, set_value);
6122 if (ret < 0)
6123 {
6124 ret = -EINVAL;
6125 goto exit;
6126 }
6127 }
6128#endif
Satyanarayana Dash72806012014-12-02 14:30:08 +05306129 else if (strncmp(command, "GETFWSTATS", 10) == 0)
6130 {
6131 eHalStatus status;
6132 char *buf = NULL;
6133 char len;
6134 long waitRet;
6135 fwStatsContext_t fwStatsCtx;
Abhishek Singh08aa7762014-12-16 13:59:03 +05306136 tSirFwStatsResult *fwStatsRsp = &(pAdapter->fwStatsRsp);
Satyanarayana Dash72806012014-12-02 14:30:08 +05306137 tANI_U8 *ptr = command;
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05306138 int stats;
Satyanarayana Dash72806012014-12-02 14:30:08 +05306139
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05306140 ret = hdd_drv_cmd_validate(command, 10);
6141 if (ret)
6142 goto exit;
6143
6144 stats = *(ptr + 11) - '0';
Satyanarayana Dash72806012014-12-02 14:30:08 +05306145 hddLog(VOS_TRACE_LEVEL_INFO, FL("stats = %d "),stats);
6146 if (!IS_FEATURE_FW_STATS_ENABLE)
6147 {
6148 hddLog(VOS_TRACE_LEVEL_INFO,
6149 FL("Get Firmware stats feature not supported"));
6150 ret = -EINVAL;
6151 goto exit;
6152 }
6153
6154 if (FW_STATS_MAX <= stats || 0 >= stats)
6155 {
6156 hddLog(VOS_TRACE_LEVEL_INFO,
6157 FL(" stats %d not supported"),stats);
6158 ret = -EINVAL;
6159 goto exit;
6160 }
6161
6162 init_completion(&(fwStatsCtx.completion));
6163 fwStatsCtx.magic = FW_STATS_CONTEXT_MAGIC;
6164 fwStatsCtx.pAdapter = pAdapter;
6165 fwStatsRsp->type = 0;
6166 status = sme_GetFwStats( (tHalHandle)pHddCtx->hHal, stats,
Abhishek Singh08aa7762014-12-16 13:59:03 +05306167 &fwStatsCtx, hdd_FWStatisCB);
Satyanarayana Dash72806012014-12-02 14:30:08 +05306168 if (eHAL_STATUS_SUCCESS != status)
6169 {
6170 hddLog(VOS_TRACE_LEVEL_ERROR,
6171 FL(" fail to post WDA cmd status = %d"), status);
6172 ret = -EINVAL;
6173 goto exit;
6174 }
6175 waitRet = wait_for_completion_timeout
6176 (&(fwStatsCtx.completion), FW_STATE_WAIT_TIME);
6177 if (waitRet <= 0)
6178 {
6179 hddLog(VOS_TRACE_LEVEL_ERROR,
6180 FL("failed to wait on GwtFwstats"));
6181 //Make magic number to zero so that callback is not executed.
6182 spin_lock(&hdd_context_lock);
6183 fwStatsCtx.magic = 0x0;
6184 spin_unlock(&hdd_context_lock);
6185 ret = -EINVAL;
6186 goto exit;
6187 }
6188 if (fwStatsRsp->type)
6189 {
6190 buf = kmalloc(FW_STATE_RSP_LEN, GFP_KERNEL);
6191 if (!buf)
6192 {
6193 hddLog(VOS_TRACE_LEVEL_ERROR,
6194 FL(" failed to allocate memory"));
6195 ret = -ENOMEM;
6196 goto exit;
6197 }
6198 switch( fwStatsRsp->type )
6199 {
6200 case FW_UBSP_STATS:
6201 {
6202 len = snprintf(buf, FW_STATE_RSP_LEN,
6203 "GETFWSTATS: ubsp_enter_cnt %d ubsp_jump_ddr_cnt %d",
Abhishek Singh08aa7762014-12-16 13:59:03 +05306204 fwStatsRsp->fwStatsData.ubspStats.ubsp_enter_cnt,
6205 fwStatsRsp->fwStatsData.ubspStats.ubsp_jump_ddr_cnt);
Satyanarayana Dash72806012014-12-02 14:30:08 +05306206 }
6207 break;
6208 default:
6209 {
6210 hddLog(VOS_TRACE_LEVEL_ERROR, FL( "No handling for stats type %d"),fwStatsRsp->type);
6211 ret = -EFAULT;
6212 kfree(buf);
6213 goto exit;
6214 }
6215 }
6216 if (copy_to_user(priv_data.buf, buf, len + 1))
6217 {
6218 hddLog(VOS_TRACE_LEVEL_ERROR,
6219 FL(" failed to copy data to user buffer"));
6220 ret = -EFAULT;
6221 kfree(buf);
6222 goto exit;
6223 }
6224 ret = len;
6225 kfree(buf);
6226 }
6227 else
6228 {
6229 hddLog(VOS_TRACE_LEVEL_ERROR,
6230 FL("failed to fetch the stats"));
6231 ret = -EFAULT;
6232 goto exit;
6233 }
6234
6235 }
Agarwal Ashish8bd53ae2015-06-12 18:03:45 +05306236 else if (strncasecmp(command, "SET_FCC_CHANNEL", 15) == 0)
6237 {
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05306238 ret = hdd_drv_cmd_validate(command, 15);
6239 if (ret)
6240 goto exit;
6241
Agarwal Ashish8bd53ae2015-06-12 18:03:45 +05306242 /*
6243 * this command wld be called by user-space when it detects WLAN
6244 * ON after airplane mode is set. When APM is set, WLAN turns off.
6245 * But it can be turned back on. Otherwise; when APM is turned back
6246 * off, WLAN wld turn back on. So at that point the command is
6247 * expected to come down. 0 means disable, 1 means enable. The
6248 * constraint is removed when parameter 1 is set or different
6249 * country code is set
6250 */
6251 ret = hdd_cmd_setFccChannel(pHddCtx, command, 15);
6252 }
Mahesh A Saptasagarbeca12c2015-09-07 16:21:06 +05306253 else if (strncasecmp(command, "DISABLE_CA_EVENT", 16) == 0)
6254 {
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05306255 ret = hdd_drv_cmd_validate(command, 16);
6256 if (ret)
6257 goto exit;
6258
Mahesh A Saptasagarbeca12c2015-09-07 16:21:06 +05306259 ret = hdd_enable_disable_ca_event(pHddCtx, command, 16);
6260 }
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07006261 else {
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05306262 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
6263 TRACE_CODE_HDD_UNSUPPORTED_IOCTL,
6264 pAdapter->sessionId, 0));
Satyanarayana Dash72806012014-12-02 14:30:08 +05306265 hddLog( VOS_TRACE_LEVEL_WARN, FL("Unsupported GUI command %s"),
6266 command);
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07006267 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006268 }
6269exit:
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05306270 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07006271 if (command)
6272 {
6273 kfree(command);
6274 }
6275 return ret;
6276}
6277
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07006278#ifdef CONFIG_COMPAT
6279static int hdd_driver_compat_ioctl(hdd_adapter_t *pAdapter, struct ifreq *ifr)
6280{
6281 struct {
6282 compat_uptr_t buf;
6283 int used_len;
6284 int total_len;
6285 } compat_priv_data;
6286 hdd_priv_data_t priv_data;
6287 int ret = 0;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006288
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07006289 /*
6290 * Note that pAdapter and ifr have already been verified by caller,
6291 * and HDD context has also been validated
6292 */
6293 if (copy_from_user(&compat_priv_data, ifr->ifr_data,
6294 sizeof(compat_priv_data))) {
6295 ret = -EFAULT;
6296 goto exit;
6297 }
6298 priv_data.buf = compat_ptr(compat_priv_data.buf);
6299 priv_data.used_len = compat_priv_data.used_len;
6300 priv_data.total_len = compat_priv_data.total_len;
6301 ret = hdd_driver_command(pAdapter, &priv_data);
6302 exit:
6303 return ret;
6304}
6305#else /* CONFIG_COMPAT */
6306static int hdd_driver_compat_ioctl(hdd_adapter_t *pAdapter, struct ifreq *ifr)
6307{
6308 /* will never be invoked */
6309 return 0;
6310}
6311#endif /* CONFIG_COMPAT */
6312
6313static int hdd_driver_ioctl(hdd_adapter_t *pAdapter, struct ifreq *ifr)
6314{
6315 hdd_priv_data_t priv_data;
6316 int ret = 0;
6317
6318 /*
6319 * Note that pAdapter and ifr have already been verified by caller,
6320 * and HDD context has also been validated
6321 */
6322 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(priv_data))) {
6323 ret = -EFAULT;
6324 } else {
6325 ret = hdd_driver_command(pAdapter, &priv_data);
6326 }
6327 return ret;
6328}
6329
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05306330int __hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07006331{
6332 hdd_adapter_t *pAdapter;
6333 hdd_context_t *pHddCtx;
6334 int ret;
6335
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05306336 ENTER();
6337
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07006338 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6339 if (NULL == pAdapter) {
6340 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6341 "%s: HDD adapter context is Null", __func__);
6342 ret = -ENODEV;
6343 goto exit;
6344 }
6345 if (dev != pAdapter->dev) {
6346 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6347 "%s: HDD adapter/dev inconsistency", __func__);
6348 ret = -ENODEV;
6349 goto exit;
6350 }
6351
6352 if ((!ifr) || (!ifr->ifr_data)) {
6353 ret = -EINVAL;
6354 goto exit;
6355 }
6356
6357 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6358 ret = wlan_hdd_validate_context(pHddCtx);
6359 if (ret) {
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07006360 ret = -EBUSY;
6361 goto exit;
6362 }
6363
6364 switch (cmd) {
6365 case (SIOCDEVPRIVATE + 1):
6366 if (is_compat_task())
6367 ret = hdd_driver_compat_ioctl(pAdapter, ifr);
6368 else
6369 ret = hdd_driver_ioctl(pAdapter, ifr);
6370 break;
6371 default:
6372 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unknown ioctl %d",
6373 __func__, cmd);
6374 ret = -EINVAL;
6375 break;
6376 }
6377 exit:
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05306378 EXIT();
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07006379 return ret;
6380}
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006381
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05306382int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
6383{
6384 int ret;
6385
6386 vos_ssr_protect(__func__);
6387 ret = __hdd_ioctl(dev, ifr, cmd);
6388 vos_ssr_unprotect(__func__);
6389
6390 return ret;
6391}
6392
Katya Nigame7b69a82015-04-28 15:24:06 +05306393int hdd_mon_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
6394{
6395 return 0;
6396}
6397
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006398#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006399/**---------------------------------------------------------------------------
6400
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006401 \brief hdd_parse_ese_beacon_req() - Parse ese beacon request
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006402
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006403 This function parses the ese beacon request passed in the format
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006404 CCXBEACONREQ<space><Number of fields><space><Measurement token>
6405 <space>Channel 1<space>Scan Mode <space>Meas Duration<space>Channel N
6406 <space>Scan Mode N<space>Meas Duration N
6407 if the Number of bcn req fields (N) does not match with the actual number of fields passed
6408 then take N.
6409 <Meas Token><Channel><Scan Mode> and <Meas Duration> are treated as one pair
6410 For example, CCXBEACONREQ 2 1 1 1 30 2 44 0 40.
6411 This function does not take care of removing duplicate channels from the list
6412
6413 \param - pValue Pointer to data
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006414 \param - pEseBcnReq output pointer to store parsed ie information
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006415
6416 \return - 0 for success non-zero for failure
6417
6418 --------------------------------------------------------------------------*/
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006419static VOS_STATUS hdd_parse_ese_beacon_req(tANI_U8 *pValue,
6420 tCsrEseBeaconReq *pEseBcnReq)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006421{
6422 tANI_U8 *inPtr = pValue;
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306423 uint8_t input = 0;
6424 uint32_t tempInt = 0;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006425 int j = 0, i = 0, v = 0;
6426 char buf[32];
6427
6428 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
6429 /*no argument after the command*/
6430 if (NULL == inPtr)
6431 {
6432 return -EINVAL;
6433 }
6434 /*no space after the command*/
6435 else if (SPACE_ASCII_VALUE != *inPtr)
6436 {
6437 return -EINVAL;
6438 }
6439
6440 /*removing empty spaces*/
6441 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
6442
6443 /*no argument followed by spaces*/
6444 if ('\0' == *inPtr) return -EINVAL;
6445
6446 /*getting the first argument ie measurement token*/
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08006447 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006448 if (1 != v) return -EINVAL;
6449
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306450 v = kstrtos8(buf, 10, &input);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006451 if ( v < 0) return -EINVAL;
6452
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306453 input = VOS_MIN(input, SIR_ESE_MAX_MEAS_IE_REQS);
6454 pEseBcnReq->numBcnReqIe = input;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006455
Srinivas Girigowda725a88e2016-03-31 19:24:25 +05306456 hddLog(LOG1, "Number of Bcn Req Ie fields: %d", pEseBcnReq->numBcnReqIe);
6457
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006458
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006459 for (j = 0; j < (pEseBcnReq->numBcnReqIe); j++)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006460 {
6461 for (i = 0; i < 4; i++)
6462 {
6463 /*inPtr pointing to the beginning of first space after number of ie fields*/
6464 inPtr = strpbrk( inPtr, " " );
6465 /*no ie data after the number of ie fields argument*/
6466 if (NULL == inPtr) return -EINVAL;
6467
6468 /*removing empty space*/
6469 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
6470
6471 /*no ie data after the number of ie fields argument and spaces*/
6472 if ( '\0' == *inPtr ) return -EINVAL;
6473
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08006474 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006475 if (1 != v) return -EINVAL;
6476
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306477 v = kstrtou32(buf, 10, &tempInt);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006478 if (v < 0) return -EINVAL;
6479
6480 switch (i)
6481 {
6482 case 0: /* Measurement token */
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306483 if (!tempInt)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006484 {
6485 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306486 "Invalid Measurement Token: %u", tempInt);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006487 return -EINVAL;
6488 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006489 pEseBcnReq->bcnReq[j].measurementToken = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006490 break;
6491
6492 case 1: /* Channel number */
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306493 if ((!tempInt) ||
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006494 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
6495 {
6496 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306497 "Invalid Channel Number: %u", tempInt);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006498 return -EINVAL;
6499 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006500 pEseBcnReq->bcnReq[j].channel = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006501 break;
6502
6503 case 2: /* Scan mode */
Varun Reddy Yeturu0b18d5a2013-12-04 11:42:23 -08006504 if ((tempInt < eSIR_PASSIVE_SCAN) || (tempInt > eSIR_BEACON_TABLE))
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006505 {
6506 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306507 "Invalid Scan Mode(%u) Expected{0|1|2}", tempInt);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006508 return -EINVAL;
6509 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006510 pEseBcnReq->bcnReq[j].scanMode= tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006511 break;
6512
6513 case 3: /* Measurement duration */
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306514 if (((!tempInt) && (pEseBcnReq->bcnReq[j].scanMode != eSIR_BEACON_TABLE)) ||
6515 ((pEseBcnReq->bcnReq[j].scanMode == eSIR_BEACON_TABLE)))
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006516 {
6517 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306518 "Invalid Measurement Duration: %u", tempInt);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006519 return -EINVAL;
6520 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006521 pEseBcnReq->bcnReq[j].measurementDuration = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006522 break;
6523 }
6524 }
6525 }
6526
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006527 for (j = 0; j < pEseBcnReq->numBcnReqIe; j++)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006528 {
6529 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arun Kumar Khandavallie8768212014-02-17 16:43:34 +05306530 "Index(%d) Measurement Token(%u)Channel(%u) Scan Mode(%u) Measurement Duration(%u)\n",
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006531 j,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006532 pEseBcnReq->bcnReq[j].measurementToken,
6533 pEseBcnReq->bcnReq[j].channel,
6534 pEseBcnReq->bcnReq[j].scanMode,
6535 pEseBcnReq->bcnReq[j].measurementDuration);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006536 }
6537
6538 return VOS_STATUS_SUCCESS;
6539}
6540
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006541static void hdd_GetTsmStatsCB( tAniTrafStrmMetrics tsmMetrics, const tANI_U32 staId, void *pContext )
6542{
6543 struct statsContext *pStatsContext = NULL;
6544 hdd_adapter_t *pAdapter = NULL;
6545
6546 if (NULL == pContext)
6547 {
6548 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnsonc135a9a2017-09-19 08:37:24 -07006549 "%s: Bad param, pContext [%pK]",
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006550 __func__, pContext);
6551 return;
6552 }
6553
Jeff Johnson72a40512013-12-19 10:14:15 -08006554 /* there is a race condition that exists between this callback
6555 function and the caller since the caller could time out either
6556 before or while this code is executing. we use a spinlock to
6557 serialize these actions */
6558 spin_lock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006559
6560 pStatsContext = pContext;
6561 pAdapter = pStatsContext->pAdapter;
6562 if ((NULL == pAdapter) || (STATS_CONTEXT_MAGIC != pStatsContext->magic))
6563 {
6564 /* the caller presumably timed out so there is nothing we can do */
Jeff Johnson72a40512013-12-19 10:14:15 -08006565 spin_unlock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006566 hddLog(VOS_TRACE_LEVEL_WARN,
Jeff Johnsonc135a9a2017-09-19 08:37:24 -07006567 "%s: Invalid context, pAdapter [%pK] magic [%08x]",
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006568 __func__, pAdapter, pStatsContext->magic);
6569 return;
6570 }
6571
Jeff Johnson72a40512013-12-19 10:14:15 -08006572 /* context is valid so caller is still waiting */
6573
6574 /* paranoia: invalidate the magic */
6575 pStatsContext->magic = 0;
6576
6577 /* copy over the tsm stats */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006578 pAdapter->tsmStats.UplinkPktQueueDly = tsmMetrics.UplinkPktQueueDly;
6579 vos_mem_copy(pAdapter->tsmStats.UplinkPktQueueDlyHist,
6580 tsmMetrics.UplinkPktQueueDlyHist,
6581 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
6582 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
6583 pAdapter->tsmStats.UplinkPktTxDly = tsmMetrics.UplinkPktTxDly;
6584 pAdapter->tsmStats.UplinkPktLoss = tsmMetrics.UplinkPktLoss;
6585 pAdapter->tsmStats.UplinkPktCount = tsmMetrics.UplinkPktCount;
6586 pAdapter->tsmStats.RoamingCount = tsmMetrics.RoamingCount;
6587 pAdapter->tsmStats.RoamingDly = tsmMetrics.RoamingDly;
6588
Jeff Johnson72a40512013-12-19 10:14:15 -08006589 /* notify the caller */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006590 complete(&pStatsContext->completion);
Jeff Johnson72a40512013-12-19 10:14:15 -08006591
6592 /* serialization is complete */
6593 spin_unlock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006594}
6595
6596
6597
6598static VOS_STATUS hdd_get_tsm_stats(hdd_adapter_t *pAdapter, const tANI_U8 tid,
6599 tAniTrafStrmMetrics* pTsmMetrics)
6600{
6601 hdd_station_ctx_t *pHddStaCtx = NULL;
6602 eHalStatus hstatus;
Jeff Johnson72a40512013-12-19 10:14:15 -08006603 VOS_STATUS vstatus = VOS_STATUS_SUCCESS;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006604 long lrc;
6605 struct statsContext context;
6606 hdd_context_t *pHddCtx = NULL;
6607
6608 if (NULL == pAdapter)
6609 {
6610 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: pAdapter is NULL", __func__);
6611 return VOS_STATUS_E_FAULT;
6612 }
6613
6614 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6615 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6616
6617 /* we are connected prepare our callback context */
6618 init_completion(&context.completion);
6619 context.pAdapter = pAdapter;
6620 context.magic = STATS_CONTEXT_MAGIC;
6621
6622 /* query tsm stats */
6623 hstatus = sme_GetTsmStats(pHddCtx->hHal, hdd_GetTsmStatsCB,
6624 pHddStaCtx->conn_info.staId[ 0 ],
6625 pHddStaCtx->conn_info.bssId,
6626 &context, pHddCtx->pvosContext, tid);
6627
6628 if (eHAL_STATUS_SUCCESS != hstatus)
6629 {
Jeff Johnson72a40512013-12-19 10:14:15 -08006630 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unable to retrieve statistics",
6631 __func__);
6632 vstatus = VOS_STATUS_E_FAULT;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006633 }
6634 else
6635 {
6636 /* request was sent -- wait for the response */
6637 lrc = wait_for_completion_interruptible_timeout(&context.completion,
6638 msecs_to_jiffies(WLAN_WAIT_TIME_STATS));
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006639 if (lrc <= 0)
6640 {
6641 hddLog(VOS_TRACE_LEVEL_ERROR,
6642 "%s: SME %s while retrieving statistics",
6643 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson72a40512013-12-19 10:14:15 -08006644 vstatus = VOS_STATUS_E_TIMEOUT;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006645 }
6646 }
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006647
Jeff Johnson72a40512013-12-19 10:14:15 -08006648 /* either we never sent a request, we sent a request and received a
6649 response or we sent a request and timed out. if we never sent a
6650 request or if we sent a request and got a response, we want to
6651 clear the magic out of paranoia. if we timed out there is a
6652 race condition such that the callback function could be
6653 executing at the same time we are. of primary concern is if the
6654 callback function had already verified the "magic" but had not
6655 yet set the completion variable when a timeout occurred. we
6656 serialize these activities by invalidating the magic while
6657 holding a shared spinlock which will cause us to block if the
6658 callback is currently executing */
6659 spin_lock(&hdd_context_lock);
6660 context.magic = 0;
6661 spin_unlock(&hdd_context_lock);
6662
6663 if (VOS_STATUS_SUCCESS == vstatus)
6664 {
6665 pTsmMetrics->UplinkPktQueueDly = pAdapter->tsmStats.UplinkPktQueueDly;
6666 vos_mem_copy(pTsmMetrics->UplinkPktQueueDlyHist,
6667 pAdapter->tsmStats.UplinkPktQueueDlyHist,
6668 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
6669 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
6670 pTsmMetrics->UplinkPktTxDly = pAdapter->tsmStats.UplinkPktTxDly;
6671 pTsmMetrics->UplinkPktLoss = pAdapter->tsmStats.UplinkPktLoss;
6672 pTsmMetrics->UplinkPktCount = pAdapter->tsmStats.UplinkPktCount;
6673 pTsmMetrics->RoamingCount = pAdapter->tsmStats.RoamingCount;
6674 pTsmMetrics->RoamingDly = pAdapter->tsmStats.RoamingDly;
6675 }
6676 return vstatus;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006677}
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006678#endif /*FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006679
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006680#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -08006681void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
6682{
6683 eCsrBand band = -1;
6684 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
6685 switch (band)
6686 {
6687 case eCSR_BAND_ALL:
6688 *pBand = WLAN_HDD_UI_BAND_AUTO;
6689 break;
6690
6691 case eCSR_BAND_24:
6692 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
6693 break;
6694
6695 case eCSR_BAND_5G:
6696 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
6697 break;
6698
6699 default:
6700 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
6701 *pBand = -1;
6702 break;
6703 }
6704}
6705
6706/**---------------------------------------------------------------------------
6707
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006708 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
6709
6710 This function parses the send action frame data passed in the format
6711 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
6712
Srinivas Girigowda56076852013-08-20 14:00:50 -07006713 \param - pValue Pointer to input data
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006714 \param - pTargetApBssid Pointer to target Ap bssid
6715 \param - pChannel Pointer to the Target AP channel
6716 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
6717 \param - pBuf Pointer to data
6718 \param - pBufLen Pointer to data length
6719
6720 \return - 0 for success non-zero for failure
6721
6722 --------------------------------------------------------------------------*/
6723VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
6724 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
6725{
6726 tANI_U8 *inPtr = pValue;
6727 tANI_U8 *dataEnd;
6728 int tempInt;
6729 int j = 0;
6730 int i = 0;
6731 int v = 0;
6732 tANI_U8 tempBuf[32];
6733 tANI_U8 tempByte = 0;
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08006734 /* 12 hexa decimal digits, 5 ':' and '\0' */
6735 tANI_U8 macAddress[18];
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006736
6737 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
6738 /*no argument after the command*/
6739 if (NULL == inPtr)
6740 {
6741 return -EINVAL;
6742 }
6743
6744 /*no space after the command*/
6745 else if (SPACE_ASCII_VALUE != *inPtr)
6746 {
6747 return -EINVAL;
6748 }
6749
6750 /*removing empty spaces*/
6751 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
6752
6753 /*no argument followed by spaces*/
6754 if ('\0' == *inPtr)
6755 {
6756 return -EINVAL;
6757 }
6758
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07006759 v = sscanf(inPtr, "%17s", macAddress);
6760 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006761 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07006762 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6763 "Invalid MAC address or All hex inputs are not read (%d)", v);
6764 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006765 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07006766
6767 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
6768 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
6769 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
6770 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
6771 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
6772 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006773
6774 /* point to the next argument */
6775 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
6776 /*no argument after the command*/
6777 if (NULL == inPtr) return -EINVAL;
6778
6779 /*removing empty spaces*/
6780 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
6781
6782 /*no argument followed by spaces*/
6783 if ('\0' == *inPtr)
6784 {
6785 return -EINVAL;
6786 }
6787
6788 /*getting the next argument ie the channel number */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08006789 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07006790 if (1 != v) return -EINVAL;
6791
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006792 v = kstrtos32(tempBuf, 10, &tempInt);
Agarwal Ashish353b3a82014-04-08 14:55:11 +05306793 if ( v < 0 || tempInt <= 0 || tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX )
Kiet Lambe150c22013-11-21 16:30:32 +05306794 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006795
6796 *pChannel = tempInt;
6797
6798 /* point to the next argument */
6799 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
6800 /*no argument after the command*/
6801 if (NULL == inPtr) return -EINVAL;
6802 /*removing empty spaces*/
6803 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
6804
6805 /*no argument followed by spaces*/
6806 if ('\0' == *inPtr)
6807 {
6808 return -EINVAL;
6809 }
6810
6811 /*getting the next argument ie the dwell time */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08006812 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07006813 if (1 != v) return -EINVAL;
6814
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006815 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda5a6e0672014-01-09 14:42:57 -08006816 if ( v < 0 || tempInt < 0) return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006817
6818 *pDwellTime = tempInt;
6819
6820 /* point to the next argument */
6821 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
6822 /*no argument after the command*/
6823 if (NULL == inPtr) return -EINVAL;
6824 /*removing empty spaces*/
6825 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
6826
6827 /*no argument followed by spaces*/
6828 if ('\0' == *inPtr)
6829 {
6830 return -EINVAL;
6831 }
6832
6833 /* find the length of data */
6834 dataEnd = inPtr;
6835 while(('\0' != *dataEnd) )
6836 {
6837 dataEnd++;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006838 }
Kiet Lambe150c22013-11-21 16:30:32 +05306839 *pBufLen = dataEnd - inPtr ;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006840 if ( *pBufLen <= 0) return -EINVAL;
6841
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07006842 /* Allocate the number of bytes based on the number of input characters
6843 whether it is even or odd.
6844 if the number of input characters are even, then we need N/2 byte.
6845 if the number of input characters are odd, then we need do (N+1)/2 to
6846 compensate rounding off.
6847 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
6848 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
6849 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006850 if (NULL == *pBuf)
6851 {
6852 hddLog(VOS_TRACE_LEVEL_FATAL,
6853 "%s: vos_mem_alloc failed ", __func__);
6854 return -EINVAL;
6855 }
6856
6857 /* the buffer received from the upper layer is character buffer,
6858 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
6859 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
6860 and f0 in 3rd location */
6861 for (i = 0, j = 0; j < *pBufLen; j += 2)
6862 {
Kiet Lambe150c22013-11-21 16:30:32 +05306863 if( j+1 == *pBufLen)
6864 {
6865 tempByte = hdd_parse_hex(inPtr[j]);
6866 }
6867 else
6868 {
6869 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
6870 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006871 (*pBuf)[i++] = tempByte;
6872 }
6873 *pBufLen = i;
6874 return VOS_STATUS_SUCCESS;
6875}
6876
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006877/**---------------------------------------------------------------------------
6878
Srinivas Girigowdade697412013-02-14 16:31:48 -08006879 \brief hdd_parse_channellist() - HDD Parse channel list
6880
6881 This function parses the channel list passed in the format
6882 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07006883 if the Number of channels (N) does not match with the actual number of channels passed
6884 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
6885 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
6886 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
6887 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08006888
6889 \param - pValue Pointer to input channel list
6890 \param - ChannelList Pointer to local output array to record channel list
6891 \param - pNumChannels Pointer to number of roam scan channels
6892
6893 \return - 0 for success non-zero for failure
6894
6895 --------------------------------------------------------------------------*/
6896VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
6897{
6898 tANI_U8 *inPtr = pValue;
6899 int tempInt;
6900 int j = 0;
6901 int v = 0;
6902 char buf[32];
6903
6904 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
6905 /*no argument after the command*/
6906 if (NULL == inPtr)
6907 {
6908 return -EINVAL;
6909 }
6910
6911 /*no space after the command*/
6912 else if (SPACE_ASCII_VALUE != *inPtr)
6913 {
6914 return -EINVAL;
6915 }
6916
6917 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07006918 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08006919
6920 /*no argument followed by spaces*/
6921 if ('\0' == *inPtr)
6922 {
6923 return -EINVAL;
6924 }
6925
6926 /*getting the first argument ie the number of channels*/
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08006927 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07006928 if (1 != v) return -EINVAL;
6929
Srinivas Girigowdade697412013-02-14 16:31:48 -08006930 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07006931 if ((v < 0) ||
6932 (tempInt <= 0) ||
6933 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
6934 {
6935 return -EINVAL;
6936 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08006937
6938 *pNumChannels = tempInt;
6939
6940 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
6941 "Number of channels are: %d", *pNumChannels);
6942
6943 for (j = 0; j < (*pNumChannels); j++)
6944 {
6945 /*inPtr pointing to the beginning of first space after number of channels*/
6946 inPtr = strpbrk( inPtr, " " );
6947 /*no channel list after the number of channels argument*/
6948 if (NULL == inPtr)
6949 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07006950 if (0 != j)
6951 {
6952 *pNumChannels = j;
6953 return VOS_STATUS_SUCCESS;
6954 }
6955 else
6956 {
6957 return -EINVAL;
6958 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08006959 }
6960
6961 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07006962 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08006963
6964 /*no channel list after the number of channels argument and spaces*/
6965 if ( '\0' == *inPtr )
6966 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07006967 if (0 != j)
6968 {
6969 *pNumChannels = j;
6970 return VOS_STATUS_SUCCESS;
6971 }
6972 else
6973 {
6974 return -EINVAL;
6975 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08006976 }
6977
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08006978 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07006979 if (1 != v) return -EINVAL;
6980
Srinivas Girigowdade697412013-02-14 16:31:48 -08006981 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07006982 if ((v < 0) ||
6983 (tempInt <= 0) ||
6984 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
6985 {
6986 return -EINVAL;
6987 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08006988 pChannelList[j] = tempInt;
6989
6990 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
6991 "Channel %d added to preferred channel list",
6992 pChannelList[j] );
6993 }
6994
Srinivas Girigowdade697412013-02-14 16:31:48 -08006995 return VOS_STATUS_SUCCESS;
6996}
6997
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07006998
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05306999/**
7000 * hdd_parse_reassoc_command_v1_data() - HDD Parse reassoc command data
7001 * This function parses the reasoc command data passed in the format
7002 * REASSOC<space><bssid><space><channel>
7003 *
7004 * @pValue: Pointer to input data (its a NUL terminated string)
7005 * @pTargetApBssid: Pointer to target Ap bssid
7006 * @pChannel: Pointer to the Target AP channel
7007 *
7008 * Return: 0 for success non-zero for failure
7009 */
7010static int hdd_parse_reassoc_command_v1_data(const tANI_U8 *pValue,
7011 tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07007012{
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05307013 const tANI_U8 *inPtr = pValue;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07007014 int tempInt;
7015 int v = 0;
7016 tANI_U8 tempBuf[32];
Kiet Lamaa8e15a2014-02-11 23:30:06 -08007017 /* 12 hexa decimal digits, 5 ':' and '\0' */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08007018 tANI_U8 macAddress[18];
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07007019
7020 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
7021 /*no argument after the command*/
7022 if (NULL == inPtr)
7023 {
7024 return -EINVAL;
7025 }
7026
7027 /*no space after the command*/
7028 else if (SPACE_ASCII_VALUE != *inPtr)
7029 {
7030 return -EINVAL;
7031 }
7032
7033 /*removing empty spaces*/
7034 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
7035
7036 /*no argument followed by spaces*/
7037 if ('\0' == *inPtr)
7038 {
7039 return -EINVAL;
7040 }
7041
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07007042 v = sscanf(inPtr, "%17s", macAddress);
7043 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07007044 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07007045 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7046 "Invalid MAC address or All hex inputs are not read (%d)", v);
7047 return -EINVAL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07007048 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07007049
7050 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
7051 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
7052 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
7053 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
7054 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
7055 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07007056
7057 /* point to the next argument */
7058 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
7059 /*no argument after the command*/
7060 if (NULL == inPtr) return -EINVAL;
7061
7062 /*removing empty spaces*/
7063 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
7064
7065 /*no argument followed by spaces*/
7066 if ('\0' == *inPtr)
7067 {
7068 return -EINVAL;
7069 }
7070
7071 /*getting the next argument ie the channel number */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08007072 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07007073 if (1 != v) return -EINVAL;
7074
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07007075 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07007076 if ((v < 0) ||
Padma, Santhosh Kumar0fa809b2014-11-13 14:56:56 +05307077 (tempInt < 0) ||
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07007078 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
7079 {
7080 return -EINVAL;
7081 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07007082
7083 *pChannel = tempInt;
7084 return VOS_STATUS_SUCCESS;
7085}
7086
7087#endif
7088
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08007089#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07007090/**---------------------------------------------------------------------------
7091
7092 \brief hdd_parse_get_cckm_ie() - HDD Parse and fetch the CCKM IE
7093
7094 This function parses the SETCCKM IE command
7095 SETCCKMIE<space><ie data>
7096
7097 \param - pValue Pointer to input data
7098 \param - pCckmIe Pointer to output cckm Ie
7099 \param - pCckmIeLen Pointer to output cckm ie length
7100
7101 \return - 0 for success non-zero for failure
7102
7103 --------------------------------------------------------------------------*/
7104VOS_STATUS hdd_parse_get_cckm_ie(tANI_U8 *pValue, tANI_U8 **pCckmIe,
7105 tANI_U8 *pCckmIeLen)
7106{
7107 tANI_U8 *inPtr = pValue;
7108 tANI_U8 *dataEnd;
7109 int j = 0;
7110 int i = 0;
7111 tANI_U8 tempByte = 0;
7112
7113 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
7114 /*no argument after the command*/
7115 if (NULL == inPtr)
7116 {
7117 return -EINVAL;
7118 }
7119
7120 /*no space after the command*/
7121 else if (SPACE_ASCII_VALUE != *inPtr)
7122 {
7123 return -EINVAL;
7124 }
7125
7126 /*removing empty spaces*/
7127 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
7128
7129 /*no argument followed by spaces*/
7130 if ('\0' == *inPtr)
7131 {
7132 return -EINVAL;
7133 }
7134
7135 /* find the length of data */
7136 dataEnd = inPtr;
7137 while(('\0' != *dataEnd) )
7138 {
7139 dataEnd++;
7140 ++(*pCckmIeLen);
7141 }
7142 if ( *pCckmIeLen <= 0) return -EINVAL;
7143
7144 /* Allocate the number of bytes based on the number of input characters
7145 whether it is even or odd.
7146 if the number of input characters are even, then we need N/2 byte.
7147 if the number of input characters are odd, then we need do (N+1)/2 to
7148 compensate rounding off.
7149 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
7150 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
7151 *pCckmIe = vos_mem_malloc((*pCckmIeLen + 1)/2);
7152 if (NULL == *pCckmIe)
7153 {
7154 hddLog(VOS_TRACE_LEVEL_FATAL,
7155 "%s: vos_mem_alloc failed ", __func__);
7156 return -EINVAL;
7157 }
7158 vos_mem_zero(*pCckmIe, (*pCckmIeLen + 1)/2);
7159 /* the buffer received from the upper layer is character buffer,
7160 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
7161 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
7162 and f0 in 3rd location */
7163 for (i = 0, j = 0; j < *pCckmIeLen; j += 2)
7164 {
7165 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
7166 (*pCckmIe)[i++] = tempByte;
7167 }
7168 *pCckmIeLen = i;
7169
7170 return VOS_STATUS_SUCCESS;
7171}
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08007172#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07007173
Jeff Johnson295189b2012-06-20 16:38:30 -07007174/**---------------------------------------------------------------------------
7175
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07007176 \brief hdd_is_valid_mac_address() - Validate MAC address
7177
7178 This function validates whether the given MAC address is valid or not
7179 Expected MAC address is of the format XX:XX:XX:XX:XX:XX
7180 where X is the hexa decimal digit character and separated by ':'
7181 This algorithm works even if MAC address is not separated by ':'
7182
7183 This code checks given input string mac contains exactly 12 hexadecimal digits.
7184 and a separator colon : appears in the input string only after
7185 an even number of hex digits.
7186
7187 \param - pMacAddr pointer to the input MAC address
7188 \return - 1 for valid and 0 for invalid
7189
7190 --------------------------------------------------------------------------*/
7191
7192v_BOOL_t hdd_is_valid_mac_address(const tANI_U8 *pMacAddr)
7193{
7194 int xdigit = 0;
7195 int separator = 0;
7196 while (*pMacAddr)
7197 {
7198 if (isxdigit(*pMacAddr))
7199 {
7200 xdigit++;
7201 }
7202 else if (':' == *pMacAddr)
7203 {
7204 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
7205 break;
7206
7207 ++separator;
7208 }
7209 else
7210 {
7211 separator = -1;
7212 /* Invalid MAC found */
7213 return 0;
7214 }
7215 ++pMacAddr;
7216 }
7217 return (xdigit == 12 && (separator == 5 || separator == 0));
7218}
7219
7220/**---------------------------------------------------------------------------
7221
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307222 \brief __hdd_open() - HDD Open function
Jeff Johnson295189b2012-06-20 16:38:30 -07007223
7224 \param - dev Pointer to net_device structure
7225
7226 \return - 0 for success non-zero for failure
7227
7228 --------------------------------------------------------------------------*/
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307229int __hdd_open(struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07007230{
7231 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7232 hdd_context_t *pHddCtx;
7233 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7234 VOS_STATUS status;
7235 v_BOOL_t in_standby = TRUE;
7236
7237 if (NULL == pAdapter)
7238 {
7239 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Agarwal Ashish971c2882013-10-30 20:11:12 +05307240 "%s: pAdapter is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007241 return -ENODEV;
7242 }
7243
7244 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05307245 MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_OPEN_REQUEST,
7246 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson295189b2012-06-20 16:38:30 -07007247 if (NULL == pHddCtx)
7248 {
7249 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007250 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007251 return -ENODEV;
7252 }
7253
7254 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7255 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
7256 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07007257 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
7258 {
7259 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307260 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07007261 in_standby = FALSE;
7262 break;
7263 }
7264 else
7265 {
7266 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7267 pAdapterNode = pNext;
7268 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007269 }
7270
7271 if (TRUE == in_standby)
7272 {
7273 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
7274 {
7275 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
7276 "wlan out of power save", __func__);
7277 return -EINVAL;
7278 }
7279 }
7280
Jeff Johnson6a81ca42013-04-05 10:37:08 -07007281 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07007282 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
7283 {
7284 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007285 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007286 /* Enable TX queues only when we are connected */
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05307287 hddLog(VOS_TRACE_LEVEL_INFO, FL("Enabling queues"));
Jeff Johnson295189b2012-06-20 16:38:30 -07007288 netif_tx_start_all_queues(dev);
7289 }
7290
7291 return 0;
7292}
7293
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307294/**---------------------------------------------------------------------------
7295
7296 \brief hdd_open() - Wrapper function for __hdd_open to protect it from SSR
7297
7298 This is called in response to ifconfig up
7299
7300 \param - dev Pointer to net_device structure
7301
7302 \return - 0 for success non-zero for failure
7303
7304 --------------------------------------------------------------------------*/
7305int hdd_open(struct net_device *dev)
7306{
7307 int ret;
7308
7309 vos_ssr_protect(__func__);
7310 ret = __hdd_open(dev);
7311 vos_ssr_unprotect(__func__);
7312
7313 return ret;
7314}
7315
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +05307316int __hdd_mon_open (struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07007317{
7318 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05307319 hdd_adapter_t *sta_adapter;
7320 hdd_context_t *hdd_ctx;
Jeff Johnson295189b2012-06-20 16:38:30 -07007321
7322 if(pAdapter == NULL) {
7323 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007324 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007325 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007326 }
7327
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05307328 if (vos_get_concurrency_mode() != VOS_STA_MON)
7329 return 0;
7330
7331 hdd_ctx = WLAN_HDD_GET_CTX(pAdapter);
7332 if (wlan_hdd_validate_context(hdd_ctx))
7333 return -EINVAL;
7334
7335 sta_adapter = hdd_get_adapter(hdd_ctx, WLAN_HDD_INFRA_STATION);
7336 if (!sta_adapter) {
7337 hddLog(LOGE, FL("No valid STA interface"));
7338 return -EINVAL;
7339 }
7340
7341 if (!test_bit(DEVICE_IFACE_OPENED, &sta_adapter->event_flags)) {
7342 hddLog(LOGE, FL("STA Interface is not OPENED"));
7343 return -EINVAL;
7344 }
7345
7346 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
7347
Jeff Johnson295189b2012-06-20 16:38:30 -07007348 return 0;
7349}
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +05307350
7351int hdd_mon_open (struct net_device *dev)
7352{
7353 int ret;
7354
7355 vos_ssr_protect(__func__);
7356 ret = __hdd_mon_open(dev);
7357 vos_ssr_unprotect(__func__);
7358
7359 return ret;
7360}
7361
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05307362int __hdd_mon_stop (struct net_device *dev)
7363{
7364 hdd_adapter_t *mon_adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7365 hdd_context_t *hdd_ctx;
7366
7367 if (vos_get_concurrency_mode() != VOS_STA_MON)
7368 return 0;
7369
7370 if(!mon_adapter) {
7371 hddLog(LOGE, FL("HDD adapter is Null"));
7372 return -EINVAL;
7373 }
7374
7375 hdd_ctx = WLAN_HDD_GET_CTX(mon_adapter);
7376 if (wlan_hdd_validate_context(hdd_ctx))
7377 return -EINVAL;
7378
7379 if (!test_bit(DEVICE_IFACE_OPENED, &mon_adapter->event_flags)) {
7380 hddLog(LOGE, FL("NETDEV Interface is not OPENED"));
7381 return -ENODEV;
7382 }
7383
7384 clear_bit(DEVICE_IFACE_OPENED, &mon_adapter->event_flags);
7385 hdd_stop_adapter(hdd_ctx, mon_adapter, VOS_FALSE);
7386
7387 return 0;
7388}
7389
Katya Nigame7b69a82015-04-28 15:24:06 +05307390int hdd_mon_stop(struct net_device *dev)
7391{
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05307392 int ret;
7393
7394 vos_ssr_protect(__func__);
7395 ret = __hdd_mon_stop(dev);
7396 vos_ssr_unprotect(__func__);
7397
7398 return ret;
Katya Nigame7b69a82015-04-28 15:24:06 +05307399}
7400
Jeff Johnson295189b2012-06-20 16:38:30 -07007401/**---------------------------------------------------------------------------
7402
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307403 \brief __hdd_stop() - HDD stop function
Jeff Johnson295189b2012-06-20 16:38:30 -07007404
7405 \param - dev Pointer to net_device structure
7406
7407 \return - 0 for success non-zero for failure
7408
7409 --------------------------------------------------------------------------*/
7410
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307411int __hdd_stop (struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07007412{
Vinay Krishna Eranna90f43532014-10-27 16:45:54 +05307413 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07007414 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7415 hdd_context_t *pHddCtx;
7416 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7417 VOS_STATUS status;
7418 v_BOOL_t enter_standby = TRUE;
7419
7420 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07007421 if (NULL == pAdapter)
7422 {
7423 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Agarwal Ashish971c2882013-10-30 20:11:12 +05307424 "%s: pAdapter is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007425 return -ENODEV;
7426 }
Sachin Ahuja9b4958f2015-01-15 21:37:00 +05307427 MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_STOP_REQUEST,
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05307428 pAdapter->sessionId, pAdapter->device_mode));
Vinay Krishna Eranna90f43532014-10-27 16:45:54 +05307429
7430 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7431 ret = wlan_hdd_validate_context(pHddCtx);
7432 if (ret)
Jeff Johnson295189b2012-06-20 16:38:30 -07007433 {
Vinay Krishna Eranna90f43532014-10-27 16:45:54 +05307434 return ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07007435 }
7436
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307437 /* Nothing to be done if the interface is not opened */
7438 if (VOS_FALSE == test_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags))
7439 {
7440 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7441 "%s: NETDEV Interface is not OPENED", __func__);
7442 return -ENODEV;
7443 }
7444
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05307445 if (pHddCtx->concurrency_mode == VOS_STA_MON) {
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05307446 /*
Rajeev Kumar Sirasanagandlaa74e1222018-01-09 17:38:55 +05307447 * In STA + Monitor mode concurrency, no point in running
7448 * capture on monitor interface, when STA interface is stopped
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05307449 */
Rajeev Kumar Sirasanagandlaa74e1222018-01-09 17:38:55 +05307450 wlan_hdd_stop_mon(pHddCtx, true);
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05307451 }
7452
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307453 /* Make sure the interface is marked as closed */
Jeff Johnson6a81ca42013-04-05 10:37:08 -07007454 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07007455 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307456
7457 /* Disable TX on the interface, after this hard_start_xmit() will not
7458 * be called on that interface
7459 */
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05307460 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
Jeff Johnson295189b2012-06-20 16:38:30 -07007461 netif_tx_disable(pAdapter->dev);
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307462
7463 /* Mark the interface status as "down" for outside world */
Jeff Johnson295189b2012-06-20 16:38:30 -07007464 netif_carrier_off(pAdapter->dev);
7465
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307466 /* The interface is marked as down for outside world (aka kernel)
7467 * But the driver is pretty much alive inside. The driver needs to
7468 * tear down the existing connection on the netdev (session)
7469 * cleanup the data pipes and wait until the control plane is stabilized
7470 * for this interface. The call also needs to wait until the above
7471 * mentioned actions are completed before returning to the caller.
7472 * Notice that the hdd_stop_adapter is requested not to close the session
7473 * That is intentional to be able to scan if it is a STA/P2P interface
7474 */
7475 hdd_stop_adapter(pHddCtx, pAdapter, VOS_FALSE);
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05307476#ifdef FEATURE_WLAN_TDLS
7477 mutex_lock(&pHddCtx->tdls_lock);
7478#endif
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307479 /* DeInit the adapter. This ensures datapath cleanup as well */
c_hpothu002231a2015-02-05 14:58:51 +05307480 hdd_deinit_adapter(pHddCtx, pAdapter, TRUE);
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05307481#ifdef FEATURE_WLAN_TDLS
7482 mutex_unlock(&pHddCtx->tdls_lock);
7483#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007484 /* SoftAP ifaces should never go in power save mode
7485 making sure same here. */
7486 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07007487 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07007488 )
7489 {
7490 /* SoftAP mode, so return from here */
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307491 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
7492 "%s: In SAP MODE", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007493 EXIT();
7494 return 0;
7495 }
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307496 /* Find if any iface is up. If any iface is up then can't put device to
7497 * sleep/power save mode
7498 */
Jeff Johnson295189b2012-06-20 16:38:30 -07007499 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7500 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
7501 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07007502 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
7503 {
7504 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307505 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07007506 enter_standby = FALSE;
7507 break;
7508 }
7509 else
7510 {
7511 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7512 pAdapterNode = pNext;
7513 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007514 }
7515
7516 if (TRUE == enter_standby)
7517 {
7518 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
7519 "entering standby", __func__);
7520 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
7521 {
7522 /*log and return success*/
7523 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
7524 "wlan in power save", __func__);
7525 }
7526 }
7527
7528 EXIT();
7529 return 0;
7530}
7531
7532/**---------------------------------------------------------------------------
7533
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307534 \brief hdd_stop() - wrapper_function for __hdd_stop to protect it from SSR
Jeff Johnson295189b2012-06-20 16:38:30 -07007535
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307536 This is called in response to ifconfig down
7537
7538 \param - dev Pointer to net_device structure
7539
7540 \return - 0 for success non-zero for failure
7541-----------------------------------------------------------------------------*/
7542int hdd_stop (struct net_device *dev)
7543{
7544 int ret;
7545
7546 vos_ssr_protect(__func__);
7547 ret = __hdd_stop(dev);
7548 vos_ssr_unprotect(__func__);
7549
7550 return ret;
7551}
7552
7553/**---------------------------------------------------------------------------
7554
7555 \brief __hdd_uninit() - HDD uninit function
Jeff Johnson295189b2012-06-20 16:38:30 -07007556
7557 \param - dev Pointer to net_device structure
7558
7559 \return - void
7560
7561 --------------------------------------------------------------------------*/
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307562static void __hdd_uninit (struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07007563{
7564 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05307565 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07007566 ENTER();
7567
7568 do
7569 {
7570 if (NULL == pAdapter)
7571 {
7572 hddLog(VOS_TRACE_LEVEL_FATAL,
7573 "%s: NULL pAdapter", __func__);
7574 break;
7575 }
7576
7577 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
7578 {
7579 hddLog(VOS_TRACE_LEVEL_FATAL,
7580 "%s: Invalid magic", __func__);
7581 break;
7582 }
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05307583 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7584 if (NULL == pHddCtx)
Jeff Johnson295189b2012-06-20 16:38:30 -07007585 {
7586 hddLog(VOS_TRACE_LEVEL_FATAL,
7587 "%s: NULL pHddCtx", __func__);
7588 break;
7589 }
7590
7591 if (dev != pAdapter->dev)
7592 {
7593 hddLog(VOS_TRACE_LEVEL_FATAL,
7594 "%s: Invalid device reference", __func__);
7595 /* we haven't validated all cases so let this go for now */
7596 }
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05307597#ifdef FEATURE_WLAN_TDLS
7598 mutex_lock(&pHddCtx->tdls_lock);
7599#endif
c_hpothu002231a2015-02-05 14:58:51 +05307600 hdd_deinit_adapter(pHddCtx, pAdapter, TRUE);
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05307601#ifdef FEATURE_WLAN_TDLS
7602 mutex_unlock(&pHddCtx->tdls_lock);
7603#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007604
7605 /* after uninit our adapter structure will no longer be valid */
7606 pAdapter->dev = NULL;
7607 pAdapter->magic = 0;
Manjeet Singh47ee8472016-04-11 11:57:18 +05307608 pAdapter->pHddCtx = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007609 } while (0);
7610
7611 EXIT();
7612}
7613
7614/**---------------------------------------------------------------------------
7615
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307616 \brief hdd_uninit() - Wrapper function to protect __hdd_uninit from SSR
7617
7618 This is called during the netdev unregister to uninitialize all data
7619associated with the device
7620
7621 \param - dev Pointer to net_device structure
7622
7623 \return - void
7624
7625 --------------------------------------------------------------------------*/
7626static void hdd_uninit (struct net_device *dev)
7627{
7628 vos_ssr_protect(__func__);
7629 __hdd_uninit(dev);
7630 vos_ssr_unprotect(__func__);
7631}
7632
7633/**---------------------------------------------------------------------------
7634
Jeff Johnson295189b2012-06-20 16:38:30 -07007635 \brief hdd_release_firmware() -
7636
7637 This function calls the release firmware API to free the firmware buffer.
7638
7639 \param - pFileName Pointer to the File Name.
7640 pCtx - Pointer to the adapter .
7641
7642
7643 \return - 0 for success, non zero for failure
7644
7645 --------------------------------------------------------------------------*/
7646
7647VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
7648{
7649 VOS_STATUS status = VOS_STATUS_SUCCESS;
7650 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
7651 ENTER();
7652
7653
7654 if (!strcmp(WLAN_FW_FILE, pFileName)) {
7655
7656 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
7657
7658 if(pHddCtx->fw) {
7659 release_firmware(pHddCtx->fw);
7660 pHddCtx->fw = NULL;
7661 }
7662 else
7663 status = VOS_STATUS_E_FAILURE;
7664 }
7665 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
7666 if(pHddCtx->nv) {
7667 release_firmware(pHddCtx->nv);
7668 pHddCtx->nv = NULL;
7669 }
7670 else
7671 status = VOS_STATUS_E_FAILURE;
7672
7673 }
7674
7675 EXIT();
7676 return status;
7677}
7678
7679/**---------------------------------------------------------------------------
7680
7681 \brief hdd_request_firmware() -
7682
7683 This function reads the firmware file using the request firmware
7684 API and returns the the firmware data and the firmware file size.
7685
7686 \param - pfileName - Pointer to the file name.
7687 - pCtx - Pointer to the adapter .
7688 - ppfw_data - Pointer to the pointer of the firmware data.
7689 - pSize - Pointer to the file size.
7690
7691 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
7692
7693 --------------------------------------------------------------------------*/
7694
7695
7696VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
7697{
7698 int status;
7699 VOS_STATUS retval = VOS_STATUS_SUCCESS;
7700 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
7701 ENTER();
7702
7703 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
7704
7705 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
7706
7707 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
7708 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
7709 __func__, pfileName);
7710 retval = VOS_STATUS_E_FAILURE;
7711 }
7712
7713 else {
7714 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
7715 *pSize = pHddCtx->fw->size;
7716 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
7717 __func__, *pSize);
7718 }
7719 }
7720 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
7721
7722 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
7723
7724 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
7725 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
7726 __func__, pfileName);
7727 retval = VOS_STATUS_E_FAILURE;
7728 }
7729
7730 else {
7731 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
7732 *pSize = pHddCtx->nv->size;
7733 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
7734 __func__, *pSize);
7735 }
7736 }
7737
7738 EXIT();
7739 return retval;
7740}
7741/**---------------------------------------------------------------------------
7742 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
7743
7744 This is the function invoked by SME to inform the result of a full power
7745 request issued by HDD
7746
7747 \param - callbackcontext - Pointer to cookie
7748 status - result of request
7749
7750 \return - None
7751
7752--------------------------------------------------------------------------*/
7753void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
7754{
7755 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
7756
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07007757 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07007758 if(&pHddCtx->full_pwr_comp_var)
7759 {
7760 complete(&pHddCtx->full_pwr_comp_var);
7761 }
7762}
7763
Abhishek Singh00b71972016-01-07 10:51:04 +05307764#ifdef WLAN_FEATURE_RMC
7765static void hdd_tx_fail_ind_callback(v_U8_t *MacAddr, v_U8_t seqNo)
7766{
7767 int payload_len;
7768 struct sk_buff *skb;
7769 struct nlmsghdr *nlh;
7770 v_U8_t *data;
7771
7772 payload_len = ETH_ALEN;
7773
7774 if (0 == cesium_pid)
7775 {
7776 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: cesium process not registered",
7777 __func__);
7778 return;
7779 }
7780
7781 if ((skb = nlmsg_new(payload_len,GFP_ATOMIC)) == NULL)
7782 {
7783 hddLog(VOS_TRACE_LEVEL_ERROR,
7784 "%s: nlmsg_new() failed for msg size[%d]",
7785 __func__, NLMSG_SPACE(payload_len));
7786 return;
7787 }
7788
7789 nlh = nlmsg_put(skb, cesium_pid, seqNo, 0, payload_len, NLM_F_REQUEST);
7790
7791 if (NULL == nlh)
7792 {
7793 hddLog(VOS_TRACE_LEVEL_ERROR,
7794 "%s: nlmsg_put() failed for msg size[%d]",
7795 __func__, NLMSG_SPACE(payload_len));
7796
7797 kfree_skb(skb);
7798 return;
7799 }
7800
7801 data = nlmsg_data(nlh);
7802 memcpy(data, MacAddr, ETH_ALEN);
7803
7804 if (nlmsg_unicast(cesium_nl_srv_sock, skb, cesium_pid) < 0)
7805 {
7806 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: nlmsg_unicast() failed for msg size[%d]",
7807 __func__, NLMSG_SPACE(payload_len));
7808 }
7809
7810 return;
7811}
7812
7813/**---------------------------------------------------------------------------
7814 \brief hdd_ParseuserParams - return a pointer to the next argument
7815
7816 \return - status
7817
7818--------------------------------------------------------------------------*/
7819static int hdd_ParseUserParams(tANI_U8 *pValue, tANI_U8 **ppArg)
7820{
7821 tANI_U8 *pVal;
7822
7823 pVal = strchr(pValue, ' ');
7824
7825 if (NULL == pVal)
7826 {
7827 /* no argument remains */
7828 return -EINVAL;
7829 }
7830 else if (SPACE_ASCII_VALUE != *pVal)
7831 {
7832 /* no space after the current argument */
7833 return -EINVAL;
7834 }
7835
7836 pVal++;
7837
7838 /* remove empty spaces */
7839 while ((SPACE_ASCII_VALUE == *pVal) && ('\0' != *pVal))
7840 {
7841 pVal++;
7842 }
7843
7844 /* no argument followed by spaces */
7845 if ('\0' == *pVal)
7846 {
7847 return -EINVAL;
7848 }
7849
7850 *ppArg = pVal;
7851
7852 return 0;
7853}
7854
7855/**----------------------------------------------------------------------------
7856 \brief hdd_ParseIBSSTXFailEventParams - Parse params for SETIBSSTXFAILEVENT
7857
7858 \return - status
7859
7860------------------------------------------------------------------------------*/
7861static int hdd_ParseIBSSTXFailEventParams(tANI_U8 *pValue,
7862 tANI_U8 *tx_fail_count,
7863 tANI_U16 *pid)
7864{
7865 tANI_U8 *param = NULL;
7866 int ret;
7867
7868 ret = hdd_ParseUserParams(pValue, &param);
7869
7870 if (0 == ret && NULL != param)
7871 {
7872 if (1 != sscanf(param, "%hhu", tx_fail_count))
7873 {
7874 ret = -EINVAL;
7875 goto done;
7876 }
7877 }
7878 else
7879 {
7880 goto done;
7881 }
7882
7883 if (0 == *tx_fail_count)
7884 {
7885 *pid = 0;
7886 goto done;
7887 }
7888
7889 pValue = param;
7890 pValue++;
7891
7892 ret = hdd_ParseUserParams(pValue, &param);
7893
7894 if (0 == ret)
7895 {
7896 if (1 != sscanf(param, "%hu", pid))
7897 {
7898 ret = -EINVAL;
7899 goto done;
7900 }
7901 }
7902 else
7903 {
7904 goto done;
7905 }
7906
7907done:
7908 return ret;
7909}
7910
7911static int hdd_open_cesium_nl_sock()
7912{
7913#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
7914 struct netlink_kernel_cfg cfg = {
7915 .groups = WLAN_NLINK_MCAST_GRP_ID,
7916 .input = NULL
7917 };
7918#endif
7919 int ret = 0;
7920
7921#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
7922 cesium_nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_CESIUM,
7923#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0))
7924 THIS_MODULE,
7925#endif
7926 &cfg);
7927#else
7928 cesium_nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_CESIUM,
7929 WLAN_NLINK_MCAST_GRP_ID, NULL, NULL, THIS_MODULE);
7930#endif
7931
7932 if (cesium_nl_srv_sock == NULL)
7933 {
7934 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7935 "NLINK: cesium netlink_kernel_create failed");
7936 ret = -ECONNREFUSED;
7937 }
7938
7939 return ret;
7940}
7941
7942static void hdd_close_cesium_nl_sock()
7943{
7944 if (NULL != cesium_nl_srv_sock)
7945 {
7946 netlink_kernel_release(cesium_nl_srv_sock);
7947 cesium_nl_srv_sock = NULL;
7948 }
7949}
7950#endif /* WLAN_FEATURE_RMC */
Jeff Johnson295189b2012-06-20 16:38:30 -07007951/**---------------------------------------------------------------------------
7952
7953 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
7954
7955 This is the function invoked by SME to inform the result of BMPS
7956 request issued by HDD
7957
7958 \param - callbackcontext - Pointer to cookie
7959 status - result of request
7960
7961 \return - None
7962
7963--------------------------------------------------------------------------*/
7964void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
7965{
7966
7967 struct completion *completion_var = (struct completion*) callbackContext;
7968
Arif Hussain6d2a3322013-11-17 19:50:10 -08007969 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07007970 if(completion_var != NULL)
7971 {
7972 complete(completion_var);
7973 }
7974}
7975
7976/**---------------------------------------------------------------------------
7977
7978 \brief hdd_get_cfg_file_size() -
7979
7980 This function reads the configuration file using the request firmware
7981 API and returns the configuration file size.
7982
7983 \param - pCtx - Pointer to the adapter .
7984 - pFileName - Pointer to the file name.
7985 - pBufSize - Pointer to the buffer size.
7986
7987 \return - 0 for success, non zero for failure
7988
7989 --------------------------------------------------------------------------*/
7990
7991VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
7992{
7993 int status;
7994 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
7995
7996 ENTER();
7997
7998 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
7999
8000 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
8001 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
8002 status = VOS_STATUS_E_FAILURE;
8003 }
8004 else {
8005 *pBufSize = pHddCtx->fw->size;
8006 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
8007 release_firmware(pHddCtx->fw);
8008 pHddCtx->fw = NULL;
8009 }
8010
8011 EXIT();
8012 return VOS_STATUS_SUCCESS;
8013}
8014
8015/**---------------------------------------------------------------------------
8016
8017 \brief hdd_read_cfg_file() -
8018
8019 This function reads the configuration file using the request firmware
8020 API and returns the cfg data and the buffer size of the configuration file.
8021
8022 \param - pCtx - Pointer to the adapter .
8023 - pFileName - Pointer to the file name.
8024 - pBuffer - Pointer to the data buffer.
8025 - pBufSize - Pointer to the buffer size.
8026
8027 \return - 0 for success, non zero for failure
8028
8029 --------------------------------------------------------------------------*/
8030
8031VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
8032 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
8033{
8034 int status;
8035 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
8036
8037 ENTER();
8038
8039 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
8040
8041 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
8042 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
8043 return VOS_STATUS_E_FAILURE;
8044 }
8045 else {
8046 if(*pBufSize != pHddCtx->fw->size) {
8047 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
8048 "file size", __func__);
8049 release_firmware(pHddCtx->fw);
8050 pHddCtx->fw = NULL;
8051 return VOS_STATUS_E_FAILURE;
8052 }
8053 else {
8054 if(pBuffer) {
8055 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
8056 }
8057 release_firmware(pHddCtx->fw);
8058 pHddCtx->fw = NULL;
8059 }
8060 }
8061
8062 EXIT();
8063
8064 return VOS_STATUS_SUCCESS;
8065}
8066
8067/**---------------------------------------------------------------------------
8068
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05308069 \brief __hdd_set_mac_address() -
Jeff Johnson295189b2012-06-20 16:38:30 -07008070
8071 This function sets the user specified mac address using
8072 the command ifconfig wlanX hw ether <mac adress>.
8073
8074 \param - dev - Pointer to the net device.
8075 - addr - Pointer to the sockaddr.
8076 \return - 0 for success, non zero for failure
8077
8078 --------------------------------------------------------------------------*/
8079
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05308080static int __hdd_set_mac_address(struct net_device *dev, void *addr)
Jeff Johnson295189b2012-06-20 16:38:30 -07008081{
Mahesh A Saptasagar74088392015-02-05 17:22:09 +05308082 hdd_adapter_t *pAdapter;
8083 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07008084 struct sockaddr *psta_mac_addr = addr;
8085 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
Mahesh A Saptasagar74088392015-02-05 17:22:09 +05308086 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07008087
8088 ENTER();
Mahesh A Saptasagar74088392015-02-05 17:22:09 +05308089 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
8090 if (NULL == pAdapter)
8091 {
8092 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8093 "%s: Adapter is NULL",__func__);
8094 return -EINVAL;
8095 }
8096 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
8097 ret = wlan_hdd_validate_context(pHddCtx);
8098 if (0 != ret)
8099 {
Mahesh A Saptasagar74088392015-02-05 17:22:09 +05308100 return ret;
8101 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008102
8103 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
Jeff Johnson295189b2012-06-20 16:38:30 -07008104 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
8105
8106 EXIT();
8107 return halStatus;
8108}
8109
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05308110/**---------------------------------------------------------------------------
8111
8112 \brief hdd_set_mac_address() -
8113
8114 Wrapper function to protect __hdd_set_mac_address() function from ssr
8115
8116 \param - dev - Pointer to the net device.
8117 - addr - Pointer to the sockaddr.
8118 \return - 0 for success, non zero for failure
8119
8120 --------------------------------------------------------------------------*/
8121static int hdd_set_mac_address(struct net_device *dev, void *addr)
8122{
8123 int ret;
8124
8125 vos_ssr_protect(__func__);
8126 ret = __hdd_set_mac_address(dev, addr);
8127 vos_ssr_unprotect(__func__);
8128
8129 return ret;
8130}
8131
Jeff Johnson295189b2012-06-20 16:38:30 -07008132tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
8133{
8134 int i;
8135 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
8136 {
Abhishek Singheb183782014-02-06 13:37:21 +05308137 if( 0 == ((pHddCtx->cfg_ini->intfAddrMask) & (1 << i)) )
Jeff Johnson295189b2012-06-20 16:38:30 -07008138 break;
8139 }
8140
8141 if( VOS_MAX_CONCURRENCY_PERSONA == i)
8142 return NULL;
8143
8144 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
8145 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
8146}
8147
8148void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
8149{
8150 int i;
8151 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
8152 {
8153 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
8154 {
8155 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
8156 break;
8157 }
8158 }
8159 return;
8160}
8161
8162#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
8163 static struct net_device_ops wlan_drv_ops = {
8164 .ndo_open = hdd_open,
8165 .ndo_stop = hdd_stop,
8166 .ndo_uninit = hdd_uninit,
8167 .ndo_start_xmit = hdd_hard_start_xmit,
8168 .ndo_tx_timeout = hdd_tx_timeout,
8169 .ndo_get_stats = hdd_stats,
8170 .ndo_do_ioctl = hdd_ioctl,
8171 .ndo_set_mac_address = hdd_set_mac_address,
8172 .ndo_select_queue = hdd_select_queue,
8173#ifdef WLAN_FEATURE_PACKET_FILTERING
8174#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
8175 .ndo_set_rx_mode = hdd_set_multicast_list,
8176#else
8177 .ndo_set_multicast_list = hdd_set_multicast_list,
8178#endif //LINUX_VERSION_CODE
8179#endif
8180 };
Jeff Johnson295189b2012-06-20 16:38:30 -07008181 static struct net_device_ops wlan_mon_drv_ops = {
8182 .ndo_open = hdd_mon_open,
Katya Nigame7b69a82015-04-28 15:24:06 +05308183 .ndo_stop = hdd_mon_stop,
Jeff Johnson295189b2012-06-20 16:38:30 -07008184 .ndo_uninit = hdd_uninit,
8185 .ndo_start_xmit = hdd_mon_hard_start_xmit,
8186 .ndo_tx_timeout = hdd_tx_timeout,
8187 .ndo_get_stats = hdd_stats,
Katya Nigame7b69a82015-04-28 15:24:06 +05308188 .ndo_do_ioctl = hdd_mon_ioctl,
Jeff Johnson295189b2012-06-20 16:38:30 -07008189 .ndo_set_mac_address = hdd_set_mac_address,
8190 };
Mahesh A Saptasagar305e2632015-03-04 12:57:33 +05308191
Jeff Johnson295189b2012-06-20 16:38:30 -07008192#endif
8193
8194void hdd_set_station_ops( struct net_device *pWlanDev )
8195{
8196#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
Jeff Johnson295189b2012-06-20 16:38:30 -07008197 pWlanDev->netdev_ops = &wlan_drv_ops;
8198#else
8199 pWlanDev->open = hdd_open;
8200 pWlanDev->stop = hdd_stop;
8201 pWlanDev->uninit = hdd_uninit;
8202 pWlanDev->hard_start_xmit = NULL;
8203 pWlanDev->tx_timeout = hdd_tx_timeout;
8204 pWlanDev->get_stats = hdd_stats;
8205 pWlanDev->do_ioctl = hdd_ioctl;
Jeff Johnson295189b2012-06-20 16:38:30 -07008206 pWlanDev->set_mac_address = hdd_set_mac_address;
8207#endif
8208}
8209
Katya Nigam1fd24402015-02-16 14:52:19 +05308210void hdd_set_ibss_ops( hdd_adapter_t *pAdapter )
8211{
8212 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
8213 wlan_drv_ops.ndo_start_xmit = hdd_ibss_hard_start_xmit;
8214 #else
8215 pAdapter->dev->hard_start_xmit = hdd_ibss_hard_start_xmit;
8216 #endif
8217}
8218
Jeff Johnsoneed415b2013-01-18 16:11:20 -08008219static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07008220{
8221 struct net_device *pWlanDev = NULL;
8222 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07008223 /*
8224 * cfg80211 initialization and registration....
8225 */
Anand N Sunkadc34abbd2015-07-29 09:52:59 +05308226 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name,
8227#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0))
8228 NET_NAME_UNKNOWN,
8229#endif
8230 ether_setup, NUM_TX_QUEUES);
Jeff Johnson295189b2012-06-20 16:38:30 -07008231 if(pWlanDev != NULL)
8232 {
8233
8234 //Save the pointer to the net_device in the HDD adapter
8235 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
8236
Jeff Johnson295189b2012-06-20 16:38:30 -07008237 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
8238
8239 pAdapter->dev = pWlanDev;
8240 pAdapter->pHddCtx = pHddCtx;
8241 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
Agarwal Ashish47d18112014-08-04 19:55:07 +05308242 spin_lock_init(&pAdapter->lock_for_active_session);
Jeff Johnson295189b2012-06-20 16:38:30 -07008243
Rajeev79dbe4c2013-10-05 11:03:42 +05308244#ifdef FEATURE_WLAN_BATCH_SCAN
Rajeev79dbe4c2013-10-05 11:03:42 +05308245 pAdapter->pBatchScanRsp = NULL;
8246 pAdapter->numScanList = 0;
Rajeev Kumar20140c12013-10-21 19:39:02 -07008247 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
Kiet Lamaa8e15a2014-02-11 23:30:06 -08008248 pAdapter->prev_batch_id = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05308249 mutex_init(&pAdapter->hdd_batch_scan_lock);
8250#endif
8251
Jeff Johnson295189b2012-06-20 16:38:30 -07008252 pAdapter->isLinkUpSvcNeeded = FALSE;
8253 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
8254 //Init the net_device structure
8255 strlcpy(pWlanDev->name, name, IFNAMSIZ);
8256
8257 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
8258 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
8259 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
8260 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
8261
8262 hdd_set_station_ops( pAdapter->dev );
8263
8264 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07008265 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
8266 pAdapter->wdev.wiphy = pHddCtx->wiphy;
8267 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07008268 /* set pWlanDev's parent to underlying device */
8269 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
Kumar Anand82c009f2014-05-29 00:29:42 -07008270
8271 hdd_wmm_init( pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07008272 }
8273
8274 return pAdapter;
8275}
8276
8277VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
8278{
8279 struct net_device *pWlanDev = pAdapter->dev;
8280 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
8281 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
8282 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
8283
8284 if( rtnl_lock_held )
8285 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08008286 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07008287 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
8288 {
8289 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
8290 return VOS_STATUS_E_FAILURE;
8291 }
8292 }
8293 if (register_netdevice(pWlanDev))
8294 {
8295 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
8296 return VOS_STATUS_E_FAILURE;
8297 }
8298 }
8299 else
8300 {
8301 if(register_netdev(pWlanDev))
8302 {
8303 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
8304 return VOS_STATUS_E_FAILURE;
8305 }
8306 }
8307 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
8308
8309 return VOS_STATUS_SUCCESS;
8310}
8311
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008312static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07008313{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008314 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07008315
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008316 if (NULL == pAdapter)
8317 {
8318 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
8319 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07008320 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008321
8322 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
8323 {
8324 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
8325 return eHAL_STATUS_NOT_INITIALIZED;
8326 }
8327
8328 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
8329
Sameer Thalappilbee426e2013-10-30 10:30:30 -07008330#ifndef WLAN_OPEN_SOURCE
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008331 /* need to make sure all of our scheduled work has completed.
8332 * This callback is called from MC thread context, so it is safe to
8333 * to call below flush workqueue API from here.
Sameer Thalappilbee426e2013-10-30 10:30:30 -07008334 *
8335 * Even though this is called from MC thread context, if there is a faulty
8336 * work item in the system, that can hang this call forever. So flushing
8337 * this global work queue is not safe; and now we make sure that
8338 * individual work queues are stopped correctly. But the cancel work queue
8339 * is a GPL only API, so the proprietary version of the driver would still
8340 * rely on the global work queue flush.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008341 */
8342 flush_scheduled_work();
Sameer Thalappilbee426e2013-10-30 10:30:30 -07008343#endif
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008344
8345 /* We can be blocked while waiting for scheduled work to be
8346 * flushed, and the adapter structure can potentially be freed, in
8347 * which case the magic will have been reset. So make sure the
8348 * magic is still good, and hence the adapter structure is still
8349 * valid, before signaling completion */
8350 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
8351 {
8352 complete(&pAdapter->session_close_comp_var);
8353 }
8354
Jeff Johnson295189b2012-06-20 16:38:30 -07008355 return eHAL_STATUS_SUCCESS;
8356}
Manjeet Singh47ee8472016-04-11 11:57:18 +05308357/**
8358 * hdd_close_tx_queues() - close tx queues
8359 * @hdd_ctx: hdd global context
8360 *
8361 * Return: None
8362 */
8363static void hdd_close_tx_queues(hdd_context_t *hdd_ctx)
8364{
8365 VOS_STATUS status;
8366 hdd_adapter_t *adapter;
8367 hdd_adapter_list_node_t *adapter_node = NULL, *next_adapter = NULL;
8368 /* Not validating hdd_ctx as it's already done by the caller */
8369 ENTER();
8370 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
8371 while (NULL != adapter_node && VOS_STATUS_SUCCESS == status) {
8372 adapter = adapter_node->pAdapter;
8373 if (adapter && adapter->dev) {
8374 netif_tx_disable (adapter->dev);
8375 netif_carrier_off(adapter->dev);
8376 }
8377 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
8378 &next_adapter);
8379 adapter_node = next_adapter;
8380 }
8381 EXIT();
8382}
Jeff Johnson295189b2012-06-20 16:38:30 -07008383
8384VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
8385{
8386 struct net_device *pWlanDev = pAdapter->dev;
8387 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
8388 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
8389 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
8390 VOS_STATUS status = VOS_STATUS_E_FAILURE;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308391 long rc = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07008392
Nirav Shah7e3c8132015-06-22 23:51:42 +05308393 spin_lock_init( &pAdapter->sta_hash_lock);
8394 pAdapter->is_sta_id_hash_initialized = VOS_FALSE;
8395
Jeff Johnson295189b2012-06-20 16:38:30 -07008396 INIT_COMPLETION(pAdapter->session_open_comp_var);
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07008397 sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07008398 //Open a SME session for future operation
8399 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07008400 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07008401 if ( !HAL_STATUS_SUCCESS( halStatus ) )
8402 {
8403 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07008404 "sme_OpenSession() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07008405 halStatus, halStatus );
8406 status = VOS_STATUS_E_FAILURE;
8407 goto error_sme_open;
8408 }
8409
8410 //Block on a completion variable. Can't wait forever though.
Vinay Krishna Eranna0fe2e7c2014-04-09 21:32:08 +05308411 rc = wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07008412 &pAdapter->session_open_comp_var,
8413 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308414 if (rc <= 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07008415 {
8416 hddLog(VOS_TRACE_LEVEL_FATAL,
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308417 "Session is not opened within timeout period code %ld", rc );
Jeff Johnson295189b2012-06-20 16:38:30 -07008418 status = VOS_STATUS_E_FAILURE;
8419 goto error_sme_open;
8420 }
8421
8422 // Register wireless extensions
8423 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
8424 {
8425 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07008426 "hdd_register_wext() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07008427 halStatus, halStatus );
8428 status = VOS_STATUS_E_FAILURE;
8429 goto error_register_wext;
8430 }
Katya Nigam1fd24402015-02-16 14:52:19 +05308431
Jeff Johnson295189b2012-06-20 16:38:30 -07008432 //Safe to register the hard_start_xmit function again
Katya Nigam1fd24402015-02-16 14:52:19 +05308433 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
8434 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
8435 #else
8436 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
8437 #endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008438
8439 //Set the Connection State to Not Connected
Abhishek Singhf4669da2014-05-26 15:07:49 +05308440 hddLog(VOS_TRACE_LEVEL_INFO,
8441 "%s: Set HDD connState to eConnectionState_NotConnected",
8442 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008443 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
8444
8445 //Set the default operation channel
8446 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
8447
8448 /* Make the default Auth Type as OPEN*/
8449 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
8450
8451 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
8452 {
8453 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07008454 "hdd_init_tx_rx() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07008455 status, status );
8456 goto error_init_txrx;
8457 }
8458
8459 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
8460
8461 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
8462 {
8463 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07008464 "hdd_wmm_adapter_init() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07008465 status, status );
8466 goto error_wmm_init;
8467 }
8468
8469 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
8470
8471 return VOS_STATUS_SUCCESS;
8472
8473error_wmm_init:
8474 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
8475 hdd_deinit_tx_rx(pAdapter);
8476error_init_txrx:
8477 hdd_UnregisterWext(pWlanDev);
8478error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008479 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07008480 {
8481 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008482 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Agrawal Ashish5a3522c2016-03-02 15:08:28 +05308483 pAdapter->sessionId, FALSE, VOS_TRUE,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008484 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07008485 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308486 unsigned long rc;
8487
Jeff Johnson295189b2012-06-20 16:38:30 -07008488 //Block on a completion variable. Can't wait forever though.
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308489 rc = wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07008490 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008491 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308492 if (rc <= 0)
8493 hddLog(VOS_TRACE_LEVEL_ERROR,
8494 FL("Session is not opened within timeout period code %ld"), rc);
Jeff Johnson295189b2012-06-20 16:38:30 -07008495 }
8496}
8497error_sme_open:
8498 return status;
8499}
8500
Jeff Johnson295189b2012-06-20 16:38:30 -07008501void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
8502{
8503 hdd_cfg80211_state_t *cfgState;
8504
8505 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
8506
8507 if( NULL != cfgState->buf )
8508 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308509 long rc;
Jeff Johnson295189b2012-06-20 16:38:30 -07008510 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
8511 rc = wait_for_completion_interruptible_timeout(
8512 &pAdapter->tx_action_cnf_event,
8513 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308514 if (rc <= 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07008515 {
Deepthi Gowri91b3e9c2015-08-25 13:14:58 +05308516 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8517 "%s ERROR: HDD Wait for Action Confirmation Failed!! %ld"
8518 , __func__, rc);
8519
8520 // Inform tx status as FAILURE to upper layer and free cfgState->buf
8521 hdd_sendActionCnf( pAdapter, FALSE );
Jeff Johnson295189b2012-06-20 16:38:30 -07008522 }
8523 }
8524 return;
8525}
Jeff Johnson295189b2012-06-20 16:38:30 -07008526
c_hpothu002231a2015-02-05 14:58:51 +05308527void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
Jeff Johnson295189b2012-06-20 16:38:30 -07008528{
8529 ENTER();
8530 switch ( pAdapter->device_mode )
8531 {
Katya Nigam1fd24402015-02-16 14:52:19 +05308532 case WLAN_HDD_IBSS:
8533 {
8534 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
8535 {
8536 hdd_ibss_deinit_tx_rx( pAdapter );
8537 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
8538 }
8539 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008540 case WLAN_HDD_INFRA_STATION:
8541 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07008542 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07008543 {
8544 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
8545 {
8546 hdd_deinit_tx_rx( pAdapter );
8547 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
8548 }
8549
8550 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
8551 {
8552 hdd_wmm_adapter_close( pAdapter );
8553 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
8554 }
8555
Jeff Johnson295189b2012-06-20 16:38:30 -07008556 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07008557 break;
8558 }
8559
8560 case WLAN_HDD_SOFTAP:
8561 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07008562 {
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05308563
8564 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
8565 {
8566 hdd_wmm_adapter_close( pAdapter );
8567 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
8568 }
8569
Jeff Johnson295189b2012-06-20 16:38:30 -07008570 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07008571
c_hpothu002231a2015-02-05 14:58:51 +05308572 hdd_unregister_hostapd(pAdapter, rtnl_held);
Agrawal Ashisha0584d42016-09-29 13:03:45 +05308573 /* set con_mode to STA only when no SAP concurrency mode */
8574 if (!(hdd_get_concurrency_mode() & (VOS_SAP | VOS_P2P_GO)))
8575 hdd_set_conparam(0);
Jeff Johnson295189b2012-06-20 16:38:30 -07008576 break;
8577 }
8578
8579 case WLAN_HDD_MONITOR:
8580 {
Jeff Johnson295189b2012-06-20 16:38:30 -07008581 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
8582 {
8583 hdd_deinit_tx_rx( pAdapter );
8584 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
8585 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008586 break;
8587 }
8588
8589
8590 default:
8591 break;
8592 }
8593
8594 EXIT();
8595}
8596
8597void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
8598{
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -08008599 struct net_device *pWlanDev = NULL;
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05308600
8601 ENTER();
8602 if (NULL == pAdapter)
8603 {
8604 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8605 "%s: HDD adapter is Null", __func__);
8606 return;
8607 }
8608
8609 pWlanDev = pAdapter->dev;
Jeff Johnson295189b2012-06-20 16:38:30 -07008610
Rajeev79dbe4c2013-10-05 11:03:42 +05308611#ifdef FEATURE_WLAN_BATCH_SCAN
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05308612 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
8613 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Rajeev Kumarf999e582014-01-09 17:33:29 -08008614 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05308615 || (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)
8616 )
8617 {
Rajeev Kumarf999e582014-01-09 17:33:29 -08008618 if (pAdapter)
Rajeev79dbe4c2013-10-05 11:03:42 +05308619 {
Rajeev Kumarf999e582014-01-09 17:33:29 -08008620 if (eHDD_BATCH_SCAN_STATE_STARTED == pAdapter->batchScanState)
8621 {
8622 hdd_deinit_batch_scan(pAdapter);
8623 }
Rajeev79dbe4c2013-10-05 11:03:42 +05308624 }
Rajeev Kumarf999e582014-01-09 17:33:29 -08008625 }
Rajeev79dbe4c2013-10-05 11:03:42 +05308626#endif
8627
Jeff Johnson295189b2012-06-20 16:38:30 -07008628 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
8629 if( rtnl_held )
8630 {
8631 unregister_netdevice(pWlanDev);
8632 }
8633 else
8634 {
8635 unregister_netdev(pWlanDev);
8636 }
8637 // note that the pAdapter is no longer valid at this point
8638 // since the memory has been reclaimed
8639 }
8640
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05308641 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07008642}
8643
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008644void hdd_set_pwrparams(hdd_context_t *pHddCtx)
8645{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308646 VOS_STATUS status;
8647 hdd_adapter_t *pAdapter = NULL;
8648 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008649
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308650 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008651
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308652 /*loop through all adapters.*/
8653 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008654 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308655 pAdapter = pAdapterNode->pAdapter;
8656 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
8657 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008658
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308659 { // we skip this registration for modes other than STA and P2P client modes.
8660 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
8661 pAdapterNode = pNext;
8662 continue;
8663 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008664
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308665 //Apply Dynamic DTIM For P2P
8666 //Only if ignoreDynamicDtimInP2pMode is not set in ini
8667 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
8668 pHddCtx->cfg_ini->enableModulatedDTIM) &&
8669 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
8670 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
8671 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
8672 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
8673 (eConnectionState_Associated ==
8674 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
8675 (pHddCtx->cfg_ini->fIsBmpsEnabled))
8676 {
8677 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008678
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308679 powerRequest.uIgnoreDTIM = 1;
8680 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
8681
8682 if (pHddCtx->cfg_ini->enableModulatedDTIM)
8683 {
8684 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
8685 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
8686 }
8687 else
8688 {
8689 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
8690 }
8691
8692 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
8693 * specified during Enter/Exit BMPS when LCD off*/
8694 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
8695 NULL, eANI_BOOLEAN_FALSE);
8696 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
8697 NULL, eANI_BOOLEAN_FALSE);
8698
8699 /* switch to the DTIM specified in cfg.ini */
8700 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Abhishek Singh1e390cf2015-10-27 13:45:17 +05308701 "Switch to DTIM %d Listen interval %d",
8702 powerRequest.uDTIMPeriod,
8703 powerRequest.uListenInterval);
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308704 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
8705 break;
8706
8707 }
8708
8709 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
8710 pAdapterNode = pNext;
8711 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008712}
8713
8714void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
8715{
8716 /*Switch back to DTIM 1*/
8717 tSirSetPowerParamsReq powerRequest = { 0 };
8718
8719 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
8720 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07008721 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008722
8723 /* Update ignoreDTIM and ListedInterval in CFG with default values */
8724 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
8725 NULL, eANI_BOOLEAN_FALSE);
8726 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
8727 NULL, eANI_BOOLEAN_FALSE);
8728
8729 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8730 "Switch to DTIM%d",powerRequest.uListenInterval);
8731 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
8732
8733}
8734
Jeff Johnson295189b2012-06-20 16:38:30 -07008735VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
8736{
8737 VOS_STATUS status = VOS_STATUS_SUCCESS;
Sushant Kaushik4928e542014-12-29 15:25:54 +05308738 if (WLAN_HDD_IS_UNLOAD_IN_PROGRESS(pHddCtx))
8739 {
8740 hddLog( LOGE, FL("Wlan Unload in progress"));
8741 return VOS_STATUS_E_PERM;
8742 }
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05308743
8744 if (wlan_hdd_check_monitor_state(pHddCtx)) {
8745 hddLog(LOG1, FL("Monitor mode is started, cannot enable BMPS"));
8746 return VOS_STATUS_SUCCESS;
8747 }
8748
Jeff Johnson295189b2012-06-20 16:38:30 -07008749 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
8750 {
8751 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
8752 }
8753
8754 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
8755 {
8756 sme_StartAutoBmpsTimer(pHddCtx->hHal);
8757 }
8758
8759 if (pHddCtx->cfg_ini->fIsImpsEnabled)
8760 {
8761 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
8762 }
8763
8764 return status;
8765}
8766
8767VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
8768{
8769 hdd_adapter_t *pAdapter = NULL;
8770 eHalStatus halStatus;
8771 VOS_STATUS status = VOS_STATUS_E_INVAL;
8772 v_BOOL_t disableBmps = FALSE;
8773 v_BOOL_t disableImps = FALSE;
8774
8775 switch(session_type)
8776 {
8777 case WLAN_HDD_INFRA_STATION:
8778 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07008779 case WLAN_HDD_P2P_CLIENT:
8780 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07008781 //Exit BMPS -> Is Sta/P2P Client is already connected
8782 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
8783 if((NULL != pAdapter)&&
8784 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
8785 {
8786 disableBmps = TRUE;
8787 }
8788
8789 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
8790 if((NULL != pAdapter)&&
8791 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
8792 {
8793 disableBmps = TRUE;
8794 }
8795
8796 //Exit both Bmps and Imps incase of Go/SAP Mode
8797 if((WLAN_HDD_SOFTAP == session_type) ||
8798 (WLAN_HDD_P2P_GO == session_type))
8799 {
8800 disableBmps = TRUE;
8801 disableImps = TRUE;
8802 }
8803
8804 if(TRUE == disableImps)
8805 {
8806 if (pHddCtx->cfg_ini->fIsImpsEnabled)
8807 {
8808 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
8809 }
8810 }
8811
8812 if(TRUE == disableBmps)
8813 {
8814 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
8815 {
8816 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
8817
8818 if(eHAL_STATUS_SUCCESS != halStatus)
8819 {
8820 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08008821 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008822 VOS_ASSERT(0);
8823 return status;
8824 }
8825 }
8826
8827 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
8828 {
8829 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
8830
8831 if(eHAL_STATUS_SUCCESS != halStatus)
8832 {
8833 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08008834 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008835 VOS_ASSERT(0);
8836 return status;
8837 }
8838 }
8839 }
8840
8841 if((TRUE == disableBmps) ||
8842 (TRUE == disableImps))
8843 {
8844 /* Now, get the chip into Full Power now */
8845 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
8846 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
8847 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
8848
8849 if(halStatus != eHAL_STATUS_SUCCESS)
8850 {
8851 if(halStatus == eHAL_STATUS_PMC_PENDING)
8852 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308853 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07008854 //Block on a completion variable. Can't wait forever though
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308855 ret = wait_for_completion_interruptible_timeout(
8856 &pHddCtx->full_pwr_comp_var,
8857 msecs_to_jiffies(1000));
8858 if (ret <= 0)
8859 {
8860 hddLog(VOS_TRACE_LEVEL_ERROR,
8861 "%s: wait on full_pwr_comp_var failed %ld",
8862 __func__, ret);
8863 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008864 }
8865 else
8866 {
8867 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08008868 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008869 VOS_ASSERT(0);
8870 return status;
8871 }
8872 }
8873
8874 status = VOS_STATUS_SUCCESS;
8875 }
8876
8877 break;
8878 }
8879 return status;
8880}
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +05308881
8882void hdd_monPostMsgCb(tANI_U32 *magic, struct completion *cmpVar)
8883{
8884 if (magic == NULL || cmpVar == NULL) {
8885 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnsonc135a9a2017-09-19 08:37:24 -07008886 FL("invalid arguments %pK %pK"), magic, cmpVar);
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +05308887 return;
8888 }
8889 if (*magic != MON_MODE_MSG_MAGIC) {
8890 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8891 FL("maic: %x"), *magic);
8892 return;
8893 }
8894
8895 complete(cmpVar);
8896 return;
8897}
8898
Katya Nigame7b69a82015-04-28 15:24:06 +05308899void hdd_init_mon_mode (hdd_adapter_t *pAdapter)
8900 {
8901 hdd_mon_ctx_t *pMonCtx = NULL;
8902 pMonCtx = WLAN_HDD_GET_MONITOR_CTX_PTR(pAdapter);
8903
8904 pMonCtx->state = 0;
8905 pMonCtx->ChannelNo = 1;
8906 pMonCtx->ChannelBW = 20;
Katya Nigamd7d3a1f2015-06-11 14:04:24 +05308907 pMonCtx->crcCheckEnabled = 1;
8908 pMonCtx->typeSubtypeBitmap = 0xFFFF00000000;
8909 pMonCtx->is80211to803ConReq = 1;
Katya Nigame7b69a82015-04-28 15:24:06 +05308910 pMonCtx->numOfMacFilters = 0;
8911 }
8912
Jeff Johnson295189b2012-06-20 16:38:30 -07008913
8914hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08008915 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07008916 tANI_U8 rtnl_held )
8917{
8918 hdd_adapter_t *pAdapter = NULL;
8919 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
8920 VOS_STATUS status = VOS_STATUS_E_FAILURE;
8921 VOS_STATUS exitbmpsStatus;
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05308922 v_CONTEXT_t pVosContext = NULL;
8923
8924 /* No need to check for NULL, reaching this step
8925 * means vos context is initialized
8926 */
8927 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07008928
Arif Hussain6d2a3322013-11-17 19:50:10 -08008929 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d",__func__,iface_name,session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07008930
Nirav Shah436658f2014-02-28 17:05:45 +05308931 if(macAddr == NULL)
8932 {
8933 /* Not received valid macAddr */
8934 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8935 "%s:Unable to add virtual intf: Not able to get"
8936 "valid mac address",__func__);
8937 return NULL;
8938 }
8939
Jeff Johnson295189b2012-06-20 16:38:30 -07008940 //Disable BMPS incase of Concurrency
8941 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
8942
8943 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
8944 {
8945 //Fail to Exit BMPS
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308946 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Exit BMPS", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008947 VOS_ASSERT(0);
8948 return NULL;
8949 }
8950
8951 switch(session_type)
8952 {
8953 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07008954 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07008955 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07008956 {
8957 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
8958
8959 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308960 {
8961 hddLog(VOS_TRACE_LEVEL_FATAL,
8962 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07008963 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308964 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008965
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05308966#ifdef FEATURE_WLAN_TDLS
8967 /* A Mutex Lock is introduced while changing/initializing the mode to
8968 * protect the concurrent access for the Adapters by TDLS module.
8969 */
Rajesh Chauhana34c6e62014-03-25 16:37:58 +05308970 mutex_lock(&pHddCtx->tdls_lock);
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05308971#endif
8972
Jeff Johnsone7245742012-09-05 17:12:55 -07008973 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
8974 NL80211_IFTYPE_P2P_CLIENT:
8975 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07008976
Jeff Johnson295189b2012-06-20 16:38:30 -07008977 pAdapter->device_mode = session_type;
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05308978#ifdef FEATURE_WLAN_TDLS
8979 mutex_unlock(&pHddCtx->tdls_lock);
8980#endif
Sunil Dutt66485cb2013-12-19 19:05:03 +05308981
Mahesh A Saptasagar67ab9222015-10-21 15:38:41 +05308982 hdd_initialize_adapter_common(pAdapter);
Sunil Dutt66485cb2013-12-19 19:05:03 +05308983 status = hdd_init_station_mode( pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07008984 if( VOS_STATUS_SUCCESS != status )
8985 goto err_free_netdev;
8986
8987 status = hdd_register_interface( pAdapter, rtnl_held );
8988 if( VOS_STATUS_SUCCESS != status )
8989 {
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05308990#ifdef FEATURE_WLAN_TDLS
8991 mutex_lock(&pHddCtx->tdls_lock);
8992#endif
c_hpothu002231a2015-02-05 14:58:51 +05308993 hdd_deinit_adapter(pHddCtx, pAdapter, rtnl_held);
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05308994#ifdef FEATURE_WLAN_TDLS
8995 mutex_unlock(&pHddCtx->tdls_lock);
8996#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008997 goto err_free_netdev;
8998 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05308999
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05309000 // Workqueue which gets scheduled in IPv4 notification callback.
Anand N Sunkaddc63c792015-06-03 14:33:24 +05309001 vos_init_work(&pAdapter->ipv4NotifierWorkQueue, hdd_ipv4_notifier_work_queue);
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05309002
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05309003#ifdef WLAN_NS_OFFLOAD
9004 // Workqueue which gets scheduled in IPv6 notification callback.
Anand N Sunkaddc63c792015-06-03 14:33:24 +05309005 vos_init_work(&pAdapter->ipv6NotifierWorkQueue, hdd_ipv6_notifier_work_queue);
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05309006#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009007 //Stop the Interface TX queue.
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05309008 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
Jeff Johnson295189b2012-06-20 16:38:30 -07009009 netif_tx_disable(pAdapter->dev);
9010 //netif_tx_disable(pWlanDev);
9011 netif_carrier_off(pAdapter->dev);
9012
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +05309013 if (WLAN_HDD_P2P_CLIENT == session_type ||
9014 WLAN_HDD_P2P_DEVICE == session_type)
9015 {
9016 /* Initialize the work queue to defer the
9017 * back to back RoC request */
Anand N Sunkaddc63c792015-06-03 14:33:24 +05309018 vos_init_delayed_work(&pAdapter->roc_work,
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +05309019 hdd_p2p_roc_work_queue);
9020 }
9021
Jeff Johnson295189b2012-06-20 16:38:30 -07009022 break;
9023 }
9024
Jeff Johnson295189b2012-06-20 16:38:30 -07009025 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07009026 case WLAN_HDD_SOFTAP:
9027 {
9028 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
9029 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309030 {
9031 hddLog(VOS_TRACE_LEVEL_FATAL,
9032 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07009033 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309034 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009035
Jeff Johnson295189b2012-06-20 16:38:30 -07009036 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
9037 NL80211_IFTYPE_AP:
9038 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07009039 pAdapter->device_mode = session_type;
9040
Mahesh A Saptasagar67ab9222015-10-21 15:38:41 +05309041 hdd_initialize_adapter_common(pAdapter);
Hanumanth Reddy Pothula15bc0fa2017-02-03 17:24:17 +05309042 status = hdd_init_ap_mode(pAdapter, false);
Jeff Johnson295189b2012-06-20 16:38:30 -07009043 if( VOS_STATUS_SUCCESS != status )
9044 goto err_free_netdev;
9045
Nirav Shah7e3c8132015-06-22 23:51:42 +05309046 status = hdd_sta_id_hash_attach(pAdapter);
9047 if (VOS_STATUS_SUCCESS != status)
9048 {
9049 hddLog(VOS_TRACE_LEVEL_FATAL,
9050 FL("failed to attach hash for session %d"), session_type);
9051 hdd_deinit_adapter(pHddCtx, pAdapter, rtnl_held);
9052 goto err_free_netdev;
9053 }
9054
Jeff Johnson295189b2012-06-20 16:38:30 -07009055 status = hdd_register_hostapd( pAdapter, rtnl_held );
9056 if( VOS_STATUS_SUCCESS != status )
9057 {
c_hpothu002231a2015-02-05 14:58:51 +05309058 hdd_deinit_adapter(pHddCtx, pAdapter, rtnl_held);
Jeff Johnson295189b2012-06-20 16:38:30 -07009059 goto err_free_netdev;
9060 }
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05309061 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
Jeff Johnson295189b2012-06-20 16:38:30 -07009062 netif_tx_disable(pAdapter->dev);
9063 netif_carrier_off(pAdapter->dev);
9064
9065 hdd_set_conparam( 1 );
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +05309066
Hanumanth Reddy Pothulab4537b82018-03-02 12:20:38 +05309067 // Workqueue which gets scheduled in IPv4 notification callback.
9068 vos_init_work(&pAdapter->ipv4NotifierWorkQueue,
9069 hdd_ipv4_notifier_work_queue);
9070
9071#ifdef WLAN_NS_OFFLOAD
9072 // Workqueue which gets scheduled in IPv6 notification callback.
9073 vos_init_work(&pAdapter->ipv6NotifierWorkQueue,
9074 hdd_ipv6_notifier_work_queue);
9075#endif
9076
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +05309077 if (WLAN_HDD_P2P_GO == session_type)
9078 {
9079 /* Initialize the work queue to
9080 * defer the back to back RoC request */
9081 INIT_DELAYED_WORK(&pAdapter->roc_work,
9082 hdd_p2p_roc_work_queue);
9083 }
Bhargav Shahd0715912015-10-01 18:17:37 +05309084
Jeff Johnson295189b2012-06-20 16:38:30 -07009085 break;
9086 }
9087 case WLAN_HDD_MONITOR:
9088 {
Jeff Johnson295189b2012-06-20 16:38:30 -07009089 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
9090 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309091 {
9092 hddLog(VOS_TRACE_LEVEL_FATAL,
9093 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07009094 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309095 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009096
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05309097 pAdapter->device_mode = session_type;
9098 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
9099
Katya Nigame7b69a82015-04-28 15:24:06 +05309100 // Register wireless extensions
9101 if( VOS_STATUS_SUCCESS != (status = hdd_register_wext(pAdapter->dev)))
9102 {
9103 hddLog(VOS_TRACE_LEVEL_FATAL,
9104 "hdd_register_wext() failed with status code %08d [x%08x]",
9105 status, status );
9106 status = VOS_STATUS_E_FAILURE;
9107 }
9108
Jeff Johnson295189b2012-06-20 16:38:30 -07009109#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
9110 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
9111#else
9112 pAdapter->dev->open = hdd_mon_open;
9113 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
Katya Nigame7b69a82015-04-28 15:24:06 +05309114 pAdapter->dev->stop = hdd_mon_stop;
9115 pAdapter->dev->do_ioctl = hdd_mon_ioctl;
Jeff Johnson295189b2012-06-20 16:38:30 -07009116#endif
Katya Nigame7b69a82015-04-28 15:24:06 +05309117 hdd_init_mon_mode( pAdapter );
Mahesh A Saptasagar67ab9222015-10-21 15:38:41 +05309118 hdd_initialize_adapter_common(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07009119 hdd_init_tx_rx( pAdapter );
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05309120
9121 if (VOS_MONITOR_MODE != hdd_get_conparam())
9122 WLANTL_SetMonRxCbk( pVosContext, hdd_rx_packet_monitor_cbk );
9123
Jeff Johnson295189b2012-06-20 16:38:30 -07009124 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05309125 status = hdd_register_interface( pAdapter, rtnl_held );
Katya Nigame7b69a82015-04-28 15:24:06 +05309126 //Stop the Interface TX queue.
9127 netif_tx_disable(pAdapter->dev);
9128 netif_carrier_off(pAdapter->dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07009129 }
9130 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07009131 case WLAN_HDD_FTM:
9132 {
9133 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
9134
9135 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309136 {
9137 hddLog(VOS_TRACE_LEVEL_FATAL,
9138 FL("failed to allocate adapter for session %d"), session_type);
9139 return NULL;
9140 }
9141
Jeff Johnson295189b2012-06-20 16:38:30 -07009142 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
9143 * message while loading driver in FTM mode. */
9144 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
9145 pAdapter->device_mode = session_type;
9146 status = hdd_register_interface( pAdapter, rtnl_held );
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05309147
Mahesh A Saptasagar67ab9222015-10-21 15:38:41 +05309148 hdd_initialize_adapter_common(pAdapter);
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05309149 hdd_init_tx_rx( pAdapter );
9150
9151 //Stop the Interface TX queue.
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05309152 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05309153 netif_tx_disable(pAdapter->dev);
9154 netif_carrier_off(pAdapter->dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07009155 }
9156 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07009157 default:
9158 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309159 hddLog(VOS_TRACE_LEVEL_FATAL,"%s Invalid session type %d",
9160 __func__, session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07009161 VOS_ASSERT(0);
9162 return NULL;
9163 }
9164 }
9165
Jeff Johnson295189b2012-06-20 16:38:30 -07009166 if( VOS_STATUS_SUCCESS == status )
9167 {
Mahesh A Saptasagar67ab9222015-10-21 15:38:41 +05309168 //Add it to the hdd's session list.
Jeff Johnson295189b2012-06-20 16:38:30 -07009169 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
9170 if( NULL == pHddAdapterNode )
9171 {
9172 status = VOS_STATUS_E_NOMEM;
9173 }
9174 else
9175 {
9176 pHddAdapterNode->pAdapter = pAdapter;
9177 status = hdd_add_adapter_back ( pHddCtx,
9178 pHddAdapterNode );
9179 }
9180 }
9181
9182 if( VOS_STATUS_SUCCESS != status )
9183 {
9184 if( NULL != pAdapter )
9185 {
9186 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
9187 pAdapter = NULL;
9188 }
9189 if( NULL != pHddAdapterNode )
9190 {
9191 vos_mem_free( pHddAdapterNode );
9192 }
9193
9194 goto resume_bmps;
9195 }
9196
9197 if(VOS_STATUS_SUCCESS == status)
9198 {
9199 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07009200 //Initialize the WoWL service
9201 if(!hdd_init_wowl(pAdapter))
9202 {
9203 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
9204 goto err_free_netdev;
9205 }
Manjeet Singh3ed79242017-01-11 19:04:32 +05309206 //Initialize the TSF capture data
9207 wlan_hdd_tsf_init(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07009208 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009209 return pAdapter;
9210
9211err_free_netdev:
9212 free_netdev(pAdapter->dev);
9213 wlan_hdd_release_intf_addr( pHddCtx,
9214 pAdapter->macAddressCurrent.bytes );
9215
9216resume_bmps:
9217 //If bmps disabled enable it
9218 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
9219 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05309220 if (pHddCtx->hdd_wlan_suspended)
9221 {
9222 hdd_set_pwrparams(pHddCtx);
9223 }
9224 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07009225 }
9226 return NULL;
9227}
9228
9229VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
9230 tANI_U8 rtnl_held )
9231{
9232 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
9233 VOS_STATUS status;
9234
9235 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
9236 if( VOS_STATUS_SUCCESS != status )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309237 {
9238 hddLog(VOS_TRACE_LEVEL_WARN,"%s: adapter list empty %d",
9239 __func__, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07009240 return status;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309241 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009242
9243 while ( pCurrent->pAdapter != pAdapter )
9244 {
9245 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
9246 if( VOS_STATUS_SUCCESS != status )
9247 break;
9248
9249 pCurrent = pNext;
9250 }
9251 pAdapterNode = pCurrent;
9252 if( VOS_STATUS_SUCCESS == status )
9253 {
9254 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
9255 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05309256
9257#ifdef FEATURE_WLAN_TDLS
9258
9259 /* A Mutex Lock is introduced while changing/initializing the mode to
9260 * protect the concurrent access for the Adapters by TDLS module.
9261 */
Rajesh Chauhana34c6e62014-03-25 16:37:58 +05309262 mutex_lock(&pHddCtx->tdls_lock);
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05309263#endif
9264
Jeff Johnson295189b2012-06-20 16:38:30 -07009265 hdd_remove_adapter( pHddCtx, pAdapterNode );
9266 vos_mem_free( pAdapterNode );
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08009267 pAdapterNode = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07009268
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05309269#ifdef FEATURE_WLAN_TDLS
9270 mutex_unlock(&pHddCtx->tdls_lock);
9271#endif
9272
Jeff Johnson295189b2012-06-20 16:38:30 -07009273
9274 /* If there is a single session of STA/P2P client, re-enable BMPS */
Agarwal Ashish51325b52014-06-16 16:50:49 +05309275 if ((!vos_concurrent_open_sessions_running()) &&
9276 ((pHddCtx->no_of_open_sessions[VOS_STA_MODE] >= 1) ||
9277 (pHddCtx->no_of_open_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
Jeff Johnson295189b2012-06-20 16:38:30 -07009278 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05309279 if (pHddCtx->hdd_wlan_suspended)
9280 {
9281 hdd_set_pwrparams(pHddCtx);
9282 }
9283 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07009284 }
9285
9286 return VOS_STATUS_SUCCESS;
9287 }
9288
9289 return VOS_STATUS_E_FAILURE;
9290}
9291
9292VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
9293{
9294 hdd_adapter_list_node_t *pHddAdapterNode;
9295 VOS_STATUS status;
9296
9297 ENTER();
9298
9299 do
9300 {
9301 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
9302 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
9303 {
9304 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
9305 vos_mem_free( pHddAdapterNode );
9306 }
9307 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
9308
9309 EXIT();
9310
9311 return VOS_STATUS_SUCCESS;
9312}
9313
9314void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
9315{
9316 v_U8_t addIE[1] = {0};
9317
9318 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
9319 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
9320 eANI_BOOLEAN_FALSE) )
9321 {
9322 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08009323 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07009324 }
9325
9326 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
9327 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
9328 eANI_BOOLEAN_FALSE) )
9329 {
9330 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08009331 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07009332 }
9333
9334 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
9335 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
9336 eANI_BOOLEAN_FALSE) )
9337 {
9338 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08009339 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07009340 }
9341}
9342
Anurag Chouhan83026002016-12-13 22:46:21 +05309343VOS_STATUS hdd_cleanup_ap_events(hdd_adapter_t *adapter)
9344{
9345#ifdef DHCP_SERVER_OFFLOAD
9346 vos_event_destroy(&adapter->dhcp_status.vos_event);
9347#endif
Anurag Chouhan0b29de02016-12-16 13:18:40 +05309348#ifdef MDNS_OFFLOAD
9349 vos_event_destroy(&adapter->mdns_status.vos_event);
9350#endif
Anurag Chouhan83026002016-12-13 22:46:21 +05309351 return VOS_STATUS_SUCCESS;
9352}
9353
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05309354int wlan_hdd_stop_mon(hdd_context_t *hdd_ctx, bool wait)
9355{
9356 hdd_mon_ctx_t *mon_ctx;
9357 long ret;
9358 v_U32_t magic;
9359 struct completion cmp_var;
9360 void (*func_ptr)(tANI_U32 *magic, struct completion *cmpVar) = NULL;
9361 hdd_adapter_t *adapter;
9362
9363 adapter = hdd_get_adapter(hdd_ctx, WLAN_HDD_MONITOR);
9364 if (!adapter) {
9365 hddLog(LOGE, FL("Invalid STA + MON mode"));
9366 return -EINVAL;
9367 }
9368
9369 mon_ctx = WLAN_HDD_GET_MONITOR_CTX_PTR(adapter);
9370 if (!mon_ctx)
9371 return 0;
9372
9373 if (mon_ctx->state != MON_MODE_START)
9374 return 0;
9375
9376 mon_ctx->state = MON_MODE_STOP;
9377 if (wait) {
9378 func_ptr = hdd_monPostMsgCb;
9379 magic = MON_MODE_MSG_MAGIC;
9380 init_completion(&cmp_var);
9381 }
9382
9383 if (VOS_STATUS_SUCCESS != wlan_hdd_mon_postMsg(&magic, &cmp_var,
9384 mon_ctx,
9385 hdd_monPostMsgCb)) {
9386 hddLog(LOGE, FL("failed to stop MON MODE"));
9387 mon_ctx->state = MON_MODE_START;
9388 magic = 0;
9389 return -EINVAL;
9390 }
9391
9392 if (!wait)
9393 goto bmps_roaming;
9394
9395 ret = wait_for_completion_timeout(&cmp_var, MON_MODE_MSG_TIMEOUT);
9396 magic = 0;
9397 if (ret <= 0 ) {
9398 hddLog(LOGE,
9399 FL("timeout on stop monitor mode completion %ld"), ret);
9400 return -EINVAL;
9401 }
9402
9403bmps_roaming:
9404 hddLog(LOG1, FL("Enable BMPS"));
9405 hdd_enable_bmps_imps(hdd_ctx);
9406 hdd_restore_roaming(hdd_ctx);
9407
9408 return 0;
9409}
9410
9411bool wlan_hdd_check_monitor_state(hdd_context_t *hdd_ctx)
9412{
9413 hdd_adapter_t *mon_adapter;
9414 hdd_mon_ctx_t *mon_ctx;
9415
9416 if (hdd_ctx->concurrency_mode != VOS_STA_MON)
9417 return false;
9418
9419 mon_adapter = hdd_get_adapter(hdd_ctx, WLAN_HDD_MONITOR);
9420 if (!mon_adapter) {
9421 hddLog(LOGE, FL("Invalid concurrency mode"));
9422 return false;
9423 }
9424
9425 mon_ctx = WLAN_HDD_GET_MONITOR_CTX_PTR(mon_adapter);
9426 if (mon_ctx->state == MON_MODE_START)
9427 return true;
9428
9429 return false;
9430}
9431
9432int wlan_hdd_check_and_stop_mon(hdd_adapter_t *sta_adapter, bool wait)
9433{
9434 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(sta_adapter);
9435
9436 if ((sta_adapter->device_mode != WLAN_HDD_INFRA_STATION) ||
9437 !wlan_hdd_check_monitor_state(hdd_ctx))
9438 return 0;
9439
9440 if (wlan_hdd_stop_mon(hdd_ctx, wait))
9441 return -EINVAL;
9442
9443 return 0;
9444}
9445
9446void hdd_disable_roaming(hdd_context_t *hdd_ctx)
9447{
9448 if (!hdd_ctx)
9449 return;
9450
9451 if (!hdd_ctx->cfg_ini->isFastRoamIniFeatureEnabled) {
9452 hdd_ctx->roaming_ini_original = CFG_LFR_FEATURE_ENABLED_MIN;
9453 return;
9454 }
9455
9456 hddLog(LOG1, FL("Disable driver and firmware roaming"));
9457
9458 hdd_ctx->roaming_ini_original =
9459 hdd_ctx->cfg_ini->isFastRoamIniFeatureEnabled;
9460
9461 hdd_ctx->cfg_ini->isFastRoamIniFeatureEnabled =
9462 CFG_LFR_FEATURE_ENABLED_MIN;
9463
9464 sme_UpdateIsFastRoamIniFeatureEnabled(hdd_ctx->hHal,
9465 CFG_LFR_FEATURE_ENABLED_MIN);
9466}
9467
9468void hdd_restore_roaming(hdd_context_t *hdd_ctx)
9469{
9470 if (!hdd_ctx->roaming_ini_original)
9471 return;
9472
9473 hddLog(LOG1, FL("Enable driver and firmware roaming"));
9474
9475 hdd_ctx->cfg_ini->isFastRoamIniFeatureEnabled =
9476 CFG_LFR_FEATURE_ENABLED_MAX;
9477
9478 hdd_ctx->roaming_ini_original = CFG_LFR_FEATURE_ENABLED_MIN;
9479
9480 sme_UpdateIsFastRoamIniFeatureEnabled(hdd_ctx->hHal,
9481 CFG_LFR_FEATURE_ENABLED_MAX);
9482}
Anurag Chouhan83026002016-12-13 22:46:21 +05309483
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05309484VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
9485 const v_BOOL_t bCloseSession )
Jeff Johnson295189b2012-06-20 16:38:30 -07009486{
9487 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
9488 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
Kaushik, Sushant4975a572014-10-21 16:07:48 +05309489 hdd_scaninfo_t *pScanInfo = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07009490 union iwreq_data wrqu;
Kaushik, Sushant7005e372014-04-08 11:36:54 +05309491 v_U8_t retry = 0;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309492 long ret;
Nirav Shah7e3c8132015-06-22 23:51:42 +05309493 VOS_STATUS status;
Jeff Johnson295189b2012-06-20 16:38:30 -07009494
Anand N Sunkad26d71b92014-12-24 18:08:22 +05309495 if (pHddCtx->isLogpInProgress) {
9496 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
9497 "%s:LOGP in Progress. Ignore!!!",__func__);
9498 return VOS_STATUS_E_FAILURE;
9499 }
9500
Jeff Johnson295189b2012-06-20 16:38:30 -07009501 ENTER();
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +05309502
Kaushik, Sushant4975a572014-10-21 16:07:48 +05309503 pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07009504 switch(pAdapter->device_mode)
9505 {
Nirav Shah0cf4d892015-11-05 16:27:27 +05309506 case WLAN_HDD_IBSS:
9507 if ( VOS_TRUE == bCloseSession )
9508 {
9509 status = hdd_sta_id_hash_detach(pAdapter);
9510 if (status != VOS_STATUS_SUCCESS)
9511 hddLog(VOS_TRACE_LEVEL_ERROR,
9512 FL("sta id hash detach failed"));
9513 }
9514
Jeff Johnson295189b2012-06-20 16:38:30 -07009515 case WLAN_HDD_INFRA_STATION:
9516 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07009517 case WLAN_HDD_P2P_DEVICE:
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05309518 {
9519 hdd_station_ctx_t *pstation = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Mahesh A Saptasagare4d05d42015-07-02 16:17:20 +05309520#ifdef FEATURE_WLAN_TDLS
9521 mutex_lock(&pHddCtx->tdls_lock);
9522 wlan_hdd_tdls_exit(pAdapter, TRUE);
9523 mutex_unlock(&pHddCtx->tdls_lock);
9524#endif
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05309525 if( hdd_connIsConnected(pstation) ||
9526 (pstation->conn_info.connState == eConnectionState_Connecting) )
Jeff Johnson295189b2012-06-20 16:38:30 -07009527 {
Abhishek Singhe21a5212017-06-09 09:42:58 +05309528 /*
9529 * Indicate sme of disconnect so that in progress connection
9530 * or preauth can be aborted.
9531 */
9532 sme_abortConnection(WLAN_HDD_GET_HAL_CTX(pAdapter),
9533 pAdapter->sessionId);
Abhishek Singh99f17b82017-02-06 16:57:56 +05309534 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07009535 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
9536 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
9537 pAdapter->sessionId,
9538 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
9539 else
9540 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
9541 pAdapter->sessionId,
9542 eCSR_DISCONNECT_REASON_UNSPECIFIED);
Abhishek Singh7b52ed52016-02-11 17:45:54 +05309543 /* Success implies disconnect command got queued up successfully
9544 * Or cmd not queued as scan for SSID is in progress
9545 */
9546 if((eHAL_STATUS_SUCCESS == halStatus) ||
9547 (eHAL_STATUS_CMD_NOT_QUEUED == halStatus))
Jeff Johnson295189b2012-06-20 16:38:30 -07009548 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309549 ret = wait_for_completion_interruptible_timeout(
9550 &pAdapter->disconnect_comp_var,
9551 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Abhishek Singh7b52ed52016-02-11 17:45:54 +05309552 if (ret <= 0 &&
9553 (eHAL_STATUS_CMD_NOT_QUEUED != halStatus))
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309554 {
9555 hddLog(VOS_TRACE_LEVEL_ERROR,
9556 "%s: wait on disconnect_comp_var failed %ld",
9557 __func__, ret);
9558 }
9559 }
9560 else
9561 {
9562 hddLog(LOGE, "%s: failed to post disconnect event to SME",
9563 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009564 }
9565 memset(&wrqu, '\0', sizeof(wrqu));
9566 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
9567 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
9568 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
9569 }
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05309570 else if(pstation->conn_info.connState ==
9571 eConnectionState_Disconnecting)
9572 {
9573 ret = wait_for_completion_interruptible_timeout(
9574 &pAdapter->disconnect_comp_var,
9575 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
9576 if (ret <= 0)
9577 {
9578 hddLog(VOS_TRACE_LEVEL_ERROR,
9579 FL("wait on disconnect_comp_var failed %ld"), ret);
9580 }
9581 }
Sachin Ahuja27dd2402016-08-01 20:30:31 +05309582 if(pScanInfo != NULL && pHddCtx->scan_info.mScanPending)
Jeff Johnson295189b2012-06-20 16:38:30 -07009583 {
Mahesh A Saptasagar0b61dcc2016-02-15 14:23:38 +05309584 wlan_hdd_scan_abort(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07009585 }
Abhishek Singh3ac179b2015-09-21 10:01:34 +05309586 if ((pAdapter->device_mode != WLAN_HDD_INFRA_STATION) &&
9587 (pAdapter->device_mode != WLAN_HDD_IBSS))
Kaushik, Sushant7005e372014-04-08 11:36:54 +05309588 {
9589 while (pAdapter->is_roc_inprogress)
9590 {
9591 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9592 "%s: ROC in progress for session %d!!!",
9593 __func__, pAdapter->sessionId);
9594 // waiting for ROC to expire
9595 msleep(500);
9596 /* In GO present case , if retry exceeds 3,
9597 it means something went wrong. */
9598 if ( retry++ > MAX_WAIT_FOR_ROC_COMPLETION )
9599 {
9600 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9601 "%s: ROC completion is not received.!!!", __func__);
Deepthi Gowri70498252015-01-20 15:56:45 +05309602 if (eHAL_STATUS_SUCCESS !=
9603 sme_CancelRemainOnChannel( WLAN_HDD_GET_HAL_CTX( pAdapter),
9604 pAdapter->sessionId ))
9605 {
9606 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9607 FL("Failed to Cancel Remain on Channel"));
9608 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +05309609 wait_for_completion_interruptible_timeout(
9610 &pAdapter->cancel_rem_on_chan_var,
9611 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
9612 break;
9613 }
9614 }
Anand N Sunkaddc63c792015-06-03 14:33:24 +05309615 vos_flush_delayed_work(&pAdapter->roc_work);
Kaushik, Sushant7005e372014-04-08 11:36:54 +05309616 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05309617#ifdef WLAN_NS_OFFLOAD
Anand N Sunkaddc63c792015-06-03 14:33:24 +05309618 vos_flush_work(&pAdapter->ipv6NotifierWorkQueue);
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05309619#endif
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +05309620
Anand N Sunkaddc63c792015-06-03 14:33:24 +05309621 vos_flush_work(&pAdapter->ipv4NotifierWorkQueue);
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +05309622
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05309623 /* It is possible that the caller of this function does not
9624 * wish to close the session
9625 */
9626 if (VOS_TRUE == bCloseSession &&
9627 test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07009628 {
9629 INIT_COMPLETION(pAdapter->session_close_comp_var);
9630 if (eHAL_STATUS_SUCCESS ==
Agrawal Ashish5a3522c2016-03-02 15:08:28 +05309631 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId, FALSE,
9632 VOS_FALSE, hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07009633 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309634 unsigned long ret;
9635
Jeff Johnson295189b2012-06-20 16:38:30 -07009636 //Block on a completion variable. Can't wait forever though.
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309637 ret = wait_for_completion_timeout(
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05309638 &pAdapter->session_close_comp_var,
9639 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309640 if ( 0 >= ret)
9641 {
9642 hddLog(LOGE, "%s: failure waiting for session_close_comp_var %ld",
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05309643 __func__, ret);
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309644 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009645 }
9646 }
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05309647 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009648 break;
9649
9650 case WLAN_HDD_SOFTAP:
9651 case WLAN_HDD_P2P_GO:
Nirav Shah0cf4d892015-11-05 16:27:27 +05309652 if ( VOS_TRUE == bCloseSession )
9653 {
9654 status = hdd_sta_id_hash_detach(pAdapter);
9655 if (status != VOS_STATUS_SUCCESS)
9656 hddLog(VOS_TRACE_LEVEL_ERROR,
9657 FL("sta id hash detach failed"));
9658 }
9659
Jeff Johnson295189b2012-06-20 16:38:30 -07009660 //Any softap specific cleanup here...
Anurag Chouhan83026002016-12-13 22:46:21 +05309661 hdd_cleanup_ap_events(pAdapter);
Kaushik, Sushant7005e372014-04-08 11:36:54 +05309662 if (pAdapter->device_mode == WLAN_HDD_P2P_GO) {
9663 while (pAdapter->is_roc_inprogress) {
9664 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9665 "%s: ROC in progress for session %d!!!",
9666 __func__, pAdapter->sessionId);
9667 msleep(500);
9668 if ( retry++ > MAX_WAIT_FOR_ROC_COMPLETION ) {
9669 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9670 "%s: ROC completion is not received.!!!", __func__);
9671 WLANSAP_CancelRemainOnChannel(
9672 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
9673 wait_for_completion_interruptible_timeout(
9674 &pAdapter->cancel_rem_on_chan_var,
9675 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
9676 break;
9677 }
9678 }
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +05309679
Anand N Sunkaddc63c792015-06-03 14:33:24 +05309680 vos_flush_delayed_work(&pAdapter->roc_work);
Kaushik, Sushant7005e372014-04-08 11:36:54 +05309681 }
Agrawal Ashish17ef5082016-10-17 18:33:21 +05309682#ifdef SAP_AUTH_OFFLOAD
9683 if (pHddCtx->cfg_ini->enable_sap_auth_offload)
9684 hdd_set_sap_auth_offload(pAdapter, FALSE);
9685#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009686 mutex_lock(&pHddCtx->sap_lock);
9687 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
9688 {
9689 VOS_STATUS status;
9690 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9691
9692 //Stop Bss.
9693 status = WLANSAP_StopBss(pHddCtx->pvosContext);
9694 if (VOS_IS_STATUS_SUCCESS(status))
9695 {
9696 hdd_hostapd_state_t *pHostapdState =
9697 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
9698
9699 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
9700
9701 if (!VOS_IS_STATUS_SUCCESS(status))
9702 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309703 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss %d",
9704 __func__, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07009705 }
9706 }
9707 else
9708 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07009709 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009710 }
9711 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
Agarwal Ashish51325b52014-06-16 16:50:49 +05309712 wlan_hdd_decr_active_session(pHddCtx, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07009713
9714 if (eHAL_STATUS_FAILURE ==
9715 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
9716 0, NULL, eANI_BOOLEAN_FALSE))
9717 {
9718 hddLog(LOGE,
9719 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07009720 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009721 }
9722
9723 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
9724 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
9725 eANI_BOOLEAN_FALSE) )
9726 {
9727 hddLog(LOGE,
9728 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
9729 }
9730
9731 // Reset WNI_CFG_PROBE_RSP Flags
9732 wlan_hdd_reset_prob_rspies(pAdapter);
9733 kfree(pAdapter->sessionCtx.ap.beacon);
9734 pAdapter->sessionCtx.ap.beacon = NULL;
9735 }
9736 mutex_unlock(&pHddCtx->sap_lock);
Hanumanth Reddy Pothulab4537b82018-03-02 12:20:38 +05309737
9738#ifdef WLAN_NS_OFFLOAD
9739 vos_flush_work(&pAdapter->ipv6NotifierWorkQueue);
9740#endif
9741 vos_flush_work(&pAdapter->ipv4NotifierWorkQueue);
9742
Jeff Johnson295189b2012-06-20 16:38:30 -07009743 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07009744
Jeff Johnson295189b2012-06-20 16:38:30 -07009745 case WLAN_HDD_MONITOR:
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05309746 if (VOS_MONITOR_MODE != hdd_get_conparam())
9747 wlan_hdd_stop_mon(pHddCtx, true);
9748 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07009749
Jeff Johnson295189b2012-06-20 16:38:30 -07009750 default:
9751 break;
9752 }
9753
9754 EXIT();
9755 return VOS_STATUS_SUCCESS;
9756}
9757
Kapil Gupta137ef892016-12-13 19:38:00 +05309758/**
9759 * wlan_hdd_restart_sap() - to restart SAP in driver internally
9760 * @ap_adapter: - Pointer to SAP hdd_adapter_t structure
9761 *
9762 * wlan_hdd_restart_sap first delete SAP and do cleanup.
9763 * After that WLANSAP_StartBss start re-start process of SAP.
9764 *
9765 * Return: None
9766 */
9767static void wlan_hdd_restart_sap(hdd_adapter_t *ap_adapter)
9768{
9769 hdd_ap_ctx_t *pHddApCtx;
9770 hdd_hostapd_state_t *pHostapdState;
9771 VOS_STATUS vos_status;
9772 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(ap_adapter);
Rajeev Kumar Sirasanagandla5b21a9c2018-01-08 17:05:11 +05309773#ifdef USE_CFG80211_DEL_STA_V2
Kapil Gupta137ef892016-12-13 19:38:00 +05309774 struct station_del_parameters delStaParams;
9775#endif
9776 tsap_Config_t *pConfig;
9777
9778 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
9779 pConfig = &pHddApCtx->sapConfig;
9780
9781 mutex_lock(&pHddCtx->sap_lock);
9782 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags)) {
Rajeev Kumar Sirasanagandla5b21a9c2018-01-08 17:05:11 +05309783#ifdef USE_CFG80211_DEL_STA_V2
Kapil Gupta137ef892016-12-13 19:38:00 +05309784 delStaParams.mac = NULL;
9785 delStaParams.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
9786 delStaParams.reason_code = eCsrForcedDeauthSta;
9787 wlan_hdd_cfg80211_del_station(ap_adapter->wdev.wiphy, ap_adapter->dev,
9788 &delStaParams);
9789#else
9790 wlan_hdd_cfg80211_del_station(ap_adapter->wdev.wiphy, ap_adapter->dev,
9791 NULL);
9792#endif
9793 hdd_cleanup_actionframe(pHddCtx, ap_adapter);
9794
9795 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
9796 vos_event_reset(&pHostapdState->vosEvent);
9797
9798 if (VOS_STATUS_SUCCESS == WLANSAP_StopBss(pHddCtx->pvosContext)) {
9799 vos_status = vos_wait_single_event(&pHostapdState->vosEvent,
9800 10000);
9801 if (!VOS_IS_STATUS_SUCCESS(vos_status)) {
9802 hddLog(LOGE, FL("SAP Stop Failed"));
9803 goto end;
9804 }
9805 }
9806 clear_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
9807 wlan_hdd_decr_active_session(pHddCtx, ap_adapter->device_mode);
9808 hddLog(LOG1, FL("SAP Stop Success"));
9809
9810 if (0 != wlan_hdd_cfg80211_update_apies(ap_adapter)) {
9811 hddLog(LOGE, FL("SAP Not able to set AP IEs"));
9812 goto end;
9813 }
9814
9815 if (WLANSAP_StartBss(pHddCtx->pvosContext, hdd_hostapd_SAPEventCB,
9816 pConfig, (v_PVOID_t)ap_adapter->dev) != VOS_STATUS_SUCCESS) {
9817 hddLog(LOGE, FL("SAP Start Bss fail"));
9818 goto end;
9819 }
9820
9821 hddLog(LOG1, FL("Waiting for SAP to start"));
9822 vos_status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
9823 if (!VOS_IS_STATUS_SUCCESS(vos_status)) {
9824 hddLog(LOGE, FL("SAP Start failed"));
9825 goto end;
9826 }
9827 hddLog(LOG1, FL("SAP Start Success"));
9828 set_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
9829 wlan_hdd_incr_active_session(pHddCtx, ap_adapter->device_mode);
9830 pHostapdState->bCommit = TRUE;
Anurag Chouhanb2951ae2017-03-12 13:41:35 +05309831 if (!VOS_IS_STATUS_SUCCESS(hdd_dhcp_mdns_offload(ap_adapter))) {
9832 hddLog(VOS_TRACE_LEVEL_ERROR, FL("DHCP/MDNS offload Failed!!"));
9833 vos_event_reset(&pHostapdState->vosEvent);
9834 if (VOS_STATUS_SUCCESS == WLANSAP_StopBss(pHddCtx->pvosContext)) {
9835 vos_status = vos_wait_single_event(&pHostapdState->vosEvent,
9836 10000);
9837 if (!VOS_IS_STATUS_SUCCESS(vos_status)) {
9838 hddLog(LOGE, FL("SAP Stop Failed"));
9839 goto end;
9840 }
9841 }
9842 }
Kapil Gupta137ef892016-12-13 19:38:00 +05309843 }
9844end:
9845 mutex_unlock(&pHddCtx->sap_lock);
9846 return;
9847}
9848
9849/**
9850 * __hdd_sap_restart_handle() - to handle restarting of SAP
9851 * @work: name of the work
9852 *
9853 * Purpose of this function is to trigger sap start. this function
9854 * will be called from workqueue.
9855 *
9856 * Return: void.
9857 */
9858static void __hdd_sap_restart_handle(struct work_struct *work)
9859{
9860 hdd_adapter_t *sap_adapter;
9861 hdd_context_t *hdd_ctx = container_of(work,
9862 hdd_context_t,
9863 sap_start_work);
9864 if (0 != wlan_hdd_validate_context(hdd_ctx)) {
9865 vos_ssr_unprotect(__func__);
9866 return;
9867 }
9868 sap_adapter = hdd_get_adapter(hdd_ctx,
9869 WLAN_HDD_SOFTAP);
9870 if (sap_adapter == NULL) {
9871 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9872 FL("sap_adapter is NULL"));
9873 vos_ssr_unprotect(__func__);
9874 return;
9875 }
9876
9877 if (hdd_ctx->is_ch_avoid_in_progress) {
9878 sap_adapter->sessionCtx.ap.sapConfig.channel = AUTO_CHANNEL_SELECT;
9879 wlan_hdd_restart_sap(sap_adapter);
9880 hdd_change_ch_avoidance_status(hdd_ctx, false);
9881 }
Agrawal Ashish574b3e62017-02-09 18:58:34 +05309882 if (hdd_ctx->cfg_ini->enable_sap_auth_offload)
9883 wlan_hdd_restart_sap(sap_adapter);
Kapil Gupta137ef892016-12-13 19:38:00 +05309884}
9885
9886/**
9887 * hdd_sap_restart_handle() - to handle restarting of SAP
9888 * @work: name of the work
9889 *
9890 * Purpose of this function is to trigger sap start. this function
9891 * will be called from workqueue.
9892 *
9893 * Return: void.
9894 */
9895static void hdd_sap_restart_handle(struct work_struct *work)
9896{
9897 vos_ssr_protect(__func__);
9898 __hdd_sap_restart_handle(work);
9899 vos_ssr_unprotect(__func__);
9900}
9901
9902
Abhishek Singh78c691f2017-11-30 13:48:44 +05309903/**
9904 * __hdd_force_scc_with_ecsa_handle() - to handle force scc using ecsa
9905 * @work: name of the work
9906 *
9907 * Purpose of this function is to force SCC using ECSA. This function
9908 * will be called from workqueue.
9909 *
9910 * Return: void.
9911 */
9912static void
9913__hdd_force_scc_with_ecsa_handle(struct work_struct *work)
9914{
9915 hdd_adapter_t *sap_adapter;
9916 hdd_station_ctx_t *sta_ctx;
9917 hdd_adapter_t *sta_adapter;
Ganesh Kondabattini3655a6d2018-01-08 20:25:39 +05309918 ptSapContext sap_ctx = NULL;
9919 v_CONTEXT_t vos_ctx;
9920 tANI_U8 target_channel;
9921 tsap_Config_t *sap_config;
9922 bool sta_sap_scc_on_dfs_chan;
9923 eNVChannelEnabledType chan_state;
Abhishek Singh78c691f2017-11-30 13:48:44 +05309924 hdd_context_t *hdd_ctx = container_of(to_delayed_work(work),
9925 hdd_context_t,
9926 ecsa_chan_change_work);
9927
9928 if (wlan_hdd_validate_context(hdd_ctx))
9929 return;
9930
9931 sap_adapter = hdd_get_adapter(hdd_ctx,
9932 WLAN_HDD_SOFTAP);
9933 if (!sap_adapter) {
9934 hddLog(LOGE, FL("sap_adapter is NULL"));
9935 return;
9936 }
9937
Ganesh Kondabattini3655a6d2018-01-08 20:25:39 +05309938 vos_ctx = hdd_ctx->pvosContext;
9939 if (!vos_ctx) {
9940 hddLog(LOGE, FL("vos_ctx is NULL"));
9941 return;
9942 }
9943
9944 sap_ctx = VOS_GET_SAP_CB(vos_ctx);
9945 if (!sap_ctx) {
9946 hddLog(LOGE, FL("sap_ctx is NULL"));
9947 return;
9948 }
9949
9950 sap_config = &sap_adapter->sessionCtx.ap.sapConfig;
9951
9952 sta_sap_scc_on_dfs_chan = hdd_is_sta_sap_scc_allowed_on_dfs_chan(hdd_ctx);
9953
Abhishek Singh78c691f2017-11-30 13:48:44 +05309954 sta_adapter = hdd_get_adapter(hdd_ctx,
9955 WLAN_HDD_INFRA_STATION);
9956 if (!sta_adapter) {
9957 hddLog(LOGE, FL("sta_adapter is NULL"));
9958 return;
9959 }
9960 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(sta_adapter);
9961
9962 if (sta_ctx->conn_info.connState != eConnectionState_Associated) {
Ganesh Kondabattini3655a6d2018-01-08 20:25:39 +05309963 chan_state = vos_nv_getChannelEnabledState(sap_ctx->channel);
9964 hddLog(LOG1, FL("sta not in connected state %d, sta_sap_scc_on_dfs_chan %d, chan_state %d"),
9965 sta_ctx->conn_info.connState, sta_sap_scc_on_dfs_chan,
9966 chan_state);
9967 if (sta_sap_scc_on_dfs_chan &&
9968 (chan_state == NV_CHANNEL_DFS)) {
9969 hddLog(LOG1, FL("Switch SAP to user configured channel"));
9970 target_channel = sap_config->user_config_channel;
9971 goto switch_channel;
9972
9973 }
Abhishek Singh78c691f2017-11-30 13:48:44 +05309974 return;
9975 }
9976
Ganesh Kondabattini3655a6d2018-01-08 20:25:39 +05309977 target_channel = sta_ctx->conn_info.operationChannel;
9978switch_channel:
9979 hddLog(LOGE, FL("Switch SAP to %d channel"),
9980 target_channel);
9981 wlansap_set_channel_change(vos_ctx, target_channel, true);
Abhishek Singh78c691f2017-11-30 13:48:44 +05309982}
9983
9984/**
9985 * hdd_force_scc_with_ecsa_handle() - to handle force scc using ecsa
9986 * @work: name of the work
9987 *
9988 * Purpose of this function is to force SCC using ECSA. This function
9989 * will be called from workqueue.
9990 *
9991 * Return: void.
9992 */
9993static void
9994hdd_force_scc_with_ecsa_handle(struct work_struct *work)
9995{
9996 vos_ssr_protect(__func__);
9997 __hdd_force_scc_with_ecsa_handle(work);
9998 vos_ssr_unprotect(__func__);
9999}
10000
Ganesh Kondabattini3655a6d2018-01-08 20:25:39 +053010001/**
10002 * hdd_is_sta_sap_scc_allowed_on_dfs_chan() - check if sta+sap scc allowed on
10003 * dfs chan
10004 * @hdd_ctx: pointer to hdd context
10005 *
10006 * This function used to check if sta+sap scc allowed on DFS channel.
10007 *
10008 * Return: None
10009 */
10010bool hdd_is_sta_sap_scc_allowed_on_dfs_chan(hdd_context_t *hdd_ctx)
10011{
10012 if (hdd_ctx->cfg_ini->force_scc_with_ecsa &&
10013 hdd_ctx->cfg_ini->sta_sap_scc_on_dfs_chan)
10014 return true;
10015 else
10016 return false;
10017}
10018
Jeff Johnson295189b2012-06-20 16:38:30 -070010019VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
10020{
10021 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
10022 VOS_STATUS status;
10023 hdd_adapter_t *pAdapter;
10024
10025 ENTER();
10026
10027 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10028
10029 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
10030 {
10031 pAdapter = pAdapterNode->pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -070010032
Agarwal Ashish3a38bd12014-06-12 15:16:52 +053010033 hdd_stop_adapter( pHddCtx, pAdapter, VOS_TRUE );
Jeff Johnson295189b2012-06-20 16:38:30 -070010034
10035 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10036 pAdapterNode = pNext;
10037 }
10038
10039 EXIT();
10040
10041 return VOS_STATUS_SUCCESS;
10042}
10043
Rajeev Kumarf999e582014-01-09 17:33:29 -080010044
10045#ifdef FEATURE_WLAN_BATCH_SCAN
10046/**---------------------------------------------------------------------------
10047
10048 \brief hdd_deinit_batch_scan () - This function cleans up batch scan data
10049 structures
10050
10051 \param - pAdapter Pointer to HDD adapter
10052
10053 \return - None
10054
10055 --------------------------------------------------------------------------*/
10056void hdd_deinit_batch_scan(hdd_adapter_t *pAdapter)
10057{
10058 tHddBatchScanRsp *pNode;
10059 tHddBatchScanRsp *pPrev;
10060
Siddharth Bhalb3e9b792014-02-24 15:14:16 +053010061 if (NULL == pAdapter)
Rajeev Kumarf999e582014-01-09 17:33:29 -080010062 {
Siddharth Bhalb3e9b792014-02-24 15:14:16 +053010063 hddLog(VOS_TRACE_LEVEL_ERROR,
10064 "%s: Adapter context is Null", __func__);
10065 return;
10066 }
10067
10068 pNode = pAdapter->pBatchScanRsp;
10069 while (pNode)
10070 {
10071 pPrev = pNode;
10072 pNode = pNode->pNext;
10073 vos_mem_free((v_VOID_t * )pPrev);
Rajeev Kumarf999e582014-01-09 17:33:29 -080010074 }
10075
10076 pAdapter->pBatchScanRsp = NULL;
10077 pAdapter->numScanList = 0;
10078 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
10079 pAdapter->prev_batch_id = 0;
10080
10081 return;
10082}
10083#endif
10084
10085
Jeff Johnson295189b2012-06-20 16:38:30 -070010086VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
10087{
10088 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
10089 VOS_STATUS status;
10090 hdd_adapter_t *pAdapter;
10091
10092 ENTER();
10093
10094 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10095
10096 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
10097 {
10098 pAdapter = pAdapterNode->pAdapter;
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +053010099 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
Jeff Johnson295189b2012-06-20 16:38:30 -070010100 netif_tx_disable(pAdapter->dev);
Hanumanth Reddy Pothulad864f312017-01-18 16:16:08 +053010101
10102 if (pHddCtx->cfg_ini->sap_internal_restart &&
10103 pAdapter->device_mode == WLAN_HDD_SOFTAP) {
10104 hddLog(LOG1, FL("driver supports sap restart"));
10105 vos_flush_work(&pHddCtx->sap_start_work);
10106 hdd_sap_indicate_disconnect_for_sta(pAdapter);
10107 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Hanumanth Reddy Pothula15bc0fa2017-02-03 17:24:17 +053010108 hdd_softap_deinit_tx_rx(pAdapter, true);
10109 hdd_sap_destroy_timers(pAdapter);
Hanumanth Reddy Pothulad864f312017-01-18 16:16:08 +053010110 } else {
10111 netif_carrier_off(pAdapter->dev);
10112 }
Jeff Johnson295189b2012-06-20 16:38:30 -070010113
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -070010114 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +053010115 pAdapter->sessionCtx.monitor.state = MON_MODE_STOP;
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -070010116
Jeff Johnson295189b2012-06-20 16:38:30 -070010117 hdd_deinit_tx_rx(pAdapter);
Agarwal Ashish6267caa2014-08-06 19:16:21 +053010118
Katya Nigam1fd24402015-02-16 14:52:19 +053010119 if(pAdapter->device_mode == WLAN_HDD_IBSS )
10120 hdd_ibss_deinit_tx_rx(pAdapter);
10121
Nirav Shah7e3c8132015-06-22 23:51:42 +053010122 status = hdd_sta_id_hash_detach(pAdapter);
10123 if (status != VOS_STATUS_SUCCESS)
10124 hddLog(VOS_TRACE_LEVEL_ERROR,
10125 FL("sta id hash detach failed for session id %d"),
10126 pAdapter->sessionId);
10127
Agarwal Ashish6267caa2014-08-06 19:16:21 +053010128 wlan_hdd_decr_active_session(pHddCtx, pAdapter->device_mode);
10129
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +053010130 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
10131 {
10132 hdd_wmm_adapter_close( pAdapter );
10133 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
10134 }
Jeff Johnson295189b2012-06-20 16:38:30 -070010135
Siddharth Bhal2db319d2014-12-03 12:37:18 +053010136 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
10137 {
10138 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
10139 }
10140
Rajeev Kumarf999e582014-01-09 17:33:29 -080010141#ifdef FEATURE_WLAN_BATCH_SCAN
10142 if (eHDD_BATCH_SCAN_STATE_STARTED == pAdapter->batchScanState)
10143 {
10144 hdd_deinit_batch_scan(pAdapter);
10145 }
10146#endif
10147
Mahesh A Saptasagarf5b8eff2015-01-31 01:07:07 +053010148#ifdef FEATURE_WLAN_TDLS
10149 mutex_lock(&pHddCtx->tdls_lock);
Pradeep Reddy POTTETI2d4d5c42015-03-03 14:34:19 +053010150 wlan_hdd_tdls_exit(pAdapter, TRUE);
Mahesh A Saptasagarf5b8eff2015-01-31 01:07:07 +053010151 mutex_unlock(&pHddCtx->tdls_lock);
10152#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070010153 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10154 pAdapterNode = pNext;
10155 }
10156
10157 EXIT();
10158
10159 return VOS_STATUS_SUCCESS;
10160}
10161
Abhishek Singhbbe0b2a2016-12-05 11:57:36 +053010162/**
Abhishek Singh5a597e62016-12-05 15:16:30 +053010163 * hdd_get_bss_entry() - Get the bss entry matching the chan, bssid and ssid
10164 * @wiphy: wiphy
10165 * @channel: channel of the BSS to find
10166 * @bssid: bssid of the BSS to find
10167 * @ssid: ssid of the BSS to find
10168 * @ssid_len: ssid len of of the BSS to find
10169 *
10170 * The API is a wrapper to get bss from kernel matching the chan,
10171 * bssid and ssid
10172 *
10173 * Return: Void
10174 */
10175#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) \
10176 && !defined(WITH_BACKPORTS) && !defined(IEEE80211_PRIVACY)
10177
10178struct cfg80211_bss* hdd_get_bss_entry(struct wiphy *wiphy,
10179 struct ieee80211_channel *channel,
10180 const u8 *bssid,
10181 const u8 *ssid, size_t ssid_len)
10182{
10183 return cfg80211_get_bss(wiphy, channel, bssid,
10184 ssid, ssid_len,
10185 WLAN_CAPABILITY_ESS,
10186 WLAN_CAPABILITY_ESS);
10187}
10188#else
10189struct cfg80211_bss* hdd_get_bss_entry(struct wiphy *wiphy,
10190 struct ieee80211_channel *channel,
10191 const u8 *bssid,
10192 const u8 *ssid, size_t ssid_len)
10193{
10194 return cfg80211_get_bss(wiphy, channel, bssid,
10195 ssid, ssid_len,
10196 IEEE80211_BSS_TYPE_ESS,
10197 IEEE80211_PRIVACY_ANY);
10198}
10199#endif
10200
Rajeev Kumar Sirasanagandla5b21a9c2018-01-08 17:05:11 +053010201#if defined(CFG80211_CONNECT_BSS) || \
10202 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
10203
10204#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) || \
10205 defined (CFG80211_CONNECT_TIMEOUT_REASON_CODE)
10206/**
10207 * hdd_connect_bss() - helper function to send connection status to supplicant
10208 * @dev: network device
10209 * @bssid: bssid to which we want to associate
10210 * @bss: information about connected bss
10211 * @req_ie: Request Information Element
10212 * @req_ie_len: len of the req IE
10213 * @resp_ie: Response IE
10214 * @resp_ie_len: len of ht response IE
10215 * @status: status
10216 * @gfp: Kernel Flag
10217 *
10218 * This is a helper function to send connection status to supplicant
10219 * and gets invoked from wrapper API
10220 *
10221 * Return: Void
10222 */
10223static void hdd_connect_bss(struct net_device *dev,
10224 const u8 *bssid,
10225 struct cfg80211_bss *bss,
10226 const u8 *req_ie,
10227 size_t req_ie_len,
10228 const u8 *resp_ie,
10229 size_t resp_ie_len,
10230 u16 status,
10231 gfp_t gfp)
10232{
10233 cfg80211_connect_bss(dev, bssid, bss, req_ie, req_ie_len,
10234 resp_ie, resp_ie_len, status, gfp, NL80211_TIMEOUT_UNSPECIFIED);
10235}
10236#else
10237/**
10238 * hdd_connect_bss() - helper function to send connection status to supplicant
10239 * @dev: network device
10240 * @bssid: bssid to which we want to associate
10241 * @bss: information about connected bss
10242 * @req_ie: Request Information Element
10243 * @req_ie_len: len of the req IE
10244 * @resp_ie: Response IE
10245 * @resp_ie_len: len of ht response IE
10246 * @status: status
10247 * @gfp: Kernel Flag
10248 *
10249 * This is a helper function to send connection status to supplicant
10250 * and gets invoked from wrapper API
10251 *
10252 * Return: Void
10253 */
10254static void hdd_connect_bss(struct net_device *dev,
10255 const u8 *bssid,
10256 struct cfg80211_bss *bss,
10257 const u8 *req_ie,
10258 size_t req_ie_len,
10259 const u8 *resp_ie,
10260 size_t resp_ie_len,
10261 u16 status,
10262 gfp_t gfp)
10263{
10264 cfg80211_connect_bss(dev, bssid, bss, req_ie, req_ie_len,
10265 resp_ie, resp_ie_len, status, gfp);
10266}
10267#endif
10268
Abhishek Singh5a597e62016-12-05 15:16:30 +053010269/**
Abhishek Singhbbe0b2a2016-12-05 11:57:36 +053010270 * hdd_connect_result() - API to send connection status to supplicant
10271 * @dev: network device
10272 * @bssid: bssid to which we want to associate
10273 * @roam_info: information about connected bss
10274 * @req_ie: Request Information Element
10275 * @req_ie_len: len of the req IE
10276 * @resp_ie: Response IE
10277 * @resp_ie_len: len of ht response IE
10278 * @status: status
10279 * @gfp: Kernel Flag
10280 *
10281 * The API is a wrapper to send connection status to supplicant
10282 *
10283 * Return: Void
10284 */
Abhishek Singhbbe0b2a2016-12-05 11:57:36 +053010285void hdd_connect_result(struct net_device *dev,
10286 const u8 *bssid,
10287 tCsrRoamInfo *roam_info,
10288 const u8 *req_ie,
10289 size_t req_ie_len,
10290 const u8 *resp_ie,
10291 size_t resp_ie_len,
10292 u16 status,
10293 gfp_t gfp)
10294{
10295 hdd_adapter_t *padapter = (hdd_adapter_t *) netdev_priv(dev);
10296 struct cfg80211_bss *bss = NULL;
10297
10298 if (WLAN_STATUS_SUCCESS == status) {
10299 struct ieee80211_channel *chan;
10300 int freq;
10301 int chan_no = roam_info->pBssDesc->channelId;;
10302
10303 if (chan_no <= 14)
10304 freq = ieee80211_channel_to_frequency(chan_no,
Rajeev Kumar Sirasanagandla5b21a9c2018-01-08 17:05:11 +053010305 HDD_NL80211_BAND_2GHZ);
Abhishek Singhbbe0b2a2016-12-05 11:57:36 +053010306 else
10307 freq = ieee80211_channel_to_frequency(chan_no,
Rajeev Kumar Sirasanagandla5b21a9c2018-01-08 17:05:11 +053010308 HDD_NL80211_BAND_5GHZ);
Abhishek Singhbbe0b2a2016-12-05 11:57:36 +053010309
10310 chan = ieee80211_get_channel(padapter->wdev.wiphy, freq);
Abhishek Singh5a597e62016-12-05 15:16:30 +053010311 bss = hdd_get_bss_entry(padapter->wdev.wiphy,
10312 chan, bssid,
10313 roam_info->u.pConnectedProfile->SSID.ssId,
10314 roam_info->u.pConnectedProfile->SSID.length);
Abhishek Singhbbe0b2a2016-12-05 11:57:36 +053010315 }
10316
Rajeev Kumar Sirasanagandla5b21a9c2018-01-08 17:05:11 +053010317 hdd_connect_bss(dev, bssid, bss, req_ie, req_ie_len, resp_ie, resp_ie_len,
10318 status, gfp);
Abhishek Singhbbe0b2a2016-12-05 11:57:36 +053010319}
10320#else
Rajeev Kumar Sirasanagandla5b21a9c2018-01-08 17:05:11 +053010321/**
10322 * hdd_connect_result() - API to send connection status to supplicant
10323 * @dev: network device
10324 * @bssid: bssid to which we want to associate
10325 * @roam_info: information about connected bss
10326 * @req_ie: Request Information Element
10327 * @req_ie_len: len of the req IE
10328 * @resp_ie: Response IE
10329 * @resp_ie_len: len of ht response IE
10330 * @status: status
10331 * @gfp: Kernel Flag
10332 *
10333 * The API is a wrapper to send connection status to supplicant
10334 *
10335 * Return: Void
10336 */
Abhishek Singhbbe0b2a2016-12-05 11:57:36 +053010337void hdd_connect_result(struct net_device *dev,
10338 const u8 *bssid,
10339 tCsrRoamInfo *roam_info,
10340 const u8 *req_ie,
10341 size_t req_ie_len,
10342 const u8 * resp_ie,
10343 size_t resp_ie_len,
10344 u16 status,
10345 gfp_t gfp)
10346{
10347 cfg80211_connect_result(dev, bssid, req_ie, req_ie_len,
10348 resp_ie, resp_ie_len, status, gfp);
10349}
10350#endif
10351
Jeff Johnson295189b2012-06-20 16:38:30 -070010352VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
10353{
10354 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
10355 VOS_STATUS status;
10356 hdd_adapter_t *pAdapter;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +053010357 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -070010358
10359 ENTER();
10360
10361 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10362
10363 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
10364 {
10365 pAdapter = pAdapterNode->pAdapter;
10366
Kumar Anand82c009f2014-05-29 00:29:42 -070010367 hdd_wmm_init( pAdapter );
10368
Jeff Johnson295189b2012-06-20 16:38:30 -070010369 switch(pAdapter->device_mode)
10370 {
10371 case WLAN_HDD_INFRA_STATION:
10372 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -070010373 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +053010374
10375 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
10376
Jeff Johnson295189b2012-06-20 16:38:30 -070010377 hdd_init_station_mode(pAdapter);
10378 /* Open the gates for HDD to receive Wext commands */
10379 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -070010380 pHddCtx->scan_info.mScanPending = FALSE;
10381 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -070010382
10383 //Trigger the initial scan
Mukul Sharmae74e42c2015-08-06 23:55:49 +053010384 if (!pHddCtx->isLogpInProgress)
10385 hdd_wlan_initial_scan(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -070010386
10387 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +053010388 if (eConnectionState_Associated == connState ||
10389 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -070010390 {
10391 union iwreq_data wrqu;
10392 memset(&wrqu, '\0', sizeof(wrqu));
10393 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
10394 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
10395 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -070010396 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -070010397
Jeff Johnson295189b2012-06-20 16:38:30 -070010398 /* indicate disconnected event to nl80211 */
Mahesh A Saptasagar9ff4bcc2016-06-01 17:17:50 +053010399 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, false,
Mahesh A Saptasagarb5a15142016-05-25 11:27:43 +053010400 WLAN_REASON_UNSPECIFIED);
Jeff Johnson295189b2012-06-20 16:38:30 -070010401 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +053010402 else if (eConnectionState_Connecting == connState)
10403 {
10404 /*
10405 * Indicate connect failure to supplicant if we were in the
10406 * process of connecting
10407 */
Abhishek Singhbbe0b2a2016-12-05 11:57:36 +053010408 hdd_connect_result(pAdapter->dev, NULL, NULL,
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +053010409 NULL, 0, NULL, 0,
10410 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
10411 GFP_KERNEL);
10412 }
Jeff Johnson295189b2012-06-20 16:38:30 -070010413 break;
10414
10415 case WLAN_HDD_SOFTAP:
Hanumanth Reddy Pothulad864f312017-01-18 16:16:08 +053010416 if (pHddCtx->cfg_ini->sap_internal_restart) {
Hanumanth Reddy Pothula15bc0fa2017-02-03 17:24:17 +053010417 hdd_init_ap_mode(pAdapter, true);
Hanumanth Reddy Pothulad864f312017-01-18 16:16:08 +053010418 status = hdd_sta_id_hash_attach(pAdapter);
10419 if (VOS_STATUS_SUCCESS != status)
10420 {
10421 hddLog(VOS_TRACE_LEVEL_FATAL,
10422 FL("failed to attach hash for"));
10423 }
10424 }
Jeff Johnson295189b2012-06-20 16:38:30 -070010425 break;
10426
10427 case WLAN_HDD_P2P_GO:
Sameer Thalappiledf0d792013-08-09 14:31:03 -070010428 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send stop ap to supplicant",
Jeff Johnson295189b2012-06-20 16:38:30 -070010429 __func__);
Sameer Thalappiledf0d792013-08-09 14:31:03 -070010430 cfg80211_ap_stopped(pAdapter->dev, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -070010431 break;
10432
10433 case WLAN_HDD_MONITOR:
10434 /* monitor interface start */
10435 break;
10436 default:
10437 break;
10438 }
10439
10440 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10441 pAdapterNode = pNext;
10442 }
10443
10444 EXIT();
10445
10446 return VOS_STATUS_SUCCESS;
10447}
10448
10449VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
10450{
10451 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
10452 hdd_adapter_t *pAdapter;
10453 VOS_STATUS status;
10454 v_U32_t roamId;
c_hpothu6ff1c3c2013-10-01 19:01:57 +053010455 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -070010456
10457 ENTER();
10458
10459 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10460
10461 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
10462 {
10463 pAdapter = pAdapterNode->pAdapter;
10464
10465 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
10466 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
10467 {
10468 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10469 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10470
Abhishek Singhf4669da2014-05-26 15:07:49 +053010471 hddLog(VOS_TRACE_LEVEL_INFO,
10472 "%s: Set HDD connState to eConnectionState_NotConnected",
10473 __func__);
Ganesh Kondabattini04338412015-09-14 15:39:09 +053010474 spin_lock_bh(&pAdapter->lock_for_active_session);
10475 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState)
10476 {
10477 wlan_hdd_decr_active_session(pHddCtx, pAdapter->device_mode);
10478 }
Jeff Johnson295189b2012-06-20 16:38:30 -070010479 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
Ganesh Kondabattini04338412015-09-14 15:39:09 +053010480 spin_unlock_bh(&pAdapter->lock_for_active_session);
Jeff Johnson295189b2012-06-20 16:38:30 -070010481 init_completion(&pAdapter->disconnect_comp_var);
10482 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
10483 eCSR_DISCONNECT_REASON_UNSPECIFIED);
10484
c_hpothu6ff1c3c2013-10-01 19:01:57 +053010485 ret = wait_for_completion_interruptible_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -070010486 &pAdapter->disconnect_comp_var,
10487 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +053010488 if (0 >= ret)
10489 hddLog(LOGE, "%s: failure waiting for disconnect_comp_var %ld",
10490 __func__, ret);
Jeff Johnson295189b2012-06-20 16:38:30 -070010491
10492 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
10493 pHddCtx->isAmpAllowed = VOS_FALSE;
10494 sme_RoamConnect(pHddCtx->hHal,
10495 pAdapter->sessionId, &(pWextState->roamProfile),
10496 &roamId);
10497 }
10498
10499 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10500 pAdapterNode = pNext;
10501 }
10502
10503 EXIT();
10504
10505 return VOS_STATUS_SUCCESS;
10506}
10507
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -070010508void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
10509{
10510 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
10511 VOS_STATUS status;
10512 hdd_adapter_t *pAdapter;
10513 hdd_station_ctx_t *pHddStaCtx;
10514 hdd_ap_ctx_t *pHddApCtx;
10515 hdd_hostapd_state_t * pHostapdState;
10516 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
10517 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
10518 const char *p2pMode = "DEV";
10519 const char *ccMode = "Standalone";
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -070010520
10521 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10522 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
10523 {
10524 pAdapter = pAdapterNode->pAdapter;
10525 switch (pAdapter->device_mode) {
10526 case WLAN_HDD_INFRA_STATION:
10527 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10528 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
10529 staChannel = pHddStaCtx->conn_info.operationChannel;
10530 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
10531 }
10532 break;
10533 case WLAN_HDD_P2P_CLIENT:
10534 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10535 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
10536 p2pChannel = pHddStaCtx->conn_info.operationChannel;
10537 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
10538 p2pMode = "CLI";
10539 }
10540 break;
10541 case WLAN_HDD_P2P_GO:
10542 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
10543 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
10544 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
10545 p2pChannel = pHddApCtx->operatingChannel;
10546 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
10547 }
10548 p2pMode = "GO";
10549 break;
10550 case WLAN_HDD_SOFTAP:
10551 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
10552 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
10553 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
10554 apChannel = pHddApCtx->operatingChannel;
10555 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
10556 }
10557 break;
10558 default:
10559 break;
10560 }
10561 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10562 pAdapterNode = pNext;
10563 }
10564 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
10565 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
10566 }
Yeshwanth Sriram Guntuka0004c0b2017-12-06 14:43:49 +053010567 hddLog(VOS_TRACE_LEVEL_ERROR, "wlan(%d) " MAC_ADDRESS_STR " %s",
10568 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -070010569 if (p2pChannel > 0) {
Sushant Kaushikdc3184b2015-10-09 12:00:21 +053010570 hddLog(VOS_TRACE_LEVEL_ERROR, "p2p-%s(%d) " MAC_ADDRESS_STR,
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -070010571 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
10572 }
10573 if (apChannel > 0) {
Sushant Kaushikdc3184b2015-10-09 12:00:21 +053010574 hddLog(VOS_TRACE_LEVEL_ERROR, "AP(%d) " MAC_ADDRESS_STR,
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -070010575 apChannel, MAC_ADDR_ARRAY(apBssid));
10576 }
10577
10578 if (p2pChannel > 0 && apChannel > 0) {
10579 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
10580 }
10581}
10582
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -070010583bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -070010584{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -070010585 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -070010586}
10587
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -070010588/* Once SSR is disabled then it cannot be set. */
10589void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -070010590{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -070010591 if (HDD_SSR_DISABLED == isSsrRequired)
10592 return;
10593
Jeff Johnson295189b2012-06-20 16:38:30 -070010594 isSsrRequired = value;
10595}
10596
Hema Aparna Medicharla6b4d4f32015-06-23 04:09:12 +053010597void hdd_set_pre_close( hdd_context_t *pHddCtx)
10598{
10599 sme_PreClose(pHddCtx->hHal);
10600}
10601
Jeff Johnson295189b2012-06-20 16:38:30 -070010602VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
10603 hdd_adapter_list_node_t** ppAdapterNode)
10604{
10605 VOS_STATUS status;
Mukul Sharmaae1266d2015-06-26 15:29:53 +053010606 spin_lock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010607 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
10608 (hdd_list_node_t**) ppAdapterNode );
Mukul Sharmaae1266d2015-06-26 15:29:53 +053010609 spin_unlock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010610 return status;
10611}
10612
10613VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
10614 hdd_adapter_list_node_t* pAdapterNode,
10615 hdd_adapter_list_node_t** pNextAdapterNode)
10616{
10617 VOS_STATUS status;
Mukul Sharmaae1266d2015-06-26 15:29:53 +053010618 spin_lock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010619 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
10620 (hdd_list_node_t*) pAdapterNode,
10621 (hdd_list_node_t**)pNextAdapterNode );
10622
Mukul Sharmaae1266d2015-06-26 15:29:53 +053010623 spin_unlock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010624 return status;
10625}
10626
10627VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
10628 hdd_adapter_list_node_t* pAdapterNode)
10629{
10630 VOS_STATUS status;
Mukul Sharmaae1266d2015-06-26 15:29:53 +053010631 spin_lock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010632 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
10633 &pAdapterNode->node );
Mukul Sharmaae1266d2015-06-26 15:29:53 +053010634 spin_unlock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010635 return status;
10636}
10637
10638VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
10639 hdd_adapter_list_node_t** ppAdapterNode)
10640{
10641 VOS_STATUS status;
Mukul Sharmaae1266d2015-06-26 15:29:53 +053010642 spin_lock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010643 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
10644 (hdd_list_node_t**) ppAdapterNode );
Mukul Sharmaae1266d2015-06-26 15:29:53 +053010645 spin_unlock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010646 return status;
10647}
10648
10649VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
10650 hdd_adapter_list_node_t* pAdapterNode)
10651{
10652 VOS_STATUS status;
Mukul Sharmaae1266d2015-06-26 15:29:53 +053010653 spin_lock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010654 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
10655 (hdd_list_node_t*) pAdapterNode );
Mukul Sharmaae1266d2015-06-26 15:29:53 +053010656 spin_unlock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010657 return status;
10658}
10659
10660VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
10661 hdd_adapter_list_node_t* pAdapterNode)
10662{
10663 VOS_STATUS status;
Mukul Sharmaae1266d2015-06-26 15:29:53 +053010664 spin_lock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010665 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
10666 (hdd_list_node_t*) pAdapterNode );
Mukul Sharmaae1266d2015-06-26 15:29:53 +053010667 spin_unlock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010668 return status;
10669}
10670
10671hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
10672 tSirMacAddr macAddr )
10673{
10674 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
10675 hdd_adapter_t *pAdapter;
10676 VOS_STATUS status;
10677
10678 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10679
10680 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
10681 {
10682 pAdapter = pAdapterNode->pAdapter;
10683
10684 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
10685 macAddr, sizeof(tSirMacAddr) ) )
10686 {
10687 return pAdapter;
10688 }
10689 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10690 pAdapterNode = pNext;
10691 }
10692
10693 return NULL;
10694
10695}
10696
10697hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
10698{
10699 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
10700 hdd_adapter_t *pAdapter;
10701 VOS_STATUS status;
10702
10703 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10704
10705 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
10706 {
10707 pAdapter = pAdapterNode->pAdapter;
10708
10709 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
10710 IFNAMSIZ ) )
10711 {
10712 return pAdapter;
10713 }
10714 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10715 pAdapterNode = pNext;
10716 }
10717
10718 return NULL;
10719
10720}
10721
Ganesh Kondabattinicbfdc392015-09-11 19:12:59 +053010722hdd_adapter_t *hdd_get_adapter_by_sme_session_id( hdd_context_t *pHddCtx,
10723 tANI_U32 sme_session_id )
10724{
10725 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
10726 hdd_adapter_t *pAdapter;
10727 VOS_STATUS vos_status;
10728
10729
10730 vos_status = hdd_get_front_adapter( pHddCtx, &pAdapterNode);
10731
10732 while ((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == vos_status))
10733 {
10734 pAdapter = pAdapterNode->pAdapter;
10735
10736 if (pAdapter->sessionId == sme_session_id)
10737 return pAdapter;
10738
10739 vos_status = hdd_get_next_adapter(pHddCtx, pAdapterNode, &pNext);
10740 pAdapterNode = pNext;
10741 }
10742
10743 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
10744 "%s: sme_session_id %d does not exist with host",
10745 __func__, sme_session_id);
10746
10747 return NULL;
10748}
10749
Jeff Johnson295189b2012-06-20 16:38:30 -070010750hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
10751{
10752 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
10753 hdd_adapter_t *pAdapter;
10754 VOS_STATUS status;
10755
10756 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10757
10758 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
10759 {
10760 pAdapter = pAdapterNode->pAdapter;
10761
10762 if( pAdapter && (mode == pAdapter->device_mode) )
10763 {
10764 return pAdapter;
10765 }
10766 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10767 pAdapterNode = pNext;
10768 }
10769
10770 return NULL;
10771
10772}
10773
10774//Remove this function later
10775hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
10776{
10777 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
10778 hdd_adapter_t *pAdapter;
10779 VOS_STATUS status;
10780
10781 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10782
10783 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
10784 {
10785 pAdapter = pAdapterNode->pAdapter;
10786
10787 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
10788 {
10789 return pAdapter;
10790 }
10791
10792 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10793 pAdapterNode = pNext;
10794 }
10795
10796 return NULL;
10797
10798}
10799
Jeff Johnson295189b2012-06-20 16:38:30 -070010800/**---------------------------------------------------------------------------
10801
Mahesh A Saptasgar64534612014-09-23 13:13:33 +053010802 \brief hdd_get_operating_channel() -
Jeff Johnson295189b2012-06-20 16:38:30 -070010803
10804 This API returns the operating channel of the requested device mode
10805
10806 \param - pHddCtx - Pointer to the HDD context.
10807 - mode - Device mode for which operating channel is required
10808 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
10809 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
10810 \return - channel number. "0" id the requested device is not found OR it is not connected.
10811 --------------------------------------------------------------------------*/
10812v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
10813{
10814 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
10815 VOS_STATUS status;
10816 hdd_adapter_t *pAdapter;
10817 v_U8_t operatingChannel = 0;
10818
10819 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10820
10821 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
10822 {
10823 pAdapter = pAdapterNode->pAdapter;
10824
10825 if( mode == pAdapter->device_mode )
10826 {
10827 switch(pAdapter->device_mode)
10828 {
10829 case WLAN_HDD_INFRA_STATION:
10830 case WLAN_HDD_P2P_CLIENT:
10831 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
10832 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
10833 break;
10834 case WLAN_HDD_SOFTAP:
10835 case WLAN_HDD_P2P_GO:
10836 /*softap connection info */
10837 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
10838 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
10839 break;
10840 default:
10841 break;
10842 }
10843
10844 break; //Found the device of interest. break the loop
10845 }
10846
10847 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10848 pAdapterNode = pNext;
10849 }
10850 return operatingChannel;
10851}
10852
10853#ifdef WLAN_FEATURE_PACKET_FILTERING
10854/**---------------------------------------------------------------------------
10855
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +053010856 \brief __hdd_set_multicast_list() -
Jeff Johnson295189b2012-06-20 16:38:30 -070010857
10858 This used to set the multicast address list.
10859
10860 \param - dev - Pointer to the WLAN device.
10861 - skb - Pointer to OS packet (sk_buff).
Mahesh A Saptasagar74088392015-02-05 17:22:09 +053010862 \return - success/fail
Jeff Johnson295189b2012-06-20 16:38:30 -070010863
10864 --------------------------------------------------------------------------*/
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +053010865static void __hdd_set_multicast_list(struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -070010866{
Mahesh A Saptasagar74088392015-02-05 17:22:09 +053010867 hdd_adapter_t *pAdapter;
10868 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -070010869 int mc_count;
Mahesh A Saptasagar74088392015-02-05 17:22:09 +053010870 int i = 0, ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -070010871 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +053010872
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +053010873 ENTER();
10874
Mahesh A Saptasagar74088392015-02-05 17:22:09 +053010875 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Gopichand Nakkala0f276812013-02-24 14:45:51 +053010876 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -070010877 {
10878 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +053010879 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -070010880 return;
10881 }
Mahesh A Saptasagar74088392015-02-05 17:22:09 +053010882 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10883 ret = wlan_hdd_validate_context(pHddCtx);
10884 if (0 != ret)
10885 {
Mahesh A Saptasagar74088392015-02-05 17:22:09 +053010886 return;
10887 }
Jeff Johnson295189b2012-06-20 16:38:30 -070010888 if (dev->flags & IFF_ALLMULTI)
10889 {
10890 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070010891 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +053010892 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -070010893 }
Mahesh A Saptasagar74088392015-02-05 17:22:09 +053010894 else
Jeff Johnson295189b2012-06-20 16:38:30 -070010895 {
10896 mc_count = netdev_mc_count(dev);
10897 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070010898 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -070010899 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
10900 {
10901 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070010902 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +053010903 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -070010904 return;
10905 }
10906
Gopichand Nakkala0f276812013-02-24 14:45:51 +053010907 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -070010908
10909 netdev_for_each_mc_addr(ha, dev) {
10910 if (i == mc_count)
10911 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +053010912 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
10913 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
Arif Hussain6d2a3322013-11-17 19:50:10 -080010914 hddLog(VOS_TRACE_LEVEL_INFO, "%s: mlist[%d] = "MAC_ADDRESS_STR,
Mahesh A Saptasagar74088392015-02-05 17:22:09 +053010915 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +053010916 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -070010917 i++;
10918 }
10919 }
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +053010920
Ganesh Kondabattinifb37e652015-10-09 15:46:47 +053010921 if (pHddCtx->hdd_wlan_suspended)
10922 {
10923 /*
10924 * Configure the Mcast address list to FW
10925 * If wlan is already in suspend mode
10926 */
10927 wlan_hdd_set_mc_addr_list(pAdapter, TRUE);
10928 }
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +053010929 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -070010930 return;
10931}
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +053010932
10933static void hdd_set_multicast_list(struct net_device *dev)
10934{
10935 vos_ssr_protect(__func__);
10936 __hdd_set_multicast_list(dev);
10937 vos_ssr_unprotect(__func__);
10938}
Jeff Johnson295189b2012-06-20 16:38:30 -070010939#endif
10940
10941/**---------------------------------------------------------------------------
10942
10943 \brief hdd_select_queue() -
10944
10945 This function is registered with the Linux OS for network
10946 core to decide which queue to use first.
10947
10948 \param - dev - Pointer to the WLAN device.
10949 - skb - Pointer to OS packet (sk_buff).
10950 \return - ac, Queue Index/access category corresponding to UP in IP header
10951
10952 --------------------------------------------------------------------------*/
10953v_U16_t hdd_select_queue(struct net_device *dev,
Anand N Sunkade9adb1b2015-07-29 09:56:45 +053010954 struct sk_buff *skb
10955#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0))
10956 , void *accel_priv
10957#endif
10958#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0))
10959 , select_queue_fallback_t fallback
10960#endif
10961)
Jeff Johnson295189b2012-06-20 16:38:30 -070010962{
10963 return hdd_wmm_select_queue(dev, skb);
10964}
10965
10966
10967/**---------------------------------------------------------------------------
10968
10969 \brief hdd_wlan_initial_scan() -
10970
10971 This function triggers the initial scan
10972
10973 \param - pAdapter - Pointer to the HDD adapter.
10974
10975 --------------------------------------------------------------------------*/
10976void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
10977{
10978 tCsrScanRequest scanReq;
10979 tCsrChannelInfo channelInfo;
10980 eHalStatus halStatus;
Jeff Johnson02797792013-10-26 19:17:13 -070010981 tANI_U32 scanId;
Jeff Johnson295189b2012-06-20 16:38:30 -070010982 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10983
10984 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
10985 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
10986 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
10987
10988 if(sme_Is11dSupported(pHddCtx->hHal))
10989 {
10990 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
10991 if ( HAL_STATUS_SUCCESS( halStatus ) )
10992 {
10993 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
10994 if( !scanReq.ChannelInfo.ChannelList )
10995 {
10996 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
10997 vos_mem_free(channelInfo.ChannelList);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -080010998 channelInfo.ChannelList = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -070010999 return;
11000 }
11001 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
11002 channelInfo.numOfChannels);
11003 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
11004 vos_mem_free(channelInfo.ChannelList);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -080011005 channelInfo.ChannelList = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -070011006 }
11007
11008 scanReq.scanType = eSIR_PASSIVE_SCAN;
11009 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
11010 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
11011 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
11012 }
11013 else
11014 {
11015 scanReq.scanType = eSIR_ACTIVE_SCAN;
11016 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
11017 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
11018 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
11019 }
11020
11021 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
11022 if ( !HAL_STATUS_SUCCESS( halStatus ) )
11023 {
11024 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
11025 __func__, halStatus );
11026 }
11027
11028 if(sme_Is11dSupported(pHddCtx->hHal))
11029 vos_mem_free(scanReq.ChannelInfo.ChannelList);
11030}
11031
Jeff Johnson295189b2012-06-20 16:38:30 -070011032/**---------------------------------------------------------------------------
11033
11034 \brief hdd_full_power_callback() - HDD full power callback function
11035
11036 This is the function invoked by SME to inform the result of a full power
11037 request issued by HDD
11038
11039 \param - callbackcontext - Pointer to cookie
11040 \param - status - result of request
11041
11042 \return - None
11043
11044 --------------------------------------------------------------------------*/
11045static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
11046{
Jeff Johnson72a40512013-12-19 10:14:15 -080011047 struct statsContext *pContext = callbackContext;
Jeff Johnson295189b2012-06-20 16:38:30 -070011048
11049 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnsonc135a9a2017-09-19 08:37:24 -070011050 "%s: context = %pK, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -070011051
11052 if (NULL == callbackContext)
11053 {
11054 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnsonc135a9a2017-09-19 08:37:24 -070011055 "%s: Bad param, context [%pK]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070011056 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -070011057 return;
11058 }
11059
Jeff Johnson72a40512013-12-19 10:14:15 -080011060 /* there is a race condition that exists between this callback
11061 function and the caller since the caller could time out either
11062 before or while this code is executing. we use a spinlock to
11063 serialize these actions */
11064 spin_lock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070011065
11066 if (POWER_CONTEXT_MAGIC != pContext->magic)
11067 {
11068 /* the caller presumably timed out so there is nothing we can do */
Jeff Johnson72a40512013-12-19 10:14:15 -080011069 spin_unlock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070011070 hddLog(VOS_TRACE_LEVEL_WARN,
11071 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070011072 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -070011073 return;
11074 }
11075
Jeff Johnson72a40512013-12-19 10:14:15 -080011076 /* context is valid so caller is still waiting */
11077
11078 /* paranoia: invalidate the magic */
11079 pContext->magic = 0;
11080
11081 /* notify the caller */
Jeff Johnson295189b2012-06-20 16:38:30 -070011082 complete(&pContext->completion);
Jeff Johnson72a40512013-12-19 10:14:15 -080011083
11084 /* serialization is complete */
11085 spin_unlock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070011086}
11087
Katya Nigamf0511f62015-05-05 16:40:57 +053011088void wlan_hdd_mon_set_typesubtype( hdd_mon_ctx_t *pMonCtx,int type)
11089{
11090 pMonCtx->typeSubtypeBitmap = 0;
11091 if( type%10 ) /* Management Packets */
11092 pMonCtx->typeSubtypeBitmap |= 0xFFFF;
11093 type/=10;
11094 if( type%10 ) /* Control Packets */
11095 pMonCtx->typeSubtypeBitmap |= 0xFFFF0000;
11096 type/=10;
11097 if( type%10 ) /* Data Packets */
11098 pMonCtx->typeSubtypeBitmap |= 0xFFFF00000000;
11099}
11100
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053011101VOS_STATUS wlan_hdd_mon_postMsg(tANI_U32 *magic, struct completion *cmpVar,
11102 hdd_mon_ctx_t *pMonCtx , void* callback)
Katya Nigamf0511f62015-05-05 16:40:57 +053011103{
11104 vos_msg_t monMsg;
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053011105 tSirMonModeReq *pMonModeReq;
Katya Nigamf0511f62015-05-05 16:40:57 +053011106
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053011107 if (MON_MODE_START == pMonCtx->state)
11108 monMsg.type = WDA_MON_START_REQ;
11109 else if (MON_MODE_STOP == pMonCtx->state)
11110 monMsg.type = WDA_MON_STOP_REQ;
11111 else {
11112 hddLog(VOS_TRACE_LEVEL_ERROR,
11113 FL("invalid monitor state %d"), pMonCtx->state);
Katya Nigamf0511f62015-05-05 16:40:57 +053011114 return VOS_STATUS_E_FAILURE;
11115 }
11116
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053011117 pMonModeReq = vos_mem_malloc(sizeof(tSirMonModeReq));
11118 if (pMonModeReq == NULL) {
11119 hddLog(VOS_TRACE_LEVEL_ERROR,
11120 FL("fail to allocate memory for monitor mode req"));
11121 return VOS_STATUS_E_FAILURE;
11122 }
Katya Nigamf0511f62015-05-05 16:40:57 +053011123
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053011124 pMonModeReq->magic = magic;
11125 pMonModeReq->cmpVar = cmpVar;
11126 pMonModeReq->data = pMonCtx;
11127 pMonModeReq->callback = callback;
Katya Nigamf0511f62015-05-05 16:40:57 +053011128
Katya Nigamf0511f62015-05-05 16:40:57 +053011129 monMsg.reserved = 0;
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053011130 monMsg.bodyptr = pMonModeReq;
Katya Nigamf0511f62015-05-05 16:40:57 +053011131 monMsg.bodyval = 0;
11132
11133 if (VOS_STATUS_SUCCESS != vos_mq_post_message(
11134 VOS_MODULE_ID_WDA,(vos_msg_t *)&monMsg)) {
11135 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: : Failed to post Msg to HAL",__func__);
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053011136 vos_mem_free(pMonModeReq);
Katya Nigamf0511f62015-05-05 16:40:57 +053011137 }
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053011138 return VOS_STATUS_SUCCESS;
Katya Nigamf0511f62015-05-05 16:40:57 +053011139}
11140
Katya Nigame7b69a82015-04-28 15:24:06 +053011141void wlan_hdd_mon_close(hdd_context_t *pHddCtx)
11142{
11143 VOS_STATUS vosStatus;
11144 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053011145 long ret;
11146 hdd_mon_ctx_t *pMonCtx = NULL;
11147 v_U32_t magic;
11148 struct completion cmpVar;
Hanumantha Reddy Pothulac99bc062015-09-08 14:59:26 +053011149
Katya Nigame7b69a82015-04-28 15:24:06 +053011150 hdd_adapter_t *pAdapter = hdd_get_adapter(pHddCtx,WLAN_HDD_MONITOR);
11151 if(pAdapter == NULL || pVosContext == NULL)
11152 {
11153 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:pAdapter is NULL",__func__);
11154 return ;
11155 }
Katya Nigamf0511f62015-05-05 16:40:57 +053011156
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053011157 pMonCtx = WLAN_HDD_GET_MONITOR_CTX_PTR(pAdapter);
11158 if (pMonCtx!= NULL && pMonCtx->state == MON_MODE_START) {
11159 pMonCtx->state = MON_MODE_STOP;
11160 magic = MON_MODE_MSG_MAGIC;
11161 init_completion(&cmpVar);
11162 if (VOS_STATUS_SUCCESS !=
11163 wlan_hdd_mon_postMsg(&magic, &cmpVar,
11164 pMonCtx, hdd_monPostMsgCb)) {
11165 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
11166 FL("failed to post MON MODE REQ"));
11167 pMonCtx->state = MON_MODE_START;
11168 magic = 0;
11169 return;
11170 }
11171 ret = wait_for_completion_timeout(&cmpVar, MON_MODE_MSG_TIMEOUT);
11172 magic = 0;
11173 if (ret <= 0 ) {
11174 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
11175 FL("timeout on monitor mode completion %ld"), ret);
11176 }
11177 }
11178
Katya Nigame7b69a82015-04-28 15:24:06 +053011179 hdd_UnregisterWext(pAdapter->dev);
11180
11181 vos_mon_stop( pVosContext );
11182
11183 vosStatus = vos_sched_close( pVosContext );
11184 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
11185 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
11186 "%s: Failed to close VOSS Scheduler",__func__);
11187 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
11188 }
11189
11190 vosStatus = vos_nv_close();
11191 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
11192 {
11193 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
11194 "%s: Failed to close NV", __func__);
11195 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
11196 }
11197
11198 vos_close(pVosContext);
11199
11200 #ifdef WLAN_KD_READY_NOTIFIER
11201 nl_srv_exit(pHddCtx->ptt_pid);
11202 #else
11203 nl_srv_exit();
11204 #endif
11205
Katya Nigame7b69a82015-04-28 15:24:06 +053011206 hdd_close_all_adapters( pHddCtx );
Katya Nigame7b69a82015-04-28 15:24:06 +053011207}
Agrawal Ashish33ec71e2015-11-26 20:20:58 +053011208/**
11209 * hdd_wlan_free_wiphy_channels - free Channel pointer for wiphy
11210 * @ wiphy: the wiphy to validate against
11211 *
11212 * Return: void
11213 */
11214void hdd_wlan_free_wiphy_channels(struct wiphy *wiphy)
11215{
11216 int i =0;
Rajeev Kumar Sirasanagandla5b21a9c2018-01-08 17:05:11 +053011217 for (i = 0; i < HDD_NUM_NL80211_BANDS; i++)
Agrawal Ashish33ec71e2015-11-26 20:20:58 +053011218 {
11219 if (NULL != wiphy->bands[i] &&
11220 (NULL != wiphy->bands[i]->channels))
11221 {
11222 vos_mem_free(wiphy->bands[i]->channels);
11223 wiphy->bands[i]->channels = NULL;
11224 }
11225 }
11226}
Jeff Johnson295189b2012-06-20 16:38:30 -070011227/**---------------------------------------------------------------------------
11228
11229 \brief hdd_wlan_exit() - HDD WLAN exit function
11230
11231 This is the driver exit point (invoked during rmmod)
11232
11233 \param - pHddCtx - Pointer to the HDD Context
11234
11235 \return - None
11236
11237 --------------------------------------------------------------------------*/
11238void hdd_wlan_exit(hdd_context_t *pHddCtx)
11239{
11240 eHalStatus halStatus;
11241 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
11242 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +053011243 struct wiphy *wiphy = pHddCtx->wiphy;
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -080011244 hdd_adapter_t* pAdapter = NULL;
Jeff Johnson72a40512013-12-19 10:14:15 -080011245 struct statsContext powerContext;
Jeff Johnson295189b2012-06-20 16:38:30 -070011246 long lrc;
c_hpothu5ab05e92014-06-13 17:34:05 +053011247 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -070011248
11249 ENTER();
11250
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053011251
Katya Nigame7b69a82015-04-28 15:24:06 +053011252 if (VOS_MONITOR_MODE == hdd_get_conparam())
11253 {
11254 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: MONITOR MODE",__func__);
11255 wlan_hdd_mon_close(pHddCtx);
Hanumantha Reddy Pothulac99bc062015-09-08 14:59:26 +053011256 goto free_hdd_ctx;
Katya Nigame7b69a82015-04-28 15:24:06 +053011257 }
11258 else if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -080011259 {
11260 // Unloading, restart logic is no more required.
11261 wlan_hdd_restart_deinit(pHddCtx);
Jeff Johnsone7245742012-09-05 17:12:55 -070011262
Agarwal Ashishb20e0ff2014-12-17 22:50:19 +053011263#ifdef FEATURE_WLAN_TDLS
11264 /* At the time of driver unloading; if tdls connection is present;
11265 * hdd_rx_packet_cbk calls wlan_hdd_tdls_find_peer.
11266 * wlan_hdd_tdls_find_peer always checks for valid context;
11267 * as load/unload in progress there can be a race condition.
11268 * hdd_rx_packet_cbk calls wlan_hdd_tdls_find_peer only
11269 * when tdls state is enabled.
11270 * As soon as driver set load/unload flag; tdls flag also needs
11271 * to be disabled so that hdd_rx_packet_cbk won't call
11272 * wlan_hdd_tdls_find_peer.
11273 */
Masti, Narayanraddi20494af2015-12-17 20:56:42 +053011274 wlan_hdd_tdls_set_mode(pHddCtx, eTDLS_SUPPORT_DISABLED, FALSE,
11275 HDD_SET_TDLS_MODE_SOURCE_USER);
Agarwal Ashishb20e0ff2014-12-17 22:50:19 +053011276#endif
11277
c_hpothu5ab05e92014-06-13 17:34:05 +053011278 vosStatus = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
11279 while (NULL != pAdapterNode && VOS_STATUS_E_EMPTY != vosStatus)
Jeff Johnson295189b2012-06-20 16:38:30 -070011280 {
c_hpothu5ab05e92014-06-13 17:34:05 +053011281 pAdapter = pAdapterNode->pAdapter;
11282 if (NULL != pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -070011283 {
Mahesh A Saptasagar305e2632015-03-04 12:57:33 +053011284 /* Disable TX on the interface, after this hard_start_xmit() will
11285 * not be called on that interface
11286 */
11287 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
11288 netif_tx_disable(pAdapter->dev);
11289
11290 /* Mark the interface status as "down" for outside world */
11291 netif_carrier_off(pAdapter->dev);
11292
Agarwal Ashish9ffa5b92014-11-18 21:07:02 +053011293 /* DeInit the adapter. This ensures that all data packets
11294 * are freed.
11295 */
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +053011296#ifdef FEATURE_WLAN_TDLS
11297 mutex_lock(&pHddCtx->tdls_lock);
11298#endif
c_hpothu002231a2015-02-05 14:58:51 +053011299 hdd_deinit_adapter(pHddCtx, pAdapter, FALSE);
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +053011300#ifdef FEATURE_WLAN_TDLS
11301 mutex_unlock(&pHddCtx->tdls_lock);
11302#endif
Masti, Narayanraddi26378462016-01-05 18:20:28 +053011303 vos_flush_delayed_work(&pHddCtx->scan_ctxt.scan_work);
11304
11305 wlan_hdd_init_deinit_defer_scan_context(&pHddCtx->scan_ctxt);
Agarwal Ashish9ffa5b92014-11-18 21:07:02 +053011306
c_hpothu5ab05e92014-06-13 17:34:05 +053011307 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode ||
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +053011308 WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ||
11309 WLAN_HDD_MONITOR == pAdapter->device_mode)
c_hpothu5ab05e92014-06-13 17:34:05 +053011310 {
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +053011311 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode ||
11312 WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)
11313 wlan_hdd_cfg80211_deregister_frames(pAdapter);
11314
c_hpothu5ab05e92014-06-13 17:34:05 +053011315 hdd_UnregisterWext(pAdapter->dev);
11316 }
Kaushik, Sushant4975a572014-10-21 16:07:48 +053011317
Jeff Johnson295189b2012-06-20 16:38:30 -070011318 }
c_hpothu5ab05e92014-06-13 17:34:05 +053011319 vosStatus = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
11320 pAdapterNode = pNext;
Jeff Johnson295189b2012-06-20 16:38:30 -070011321 }
mukul sharmabab477d2015-06-11 17:14:55 +053011322
Kaushik, Sushant4975a572014-10-21 16:07:48 +053011323 // Cancel any outstanding scan requests. We are about to close all
11324 // of our adapters, but an adapter structure is what SME passes back
11325 // to our callback function. Hence if there are any outstanding scan
11326 // requests then there is a race condition between when the adapter
11327 // is closed and when the callback is invoked.We try to resolve that
11328 // race condition here by canceling any outstanding scans before we
11329 // close the adapters.
11330 // Note that the scans may be cancelled in an asynchronous manner,
11331 // so ideally there needs to be some kind of synchronization. Rather
11332 // than introduce a new synchronization here, we will utilize the
11333 // fact that we are about to Request Full Power, and since that is
11334 // synchronized, the expectation is that by the time Request Full
11335 // Power has completed all scans will be cancelled.
11336 if (pHddCtx->scan_info.mScanPending)
11337 {
Hema Aparna Medicharlaf05f6cd2015-01-21 14:44:19 +053011338 if(NULL != pAdapter)
11339 {
11340 hddLog(VOS_TRACE_LEVEL_INFO,
11341 FL("abort scan mode: %d sessionId: %d"),
11342 pAdapter->device_mode,
11343 pAdapter->sessionId);
11344 }
11345 hdd_abort_mac_scan(pHddCtx,
11346 pHddCtx->scan_info.sessionId,
11347 eCSR_SCAN_ABORT_DEFAULT);
Kaushik, Sushant4975a572014-10-21 16:07:48 +053011348 }
Jeff Johnson295189b2012-06-20 16:38:30 -070011349 }
c_hpothu5ab05e92014-06-13 17:34:05 +053011350 else
Jeff Johnson88ba7742013-02-27 14:36:02 -080011351 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +053011352 hddLog(VOS_TRACE_LEVEL_INFO,"%s: FTM MODE",__func__);
Hanumantha Reddy Pothula45af96b2015-02-12 16:07:58 +053011353 if (pHddCtx->ftm.ftm_state == WLAN_FTM_STARTING)
11354 {
11355 INIT_COMPLETION(pHddCtx->ftm.startCmpVar);
11356 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
11357 "%s: in middle of FTM START", __func__);
11358 lrc = wait_for_completion_timeout(&pHddCtx->ftm.startCmpVar,
11359 msecs_to_jiffies(20000));
11360 if(!lrc)
11361 {
11362 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
11363 "%s: timedout on ftmStartCmpVar fatal error", __func__);
11364 }
11365 }
Jeff Johnson88ba7742013-02-27 14:36:02 -080011366 wlan_hdd_ftm_close(pHddCtx);
11367 goto free_hdd_ctx;
11368 }
c_hpothu6ff1c3c2013-10-01 19:01:57 +053011369
Jeff Johnson295189b2012-06-20 16:38:30 -070011370 /* DeRegister with platform driver as client for Suspend/Resume */
11371 vosStatus = hddDeregisterPmOps(pHddCtx);
11372 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
11373 {
11374 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
11375 VOS_ASSERT(0);
11376 }
11377
11378 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
11379 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
11380 {
11381 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
11382 }
Jeff Johnson295189b2012-06-20 16:38:30 -070011383
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -070011384 //Stop the traffic monitor timer
Mahesh A Saptasagard461e432016-07-20 15:01:40 +053011385 if ((pHddCtx->cfg_ini->dynSplitscan) && (VOS_TIMER_STATE_RUNNING ==
11386 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr)))
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -070011387 {
11388 vos_timer_stop(&pHddCtx->tx_rx_trafficTmr);
11389 }
11390
11391 // Destroy the traffic monitor timer
Mahesh A Saptasagard461e432016-07-20 15:01:40 +053011392 if ((pHddCtx->cfg_ini->dynSplitscan) &&
11393 (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
11394 &pHddCtx->tx_rx_trafficTmr))))
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -070011395 {
11396 hddLog(VOS_TRACE_LEVEL_ERROR,
11397 "%s: Cannot deallocate Traffic monitor timer", __func__);
11398 }
11399
Bhargav Shahd0715912015-10-01 18:17:37 +053011400 if (VOS_TIMER_STATE_RUNNING ==
11401 vos_timer_getCurrentState(&pHddCtx->delack_timer)) {
11402 vos_timer_stop(&pHddCtx->delack_timer);
11403 }
11404
11405 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
11406 &pHddCtx->delack_timer))) {
11407 hddLog(VOS_TRACE_LEVEL_ERROR,
11408 "%s: Cannot deallocate Bus bandwidth timer", __func__);
11409 }
11410
Masti, Narayanraddi44b0db02015-12-22 11:54:35 +053011411 if (VOS_TIMER_STATE_RUNNING ==
11412 vos_timer_getCurrentState(&pHddCtx->tdls_source_timer)) {
11413 vos_timer_stop(&pHddCtx->tdls_source_timer);
11414 }
11415
Abhishek Singh8a3e4dc2017-01-02 10:39:18 +053011416 vos_set_snoc_high_freq_voting(false);
11417
Masti, Narayanraddi44b0db02015-12-22 11:54:35 +053011418 vos_timer_destroy(&pHddCtx->tdls_source_timer);
11419
Jeff Johnson295189b2012-06-20 16:38:30 -070011420 //Disable IMPS/BMPS as we do not want the device to enter any power
11421 //save mode during shutdown
11422 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
11423 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
11424 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
11425
11426 //Ensure that device is in full power as we will touch H/W during vos_Stop
11427 init_completion(&powerContext.completion);
11428 powerContext.magic = POWER_CONTEXT_MAGIC;
11429
11430 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
11431 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
11432
11433 if (eHAL_STATUS_SUCCESS != halStatus)
11434 {
11435 if (eHAL_STATUS_PMC_PENDING == halStatus)
11436 {
11437 /* request was sent -- wait for the response */
11438 lrc = wait_for_completion_interruptible_timeout(
11439 &powerContext.completion,
11440 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
Jeff Johnson295189b2012-06-20 16:38:30 -070011441 if (lrc <= 0)
11442 {
11443 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070011444 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -070011445 }
11446 }
11447 else
11448 {
11449 hddLog(VOS_TRACE_LEVEL_ERROR,
11450 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070011451 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -070011452 /* continue -- need to clean up as much as possible */
11453 }
11454 }
Hanumantha Reddy Pothula81b42b22015-05-12 13:52:00 +053011455 if ((eHAL_STATUS_SUCCESS == halStatus) ||
11456 (eHAL_STATUS_PMC_PENDING == halStatus && lrc > 0))
11457 {
11458 /* This will issue a dump command which will clean up
11459 BTQM queues and unblock MC thread */
11460 vos_fwDumpReq(274, 0, 0, 0, 0, 1);
11461 }
Jeff Johnson295189b2012-06-20 16:38:30 -070011462
Jeff Johnson72a40512013-12-19 10:14:15 -080011463 /* either we never sent a request, we sent a request and received a
11464 response or we sent a request and timed out. if we never sent a
11465 request or if we sent a request and got a response, we want to
11466 clear the magic out of paranoia. if we timed out there is a
11467 race condition such that the callback function could be
11468 executing at the same time we are. of primary concern is if the
11469 callback function had already verified the "magic" but had not
11470 yet set the completion variable when a timeout occurred. we
11471 serialize these activities by invalidating the magic while
11472 holding a shared spinlock which will cause us to block if the
11473 callback is currently executing */
11474 spin_lock(&hdd_context_lock);
11475 powerContext.magic = 0;
11476 spin_unlock(&hdd_context_lock);
11477
Hema Aparna Medicharlaa6cf65e2015-06-01 16:23:28 +053011478 /* If Device is shutdown, no point for SME to wait for responses
11479 from device. Pre Close SME */
11480 if(wcnss_device_is_shutdown())
11481 {
11482 sme_PreClose(pHddCtx->hHal);
11483 }
Yue Ma0d4891e2013-08-06 17:01:45 -070011484 hdd_debugfs_exit(pHddCtx);
11485
Ratheesh S P35ed8b12015-04-27 14:01:07 +053011486#ifdef WLAN_NS_OFFLOAD
Ratheesh S P36dbc932015-08-07 14:28:57 +053011487 hddLog(LOG1, FL("Unregister IPv6 notifier"));
Ratheesh S P35ed8b12015-04-27 14:01:07 +053011488 unregister_inet6addr_notifier(&pHddCtx->ipv6_notifier);
11489#endif
Ratheesh S P36dbc932015-08-07 14:28:57 +053011490 hddLog(LOG1, FL("Unregister IPv4 notifier"));
Ratheesh S P35ed8b12015-04-27 14:01:07 +053011491 unregister_inetaddr_notifier(&pHddCtx->ipv4_notifier);
11492
Jeff Johnson295189b2012-06-20 16:38:30 -070011493 // Unregister the Net Device Notifier
11494 unregister_netdevice_notifier(&hdd_netdev_notifier);
11495
Jeff Johnson295189b2012-06-20 16:38:30 -070011496 hdd_stop_all_adapters( pHddCtx );
11497
Jeff Johnson295189b2012-06-20 16:38:30 -070011498#ifdef WLAN_BTAMP_FEATURE
11499 vosStatus = WLANBAP_Stop(pVosContext);
11500 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
11501 {
11502 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
11503 "%s: Failed to stop BAP",__func__);
11504 }
11505#endif //WLAN_BTAMP_FEATURE
11506
11507 //Stop all the modules
11508 vosStatus = vos_stop( pVosContext );
11509 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
11510 {
11511 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
11512 "%s: Failed to stop VOSS",__func__);
11513 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
Hanumantha Reddy Pothulabd9601a2016-02-12 13:22:27 +053011514 if (isSsrPanicOnFailure())
11515 VOS_BUG(0);
Jeff Johnson295189b2012-06-20 16:38:30 -070011516 }
11517
Jeff Johnson295189b2012-06-20 16:38:30 -070011518 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -070011519 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -070011520
11521 //Close the scheduler before calling vos_close to make sure no thread is
11522 // scheduled after the each module close is called i.e after all the data
11523 // structures are freed.
11524 vosStatus = vos_sched_close( pVosContext );
11525 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
11526 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
11527 "%s: Failed to close VOSS Scheduler",__func__);
11528 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
11529 }
Jeff Johnsone7245742012-09-05 17:12:55 -070011530#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
11531 /* Destroy the wake lock */
Sushant Kaushik83392fa2015-05-05 17:44:40 +053011532 vos_wake_lock_destroy(&pHddCtx->rx_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -070011533#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -080011534 /* Destroy the wake lock */
Sushant Kaushik83392fa2015-05-05 17:44:40 +053011535 vos_wake_lock_destroy(&pHddCtx->sap_wake_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070011536
Mihir Shete7a24b5f2013-12-21 12:18:31 +053011537#ifdef CONFIG_ENABLE_LINUX_REG
11538 vosStatus = vos_nv_close();
11539 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
11540 {
11541 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
11542 "%s: Failed to close NV", __func__);
11543 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
11544 }
11545#endif
11546
Jeff Johnson295189b2012-06-20 16:38:30 -070011547 //Close VOSS
11548 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
11549 vos_close(pVosContext);
11550
Jeff Johnson295189b2012-06-20 16:38:30 -070011551 //Close Watchdog
11552 if(pHddCtx->cfg_ini->fIsLogpEnabled)
11553 vos_watchdog_close(pVosContext);
11554
Gopichand Nakkalaa0358482013-06-12 17:05:47 +053011555 //Clean up HDD Nlink Service
11556 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Gopichand Nakkalaa0358482013-06-12 17:05:47 +053011557
Manjeet Singh47ee8472016-04-11 11:57:18 +053011558 hdd_close_tx_queues(pHddCtx);
c_manjeecfd1efb2015-09-25 19:32:34 +053011559 wlan_free_fwr_mem_dump_buffer();
11560 memdump_deinit();
11561
Vinay Krishna Erannad938c422014-03-10 17:14:21 +053011562#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +053011563 if (pHddCtx->cfg_ini->wlanLoggingEnable)
Vinay Krishna Erannad938c422014-03-10 17:14:21 +053011564 {
11565 wlan_logging_sock_deactivate_svc();
11566 }
11567#endif
11568
Vinay Krishna Erannaef30b522014-08-26 17:48:16 +053011569#ifdef WLAN_KD_READY_NOTIFIER
11570 nl_srv_exit(pHddCtx->ptt_pid);
11571#else
11572 nl_srv_exit();
11573#endif /* WLAN_KD_READY_NOTIFIER */
11574
Abhishek Singh00b71972016-01-07 10:51:04 +053011575#ifdef WLAN_FEATURE_RMC
11576 hdd_close_cesium_nl_sock();
11577#endif /* WLAN_FEATURE_RMC */
Vinay Krishna Erannaef30b522014-08-26 17:48:16 +053011578
Jeff Johnson295189b2012-06-20 16:38:30 -070011579 hdd_close_all_adapters( pHddCtx );
11580
Padma, Santhosh Kumar9cd38332015-11-17 12:18:10 +053011581 vos_flush_delayed_work(&pHddCtx->spoof_mac_addr_work);
Abhishek Singh78c691f2017-11-30 13:48:44 +053011582 vos_flush_delayed_work(&pHddCtx->ecsa_chan_change_work);
Kapil Gupta137ef892016-12-13 19:38:00 +053011583 vos_flush_work(&pHddCtx->sap_start_work);
Padma, Santhosh Kumar9cd38332015-11-17 12:18:10 +053011584
Hanumantha Reddy Pothula97f9bc92015-08-10 17:21:20 +053011585free_hdd_ctx:
Jeff Johnson295189b2012-06-20 16:38:30 -070011586 /* free the power on lock from platform driver */
11587 if (free_riva_power_on_lock("wlan"))
11588 {
11589 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
11590 __func__);
11591 }
11592
c_hpothu78c7b602014-05-17 17:35:49 +053011593 //Free up dynamically allocated members inside HDD Adapter
11594 if (pHddCtx->cfg_ini)
11595 {
11596 kfree(pHddCtx->cfg_ini);
11597 pHddCtx->cfg_ini= NULL;
11598 }
11599
Hanumantha Reddy Pothula6fe221c2016-01-28 15:01:09 +053011600 /* FTM/MONITOR mode, WIPHY did not registered
Leo Changf04ddad2013-09-18 13:46:38 -070011601 If un-register here, system crash will happen */
Hanumantha Reddy Pothula6fe221c2016-01-28 15:01:09 +053011602 if (!(VOS_FTM_MODE == hdd_get_conparam() ||
11603 VOS_MONITOR_MODE == hdd_get_conparam()))
Leo Changf04ddad2013-09-18 13:46:38 -070011604 {
11605 wiphy_unregister(wiphy) ;
Agrawal Ashish33ec71e2015-11-26 20:20:58 +053011606 hdd_wlan_free_wiphy_channels(wiphy);
Leo Changf04ddad2013-09-18 13:46:38 -070011607 }
Jeff Johnson295189b2012-06-20 16:38:30 -070011608 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -070011609 if (hdd_is_ssr_required())
11610 {
11611 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -070011612 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -070011613 msleep(5000);
11614 }
11615 hdd_set_ssr_required (VOS_FALSE);
11616}
11617
11618
11619/**---------------------------------------------------------------------------
11620
11621 \brief hdd_update_config_from_nv() - Function to update the contents of
11622 the running configuration with parameters taken from NV storage
11623
11624 \param - pHddCtx - Pointer to the HDD global context
11625
11626 \return - VOS_STATUS_SUCCESS if successful
11627
11628 --------------------------------------------------------------------------*/
11629static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
11630{
Jeff Johnson295189b2012-06-20 16:38:30 -070011631 v_BOOL_t itemIsValid = VOS_FALSE;
11632 VOS_STATUS status;
11633 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
11634 v_U8_t macLoop;
11635
11636 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
11637 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
11638 if(status != VOS_STATUS_SUCCESS)
11639 {
Arif Hussain6d2a3322013-11-17 19:50:10 -080011640 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed");
Jeff Johnson295189b2012-06-20 16:38:30 -070011641 return VOS_STATUS_E_FAILURE;
11642 }
11643
11644 if (itemIsValid == VOS_TRUE)
11645 {
Arif Hussain6d2a3322013-11-17 19:50:10 -080011646 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV");
Jeff Johnson295189b2012-06-20 16:38:30 -070011647 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
11648 VOS_MAX_CONCURRENCY_PERSONA);
11649 if(status != VOS_STATUS_SUCCESS)
11650 {
11651 /* Get MAC from NV fail, not update CFG info
11652 * INI MAC value will be used for MAC setting */
Arif Hussain6d2a3322013-11-17 19:50:10 -080011653 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed");
Jeff Johnson295189b2012-06-20 16:38:30 -070011654 return VOS_STATUS_E_FAILURE;
11655 }
11656
11657 /* If first MAC is not valid, treat all others are not valid
11658 * Then all MACs will be got from ini file */
11659 if(vos_is_macaddr_zero(&macFromNV[0]))
11660 {
11661 /* MAC address in NV file is not configured yet */
11662 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
11663 return VOS_STATUS_E_INVAL;
11664 }
11665
11666 /* Get MAC address from NV, update CFG info */
11667 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
11668 {
11669 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
11670 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +053011671 hddLog(VOS_TRACE_LEVEL_ERROR,"not valid MAC from NV for %d", macLoop);
Jeff Johnson295189b2012-06-20 16:38:30 -070011672 /* This MAC is not valid, skip it
11673 * This MAC will be got from ini file */
11674 }
11675 else
11676 {
11677 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
11678 (v_U8_t *)&macFromNV[macLoop].bytes[0],
11679 VOS_MAC_ADDR_SIZE);
11680 }
11681 }
11682 }
11683 else
11684 {
11685 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
11686 return VOS_STATUS_E_FAILURE;
11687 }
Jeff Johnson295189b2012-06-20 16:38:30 -070011688
Jeff Johnson295189b2012-06-20 16:38:30 -070011689
11690 return VOS_STATUS_SUCCESS;
11691}
11692
11693/**---------------------------------------------------------------------------
11694
11695 \brief hdd_post_voss_start_config() - HDD post voss start config helper
11696
11697 \param - pAdapter - Pointer to the HDD
11698
11699 \return - None
11700
11701 --------------------------------------------------------------------------*/
11702VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
11703{
11704 eHalStatus halStatus;
11705 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +053011706 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -070011707
Jeff Johnson295189b2012-06-20 16:38:30 -070011708
11709 // Send ready indication to the HDD. This will kick off the MAC
11710 // into a 'running' state and should kick off an initial scan.
11711 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
11712 if ( !HAL_STATUS_SUCCESS( halStatus ) )
11713 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +053011714 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -070011715 "code %08d [x%08x]",__func__, halStatus, halStatus );
11716 return VOS_STATUS_E_FAILURE;
11717 }
11718
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +053011719 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -070011720 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
11721 // And RIVA will crash
11722 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
11723 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +053011724 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
11725 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
11726
11727
Jeff Johnson295189b2012-06-20 16:38:30 -070011728 return VOS_STATUS_SUCCESS;
11729}
11730
Jeff Johnson295189b2012-06-20 16:38:30 -070011731/* wake lock APIs for HDD */
Sushant Kaushik83392fa2015-05-05 17:44:40 +053011732void hdd_prevent_suspend(uint32_t reason)
Jeff Johnson295189b2012-06-20 16:38:30 -070011733{
Sushant Kaushik83392fa2015-05-05 17:44:40 +053011734
11735 vos_wake_lock_acquire(&wlan_wake_lock, reason);
11736
Jeff Johnson295189b2012-06-20 16:38:30 -070011737}
11738
Sushant Kaushik83392fa2015-05-05 17:44:40 +053011739void hdd_allow_suspend(uint32_t reason)
Jeff Johnson295189b2012-06-20 16:38:30 -070011740{
Sushant Kaushik83392fa2015-05-05 17:44:40 +053011741
11742 vos_wake_lock_release(&wlan_wake_lock, reason);
11743
Jeff Johnson295189b2012-06-20 16:38:30 -070011744}
11745
Sushant Kaushik83392fa2015-05-05 17:44:40 +053011746void hdd_prevent_suspend_timeout(v_U32_t timeout, uint32_t reason)
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -070011747{
Sushant Kaushik83392fa2015-05-05 17:44:40 +053011748
11749 vos_wake_lock_timeout_release(&wlan_wake_lock, timeout,
11750 reason);
11751
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -070011752}
11753
Jeff Johnson295189b2012-06-20 16:38:30 -070011754/**---------------------------------------------------------------------------
11755
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070011756 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
11757 information between Host and Riva
11758
11759 This function gets reported version of FW
11760 It also finds the version of Riva headers used to compile the host
11761 It compares the above two and prints a warning if they are different
11762 It gets the SW and HW version string
11763 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
11764 indicating the features they support through a bitmap
11765
11766 \param - pHddCtx - Pointer to HDD context
11767
11768 \return - void
11769
11770 --------------------------------------------------------------------------*/
11771
11772void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
11773{
11774
11775 tSirVersionType versionCompiled;
11776 tSirVersionType versionReported;
11777 tSirVersionString versionString;
11778 tANI_U8 fwFeatCapsMsgSupported = 0;
11779 VOS_STATUS vstatus;
11780
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -080011781 memset(&versionCompiled, 0, sizeof(versionCompiled));
11782 memset(&versionReported, 0, sizeof(versionReported));
11783
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070011784 /* retrieve and display WCNSS version information */
11785 do {
11786
11787 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
11788 &versionCompiled);
11789 if (!VOS_IS_STATUS_SUCCESS(vstatus))
11790 {
11791 hddLog(VOS_TRACE_LEVEL_FATAL,
11792 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070011793 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070011794 break;
11795 }
11796
11797 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
11798 &versionReported);
11799 if (!VOS_IS_STATUS_SUCCESS(vstatus))
11800 {
11801 hddLog(VOS_TRACE_LEVEL_FATAL,
11802 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070011803 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070011804 break;
11805 }
11806
11807 if ((versionCompiled.major != versionReported.major) ||
11808 (versionCompiled.minor != versionReported.minor) ||
11809 (versionCompiled.version != versionReported.version) ||
11810 (versionCompiled.revision != versionReported.revision))
11811 {
11812 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
11813 "Host expected %u.%u.%u.%u\n",
11814 WLAN_MODULE_NAME,
11815 (int)versionReported.major,
11816 (int)versionReported.minor,
11817 (int)versionReported.version,
11818 (int)versionReported.revision,
11819 (int)versionCompiled.major,
11820 (int)versionCompiled.minor,
11821 (int)versionCompiled.version,
11822 (int)versionCompiled.revision);
11823 }
11824 else
11825 {
11826 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
11827 WLAN_MODULE_NAME,
11828 (int)versionReported.major,
11829 (int)versionReported.minor,
11830 (int)versionReported.version,
11831 (int)versionReported.revision);
11832 }
11833
11834 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
11835 versionString,
11836 sizeof(versionString));
11837 if (!VOS_IS_STATUS_SUCCESS(vstatus))
11838 {
11839 hddLog(VOS_TRACE_LEVEL_FATAL,
11840 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070011841 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070011842 break;
11843 }
11844
11845 pr_info("%s: WCNSS software version %s\n",
11846 WLAN_MODULE_NAME, versionString);
Sushant Kaushik084f6592015-09-10 13:11:56 +053011847 vos_mem_copy(pHddCtx->fw_Version, versionString, sizeof(versionString));
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070011848
11849 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
11850 versionString,
11851 sizeof(versionString));
11852 if (!VOS_IS_STATUS_SUCCESS(vstatus))
11853 {
11854 hddLog(VOS_TRACE_LEVEL_FATAL,
11855 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070011856 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070011857 break;
11858 }
11859
11860 pr_info("%s: WCNSS hardware version %s\n",
11861 WLAN_MODULE_NAME, versionString);
11862
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -070011863 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
11864 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070011865 send the message only if it the riva is 1.1
11866 minor numbers for different riva branches:
11867 0 -> (1.0)Mainline Build
11868 1 -> (1.1)Mainline Build
11869 2->(1.04) Stability Build
11870 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -070011871 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070011872 ((versionReported.minor>=1) && (versionReported.version>=1)))
11873 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
11874 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -070011875
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070011876 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -080011877 {
11878#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
11879 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
11880 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
11881#endif
Ravi Joshid2ca7c42013-07-23 08:37:49 -070011882 /* Indicate if IBSS heartbeat monitoring needs to be offloaded */
11883 if (!pHddCtx->cfg_ini->enableIbssHeartBeatOffload)
11884 {
11885 sme_disableFeatureCapablity(IBSS_HEARTBEAT_OFFLOAD);
11886 }
11887
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070011888 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -080011889 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070011890
11891 } while (0);
11892
11893}
Neelansh Mittaledafed22014-09-04 18:54:39 +053011894void wlan_hdd_send_svc_nlink_msg(int type, void *data, int len)
11895{
11896 struct sk_buff *skb;
11897 struct nlmsghdr *nlh;
11898 tAniMsgHdr *ani_hdr;
Hanumantha Reddy Pothulacf2c7ea2015-04-27 14:50:47 +053011899 int flags = GFP_KERNEL;
Bhargav shah23c94942015-10-13 12:48:35 +053011900 void *nl_data = NULL;
Neelansh Mittaledafed22014-09-04 18:54:39 +053011901
Hanumantha Reddy Pothulacf2c7ea2015-04-27 14:50:47 +053011902 if (in_interrupt() || irqs_disabled() || in_atomic())
11903 flags = GFP_ATOMIC;
11904
11905 skb = alloc_skb(NLMSG_SPACE(WLAN_NL_MAX_PAYLOAD), flags);
Neelansh Mittaledafed22014-09-04 18:54:39 +053011906
11907 if(skb == NULL) {
11908 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
11909 "%s: alloc_skb failed", __func__);
11910 return;
11911 }
11912
11913 nlh = (struct nlmsghdr *)skb->data;
11914 nlh->nlmsg_pid = 0; /* from kernel */
11915 nlh->nlmsg_flags = 0;
11916 nlh->nlmsg_seq = 0;
11917 nlh->nlmsg_type = WLAN_NL_MSG_SVC;
11918
11919 ani_hdr = NLMSG_DATA(nlh);
11920 ani_hdr->type = type;
11921
11922 switch(type) {
11923 case WLAN_SVC_SAP_RESTART_IND:
11924 ani_hdr->length = 0;
11925 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr)));
11926 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr)));
11927 break;
Bhargav Shahd0715912015-10-01 18:17:37 +053011928 case WLAN_SVC_WLAN_TP_IND:
11929 ani_hdr->length = len;
11930 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr)
11931 + len));
11932 nl_data = (char *)ani_hdr + sizeof(tAniMsgHdr);
11933 memcpy(nl_data, data, len);
11934 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + len));
11935 break;
Bhargav shah23c94942015-10-13 12:48:35 +053011936 case WLAN_MSG_RPS_ENABLE_IND:
11937 ani_hdr->length = len;
11938 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + len));
11939 nl_data = (char *)ani_hdr + sizeof(tAniMsgHdr);
11940 memcpy(nl_data, data, len);
11941 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + len));
11942 break;
Neelansh Mittaledafed22014-09-04 18:54:39 +053011943 default:
11944 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
11945 "Attempt to send unknown nlink message %d", type);
11946 kfree_skb(skb);
11947 return;
11948 }
11949
11950 nl_srv_bcast(skb);
11951
11952 return;
11953}
11954
Bhargav Shahd0715912015-10-01 18:17:37 +053011955/**
11956 * hdd_request_tcp_delack() - Find the Delack value based on RX packet
11957 * @pHddCtx: Valid Global HDD context pointer
11958 * @rx_packets: Number of RX packet in perticular time
11959 *
11960 * Based on the RX packet this function calculate next value of tcp delack.
11961 * This function compare rx packet value to high and low threshold limit.
11962 *
11963 * Return: void
11964 */
11965void hdd_request_tcp_delack(hdd_context_t *pHddCtx, uint64_t rx_packets)
11966{
11967 /* average of rx_packets and prev_rx is taken so that
11968 bus width doesnot fluctuate much */
11969 uint64_t temp_rx = (rx_packets + pHddCtx->prev_rx)/2;
11970 TP_IND_TYPE next_rx_level = pHddCtx->cur_rx_level;
Neelansh Mittaledafed22014-09-04 18:54:39 +053011971
Bhargav Shahd0715912015-10-01 18:17:37 +053011972 pHddCtx->prev_rx = rx_packets;
11973 if (temp_rx > pHddCtx->cfg_ini->tcpDelAckThresholdHigh)
11974 next_rx_level = TP_IND_HIGH;
11975 else if (temp_rx <= pHddCtx->cfg_ini->tcpDelAckThresholdLow)
11976 next_rx_level = TP_IND_LOW;
11977
11978 hdd_set_delack_value(pHddCtx, next_rx_level);
11979}
11980
11981#define HDD_BW_GET_DIFF(x, y) ((x) >= (y) ? (x) - (y) : (ULONG_MAX - (y) + (x)))
11982
11983/**
11984 * hdd_tcp_delack_compute_function() - get link status
11985 * @priv: Valid Global HDD context pointer
11986 *
11987 * This function find number of RX packet during timer life span.
11988 * It request tcp delack with number of RX packet and re-configure delack timer
11989 * for tcpDelAckComputeInterval timer interval.
11990 *
11991 * Return: void
11992 */
11993void hdd_tcp_delack_compute_function(void *priv)
11994{
11995 hdd_context_t *pHddCtx = (hdd_context_t *)priv;
11996 hdd_adapter_t *pAdapter = NULL;
11997 v_U32_t rx_packets = 0;
11998 hdd_adapter_list_node_t *pAdapterNode = NULL;
11999 VOS_STATUS status = 0;
12000
12001 for (status = hdd_get_front_adapter(pHddCtx, &pAdapterNode);
12002 NULL != pAdapterNode && VOS_STATUS_SUCCESS == status;
12003 status = hdd_get_next_adapter(pHddCtx, pAdapterNode, &pAdapterNode)) {
12004 if ((pAdapter = pAdapterNode->pAdapter) == NULL)
12005 continue;
12006
12007 rx_packets += HDD_BW_GET_DIFF(pAdapter->stats.rx_packets,
12008 pAdapter->prev_rx_packets);
12009 pAdapter->prev_rx_packets = pAdapter->stats.rx_packets;
12010 }
12011
12012 hdd_request_tcp_delack(pHddCtx, rx_packets);
12013
12014 vos_timer_start(&pHddCtx->delack_timer,
12015 pHddCtx->cfg_ini->tcpDelAckComputeInterval);
12016}
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070012017
12018/**---------------------------------------------------------------------------
12019
Gopichand Nakkalafce506f2013-07-03 23:55:16 +053012020 \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
12021
12022 \param - pHddCtx - Pointer to the hdd context
12023
12024 \return - true if hardware supports 5GHz
12025
12026 --------------------------------------------------------------------------*/
Vinay Krishna Erannafacf5e22014-02-24 13:16:25 +053012027boolean hdd_is_5g_supported(hdd_context_t * pHddCtx)
Gopichand Nakkalafce506f2013-07-03 23:55:16 +053012028{
12029 /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
12030 * then hardware support 5Ghz.
12031 */
12032 if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode())
12033 {
Ratheesh S P36dbc932015-08-07 14:28:57 +053012034 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware supports 5Ghz", __func__);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +053012035 return true;
12036 }
12037 else
12038 {
Ratheesh S P36dbc932015-08-07 14:28:57 +053012039 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware doesn't supports 5Ghz",
Gopichand Nakkalafce506f2013-07-03 23:55:16 +053012040 __func__);
12041 return false;
12042 }
12043}
12044
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053012045/**---------------------------------------------------------------------------
12046
12047 \brief hdd_generate_iface_mac_addr_auto() - HDD Mac Interface Auto
12048 generate function
12049
12050 This is generate the random mac address for WLAN interface
12051
12052 \param - pHddCtx - Pointer to HDD context
12053 idx - Start interface index to get auto
12054 generated mac addr.
12055 mac_addr - Mac address
12056
12057 \return - 0 for success, < 0 for failure
12058
12059 --------------------------------------------------------------------------*/
12060
12061static int hdd_generate_iface_mac_addr_auto(hdd_context_t *pHddCtx,
12062 int idx, v_MACADDR_t mac_addr)
12063{
12064 int i;
12065 unsigned int serialno;
12066 serialno = wcnss_get_serial_number();
12067
12068 if (0 != serialno)
12069 {
12070 /* MAC address has 3 bytes of OUI so we have a maximum of 3
12071 bytes of the serial number that can be used to generate
12072 the other 3 bytes of the MAC address. Mask off all but
12073 the lower 3 bytes (this will also make sure we don't
12074 overflow in the next step) */
12075 serialno &= 0x00FFFFFF;
12076
12077 /* we need a unique address for each session */
12078 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
12079
12080 /* autogen other Mac addresses */
12081 for (i = idx; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
12082 {
12083 /* start with the entire default address */
12084 pHddCtx->cfg_ini->intfMacAddr[i] = mac_addr;
12085 /* then replace the lower 3 bytes */
12086 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
12087 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
12088 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
12089
Nachiket Kukadede2e24f2017-09-25 16:24:27 +053012090 if (0 == memcmp(&pHddCtx->cfg_ini->intfMacAddr[i].bytes[0],
12091 &mac_addr.bytes[0], VOS_MAC_ADDR_SIZE))
12092 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] +=
12093 VOS_MAX_CONCURRENCY_PERSONA;
12094
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053012095 serialno++;
12096 hddLog(VOS_TRACE_LEVEL_ERROR,
12097 "%s: Derived Mac Addr: "
12098 MAC_ADDRESS_STR, __func__,
12099 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[i].bytes));
12100 }
12101
12102 }
12103 else
12104 {
12105 hddLog(LOGE, FL("Failed to Get Serial NO"));
12106 return -1;
12107 }
12108 return 0;
12109}
Gopichand Nakkalafce506f2013-07-03 23:55:16 +053012110
Katya Nigame7b69a82015-04-28 15:24:06 +053012111int wlan_hdd_mon_open(hdd_context_t *pHddCtx)
12112{
12113 VOS_STATUS status;
12114 v_CONTEXT_t pVosContext= NULL;
12115 hdd_adapter_t *pAdapter= NULL;
12116
12117 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
12118
12119 if (NULL == pVosContext)
12120 {
12121 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
12122 "%s: Trying to open VOSS without a PreOpen", __func__);
12123 VOS_ASSERT(0);
12124 return VOS_STATUS_E_FAILURE;
12125 }
12126
12127 status = vos_nv_open();
12128 if (!VOS_IS_STATUS_SUCCESS(status))
12129 {
12130 /* NV module cannot be initialized */
12131 hddLog( VOS_TRACE_LEVEL_FATAL,
12132 "%s: vos_nv_open failed", __func__);
12133 return VOS_STATUS_E_FAILURE;
12134 }
12135
12136 status = vos_init_wiphy_from_nv_bin();
12137 if (!VOS_IS_STATUS_SUCCESS(status))
12138 {
12139 /* NV module cannot be initialized */
12140 hddLog( VOS_TRACE_LEVEL_FATAL,
12141 "%s: vos_init_wiphy failed", __func__);
12142 goto err_vos_nv_close;
12143 }
12144
12145 status = vos_open( &pVosContext, pHddCtx->parent_dev);
12146 if ( !VOS_IS_STATUS_SUCCESS( status ))
12147 {
12148 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
12149 goto err_vos_nv_close;
12150 }
12151
12152 status = vos_mon_start( pVosContext );
12153 if ( !VOS_IS_STATUS_SUCCESS( status ) )
12154 {
12155 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
12156 goto err_vosclose;
12157 }
12158
12159 WLANTL_SetMonRxCbk( pVosContext, hdd_rx_packet_monitor_cbk );
12160 WDA_featureCapsExchange(pVosContext);
12161 wcnss_wlan_set_drvdata(pHddCtx->parent_dev, pHddCtx);
12162
12163 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_MONITOR, "wlan%d",
12164 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
12165 if( pAdapter == NULL )
12166 {
12167 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
12168 goto err_close_adapter;
12169 }
12170
12171 //Initialize the nlink service
12172 if(nl_srv_init() != 0)
12173 {
12174 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
12175 goto err_close_adapter;
12176 }
12177 return VOS_STATUS_SUCCESS;
12178
12179err_close_adapter:
12180 hdd_close_all_adapters( pHddCtx );
12181 vos_mon_stop( pVosContext );
12182err_vosclose:
12183 status = vos_sched_close( pVosContext );
12184 if (!VOS_IS_STATUS_SUCCESS(status)) {
12185 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
12186 "%s: Failed to close VOSS Scheduler", __func__);
12187 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
12188 }
12189 vos_close(pVosContext );
12190
12191err_vos_nv_close:
12192 vos_nv_close();
12193
12194return status;
12195}
Gopichand Nakkalafce506f2013-07-03 23:55:16 +053012196/**---------------------------------------------------------------------------
12197
Mihir Shetefc7ff5b2014-01-27 11:30:05 +053012198 \brief hdd_11d_scan_done - callback to be executed when 11d scan is
12199 completed to flush out the scan results
12200
12201 11d scan is done during driver load and is a passive scan on all
12202 channels supported by the device, 11d scans may find some APs on
12203 frequencies which are forbidden to be used in the regulatory domain
12204 the device is operating in. If these APs are notified to the supplicant
12205 it may try to connect to these APs, thus flush out all the scan results
12206 which are present in SME after 11d scan is done.
12207
12208 \return - eHalStatus
12209
12210 --------------------------------------------------------------------------*/
12211static eHalStatus hdd_11d_scan_done(tHalHandle halHandle, void *pContext,
12212 tANI_U32 scanId, eCsrScanStatus status)
12213{
12214 ENTER();
12215
12216 sme_ScanFlushResult(halHandle, 0);
12217
12218 EXIT();
12219
12220 return eHAL_STATUS_SUCCESS;
12221}
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012222/**---------------------------------------------------------------------------
12223
12224 \brief hdd_init_frame_logging_done - callback to be executed when mgmt frame
12225 logging is completed successfully.
12226
12227 \return - None
12228
12229 --------------------------------------------------------------------------*/
c_manjeecfd1efb2015-09-25 19:32:34 +053012230void hdd_init_frame_logging_done(void *fwlogInitCbContext, tAniLoggingInitRsp *pRsp)
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012231{
Siddharth Bhald1be97f2015-05-27 22:39:59 +053012232 hdd_context_t* pHddCtx = (hdd_context_t*)fwlogInitCbContext;
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012233
12234 if (NULL == pHddCtx)
12235 {
12236 hddLog(VOS_TRACE_LEVEL_ERROR,
12237 "%s: HDD context is NULL",__func__);
12238 return;
12239 }
12240
c_manjeecfd1efb2015-09-25 19:32:34 +053012241 if ((pRsp->status == VOS_STATUS_SUCCESS) &&
Mahesh A Saptasagarfabb1a02015-06-29 12:17:04 +053012242 (TRUE == pHddCtx->cfg_ini->enableMgmtLogging))
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012243 {
12244 hddLog(VOS_TRACE_LEVEL_INFO, FL("Mgmt Frame Logging init successful"));
12245 pHddCtx->mgmt_frame_logging = TRUE;
12246 }
12247 else
12248 {
12249 hddLog(VOS_TRACE_LEVEL_INFO, FL("Mgmt Frame Logging init not success"));
12250 pHddCtx->mgmt_frame_logging = FALSE;
c_manjeecfd1efb2015-09-25 19:32:34 +053012251 return;
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012252 }
12253
c_manjeecfd1efb2015-09-25 19:32:34 +053012254 /*Check feature supported by FW*/
12255 if(TRUE == sme_IsFeatureSupportedByFW(MEMORY_DUMP_SUPPORTED))
12256 {
12257 //Store fwr mem dump size given by firmware.
12258 wlan_store_fwr_mem_dump_size(pRsp->fw_mem_dump_max_size);
12259 }
12260 else
12261 {
12262 wlan_store_fwr_mem_dump_size(0);
12263 }
12264
12265
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012266}
12267/**---------------------------------------------------------------------------
12268
12269 \brief hdd_init_frame_logging - function to initialize frame logging.
12270 Currently only Mgmt Frames are logged in both TX
12271 and Rx direction and are sent to userspace
12272 application using logger thread when queried.
12273
12274 \return - None
12275
12276 --------------------------------------------------------------------------*/
Siddharth Bhald1be97f2015-05-27 22:39:59 +053012277void hdd_init_frame_logging(hdd_context_t* pHddCtx)
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012278{
12279 eHalStatus halStatus = eHAL_STATUS_FAILURE;
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053012280 tSirFWLoggingInitParam wlanFWLoggingInitParam = {0};
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012281
Siddharth Bhald1be97f2015-05-27 22:39:59 +053012282 if (TRUE != sme_IsFeatureSupportedByFW(MGMT_FRAME_LOGGING) &&
12283 TRUE != sme_IsFeatureSupportedByFW(LOGGING_ENHANCEMENT))
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012284 {
12285 hddLog(VOS_TRACE_LEVEL_INFO, FL("MGMT_FRAME_LOGGING not supp by FW"));
12286 return;
12287 }
12288
c_manjeecfd1efb2015-09-25 19:32:34 +053012289 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Configuring %s %s %s %s Logging",__func__,
Siddharth Bhald1be97f2015-05-27 22:39:59 +053012290 pHddCtx->cfg_ini->enableFWLogging?"FW Log,":"",
12291 pHddCtx->cfg_ini->enableContFWLogging ? "Cont FW log,":"",
c_manjeecfd1efb2015-09-25 19:32:34 +053012292 pHddCtx->cfg_ini->enableMgmtLogging ? "Mgmt Pkt Log":"",
12293 pHddCtx->cfg_ini->enableFwrMemDump ? "Fw Mem dump":"");
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012294
Siddharth Bhald1be97f2015-05-27 22:39:59 +053012295 if (pHddCtx->cfg_ini->enableFWLogging ||
12296 pHddCtx->cfg_ini->enableContFWLogging)
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012297 {
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053012298 wlanFWLoggingInitParam.enableFlag |= WLAN_QXDM_LOG_EN;
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012299 }
12300
Sushant Kaushik46804902015-07-08 14:46:03 +053012301 if (pHddCtx->cfg_ini->enableMgmtLogging)
12302 {
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053012303 wlanFWLoggingInitParam.enableFlag |= WLAN_FRAME_LOG_EN;
Sushant Kaushik46804902015-07-08 14:46:03 +053012304 }
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012305 if (pHddCtx->cfg_ini->enableBMUHWtracing)
12306 {
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053012307 wlanFWLoggingInitParam.enableFlag |= WLAN_BMUHW_TRACE_LOG_EN;
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012308 }
c_manjeecfd1efb2015-09-25 19:32:34 +053012309 if(pHddCtx->cfg_ini->enableFwrMemDump &&
12310 (TRUE == sme_IsFeatureSupportedByFW(MEMORY_DUMP_SUPPORTED)))
12311 {
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053012312 wlanFWLoggingInitParam.enableFlag |= WLAN_FW_MEM_DUMP_EN;
c_manjeecfd1efb2015-09-25 19:32:34 +053012313 }
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053012314 if( wlanFWLoggingInitParam.enableFlag == 0 )
c_manjeecfd1efb2015-09-25 19:32:34 +053012315 {
12316 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Logging not enabled", __func__);
12317 return;
12318 }
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053012319 wlanFWLoggingInitParam.frameType = WLAN_FRAME_LOGGING_FRAMETYPE_MGMT;
12320 wlanFWLoggingInitParam.frameSize = WLAN_MGMT_LOGGING_FRAMESIZE_128BYTES;
12321 wlanFWLoggingInitParam.bufferMode = WLAN_FRAME_LOGGING_BUFFERMODE_CIRCULAR;
12322 wlanFWLoggingInitParam.continuousFrameLogging =
Siddharth Bhald1be97f2015-05-27 22:39:59 +053012323 pHddCtx->cfg_ini->enableContFWLogging;
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012324
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053012325 wlanFWLoggingInitParam.enableFlag &= ~WLAN_DPU_TXP_LOG_EN;
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012326
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053012327 wlanFWLoggingInitParam.minLogBufferSize =
Siddharth Bhald1be97f2015-05-27 22:39:59 +053012328 pHddCtx->cfg_ini->minLoggingBufferSize;
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053012329 wlanFWLoggingInitParam.maxLogBufferSize =
Siddharth Bhald1be97f2015-05-27 22:39:59 +053012330 pHddCtx->cfg_ini->maxLoggingBufferSize;
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053012331 wlanFWLoggingInitParam.fwlogInitCallback = hdd_init_frame_logging_done;
12332 wlanFWLoggingInitParam.fwlogInitCbContext= pHddCtx;
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012333
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053012334 halStatus = sme_InitMgmtFrameLogging(pHddCtx->hHal, &wlanFWLoggingInitParam);
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012335
12336 if (eHAL_STATUS_SUCCESS != halStatus)
12337 {
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053012338 hddLog(LOGE, FL("sme_InitMgmtFrameLogging failed, returned %d"),
12339 halStatus);
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012340 }
12341
12342 return;
12343}
Mihir Shetefc7ff5b2014-01-27 11:30:05 +053012344
Bhargav shah23c94942015-10-13 12:48:35 +053012345static void hdd_dp_util_send_rps_ind(hdd_context_t *hdd_ctxt)
12346{
12347 hdd_adapter_t *adapter;
12348 hdd_adapter_list_node_t *adapter_node, *next;
12349 VOS_STATUS status = VOS_STATUS_SUCCESS;
12350 struct wlan_rps_data rps_data;
12351 int count;
12352
12353 if(!hdd_ctxt->cfg_ini->rps_mask)
12354 {
12355 return;
12356 }
12357
12358 for (count=0; count < WLAN_SVC_IFACE_NUM_QUEUES; count++)
12359 {
12360 rps_data.cpu_map[count] = hdd_ctxt->cfg_ini->rps_mask;
12361 }
12362
12363 rps_data.num_queues = WLAN_SVC_IFACE_NUM_QUEUES;
12364
12365 hddLog(LOG1, FL("0x%x 0x%x 0x%x 0x%x 0x%x 0x%x"),
12366 rps_data.cpu_map[0], rps_data.cpu_map[1],rps_data.cpu_map[2],
12367 rps_data.cpu_map[3], rps_data.cpu_map[4], rps_data.cpu_map[5]);
12368
12369 status = hdd_get_front_adapter (hdd_ctxt, &adapter_node);
12370
12371 while (NULL != adapter_node && VOS_STATUS_SUCCESS == status)
12372 {
12373 adapter = adapter_node->pAdapter;
12374 if (NULL != adapter) {
12375 strlcpy(rps_data.ifname, adapter->dev->name,
12376 sizeof(rps_data.ifname));
12377 wlan_hdd_send_svc_nlink_msg(WLAN_MSG_RPS_ENABLE_IND,
12378 (void *)&rps_data,sizeof(rps_data));
12379 }
12380 status = hdd_get_next_adapter (hdd_ctxt, adapter_node, &next);
12381 adapter_node = next;
12382 }
12383}
12384
Masti, Narayanraddi26378462016-01-05 18:20:28 +053012385void wlan_hdd_schedule_defer_scan(struct work_struct *work)
12386{
12387 scan_context_t *scan_ctx =
12388 container_of(work, scan_context_t, scan_work.work);
12389
12390 if (NULL == scan_ctx)
12391 {
12392 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
12393 FL("scan_ctx is NULL"));
12394 return;
12395 }
12396
12397 if (unlikely(TDLS_CTX_MAGIC != scan_ctx->magic))
12398 return;
12399
12400 scan_ctx->attempt++;
12401
12402 wlan_hdd_cfg80211_scan(scan_ctx->wiphy,
12403#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
12404 scan_ctx->dev,
12405#endif
12406 scan_ctx->scan_request);
12407}
12408
12409int wlan_hdd_copy_defer_scan_context(hdd_context_t *pHddCtx,
12410 struct wiphy *wiphy,
12411#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
12412 struct net_device *dev,
12413#endif
12414 struct cfg80211_scan_request *request)
12415{
12416 scan_context_t *scan_ctx;
12417
12418 ENTER();
12419 if (0 != (wlan_hdd_validate_context(pHddCtx)))
12420 {
12421 return -1;
12422 }
12423
12424 scan_ctx = &pHddCtx->scan_ctxt;
12425
12426 scan_ctx->wiphy = wiphy;
12427#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
12428 scan_ctx->dev = dev;
12429#endif
12430
12431 scan_ctx->scan_request = request;
12432
12433 EXIT();
12434 return 0;
12435}
12436
12437void wlan_hdd_defer_scan_init_work(hdd_context_t *pHddCtx,
12438 struct wiphy *wiphy,
12439#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
12440 struct net_device *dev,
12441#endif
12442 struct cfg80211_scan_request *request,
12443 unsigned long delay)
12444{
12445 if (TDLS_CTX_MAGIC != pHddCtx->scan_ctxt.magic)
12446 {
12447#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
12448 wlan_hdd_copy_defer_scan_context(pHddCtx, wiphy, dev, request);
12449#else
12450 wlan_hdd_copy_defer_scan_context(pHddCtx, wiphy, request);
12451#endif
12452 pHddCtx->scan_ctxt.attempt = 0;
12453 pHddCtx->scan_ctxt.magic = TDLS_CTX_MAGIC;
12454 }
12455 schedule_delayed_work(&pHddCtx->scan_ctxt.scan_work, delay);
12456}
12457
12458void wlan_hdd_init_deinit_defer_scan_context(scan_context_t *scan_ctx)
12459{
12460 scan_ctx->magic = 0;
12461 scan_ctx->attempt = 0;
12462 scan_ctx->reject = 0;
12463 scan_ctx->scan_request = NULL;
12464
12465 return;
12466}
12467
Mihir Shetefc7ff5b2014-01-27 11:30:05 +053012468/**---------------------------------------------------------------------------
12469
Jeff Johnson295189b2012-06-20 16:38:30 -070012470 \brief hdd_wlan_startup() - HDD init function
12471
12472 This is the driver startup code executed once a WLAN device has been detected
12473
12474 \param - dev - Pointer to the underlying device
12475
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -080012476 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -070012477
12478 --------------------------------------------------------------------------*/
12479
12480int hdd_wlan_startup(struct device *dev )
12481{
12482 VOS_STATUS status;
12483 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -070012484 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -070012485 hdd_context_t *pHddCtx = NULL;
12486 v_CONTEXT_t pVosContext= NULL;
12487#ifdef WLAN_BTAMP_FEATURE
12488 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
12489 WLANBAP_ConfigType btAmpConfig;
12490 hdd_config_t *pConfig;
12491#endif
12492 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -070012493 struct wiphy *wiphy;
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053012494 v_MACADDR_t mac_addr;
Jeff Johnson295189b2012-06-20 16:38:30 -070012495
12496 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -070012497 /*
12498 * cfg80211: wiphy allocation
12499 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +053012500 wiphy = wlan_hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t)) ;
Jeff Johnson295189b2012-06-20 16:38:30 -070012501
12502 if(wiphy == NULL)
12503 {
12504 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -080012505 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -070012506 }
Jeff Johnson295189b2012-06-20 16:38:30 -070012507 pHddCtx = wiphy_priv(wiphy);
12508
Jeff Johnson295189b2012-06-20 16:38:30 -070012509 //Initialize the adapter context to zeros.
12510 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
12511
Jeff Johnson295189b2012-06-20 16:38:30 -070012512 pHddCtx->wiphy = wiphy;
Sushant Kaushik83392fa2015-05-05 17:44:40 +053012513 hdd_prevent_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_INIT);
Mihir Shete18156292014-03-11 15:38:30 +053012514 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_LOAD_IN_PROGRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -070012515
12516 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
12517
Siddharth Bhalcd92b782015-06-29 12:25:40 +053012518 /* register for riva power on lock to platform driver
12519 * Locking power early to ensure FW doesn't reset by kernel while
12520 * host driver is busy initializing itself */
12521 if (req_riva_power_on_lock("wlan"))
12522 {
12523 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
12524 __func__);
12525 goto err_free_hdd_context;
12526 }
12527
Jeff Johnson295189b2012-06-20 16:38:30 -070012528 /*Get vos context here bcoz vos_open requires it*/
12529 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
12530
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -080012531 if(pVosContext == NULL)
12532 {
12533 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
12534 goto err_free_hdd_context;
12535 }
12536
Jeff Johnson295189b2012-06-20 16:38:30 -070012537 //Save the Global VOSS context in adapter context for future.
12538 pHddCtx->pvosContext = pVosContext;
12539
12540 //Save the adapter context in global context for future.
12541 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
12542
Jeff Johnson295189b2012-06-20 16:38:30 -070012543 pHddCtx->parent_dev = dev;
Sreelakshmi Konamkif0646d52016-12-09 12:35:31 +053012544 pHddCtx->last_scan_reject_session_id = 0xFF;
12545 pHddCtx->last_scan_reject_reason = 0;
Sreelakshmi Konamki20ebed92016-10-27 12:13:30 +053012546 pHddCtx->last_scan_reject_timestamp = 0;
Abhishek Singhe4b12562017-06-20 16:53:39 +053012547 pHddCtx->scan_reject_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -070012548
12549 init_completion(&pHddCtx->full_pwr_comp_var);
12550 init_completion(&pHddCtx->standby_comp_var);
12551 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -070012552 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -080012553 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Kiet Lam46b8e4e2013-11-06 21:49:53 +053012554 init_completion(&pHddCtx->wiphy_channel_update_event);
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +053012555 init_completion(&pHddCtx->ssr_comp_var);
Mahesh A Saptasagar67ab9222015-10-21 15:38:41 +053012556 init_completion(&pHddCtx->mc_sus_event_var);
12557 init_completion(&pHddCtx->tx_sus_event_var);
12558 init_completion(&pHddCtx->rx_sus_event_var);
12559
Amar Singhala49cbc52013-10-08 18:37:44 -070012560
mukul sharma4bd8d2e2015-08-13 20:33:25 +053012561 hdd_init_ll_stats_ctx(pHddCtx);
Anurag Chouhan6ee81542017-02-09 18:09:27 +053012562 hdd_init_nud_stats_ctx(pHddCtx);
mukul sharma4bd8d2e2015-08-13 20:33:25 +053012563
Amar Singhala49cbc52013-10-08 18:37:44 -070012564#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhalfddc28c2013-09-05 13:03:40 -070012565 init_completion(&pHddCtx->linux_reg_req);
Amar Singhala49cbc52013-10-08 18:37:44 -070012566#else
12567 init_completion(&pHddCtx->driver_crda_req);
12568#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070012569
Padma, Santhosh Kumara1aa4a32015-06-19 19:00:46 +053012570#ifdef WLAN_FEATURE_EXTSCAN
12571 init_completion(&pHddCtx->ext_scan_context.response_event);
12572#endif /* WLAN_FEATURE_EXTSCAN */
12573
Kamath Vinayak4000c9a2013-08-23 14:24:27 +053012574 spin_lock_init(&pHddCtx->schedScan_lock);
Kapil Gupta137ef892016-12-13 19:38:00 +053012575 vos_spin_lock_init(&pHddCtx->sap_update_info_lock);
Kamath Vinayak4000c9a2013-08-23 14:24:27 +053012576
Jeff Johnson295189b2012-06-20 16:38:30 -070012577 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
12578
Padma, Santhosh Kumar9cd38332015-11-17 12:18:10 +053012579 vos_init_delayed_work(&pHddCtx->spoof_mac_addr_work,
12580 hdd_processSpoofMacAddrRequest);
Kapil Gupta137ef892016-12-13 19:38:00 +053012581 vos_init_work(&pHddCtx->sap_start_work, hdd_sap_restart_handle);
Abhishek Singh78c691f2017-11-30 13:48:44 +053012582 vos_init_delayed_work(&pHddCtx->ecsa_chan_change_work,
12583 hdd_force_scc_with_ecsa_handle);
Padma, Santhosh Kumar9cd38332015-11-17 12:18:10 +053012584
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +053012585#ifdef FEATURE_WLAN_TDLS
12586 /* tdls_lock is initialized before an hdd_open_adapter ( which is
12587 * invoked by other instances also) to protect the concurrent
12588 * access for the Adapters by TDLS module.
12589 */
12590 mutex_init(&pHddCtx->tdls_lock);
12591#endif
Siddharth Bhal76972212014-10-15 16:22:51 +053012592 mutex_init(&pHddCtx->spoofMacAddr.macSpoofingLock);
Mukul Sharma1fd6efd2015-02-14 00:29:14 +053012593 mutex_init(&pHddCtx->wmmLock);
12594
Srinivas Girigowda8bf64cb2015-09-30 19:50:09 +053012595 hdd_init_offloaded_packets_ctx(pHddCtx);
Agarwal Ashish1f422872014-07-22 00:11:55 +053012596 /* By default Strict Regulatory For FCC should be false */
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +053012597
Agarwal Ashish1f422872014-07-22 00:11:55 +053012598 pHddCtx->nEnableStrictRegulatoryForFCC = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -070012599 // Load all config first as TL config is needed during vos_open
12600 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
12601 if(pHddCtx->cfg_ini == NULL)
12602 {
12603 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
12604 goto err_free_hdd_context;
12605 }
12606
12607 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
12608
12609 // Read and parse the qcom_cfg.ini file
12610 status = hdd_parse_config_ini( pHddCtx );
12611 if ( VOS_STATUS_SUCCESS != status )
12612 {
12613 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
12614 __func__, WLAN_INI_FILE);
12615 goto err_config;
12616 }
Arif Hussaind5218912013-12-05 01:10:55 -080012617#ifdef MEMORY_DEBUG
12618 if (pHddCtx->cfg_ini->IsMemoryDebugSupportEnabled)
12619 vos_mem_init();
12620
12621 hddLog(VOS_TRACE_LEVEL_INFO, "%s: gEnableMemoryDebug=%d",
12622 __func__, pHddCtx->cfg_ini->IsMemoryDebugSupportEnabled);
12623#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070012624
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +053012625 /* INI has been read, initialise the configuredMcastBcastFilter with
12626 * INI value as this will serve as the default value
12627 */
12628 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
12629 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
12630 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +053012631
12632 if (false == hdd_is_5g_supported(pHddCtx))
12633 {
12634 //5Ghz is not supported.
12635 if (1 != pHddCtx->cfg_ini->nBandCapability)
12636 {
12637 hddLog(VOS_TRACE_LEVEL_INFO,
12638 "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__);
12639 pHddCtx->cfg_ini->nBandCapability = 1;
12640 }
12641 }
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +053012642
12643 /* If SNR Monitoring is enabled, FW has to parse all beacons
12644 * for calcaluting and storing the average SNR, so set Nth beacon
12645 * filter to 1 to enable FW to parse all the beaocons
12646 */
12647 if (1 == pHddCtx->cfg_ini->fEnableSNRMonitoring)
12648 {
12649 /* The log level is deliberately set to WARN as overriding
12650 * nthBeaconFilter to 1 will increase power cosumption and this
12651 * might just prove helpful to detect the power issue.
12652 */
12653 hddLog(VOS_TRACE_LEVEL_WARN,
12654 "%s: Setting pHddCtx->cfg_ini->nthBeaconFilter = 1", __func__);
12655 pHddCtx->cfg_ini->nthBeaconFilter = 1;
12656 }
Jeff Johnson295189b2012-06-20 16:38:30 -070012657 /*
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +053012658 * cfg80211: Initialization ...
Jeff Johnson295189b2012-06-20 16:38:30 -070012659 */
Manjeet Singh61016fa2016-12-02 11:10:19 +053012660 if (0 < wlan_hdd_cfg80211_init(dev, wiphy, pHddCtx->cfg_ini))
Jeff Johnson295189b2012-06-20 16:38:30 -070012661 {
Manjeet Singh61016fa2016-12-02 11:10:19 +053012662 hddLog(VOS_TRACE_LEVEL_FATAL,
12663 "%s: wlan_hdd_cfg80211_init return failure", __func__);
12664 goto err_config;
Jeff Johnson295189b2012-06-20 16:38:30 -070012665 }
Jeff Johnson295189b2012-06-20 16:38:30 -070012666
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -080012667 // Update VOS trace levels based upon the cfg.ini
12668 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
12669 pHddCtx->cfg_ini->vosTraceEnableBAP);
12670 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
12671 pHddCtx->cfg_ini->vosTraceEnableTL);
12672 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
12673 pHddCtx->cfg_ini->vosTraceEnableWDI);
12674 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
12675 pHddCtx->cfg_ini->vosTraceEnableHDD);
12676 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
12677 pHddCtx->cfg_ini->vosTraceEnableSME);
12678 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
12679 pHddCtx->cfg_ini->vosTraceEnablePE);
Katya Nigam70d68332013-09-16 16:49:45 +053012680 hdd_vos_trace_enable(VOS_MODULE_ID_PMC,
12681 pHddCtx->cfg_ini->vosTraceEnablePMC);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -080012682 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
12683 pHddCtx->cfg_ini->vosTraceEnableWDA);
12684 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
12685 pHddCtx->cfg_ini->vosTraceEnableSYS);
12686 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
12687 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -080012688 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
12689 pHddCtx->cfg_ini->vosTraceEnableSAP);
12690 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
12691 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -080012692
Jeff Johnson295189b2012-06-20 16:38:30 -070012693 // Update WDI trace levels based upon the cfg.ini
12694 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
12695 pHddCtx->cfg_ini->wdiTraceEnableDAL);
12696 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
12697 pHddCtx->cfg_ini->wdiTraceEnableCTL);
12698 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
12699 pHddCtx->cfg_ini->wdiTraceEnableDAT);
12700 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
12701 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -070012702
Jeff Johnson88ba7742013-02-27 14:36:02 -080012703 if (VOS_FTM_MODE == hdd_get_conparam())
12704 {
Jeff Johnson295189b2012-06-20 16:38:30 -070012705 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
12706 {
12707 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
12708 goto err_free_hdd_context;
12709 }
12710 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
Sachin Ahuja38ef5e02015-03-13 17:31:16 +053012711 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_NO_LOAD_UNLOAD_IN_PROGRESS;
c_hpothu2de0ef62014-04-15 16:16:15 +053012712 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -070012713 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -080012714 }
Jeff Johnson295189b2012-06-20 16:38:30 -070012715
Katya Nigame7b69a82015-04-28 15:24:06 +053012716 if( VOS_MONITOR_MODE == hdd_get_conparam())
12717 {
12718 if ( VOS_STATUS_SUCCESS != wlan_hdd_mon_open(pHddCtx))
12719 {
12720 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_mon_open Failed",__func__);
12721 goto err_free_hdd_context;
12722 }
12723 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Driver loaded in Monitor Mode",__func__);
12724 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_NO_LOAD_UNLOAD_IN_PROGRESS;
12725 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
12726 return VOS_STATUS_SUCCESS;
12727 }
12728
Jeff Johnson88ba7742013-02-27 14:36:02 -080012729 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -070012730 if(pHddCtx->cfg_ini->fIsLogpEnabled)
12731 {
12732 status = vos_watchdog_open(pVosContext,
12733 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
12734
12735 if(!VOS_IS_STATUS_SUCCESS( status ))
12736 {
12737 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Ashish Kumar Dhanotiya532bdef2017-05-09 17:31:59 +053012738 goto err_config;
Jeff Johnson295189b2012-06-20 16:38:30 -070012739 }
12740 }
12741
12742 pHddCtx->isLogpInProgress = FALSE;
12743 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
12744
Amar Singhala49cbc52013-10-08 18:37:44 -070012745#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -070012746 /* initialize the NV module. This is required so that
12747 we can initialize the channel information in wiphy
12748 from the NV.bin data. The channel information in
12749 wiphy needs to be initialized before wiphy registration */
12750
12751 status = vos_nv_open();
12752 if (!VOS_IS_STATUS_SUCCESS(status))
12753 {
12754 /* NV module cannot be initialized */
12755 hddLog( VOS_TRACE_LEVEL_FATAL,
12756 "%s: vos_nv_open failed", __func__);
Vinay Krishna Eranna2025d892014-09-18 16:51:42 +053012757 goto err_wdclose;
Amar Singhal0a402232013-10-11 20:57:16 -070012758 }
12759
12760 status = vos_init_wiphy_from_nv_bin();
12761 if (!VOS_IS_STATUS_SUCCESS(status))
12762 {
12763 /* NV module cannot be initialized */
12764 hddLog( VOS_TRACE_LEVEL_FATAL,
12765 "%s: vos_init_wiphy failed", __func__);
12766 goto err_vos_nv_close;
12767 }
12768
Amar Singhala49cbc52013-10-08 18:37:44 -070012769#endif
Mahesh A Saptasagarc3ed0122016-01-19 16:45:11 +053012770 //Initialize the nlink service
12771 if(nl_srv_init() != 0)
12772 {
12773 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
12774 goto err_vos_nv_close;
12775 }
12776
12777#ifdef WLAN_KD_READY_NOTIFIER
12778 pHddCtx->kd_nl_init = 1;
12779#endif /* WLAN_KD_READY_NOTIFIER */
12780
Girish Gowlibf0e1ab2015-01-19 16:05:16 +053012781 vos_set_roam_delay_stats_enabled(pHddCtx->cfg_ini->gEnableRoamDelayStats);
Arun Kumar Khandavalliebb19482014-03-25 13:56:53 +053012782 status = vos_open( &pVosContext, pHddCtx->parent_dev);
Jeff Johnson295189b2012-06-20 16:38:30 -070012783 if ( !VOS_IS_STATUS_SUCCESS( status ))
12784 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -080012785 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
Mahesh A Saptasagarc3ed0122016-01-19 16:45:11 +053012786 goto err_nl_srv;
Jeff Johnson295189b2012-06-20 16:38:30 -070012787 }
12788
Jeff Johnson295189b2012-06-20 16:38:30 -070012789 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
12790
12791 if ( NULL == pHddCtx->hHal )
12792 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -080012793 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -070012794 goto err_vosclose;
12795 }
12796
Jeff Johnsonbc676b42013-02-14 16:04:08 -080012797 status = vos_preStart( pHddCtx->pvosContext );
12798 if ( !VOS_IS_STATUS_SUCCESS( status ) )
12799 {
12800 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053012801 goto err_vosclose;
Jeff Johnsonbc676b42013-02-14 16:04:08 -080012802 }
Jeff Johnsone7245742012-09-05 17:12:55 -070012803
Arif Hussaineaf68602013-12-30 23:10:44 -080012804 if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan)
12805 {
12806 pHddCtx->cfg_ini->enableDFSChnlScan = enable_dfs_chan_scan;
12807 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_dfs_chan_scan set to %d",
12808 __func__, enable_dfs_chan_scan);
12809 }
12810 if (0 == enable_11d || 1 == enable_11d)
12811 {
12812 pHddCtx->cfg_ini->Is11dSupportEnabled = enable_11d;
12813 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_11d set to %d",
12814 __func__, enable_11d);
12815 }
12816
Jeff Johnsonbc676b42013-02-14 16:04:08 -080012817 /* Note that the vos_preStart() sequence triggers the cfg download.
12818 The cfg download must occur before we update the SME config
12819 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -070012820 status = hdd_set_sme_config( pHddCtx );
12821
12822 if ( VOS_STATUS_SUCCESS != status )
12823 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -080012824 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053012825 goto err_vosclose;
Jeff Johnsonbc676b42013-02-14 16:04:08 -080012826 }
Jeff Johnson295189b2012-06-20 16:38:30 -070012827
Jeff Johnson295189b2012-06-20 16:38:30 -070012828 /* In the integrated architecture we update the configuration from
12829 the INI file and from NV before vOSS has been started so that
12830 the final contents are available to send down to the cCPU */
12831
12832 // Apply the cfg.ini to cfg.dat
12833 if (FALSE == hdd_update_config_dat(pHddCtx))
12834 {
12835 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053012836 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -070012837 }
12838
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053012839 // Get mac addr from platform driver
12840 ret = wcnss_get_wlan_mac_address((char*)&mac_addr.bytes);
12841
12842 if ((0 == ret) && (!vos_is_macaddr_zero(&mac_addr)))
Jeff Johnson295189b2012-06-20 16:38:30 -070012843 {
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053012844 /* Store the mac addr for first interface */
12845 pHddCtx->cfg_ini->intfMacAddr[0] = mac_addr;
12846
12847 hddLog(VOS_TRACE_LEVEL_ERROR,
12848 "%s: WLAN Mac Addr: "
12849 MAC_ADDRESS_STR, __func__,
12850 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
12851
12852 /* Here, passing Arg2 as 1 because we do not want to change the
12853 last 3 bytes (means non OUI bytes) of first interface mac
12854 addr.
12855 */
12856 if (0 != hdd_generate_iface_mac_addr_auto(pHddCtx, 1, mac_addr))
12857 {
12858 hddLog(VOS_TRACE_LEVEL_ERROR,
12859 "%s: Failed to generate wlan interface mac addr "
12860 "using MAC from ini file ", __func__);
12861 }
12862 }
12863 else if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
12864 {
12865 // Apply the NV to cfg.dat
12866 /* Prima Update MAC address only at here */
Jeff Johnson295189b2012-06-20 16:38:30 -070012867#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
12868 /* There was not a valid set of MAC Addresses in NV. See if the
12869 default addresses were modified by the cfg.ini settings. If so,
12870 we'll use them, but if not, we'll autogenerate a set of MAC
12871 addresses based upon the device serial number */
12872
12873 static const v_MACADDR_t default_address =
12874 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
Jeff Johnson295189b2012-06-20 16:38:30 -070012875
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053012876 if (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
12877 sizeof(default_address)))
Jeff Johnson295189b2012-06-20 16:38:30 -070012878 {
12879 /* cfg.ini has the default address, invoke autogen logic */
12880
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053012881 /* Here, passing Arg2 as 0 because we want to change the
12882 last 3 bytes (means non OUI bytes) of all the interfaces
12883 mac addr.
12884 */
12885 if (0 != hdd_generate_iface_mac_addr_auto(pHddCtx, 0,
12886 default_address))
Jeff Johnson295189b2012-06-20 16:38:30 -070012887 {
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053012888 hddLog(VOS_TRACE_LEVEL_ERROR,
12889 "%s: Failed to generate wlan interface mac addr "
12890 "using MAC from ini file " MAC_ADDRESS_STR, __func__,
12891 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
Jeff Johnson295189b2012-06-20 16:38:30 -070012892 }
Jeff Johnson295189b2012-06-20 16:38:30 -070012893 }
12894 else
12895#endif //WLAN_AUTOGEN_MACADDR_FEATURE
12896 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -080012897 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -070012898 "%s: Invalid MAC address in NV, using MAC from ini file "
12899 MAC_ADDRESS_STR, __func__,
12900 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
12901 }
12902 }
12903 {
12904 eHalStatus halStatus;
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053012905
12906 /* Set the MAC Address Currently this is used by HAL to
12907 * add self sta. Remove this once self sta is added as
12908 * part of session open.
12909 */
Jeff Johnson295189b2012-06-20 16:38:30 -070012910 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
12911 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
12912 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053012913
Jeff Johnson295189b2012-06-20 16:38:30 -070012914 if (!HAL_STATUS_SUCCESS( halStatus ))
12915 {
12916 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
12917 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053012918 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -070012919 }
12920 }
Jeff Johnson295189b2012-06-20 16:38:30 -070012921
12922 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
12923 Note: Firmware image will be read and downloaded inside vos_start API */
12924 status = vos_start( pHddCtx->pvosContext );
12925 if ( !VOS_IS_STATUS_SUCCESS( status ) )
12926 {
12927 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
Hanumantha Reddy Pothulabd9601a2016-02-12 13:22:27 +053012928 if (isSsrPanicOnFailure())
12929 VOS_BUG(0);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053012930 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -070012931 }
12932
Leo Chang6cec3e22014-01-21 15:33:49 -080012933#ifdef FEATURE_WLAN_CH_AVOID
12934 /* Plug in avoid channel notification callback
12935 * This should happen before ADD_SELF_STA
12936 * FW will send first IND with ADD_SELF_STA REQ from host */
Pradeep Reddy POTTETI5c2e16d2014-06-27 16:47:38 +053012937
12938 /* check the Channel Avoidance is enabled */
12939 if (TRUE == pHddCtx->cfg_ini->fenableCHAvoidance)
12940 {
12941 sme_AddChAvoidCallback(pHddCtx->hHal,
12942 hdd_hostapd_ch_avoid_cb);
12943 }
Leo Chang6cec3e22014-01-21 15:33:49 -080012944#endif /* FEATURE_WLAN_CH_AVOID */
12945
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070012946 /* Exchange capability info between Host and FW and also get versioning info from FW */
12947 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -070012948
Agarwal Ashishad9281b2014-06-10 14:57:30 +053012949#ifdef CONFIG_ENABLE_LINUX_REG
12950 status = wlan_hdd_init_channels(pHddCtx);
12951 if ( !VOS_IS_STATUS_SUCCESS( status ) )
12952 {
12953 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: wlan_hdd_init_channels failed",
12954 __func__);
12955 goto err_vosstop;
12956 }
12957#endif
12958
Jeff Johnson295189b2012-06-20 16:38:30 -070012959 status = hdd_post_voss_start_config( pHddCtx );
12960 if ( !VOS_IS_STATUS_SUCCESS( status ) )
12961 {
12962 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
12963 __func__);
12964 goto err_vosstop;
12965 }
Amar Singhala49cbc52013-10-08 18:37:44 -070012966
12967#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +053012968 wlan_hdd_cfg80211_update_reg_info( wiphy );
12969
12970 /* registration of wiphy dev with cfg80211 */
12971 if (0 > wlan_hdd_cfg80211_register(wiphy))
12972 {
12973 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
12974 goto err_vosstop;
12975 }
Amar Singhala49cbc52013-10-08 18:37:44 -070012976#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070012977
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053012978#ifdef CONFIG_ENABLE_LINUX_REG
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053012979 /* registration of wiphy dev with cfg80211 */
12980 if (0 > wlan_hdd_cfg80211_register(wiphy))
12981 {
12982 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
12983 goto err_vosstop;
12984 }
12985
Agarwal Ashish6db9d532014-09-30 18:19:10 +053012986 status = wlan_hdd_init_channels_for_cc(pHddCtx, INIT);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053012987 if ( !VOS_IS_STATUS_SUCCESS( status ) )
12988 {
12989 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: wlan_hdd_init_channels_for_cc failed",
12990 __func__);
12991 goto err_unregister_wiphy;
12992 }
12993#endif
12994
c_hpothu4a298be2014-12-22 21:12:51 +053012995 wcnss_wlan_set_drvdata(pHddCtx->parent_dev, pHddCtx);
12996
Jeff Johnson295189b2012-06-20 16:38:30 -070012997 if (VOS_STA_SAP_MODE == hdd_get_conparam())
12998 {
12999 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
13000 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
13001 }
13002 else
13003 {
Jeff Johnson295189b2012-06-20 16:38:30 -070013004 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
13005 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
13006 if (pAdapter != NULL)
13007 {
Katya Nigama7d81d72014-11-12 12:44:34 +053013008 if (pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated && !(pHddCtx->cfg_ini->intfMacAddr[0].bytes[0] & 0x02))
Jeff Johnson295189b2012-06-20 16:38:30 -070013009 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +053013010 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
13011 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
13012 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -070013013
Gopichand Nakkala49f96f62013-02-06 14:38:17 +053013014 /* Generate the P2P Device Address. This consists of the device's
13015 * primary MAC address with the locally administered bit set.
13016 */
13017 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -070013018 }
13019 else
13020 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +053013021 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
13022 if (p2p_dev_addr != NULL)
13023 {
13024 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
13025 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
13026 }
13027 else
13028 {
13029 hddLog(VOS_TRACE_LEVEL_FATAL,
13030 "%s: Failed to allocate mac_address for p2p_device",
13031 __func__);
13032 goto err_close_adapter;
13033 }
Jeff Johnson295189b2012-06-20 16:38:30 -070013034 }
Jeff Johnsone7245742012-09-05 17:12:55 -070013035
13036 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
13037 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
13038 if ( NULL == pP2pAdapter )
13039 {
13040 hddLog(VOS_TRACE_LEVEL_FATAL,
13041 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070013042 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -070013043 goto err_close_adapter;
13044 }
Jeff Johnsone7245742012-09-05 17:12:55 -070013045 }
Jeff Johnson295189b2012-06-20 16:38:30 -070013046 }
Jeff Johnson295189b2012-06-20 16:38:30 -070013047
13048 if( pAdapter == NULL )
13049 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -080013050 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
13051 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -070013052 }
Jeff Johnsone7245742012-09-05 17:12:55 -070013053
Arif Hussain66559122013-11-21 10:11:40 -080013054 if (country_code)
13055 {
13056 eHalStatus ret;
Arif Hussaincb607082013-12-20 11:57:42 -080013057 INIT_COMPLETION(pAdapter->change_country_code);
Arif Hussain66559122013-11-21 10:11:40 -080013058 hdd_checkandupdate_dfssetting(pAdapter, country_code);
13059#ifndef CONFIG_ENABLE_LINUX_REG
13060 hdd_checkandupdate_phymode(pAdapter, country_code);
13061#endif
Arif Hussaineaf68602013-12-30 23:10:44 -080013062 ret = sme_ChangeCountryCode(pHddCtx->hHal,
13063 (void *)(tSmeChangeCountryCallback)
13064 wlan_hdd_change_country_code_callback,
Arif Hussain66559122013-11-21 10:11:40 -080013065 country_code,
13066 pAdapter, pHddCtx->pvosContext,
Abhishek Singha306a442013-11-07 18:39:01 +053013067 eSIR_TRUE, eSIR_TRUE);
Arif Hussain66559122013-11-21 10:11:40 -080013068 if (eHAL_STATUS_SUCCESS == ret)
13069 {
Arif Hussaincb607082013-12-20 11:57:42 -080013070 ret = wait_for_completion_interruptible_timeout(
13071 &pAdapter->change_country_code,
13072 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
13073
13074 if (0 >= ret)
13075 {
13076 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
13077 "%s: SME while setting country code timed out", __func__);
13078 }
Arif Hussain66559122013-11-21 10:11:40 -080013079 }
13080 else
13081 {
Arif Hussaincb607082013-12-20 11:57:42 -080013082 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
13083 "%s: SME Change Country code from module param fail ret=%d",
13084 __func__, ret);
Arif Hussain66559122013-11-21 10:11:40 -080013085 }
13086 }
13087
Jeff Johnson295189b2012-06-20 16:38:30 -070013088#ifdef WLAN_BTAMP_FEATURE
13089 vStatus = WLANBAP_Open(pVosContext);
13090 if(!VOS_IS_STATUS_SUCCESS(vStatus))
13091 {
13092 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
13093 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -070013094 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -070013095 }
13096
13097 vStatus = BSL_Init(pVosContext);
13098 if(!VOS_IS_STATUS_SUCCESS(vStatus))
13099 {
13100 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
13101 "%s: Failed to Init BSL",__func__);
13102 goto err_bap_close;
13103 }
13104 vStatus = WLANBAP_Start(pVosContext);
13105 if (!VOS_IS_STATUS_SUCCESS(vStatus))
13106 {
13107 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
13108 "%s: Failed to start TL",__func__);
13109 goto err_bap_close;
13110 }
13111
13112 pConfig = pHddCtx->cfg_ini;
13113 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
13114 status = WLANBAP_SetConfig(&btAmpConfig);
13115
13116#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -070013117
Mihir Shete9c238772014-10-15 14:35:16 +053013118 /*
13119 * UapsdMask is 0xf if U-APSD is enbaled for all AC's...
13120 * The value of CFG_QOS_WMM_UAPSD_MASK_DEFAULT is 0xaa(Magic Value)
13121 * which is greater than 0xf. So the below check is safe to make
13122 * sure that there is no entry for UapsdMask in the ini
13123 */
13124 if (CFG_QOS_WMM_UAPSD_MASK_DEFAULT == pHddCtx->cfg_ini->UapsdMask)
13125 {
13126 if(IS_DYNAMIC_WMM_PS_ENABLED)
13127 {
13128 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: Enable UAPSD for VI & VO",
13129 __func__);
13130 pHddCtx->cfg_ini->UapsdMask =
13131 CFG_QOS_WMM_UAPSD_MASK_DYMANIC_WMM_PS_DEFAULT;
13132 }
13133 else
13134 {
13135 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: Do not enable UAPSD",
13136 __func__);
13137 pHddCtx->cfg_ini->UapsdMask =
13138 CFG_QOS_WMM_UAPSD_MASK_LEGACY_WMM_PS_DEFAULT;
13139 }
13140 }
13141
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -070013142#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
13143 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
13144 {
13145 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
13146 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
13147 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
13148 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
13149 }
13150#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070013151
Agarwal Ashish4b87f922014-06-18 03:03:21 +053013152 wlan_hdd_tdls_init(pHddCtx);
13153
Masti, Narayanraddi26378462016-01-05 18:20:28 +053013154 wlan_hdd_init_deinit_defer_scan_context(&pHddCtx->scan_ctxt);
13155
13156 vos_init_delayed_work(&pHddCtx->scan_ctxt.scan_work,
13157 wlan_hdd_schedule_defer_scan);
13158
Mihir Shetefc7ff5b2014-01-27 11:30:05 +053013159 sme_Register11dScanDoneCallback(pHddCtx->hHal, hdd_11d_scan_done);
13160
Jeff Johnson295189b2012-06-20 16:38:30 -070013161 /* Register with platform driver as client for Suspend/Resume */
13162 status = hddRegisterPmOps(pHddCtx);
13163 if ( !VOS_IS_STATUS_SUCCESS( status ) )
13164 {
13165 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
13166#ifdef WLAN_BTAMP_FEATURE
13167 goto err_bap_stop;
13168#else
Jeff Johnsone7245742012-09-05 17:12:55 -070013169 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -070013170#endif //WLAN_BTAMP_FEATURE
13171 }
13172
Yue Ma0d4891e2013-08-06 17:01:45 -070013173 /* Open debugfs interface */
13174 if (VOS_STATUS_SUCCESS != hdd_debugfs_init(pAdapter))
13175 {
13176 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
13177 "%s: hdd_debugfs_init failed!", __func__);
Yue Ma0d4891e2013-08-06 17:01:45 -070013178 }
13179
Jeff Johnson295189b2012-06-20 16:38:30 -070013180 /* Register TM level change handler function to the platform */
13181 status = hddDevTmRegisterNotifyCallback(pHddCtx);
13182 if ( !VOS_IS_STATUS_SUCCESS( status ) )
13183 {
13184 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
13185 goto err_unregister_pmops;
13186 }
Jeff Johnson295189b2012-06-20 16:38:30 -070013187
Jeff Johnson295189b2012-06-20 16:38:30 -070013188 // register net device notifier for device change notification
13189 ret = register_netdevice_notifier(&hdd_netdev_notifier);
13190
13191 if(ret < 0)
13192 {
13193 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
Siddharth Bhalcd92b782015-06-29 12:25:40 +053013194 goto err_unregister_pmops;
Jeff Johnson295189b2012-06-20 16:38:30 -070013195 }
13196
Jeff Johnson295189b2012-06-20 16:38:30 -070013197 //Initialize the BTC service
13198 if(btc_activate_service(pHddCtx) != 0)
13199 {
13200 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
Mahesh A Saptasagarc3ed0122016-01-19 16:45:11 +053013201 goto err_reg_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -070013202 }
13203
Padma, Santhosh Kumar2762e9d2015-10-20 15:02:57 +053013204#ifdef FEATURE_OEM_DATA_SUPPORT
13205 //Initialize the OEM service
13206 if (oem_activate_service(pHddCtx) != 0)
13207 {
13208 hddLog(VOS_TRACE_LEVEL_FATAL,
13209 "%s: oem_activate_service failed", __func__);
Hanumanth Reddy Pothula13789c42017-09-12 15:18:13 +053013210 goto err_btc_activate_service;
Padma, Santhosh Kumar2762e9d2015-10-20 15:02:57 +053013211 }
13212#endif
13213
Jeff Johnson295189b2012-06-20 16:38:30 -070013214#ifdef PTT_SOCK_SVC_ENABLE
13215 //Initialize the PTT service
13216 if(ptt_sock_activate_svc(pHddCtx) != 0)
13217 {
13218 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
Hanumanth Reddy Pothula13789c42017-09-12 15:18:13 +053013219 goto err_oem_activate_service;
Jeff Johnson295189b2012-06-20 16:38:30 -070013220 }
13221#endif
13222
Abhishek Singh00b71972016-01-07 10:51:04 +053013223#ifdef WLAN_FEATURE_RMC
13224 if (hdd_open_cesium_nl_sock() < 0)
13225 {
13226 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_open_cesium_nl_sock failed", __func__);
Hanumanth Reddy Pothula13789c42017-09-12 15:18:13 +053013227 goto err_ptt_sock_activate_svc;
Abhishek Singh00b71972016-01-07 10:51:04 +053013228 }
13229#endif
13230
Vinay Krishna Erannad938c422014-03-10 17:14:21 +053013231#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
13232 if(pHddCtx->cfg_ini && pHddCtx->cfg_ini->wlanLoggingEnable)
13233 {
Deepthi Gowri78083a32014-11-04 12:55:51 +053013234 if(wlan_logging_sock_activate_svc(
13235 pHddCtx->cfg_ini->wlanLoggingFEToConsole,
Sushant Kaushik33200572015-08-05 16:46:20 +053013236 pHddCtx->cfg_ini->wlanLoggingNumBuf,
13237 pHddCtx->cfg_ini->wlanPerPktStatsLogEnable,
13238 pHddCtx->cfg_ini->wlanPerPktStatsNumBuf))
Deepthi Gowri78083a32014-11-04 12:55:51 +053013239 {
13240 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wlan_logging_sock_activate_svc"
13241 " failed", __func__);
Hanumanth Reddy Pothula13789c42017-09-12 15:18:13 +053013242 goto err_open_cesium_nl_sock;
Deepthi Gowri78083a32014-11-04 12:55:51 +053013243 }
13244 //TODO: To Remove enableDhcpDebug and use gEnableDebugLog for
13245 //EAPOL and DHCP
Sachin Ahuja8c65f382014-12-12 15:34:21 +053013246 if (!pHddCtx->cfg_ini->gEnableDebugLog)
13247 pHddCtx->cfg_ini->gEnableDebugLog =
Sushant Kaushik6e4e2bc2015-10-05 17:23:07 +053013248 VOS_PKT_PROTO_TYPE_EAPOL | VOS_PKT_PROTO_TYPE_DHCP |
13249 VOS_PKT_PROTO_TYPE_ARP;
Vinay Krishna Erannad938c422014-03-10 17:14:21 +053013250 }
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053013251
Siddharth Bhald1be97f2015-05-27 22:39:59 +053013252 if (pHddCtx->cfg_ini->wlanLoggingEnable &&
13253 (pHddCtx->cfg_ini->enableFWLogging ||
Siddharth Bhaldb963232015-06-25 19:34:35 +053013254 pHddCtx->cfg_ini->enableMgmtLogging ||
c_manjeecfd1efb2015-09-25 19:32:34 +053013255 pHddCtx->cfg_ini->enableContFWLogging ||
13256 pHddCtx->cfg_ini->enableFwrMemDump )
13257 )
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053013258 {
Siddharth Bhald1be97f2015-05-27 22:39:59 +053013259 hdd_init_frame_logging(pHddCtx);
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053013260 }
13261 else
13262 {
Siddharth Bhald1be97f2015-05-27 22:39:59 +053013263 hddLog(VOS_TRACE_LEVEL_INFO, FL("Logging disabled in ini"));
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053013264 }
13265
Vinay Krishna Erannad938c422014-03-10 17:14:21 +053013266#endif
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053013267
Agrawal Ashish17ef5082016-10-17 18:33:21 +053013268#ifdef SAP_AUTH_OFFLOAD
13269 if (!sme_IsFeatureSupportedByFW(SAP_OFFLOADS))
13270 {
13271 hddLog(VOS_TRACE_LEVEL_INFO, FL(" SAP AUTH OFFLOAD not supp by FW"));
13272 pHddCtx->cfg_ini->enable_sap_auth_offload = 0;
13273 }
13274#endif
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053013275
Sushant Kaushik215778f2015-05-21 14:05:36 +053013276 if (vos_is_multicast_logging())
13277 wlan_logging_set_log_level();
13278
Jeff Johnson295189b2012-06-20 16:38:30 -070013279 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -070013280 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -070013281 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -070013282 /* Action frame registered in one adapter which will
13283 * applicable to all interfaces
13284 */
Agarwal Ashish8fa0e9a2014-05-23 00:40:12 +053013285 wlan_hdd_cfg80211_register_frames(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -070013286 }
Jeff Johnson295189b2012-06-20 16:38:30 -070013287
13288 mutex_init(&pHddCtx->sap_lock);
Mahesh A Saptasagar60627942014-10-13 13:55:14 +053013289 mutex_init(&pHddCtx->roc_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070013290
Jeff Johnsone7245742012-09-05 17:12:55 -070013291#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
13292 /* Initialize the wake lcok */
Sushant Kaushik83392fa2015-05-05 17:44:40 +053013293 vos_wake_lock_init(&pHddCtx->rx_wake_lock,
Jeff Johnsone7245742012-09-05 17:12:55 -070013294 "qcom_rx_wakelock");
Sushant Kaushik83392fa2015-05-05 17:44:40 +053013295
Jeff Johnsone7245742012-09-05 17:12:55 -070013296#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -080013297 /* Initialize the wake lcok */
Sushant Kaushik83392fa2015-05-05 17:44:40 +053013298 vos_wake_lock_init(&pHddCtx->sap_wake_lock,
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -080013299 "qcom_sap_wakelock");
Sushant Kaushik83392fa2015-05-05 17:44:40 +053013300
Jeff Johnsone7245742012-09-05 17:12:55 -070013301
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -070013302 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
13303 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -070013304
Katya Nigam5c306ea2014-06-19 15:39:54 +053013305 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_NO_LOAD_UNLOAD_IN_PROGRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -070013306 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
Sushant Kaushik83392fa2015-05-05 17:44:40 +053013307 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_INIT);
Katya Nigam5c306ea2014-06-19 15:39:54 +053013308
13309#ifdef FEATURE_WLAN_SCAN_PNO
13310 /*SME must send channel update configuration to RIVA*/
13311 sme_UpdateChannelConfig(pHddCtx->hHal);
13312#endif
Abhishek Singhf644b272014-08-21 02:59:39 +053013313 /* Send the update default channel list to the FW*/
13314 sme_UpdateChannelList(pHddCtx->hHal);
Mukul Sharma45063942015-04-01 20:07:59 +053013315
13316 /* Fwr capabilities received, Set the Dot11 mode */
Abhishek Singh41ebce12016-02-03 10:43:21 +053013317 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter),
13318 hdd_cfg_xlate_to_csr_phy_mode(pHddCtx->cfg_ini->dot11Mode));
Mukul Sharma45063942015-04-01 20:07:59 +053013319 sme_SetDefDot11Mode(pHddCtx->hHal);
13320
Abhishek Singha306a442013-11-07 18:39:01 +053013321#ifndef CONFIG_ENABLE_LINUX_REG
13322 /*updating wiphy so that regulatory user hints can be processed*/
13323 if (wiphy)
13324 {
13325 regulatory_hint(wiphy, "00");
13326 }
13327#endif
Jeff Johnsone7245742012-09-05 17:12:55 -070013328 // Initialize the restart logic
13329 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +053013330
Hanumanth Reddy Pothula146bca42016-11-08 12:01:07 +053013331 if (pHddCtx->cfg_ini->fIsLogpEnabled) {
13332 vos_wdthread_init_timer_work(vos_process_wd_timer);
13333 /* Initialize the timer to detect thread stuck issues */
13334 vos_thread_stuck_timer_init(
13335 &((VosContextType*)pVosContext)->vosWatchdog);
13336 }
13337
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -070013338 //Register the traffic monitor timer now
13339 if ( pHddCtx->cfg_ini->dynSplitscan)
13340 {
13341 vos_timer_init(&pHddCtx->tx_rx_trafficTmr,
13342 VOS_TIMER_TYPE_SW,
13343 hdd_tx_rx_pkt_cnt_stat_timer_handler,
13344 (void *)pHddCtx);
13345 }
Srinivas Dasari030bad32015-02-18 23:23:54 +053013346 wlan_hdd_cfg80211_nan_init(pHddCtx);
13347
Bhargav Shahd0715912015-10-01 18:17:37 +053013348 mutex_init(&pHddCtx->cur_rx_level_lock);
13349 vos_timer_init(&pHddCtx->delack_timer, VOS_TIMER_TYPE_SW,
13350 hdd_tcp_delack_compute_function,(void *)pHddCtx);
Masti, Narayanraddi44b0db02015-12-22 11:54:35 +053013351 vos_timer_init(&pHddCtx->tdls_source_timer, VOS_TIMER_TYPE_SW,
13352 wlan_hdd_change_tdls_mode, (void *)pHddCtx);
Bhargav Shahd0715912015-10-01 18:17:37 +053013353
Dino Mycle6fb96c12014-06-10 11:52:40 +053013354#ifdef WLAN_FEATURE_EXTSCAN
13355 sme_EXTScanRegisterCallback(pHddCtx->hHal,
13356 wlan_hdd_cfg80211_extscan_callback,
13357 pHddCtx);
13358#endif /* WLAN_FEATURE_EXTSCAN */
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053013359
Padma, Santhosh Kumar2ccac212015-10-20 17:27:27 +053013360#ifdef FEATURE_OEM_DATA_SUPPORT
13361 sme_OemDataRegisterCallback(pHddCtx->hHal,
13362 wlan_hdd_cfg80211_oemdata_callback,
13363 pHddCtx);
13364#endif /* FEATURE_OEM_DATA_SUPPORT */
13365
Gupta, Kapil7c34b322015-09-30 13:12:35 +053013366 sme_set_rssi_threshold_breached_cb(pHddCtx->hHal, hdd_rssi_threshold_breached_cb);
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053013367#ifdef WLAN_NS_OFFLOAD
13368 // Register IPv6 notifier to notify if any change in IP
13369 // So that we can reconfigure the offload parameters
13370 pHddCtx->ipv6_notifier.notifier_call = wlan_hdd_ipv6_changed;
13371 ret = register_inet6addr_notifier(&pHddCtx->ipv6_notifier);
13372 if (ret)
13373 {
Ratheesh S P36dbc932015-08-07 14:28:57 +053013374 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Failed to register IPv6 notifier"));
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053013375 }
13376 else
13377 {
Ratheesh S P36dbc932015-08-07 14:28:57 +053013378 hddLog(VOS_TRACE_LEVEL_INFO, FL("Registered IPv6 notifier"));
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053013379 }
13380#endif
13381
Sravan Kumar Kairamb0edc612016-10-26 13:55:24 +053013382 vos_mem_set((uint8_t *)&pHddCtx->bad_sta, HDD_MAX_STA_COUNT, 0);
13383
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053013384 // Register IPv4 notifier to notify if any change in IP
13385 // So that we can reconfigure the offload parameters
13386 pHddCtx->ipv4_notifier.notifier_call = wlan_hdd_ipv4_changed;
13387 ret = register_inetaddr_notifier(&pHddCtx->ipv4_notifier);
13388 if (ret)
13389 {
Ratheesh S P36dbc932015-08-07 14:28:57 +053013390 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Failed to register IPv4 notifier"));
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053013391 }
13392 else
13393 {
Ratheesh S P36dbc932015-08-07 14:28:57 +053013394 hddLog(VOS_TRACE_LEVEL_INFO, FL("Registered IPv4 notifier"));
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053013395 }
c_manjeecfd1efb2015-09-25 19:32:34 +053013396 /*Fw mem dump procfs initialization*/
13397 memdump_init();
Bhargav shah23c94942015-10-13 12:48:35 +053013398 hdd_dp_util_send_rps_ind(pHddCtx);
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053013399
Nishank Aggarwalc11826c2016-12-15 18:54:10 +053013400 pHddCtx->is_ap_mode_wow_supported =
13401 sme_IsFeatureSupportedByFW(SAP_MODE_WOW);
Sravan Kumar Kairam091e5b62017-01-23 14:14:20 +053013402
Hanumanth Reddy Pothulae92bcc12017-05-19 13:56:35 +053013403 pHddCtx->is_fatal_event_log_sup =
13404 sme_IsFeatureSupportedByFW(FATAL_EVENT_LOGGING);
13405 hddLog(VOS_TRACE_LEVEL_INFO, FL("FATAL_EVENT_LOGGING: %d"),
13406 pHddCtx->is_fatal_event_log_sup);
13407
Sravan Kumar Kairam091e5b62017-01-23 14:14:20 +053013408 hdd_assoc_registerFwdEapolCB(pVosContext);
13409
Jeff Johnson295189b2012-06-20 16:38:30 -070013410 goto success;
13411
Hanumanth Reddy Pothula13789c42017-09-12 15:18:13 +053013412err_open_cesium_nl_sock:
13413#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
13414 hdd_close_cesium_nl_sock();
13415#endif
13416
13417err_ptt_sock_activate_svc:
13418#ifdef PTT_SOCK_SVC_ENABLE
13419 ptt_sock_deactivate_svc(pHddCtx);
13420#endif
13421
13422err_oem_activate_service:
13423#ifdef FEATURE_OEM_DATA_SUPPORT
13424 oem_deactivate_service();
13425#endif
13426
13427err_btc_activate_service:
13428 btc_deactivate_service();
13429
Jeff Johnson295189b2012-06-20 16:38:30 -070013430err_reg_netdev:
13431 unregister_netdevice_notifier(&hdd_netdev_notifier);
13432
Jeff Johnson295189b2012-06-20 16:38:30 -070013433err_unregister_pmops:
13434 hddDevTmUnregisterNotifyCallback(pHddCtx);
13435 hddDeregisterPmOps(pHddCtx);
13436
Yue Ma0d4891e2013-08-06 17:01:45 -070013437 hdd_debugfs_exit(pHddCtx);
13438
Jeff Johnson295189b2012-06-20 16:38:30 -070013439#ifdef WLAN_BTAMP_FEATURE
13440err_bap_stop:
13441 WLANBAP_Stop(pVosContext);
13442#endif
13443
13444#ifdef WLAN_BTAMP_FEATURE
13445err_bap_close:
13446 WLANBAP_Close(pVosContext);
13447#endif
13448
Jeff Johnson295189b2012-06-20 16:38:30 -070013449err_close_adapter:
13450 hdd_close_all_adapters( pHddCtx );
Mahesh A Saptasagar9ecefe42014-07-15 18:43:49 +053013451#ifdef CONFIG_ENABLE_LINUX_REG
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053013452err_unregister_wiphy:
Mahesh A Saptasagar9ecefe42014-07-15 18:43:49 +053013453#endif
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +053013454 wiphy_unregister(wiphy) ;
Agrawal Ashish33ec71e2015-11-26 20:20:58 +053013455 hdd_wlan_free_wiphy_channels(wiphy);
13456
Jeff Johnson295189b2012-06-20 16:38:30 -070013457err_vosstop:
13458 vos_stop(pVosContext);
13459
Amar Singhala49cbc52013-10-08 18:37:44 -070013460err_vosclose:
Jeff Johnson295189b2012-06-20 16:38:30 -070013461 status = vos_sched_close( pVosContext );
13462 if (!VOS_IS_STATUS_SUCCESS(status)) {
13463 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
13464 "%s: Failed to close VOSS Scheduler", __func__);
13465 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
13466 }
Amar Singhala49cbc52013-10-08 18:37:44 -070013467 vos_close(pVosContext );
13468
Mahesh A Saptasagarc3ed0122016-01-19 16:45:11 +053013469err_nl_srv:
13470#ifdef WLAN_KD_READY_NOTIFIER
13471 nl_srv_exit(pHddCtx->ptt_pid);
13472#else
13473 nl_srv_exit();
13474#endif /* WLAN_KD_READY_NOTIFIER */
Amar Singhal0a402232013-10-11 20:57:16 -070013475err_vos_nv_close:
13476
c_hpothue6a36282014-03-19 12:27:38 +053013477#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -070013478 vos_nv_close();
13479
c_hpothu70f8d812014-03-22 22:59:23 +053013480#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070013481
13482err_wdclose:
13483 if(pHddCtx->cfg_ini->fIsLogpEnabled)
13484 vos_watchdog_close(pVosContext);
13485
Jeff Johnson295189b2012-06-20 16:38:30 -070013486err_config:
13487 kfree(pHddCtx->cfg_ini);
13488 pHddCtx->cfg_ini= NULL;
13489
13490err_free_hdd_context:
Sushant Kaushik83392fa2015-05-05 17:44:40 +053013491 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_INIT);
Siddharth Bhalcd92b782015-06-29 12:25:40 +053013492 free_riva_power_on_lock("wlan");
Jeff Johnson295189b2012-06-20 16:38:30 -070013493 wiphy_free(wiphy) ;
13494 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -070013495 VOS_BUG(1);
13496
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -080013497 if (hdd_is_ssr_required())
13498 {
13499 /* WDI timeout had happened during load, so SSR is needed here */
13500 subsystem_restart("wcnss");
13501 msleep(5000);
13502 }
13503 hdd_set_ssr_required (VOS_FALSE);
13504
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -080013505 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -070013506
13507success:
13508 EXIT();
13509 return 0;
13510}
13511
13512/**---------------------------------------------------------------------------
13513
Jeff Johnson32d95a32012-09-10 13:15:23 -070013514 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -070013515
Jeff Johnson32d95a32012-09-10 13:15:23 -070013516 This is the driver entry point - called in different timeline depending
13517 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -070013518
13519 \param - None
13520
13521 \return - 0 for success, non zero for failure
13522
13523 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -070013524static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -070013525{
13526 VOS_STATUS status;
13527 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -070013528 struct device *dev = NULL;
13529 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -070013530#ifdef HAVE_WCNSS_CAL_DOWNLOAD
13531 int max_retries = 0;
13532#endif
Siddharth Bhalc7e79b62014-10-10 22:37:38 +053013533#ifdef HAVE_CBC_DONE
13534 int max_cbc_retries = 0;
13535#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070013536
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +053013537#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
13538 wlan_logging_sock_init_svc();
13539#endif
13540
Jeff Johnson295189b2012-06-20 16:38:30 -070013541 ENTER();
13542
Sushant Kaushik83392fa2015-05-05 17:44:40 +053013543 vos_wake_lock_init(&wlan_wake_lock, "wlan");
Jeff Johnson295189b2012-06-20 16:38:30 -070013544
13545 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
13546 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
13547
Jeff Johnson295189b2012-06-20 16:38:30 -070013548#ifdef ANI_BUS_TYPE_PCI
13549
13550 dev = wcnss_wlan_get_device();
13551
13552#endif // ANI_BUS_TYPE_PCI
13553
13554#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -070013555
13556#ifdef HAVE_WCNSS_CAL_DOWNLOAD
13557 /* wait until WCNSS driver downloads NV */
Ravi Kumar Bokka7a139e62016-11-17 21:32:55 +053013558 while (!wcnss_device_ready() && 10 >= ++max_retries) {
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -070013559 msleep(1000);
13560 }
Siddharth Bhalc7e79b62014-10-10 22:37:38 +053013561
Ravi Kumar Bokka7a139e62016-11-17 21:32:55 +053013562 if (max_retries >= 10) {
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -070013563 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
Sushant Kaushik83392fa2015-05-05 17:44:40 +053013564 vos_wake_lock_destroy(&wlan_wake_lock);
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +053013565#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
13566 wlan_logging_sock_deinit_svc();
13567#endif
13568
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -070013569 return -ENODEV;
13570 }
13571#endif
13572
Siddharth Bhalc7e79b62014-10-10 22:37:38 +053013573#ifdef HAVE_CBC_DONE
13574 while (!wcnss_cbc_complete() && 10 >= ++max_cbc_retries) {
13575 msleep(1000);
13576 }
13577 if (max_cbc_retries >= 10) {
13578 hddLog(VOS_TRACE_LEVEL_FATAL, "%s:CBC not completed", __func__);
13579 }
13580#endif
13581
Jeff Johnson295189b2012-06-20 16:38:30 -070013582 dev = wcnss_wlan_get_device();
13583#endif // ANI_BUS_TYPE_PLATFORM
13584
13585
13586 do {
13587 if (NULL == dev) {
13588 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
13589 ret_status = -1;
13590 break;
13591 }
13592
Jeff Johnson295189b2012-06-20 16:38:30 -070013593#ifdef TIMER_MANAGER
13594 vos_timer_manager_init();
13595#endif
13596
13597 /* Preopen VOSS so that it is ready to start at least SAL */
13598 status = vos_preOpen(&pVosContext);
13599
13600 if (!VOS_IS_STATUS_SUCCESS(status))
13601 {
13602 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
13603 ret_status = -1;
13604 break;
13605 }
13606
Sushant Kaushik02beb352015-06-04 15:15:01 +053013607 hddTraceInit();
Padma, Santhosh Kumar9093b202015-07-21 15:37:38 +053013608 hdd_register_debug_callback();
13609
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070013610#ifndef MODULE
13611 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
13612 */
13613 hdd_set_conparam((v_UINT_t)con_mode);
13614#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070013615
13616 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -080013617 if (hdd_wlan_startup(dev))
13618 {
Jeff Johnson295189b2012-06-20 16:38:30 -070013619 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -080013620 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -070013621 vos_preClose( &pVosContext );
13622 ret_status = -1;
13623 break;
13624 }
13625
Jeff Johnson295189b2012-06-20 16:38:30 -070013626 } while (0);
13627
13628 if (0 != ret_status)
13629 {
Jeff Johnson295189b2012-06-20 16:38:30 -070013630#ifdef TIMER_MANAGER
13631 vos_timer_exit();
13632#endif
13633#ifdef MEMORY_DEBUG
13634 vos_mem_exit();
13635#endif
Sushant Kaushik83392fa2015-05-05 17:44:40 +053013636 vos_wake_lock_destroy(&wlan_wake_lock);
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +053013637#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
13638 wlan_logging_sock_deinit_svc();
13639#endif
13640
Jeff Johnson295189b2012-06-20 16:38:30 -070013641 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
13642 }
13643 else
13644 {
13645 //Send WLAN UP indication to Nlink Service
13646 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
13647
13648 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Jeff Johnson295189b2012-06-20 16:38:30 -070013649 }
13650
13651 EXIT();
13652
13653 return ret_status;
13654}
13655
Jeff Johnson32d95a32012-09-10 13:15:23 -070013656/**---------------------------------------------------------------------------
13657
13658 \brief hdd_module_init() - Init Function
13659
13660 This is the driver entry point (invoked when module is loaded using insmod)
13661
13662 \param - None
13663
13664 \return - 0 for success, non zero for failure
13665
13666 --------------------------------------------------------------------------*/
13667#ifdef MODULE
13668static int __init hdd_module_init ( void)
13669{
13670 return hdd_driver_init();
13671}
Jeff Johnson32d95a32012-09-10 13:15:23 -070013672#else /* #ifdef MODULE */
13673static int __init hdd_module_init ( void)
13674{
13675 /* Driver initialization is delayed to fwpath_changed_handler */
13676 return 0;
13677}
Jeff Johnson32d95a32012-09-10 13:15:23 -070013678#endif /* #ifdef MODULE */
13679
Jeff Johnson295189b2012-06-20 16:38:30 -070013680
13681/**---------------------------------------------------------------------------
13682
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070013683 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -070013684
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070013685 This is the driver exit point (invoked when module is unloaded using rmmod
13686 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -070013687
13688 \param - None
13689
13690 \return - None
13691
13692 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070013693static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -070013694{
13695 hdd_context_t *pHddCtx = NULL;
13696 v_CONTEXT_t pVosContext = NULL;
Agarwal Ashish5e414792014-06-08 15:25:23 +053013697 v_REGDOMAIN_t regId;
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +053013698 unsigned long rc = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -070013699
13700 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
13701
13702 //Get the global vos context
13703 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
13704
13705 if(!pVosContext)
13706 {
13707 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
13708 goto done;
13709 }
13710
13711 //Get the HDD context.
13712 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
13713
13714 if(!pHddCtx)
13715 {
13716 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
13717 }
Katya Nigame7b69a82015-04-28 15:24:06 +053013718 else if (VOS_MONITOR_MODE == hdd_get_conparam())
13719 {
13720 hddLog(VOS_TRACE_LEVEL_INFO,"%s: MONITOR MODE",__func__);
13721 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_UNLOAD_IN_PROGRESS;
13722 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
13723 hdd_wlan_exit(pHddCtx);
13724 vos_preClose( &pVosContext );
13725 goto done;
13726 }
Jeff Johnson295189b2012-06-20 16:38:30 -070013727 else
13728 {
Siddharth Bhal2e5871b2015-03-24 16:20:51 +053013729 /* We wait for active entry threads to exit from driver
13730 * by waiting until rtnl_lock is available.
13731 */
13732 rtnl_lock();
13733 rtnl_unlock();
13734
Siddharth Bhal3c29dca2015-02-19 00:41:40 +053013735 INIT_COMPLETION(pHddCtx->ssr_comp_var);
13736 if ((pHddCtx->isLogpInProgress) && (FALSE ==
13737 vos_is_wlan_in_badState(VOS_MODULE_ID_HDD, NULL)))
13738 {
Siddharth Bhala204f572015-01-17 02:03:36 +053013739 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Siddharth Bhal3c29dca2015-02-19 00:41:40 +053013740 "%s:SSR in Progress; block rmmod !!!", __func__);
Siddharth Bhala204f572015-01-17 02:03:36 +053013741 rc = wait_for_completion_timeout(&pHddCtx->ssr_comp_var,
13742 msecs_to_jiffies(30000));
13743 if(!rc)
13744 {
13745 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
13746 "%s:SSR timedout, fatal error", __func__);
13747 VOS_BUG(0);
13748 }
13749 }
13750
Siddharth Bhal3c29dca2015-02-19 00:41:40 +053013751 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_UNLOAD_IN_PROGRESS;
13752 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
Jeff Johnson295189b2012-06-20 16:38:30 -070013753
c_hpothu8adb97b2014-12-08 19:38:20 +053013754 /* Driver Need to send country code 00 in below condition
13755 * 1) If gCountryCodePriority is set to 1; and last country
13756 * code set is through 11d. This needs to be done in case
13757 * when NV country code is 00.
13758 * This Needs to be done as when kernel store last country
13759 * code and if stored country code is not through 11d,
13760 * in sme_HandleChangeCountryCodeByUser we will disable 11d
13761 * in next load/unload as soon as we get any country through
13762 * 11d. In sme_HandleChangeCountryCodeByUser
13763 * pMsg->countryCode will be last countryCode and
13764 * pMac->scan.countryCode11d will be country through 11d so
13765 * due to mismatch driver will disable 11d.
13766 *
13767 */
Agarwal Ashish8db39882014-07-30 21:56:07 +053013768
c_hpothu8adb97b2014-12-08 19:38:20 +053013769 if ((eANI_BOOLEAN_TRUE == sme_Is11dCountrycode(pHddCtx->hHal) &&
Agarwal Ashish8dcd2862014-07-25 11:58:52 +053013770 pHddCtx->cfg_ini->fSupplicantCountryCodeHasPriority &&
Abhishek Singh2a705962014-10-30 14:47:28 +053013771 sme_Is11dSupported(pHddCtx->hHal)))
c_hpothu8adb97b2014-12-08 19:38:20 +053013772 {
13773 hddLog(VOS_TRACE_LEVEL_INFO,
Agarwal Ashish8dcd2862014-07-25 11:58:52 +053013774 FL("CountryCode 00 is being set while unloading driver"));
c_hpothu8adb97b2014-12-08 19:38:20 +053013775 vos_nv_getRegDomainFromCountryCode(&regId , "00", COUNTRY_USER);
13776 }
Agarwal Ashish5e414792014-06-08 15:25:23 +053013777
c_hpothu8adb97b2014-12-08 19:38:20 +053013778 //Do all the cleanup before deregistering the driver
13779 hdd_wlan_exit(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -070013780 }
13781
Jeff Johnson295189b2012-06-20 16:38:30 -070013782 vos_preClose( &pVosContext );
13783
13784#ifdef TIMER_MANAGER
13785 vos_timer_exit();
13786#endif
13787#ifdef MEMORY_DEBUG
13788 vos_mem_exit();
13789#endif
13790
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +053013791#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
13792 wlan_logging_sock_deinit_svc();
13793#endif
13794
Jeff Johnson295189b2012-06-20 16:38:30 -070013795done:
Sushant Kaushik83392fa2015-05-05 17:44:40 +053013796 vos_wake_lock_destroy(&wlan_wake_lock);
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +053013797
Jeff Johnson295189b2012-06-20 16:38:30 -070013798 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
13799}
13800
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070013801/**---------------------------------------------------------------------------
13802
13803 \brief hdd_module_exit() - Exit function
13804
13805 This is the driver exit point (invoked when module is unloaded using rmmod)
13806
13807 \param - None
13808
13809 \return - None
13810
13811 --------------------------------------------------------------------------*/
13812static void __exit hdd_module_exit(void)
13813{
13814 hdd_driver_exit();
13815}
13816
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070013817#ifdef MODULE
13818static int fwpath_changed_handler(const char *kmessage,
13819 struct kernel_param *kp)
13820{
Jeff Johnson76052702013-04-16 13:55:05 -070013821 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070013822}
13823
13824static int con_mode_handler(const char *kmessage,
13825 struct kernel_param *kp)
13826{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -070013827 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070013828}
13829#else /* #ifdef MODULE */
13830/**---------------------------------------------------------------------------
13831
Jeff Johnson76052702013-04-16 13:55:05 -070013832 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070013833
Jeff Johnson76052702013-04-16 13:55:05 -070013834 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070013835 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -070013836 - invoked when module parameter fwpath is modified from userspace to signal
13837 initializing the WLAN driver or when con_mode is modified from userspace
13838 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070013839
13840 \return - 0 for success, non zero for failure
13841
13842 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -070013843static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070013844{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -070013845 int ret_status;
13846
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070013847 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -070013848 ret_status = hdd_driver_init();
13849 wlan_hdd_inited = ret_status ? 0 : 1;
13850 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070013851 }
13852
13853 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -070013854
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070013855 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -070013856
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -070013857 ret_status = hdd_driver_init();
13858 wlan_hdd_inited = ret_status ? 0 : 1;
13859 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070013860}
13861
Jeff Johnson295189b2012-06-20 16:38:30 -070013862/**---------------------------------------------------------------------------
13863
Jeff Johnson76052702013-04-16 13:55:05 -070013864 \brief fwpath_changed_handler() - Handler Function
13865
13866 Handle changes to the fwpath parameter
13867
13868 \return - 0 for success, non zero for failure
13869
13870 --------------------------------------------------------------------------*/
13871static int fwpath_changed_handler(const char *kmessage,
13872 struct kernel_param *kp)
13873{
13874 int ret;
13875
13876 ret = param_set_copystring(kmessage, kp);
13877 if (0 == ret)
13878 ret = kickstart_driver();
13879 return ret;
13880}
13881
13882/**---------------------------------------------------------------------------
13883
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070013884 \brief con_mode_handler() -
13885
13886 Handler function for module param con_mode when it is changed by userspace
13887 Dynamically linked - do nothing
13888 Statically linked - exit and init driver, as in rmmod and insmod
13889
Jeff Johnson76052702013-04-16 13:55:05 -070013890 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070013891
Jeff Johnson76052702013-04-16 13:55:05 -070013892 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070013893
13894 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -070013895static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070013896{
Jeff Johnson76052702013-04-16 13:55:05 -070013897 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070013898
Jeff Johnson76052702013-04-16 13:55:05 -070013899 ret = param_set_int(kmessage, kp);
13900 if (0 == ret)
13901 ret = kickstart_driver();
13902 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070013903}
13904#endif /* #ifdef MODULE */
13905
13906/**---------------------------------------------------------------------------
13907
Jeff Johnson295189b2012-06-20 16:38:30 -070013908 \brief hdd_get_conparam() -
13909
13910 This is the driver exit point (invoked when module is unloaded using rmmod)
13911
13912 \param - None
13913
13914 \return - tVOS_CON_MODE
13915
13916 --------------------------------------------------------------------------*/
13917tVOS_CON_MODE hdd_get_conparam ( void )
13918{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070013919#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -070013920 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070013921#else
13922 return (tVOS_CON_MODE)curr_con_mode;
13923#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070013924}
13925void hdd_set_conparam ( v_UINT_t newParam )
13926{
13927 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070013928#ifndef MODULE
13929 curr_con_mode = con_mode;
13930#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070013931}
13932/**---------------------------------------------------------------------------
13933
13934 \brief hdd_softap_sta_deauth() - function
13935
13936 This to take counter measure to handle deauth req from HDD
13937
13938 \param - pAdapter - Pointer to the HDD
13939
13940 \param - enable - boolean value
13941
13942 \return - None
13943
13944 --------------------------------------------------------------------------*/
13945
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +053013946VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter,
13947 struct tagCsrDelStaParams *pDelStaParams)
Jeff Johnson295189b2012-06-20 16:38:30 -070013948{
Jeff Johnson295189b2012-06-20 16:38:30 -070013949 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -080013950 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Hanumanth Reddy Pothula57323632017-12-06 17:55:09 +053013951 struct hdd_cache_sta_info *cache_sta_info;
13952 ptSapContext pSapCtx = VOS_GET_SAP_CB(pVosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -070013953
13954 ENTER();
13955
Jeff Johnsonc135a9a2017-09-19 08:37:24 -070013956 hddLog(LOG1, "hdd_softap_sta_deauth:(%pK, false)",
Rajesh Chauhan18488fc2013-08-22 10:15:03 -070013957 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -070013958
Hanumanth Reddy Pothula57323632017-12-06 17:55:09 +053013959 if (!pSapCtx) {
13960 hddLog(LOGE, "sap context is NULL");
13961 return vosStatus;
13962 }
13963
13964 cache_sta_info = hdd_get_cache_stainfo(pSapCtx->cache_sta_info,
13965 pDelStaParams->peerMacAddr);
13966 if (cache_sta_info) {
13967 cache_sta_info->reason_code = pDelStaParams->reason_code;
13968 cache_sta_info->rx_rate =
13969 wlan_tl_get_sta_rx_rate(pVosContext, cache_sta_info->ucSTAId);
13970 WLANTL_GetSAPStaRSSi(pVosContext, cache_sta_info->ucSTAId,
13971 &cache_sta_info->rssi);
13972 }
13973
Jeff Johnson295189b2012-06-20 16:38:30 -070013974 //Ignore request to deauth bcmc station
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +053013975 if (pDelStaParams->peerMacAddr[0] & 0x1)
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -080013976 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -070013977
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +053013978 vosStatus = WLANSAP_DeauthSta(pVosContext, pDelStaParams);
Jeff Johnson295189b2012-06-20 16:38:30 -070013979
13980 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -080013981 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -070013982}
13983
13984/**---------------------------------------------------------------------------
13985
Rashmi Ramanna1f0948d2014-08-28 15:33:48 +053013986 \brief hdd_del_all_sta() - function
13987
13988 This function removes all the stations associated on stopping AP/P2P GO.
13989
13990 \param - pAdapter - Pointer to the HDD
13991
13992 \return - None
13993
13994 --------------------------------------------------------------------------*/
13995
13996int hdd_del_all_sta(hdd_adapter_t *pAdapter)
13997{
13998 v_U16_t i;
13999 VOS_STATUS vos_status;
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +053014000 v_CONTEXT_t pVosContext = ( WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
14001 ptSapContext pSapCtx = NULL;
14002 pSapCtx = VOS_GET_SAP_CB(pVosContext);
14003 if(pSapCtx == NULL){
14004 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
14005 FL("psapCtx is NULL"));
14006 return 1;
14007 }
Rashmi Ramanna1f0948d2014-08-28 15:33:48 +053014008 ENTER();
14009
14010 hddLog(VOS_TRACE_LEVEL_INFO,
14011 "%s: Delete all STAs associated.",__func__);
14012 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
14013 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
14014 )
14015 {
14016 for(i = 0; i < WLAN_MAX_STA_COUNT; i++)
14017 {
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +053014018 if ((pSapCtx->aStaInfo[i].isUsed) &&
14019 (!pSapCtx->aStaInfo[i].isDeauthInProgress))
Rashmi Ramanna1f0948d2014-08-28 15:33:48 +053014020 {
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +053014021 struct tagCsrDelStaParams delStaParams;
14022
14023 WLANSAP_PopulateDelStaParams(
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +053014024 pSapCtx->aStaInfo[i].macAddrSTA.bytes,
Sushant Kaushik4cd28f62014-12-26 14:23:50 +053014025 eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
14026 SIR_MAC_MGMT_DEAUTH >> 4,
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +053014027 &delStaParams);
14028 vos_status = hdd_softap_sta_deauth(pAdapter, &delStaParams);
Rashmi Ramanna1f0948d2014-08-28 15:33:48 +053014029 if (VOS_IS_STATUS_SUCCESS(vos_status))
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +053014030 pSapCtx->aStaInfo[i].isDeauthInProgress = TRUE;
Rashmi Ramanna1f0948d2014-08-28 15:33:48 +053014031 }
14032 }
14033 }
14034
14035 EXIT();
14036 return 0;
14037}
14038
14039/**---------------------------------------------------------------------------
14040
Jeff Johnson295189b2012-06-20 16:38:30 -070014041 \brief hdd_softap_sta_disassoc() - function
14042
14043 This to take counter measure to handle deauth req from HDD
14044
14045 \param - pAdapter - Pointer to the HDD
14046
14047 \param - enable - boolean value
14048
14049 \return - None
14050
14051 --------------------------------------------------------------------------*/
14052
14053void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
14054{
Hanumanth Reddy Pothula57323632017-12-06 17:55:09 +053014055 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
14056 struct hdd_cache_sta_info *cache_sta_info;
14057 ptSapContext pSapCtx = VOS_GET_SAP_CB(pVosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -070014058
14059 ENTER();
14060
Jeff Johnsonc135a9a2017-09-19 08:37:24 -070014061 hddLog( LOGE, "hdd_softap_sta_disassoc:(%pK, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -070014062
Hanumanth Reddy Pothula57323632017-12-06 17:55:09 +053014063 if (!pSapCtx) {
14064 hddLog(LOGE, "sap context is NULL");
14065 return ;
14066 }
14067
Jeff Johnson295189b2012-06-20 16:38:30 -070014068 //Ignore request to disassoc bcmc station
14069 if( pDestMacAddress[0] & 0x1 )
14070 return;
14071
Hanumanth Reddy Pothula57323632017-12-06 17:55:09 +053014072 cache_sta_info = hdd_get_cache_stainfo(pSapCtx->cache_sta_info,
14073 pDestMacAddress);
14074 if (cache_sta_info) {
14075 cache_sta_info->reason_code = eSIR_MAC_DEAUTH_LEAVING_BSS_REASON;
14076 cache_sta_info->rx_rate =
14077 wlan_tl_get_sta_rx_rate(pVosContext, cache_sta_info->ucSTAId);
14078 WLANTL_GetSAPStaRSSi(pVosContext, cache_sta_info->ucSTAId,
14079 &cache_sta_info->rssi);
14080 }
14081
Jeff Johnson295189b2012-06-20 16:38:30 -070014082 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
14083}
14084
14085void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
14086{
14087 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
14088
14089 ENTER();
14090
Jeff Johnsonc135a9a2017-09-19 08:37:24 -070014091 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%pK, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -070014092
14093 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
14094}
14095
Jeff Johnson295189b2012-06-20 16:38:30 -070014096/**---------------------------------------------------------------------------
14097 *
14098 * \brief hdd_get__concurrency_mode() -
14099 *
14100 *
14101 * \param - None
14102 *
14103 * \return - CONCURRENCY MODE
14104 *
14105 * --------------------------------------------------------------------------*/
14106tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
14107{
14108 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
14109 hdd_context_t *pHddCtx;
14110
14111 if (NULL != pVosContext)
14112 {
14113 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
14114 if (NULL != pHddCtx)
14115 {
14116 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
14117 }
14118 }
14119
14120 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070014121 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -070014122 return VOS_STA;
14123}
Sushant Kaushikabb7ee62014-07-18 16:20:12 +053014124v_BOOL_t
14125wlan_hdd_is_GO_power_collapse_allowed (hdd_context_t* pHddCtx)
14126{
14127 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -070014128
Sushant Kaushikabb7ee62014-07-18 16:20:12 +053014129 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_GO);
14130 if (pAdapter == NULL)
14131 {
14132 hddLog(VOS_TRACE_LEVEL_INFO,
14133 FL("GO doesn't exist"));
14134 return TRUE;
14135 }
14136 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
14137 {
14138 hddLog(VOS_TRACE_LEVEL_INFO,
14139 FL("GO started"));
14140 return TRUE;
14141 }
14142 else
14143 /* wait till GO changes its interface to p2p device */
14144 hddLog(VOS_TRACE_LEVEL_INFO,
14145 FL("Del_bss called, avoid apps suspend"));
14146 return FALSE;
14147
14148}
Jeff Johnson295189b2012-06-20 16:38:30 -070014149/* Decide whether to allow/not the apps power collapse.
14150 * Allow apps power collapse if we are in connected state.
14151 * if not, allow only if we are in IMPS */
14152v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
14153{
14154 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -080014155 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -080014156 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -070014157 hdd_config_t *pConfig = pHddCtx->cfg_ini;
14158 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
14159 hdd_adapter_t *pAdapter = NULL;
14160 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -080014161 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -070014162
Jeff Johnson295189b2012-06-20 16:38:30 -070014163 if (VOS_STA_SAP_MODE == hdd_get_conparam())
14164 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -070014165
Yathish9f22e662012-12-10 14:21:35 -080014166 concurrent_state = hdd_get_concurrency_mode();
14167
Sushant Kaushikabb7ee62014-07-18 16:20:12 +053014168 if ((concurrent_state == (VOS_STA | VOS_P2P_GO)) &&
14169 !(wlan_hdd_is_GO_power_collapse_allowed(pHddCtx)))
14170 return FALSE;
Yathish9f22e662012-12-10 14:21:35 -080014171#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
Sushant Kaushikabb7ee62014-07-18 16:20:12 +053014172
Yathish9f22e662012-12-10 14:21:35 -080014173 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
Sushant Kaushikabb7ee62014-07-18 16:20:12 +053014174 (concurrent_state == (VOS_STA | VOS_P2P_GO)))&&
Yathish9f22e662012-12-10 14:21:35 -080014175 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
14176 return TRUE;
14177#endif
14178
Jeff Johnson295189b2012-06-20 16:38:30 -070014179 /*loop through all adapters. TBD fix for Concurrency */
14180 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
14181 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
14182 {
14183 pAdapter = pAdapterNode->pAdapter;
14184 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
14185 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
14186 {
Srikant Kuppafef66a72013-01-30 17:32:44 -080014187 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
c_hpothu4e8faac2014-05-16 17:38:44 +053014188 && (pmcState != IMPS && pmcState != BMPS && pmcState != UAPSD
c_hpothu1c6957d2015-01-06 18:19:47 +053014189 && pmcState != STOPPED && pmcState != STANDBY &&
14190 pmcState != WOWL)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -080014191 (eANI_BOOLEAN_TRUE == scanRspPending) ||
14192 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -070014193 {
Mukul Sharma4be88422015-03-09 20:29:07 +053014194 if(pmcState == FULL_POWER &&
14195 sme_IsCoexScoIndicationSet(pHddCtx->hHal))
14196 {
14197 /*
14198 * When SCO indication comes from Coex module , host will
14199 * enter in to full power mode, but this should not prevent
14200 * apps processor power collapse.
14201 */
14202 hddLog(LOG1,
14203 FL("Allow apps power collapse"
14204 "even when sco indication is set"));
14205 return TRUE;
14206 }
Srikant Kuppafef66a72013-01-30 17:32:44 -080014207 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Deepthi Gowri03a979f2016-11-03 15:20:19 +053014208 "pmcState = %d scanRspPending = %d "
14209 "inMiddleOfRoaming = %d connected = %d",
14210 __func__, pmcState, scanRspPending,
14211 inMiddleOfRoaming, hdd_connIsConnected(
14212 WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )));
14213 wlan_hdd_get_tdls_stats(pAdapter);
14214 return FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -070014215 }
14216 }
14217 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
14218 pAdapterNode = pNext;
14219 }
14220 return TRUE;
14221}
14222
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -080014223/* Decides whether to send suspend notification to Riva
14224 * if any adapter is in BMPS; then it is required */
14225v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
14226{
14227 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
14228 hdd_config_t *pConfig = pHddCtx->cfg_ini;
14229
14230 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
14231 {
14232 return TRUE;
14233 }
14234 return FALSE;
14235}
14236
Jeff Johnson295189b2012-06-20 16:38:30 -070014237void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
14238{
14239 switch(mode)
14240 {
Chilam Ngc4244af2013-04-01 15:37:32 -070014241 case VOS_STA_MODE:
14242 case VOS_P2P_CLIENT_MODE:
14243 case VOS_P2P_GO_MODE:
14244 case VOS_STA_SAP_MODE:
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +053014245 case VOS_MONITOR_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -070014246 pHddCtx->concurrency_mode |= (1 << mode);
Agarwal Ashish51325b52014-06-16 16:50:49 +053014247 pHddCtx->no_of_open_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -070014248 break;
14249 default:
14250 break;
Jeff Johnson295189b2012-06-20 16:38:30 -070014251 }
Agarwal Ashish51325b52014-06-16 16:50:49 +053014252 hddLog(VOS_TRACE_LEVEL_INFO, FL("concurrency_mode = 0x%x "
14253 "Number of open sessions for mode %d = %d"),
14254 pHddCtx->concurrency_mode, mode,
14255 pHddCtx->no_of_open_sessions[mode]);
Jeff Johnson295189b2012-06-20 16:38:30 -070014256}
14257
14258
14259void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
14260{
14261 switch(mode)
14262 {
Chilam Ngc4244af2013-04-01 15:37:32 -070014263 case VOS_STA_MODE:
14264 case VOS_P2P_CLIENT_MODE:
14265 case VOS_P2P_GO_MODE:
14266 case VOS_STA_SAP_MODE:
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +053014267 case VOS_MONITOR_MODE:
Agarwal Ashish51325b52014-06-16 16:50:49 +053014268 pHddCtx->no_of_open_sessions[mode]--;
14269 if (!(pHddCtx->no_of_open_sessions[mode]))
14270 pHddCtx->concurrency_mode &= (~(1 << mode));
Jeff Johnson295189b2012-06-20 16:38:30 -070014271 break;
14272 default:
14273 break;
14274 }
Agarwal Ashish51325b52014-06-16 16:50:49 +053014275 hddLog(VOS_TRACE_LEVEL_INFO, FL("concurrency_mode = 0x%x "
14276 "Number of open sessions for mode %d = %d"),
14277 pHddCtx->concurrency_mode, mode, pHddCtx->no_of_open_sessions[mode]);
14278
14279}
14280/**---------------------------------------------------------------------------
14281 *
14282 * \brief wlan_hdd_incr_active_session()
14283 *
14284 * This function increments the number of active sessions
14285 * maintained per device mode
14286 * Incase of STA/P2P CLI/IBSS upon connection indication it is incremented
14287 * Incase of SAP/P2P GO upon bss start it is incremented
14288 *
14289 * \param pHddCtx - HDD Context
14290 * \param mode - device mode
14291 *
14292 * \return - None
14293 *
14294 * --------------------------------------------------------------------------*/
14295void wlan_hdd_incr_active_session(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
14296{
14297 switch (mode) {
14298 case VOS_STA_MODE:
14299 case VOS_P2P_CLIENT_MODE:
14300 case VOS_P2P_GO_MODE:
14301 case VOS_STA_SAP_MODE:
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +053014302 case VOS_MONITOR_MODE:
Agarwal Ashish51325b52014-06-16 16:50:49 +053014303 pHddCtx->no_of_active_sessions[mode]++;
14304 break;
14305 default:
14306 hddLog(VOS_TRACE_LEVEL_INFO, FL("Not Expected Mode %d"), mode);
14307 break;
14308 }
14309 hddLog(VOS_TRACE_LEVEL_INFO, FL("No.# of active sessions for mode %d = %d"),
14310 mode,
14311 pHddCtx->no_of_active_sessions[mode]);
14312}
14313
14314/**---------------------------------------------------------------------------
14315 *
14316 * \brief wlan_hdd_decr_active_session()
14317 *
14318 * This function decrements the number of active sessions
14319 * maintained per device mode
14320 * Incase of STA/P2P CLI/IBSS upon disconnection it is decremented
14321 * Incase of SAP/P2P GO upon bss stop it is decremented
14322 *
14323 * \param pHddCtx - HDD Context
14324 * \param mode - device mode
14325 *
14326 * \return - None
14327 *
14328 * --------------------------------------------------------------------------*/
14329void wlan_hdd_decr_active_session(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
14330{
Bhargav Shahd0715912015-10-01 18:17:37 +053014331
Agarwal Ashish51325b52014-06-16 16:50:49 +053014332 switch (mode) {
14333 case VOS_STA_MODE:
14334 case VOS_P2P_CLIENT_MODE:
14335 case VOS_P2P_GO_MODE:
14336 case VOS_STA_SAP_MODE:
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +053014337 case VOS_MONITOR_MODE:
Agarwal Ashish5325f522014-08-06 00:58:44 +053014338 if (pHddCtx->no_of_active_sessions[mode] > 0)
14339 pHddCtx->no_of_active_sessions[mode]--;
14340 else
14341 hddLog(VOS_TRACE_LEVEL_INFO, FL(" No.# of Active sessions"
14342 "is already Zero"));
Agarwal Ashish51325b52014-06-16 16:50:49 +053014343 break;
14344 default:
14345 hddLog(VOS_TRACE_LEVEL_INFO, FL("Not Expected Mode %d"), mode);
14346 break;
14347 }
14348 hddLog(VOS_TRACE_LEVEL_INFO, FL("No.# of active sessions for mode %d = %d"),
14349 mode,
14350 pHddCtx->no_of_active_sessions[mode]);
Jeff Johnson295189b2012-06-20 16:38:30 -070014351}
14352
Jeff Johnsone7245742012-09-05 17:12:55 -070014353/**---------------------------------------------------------------------------
14354 *
14355 * \brief wlan_hdd_restart_init
14356 *
14357 * This function initalizes restart timer/flag. An internal function.
14358 *
14359 * \param - pHddCtx
14360 *
14361 * \return - None
14362 *
14363 * --------------------------------------------------------------------------*/
14364
14365static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
14366{
14367 /* Initialize */
14368 pHddCtx->hdd_restart_retries = 0;
14369 atomic_set(&pHddCtx->isRestartInProgress, 0);
14370 vos_timer_init(&pHddCtx->hdd_restart_timer,
14371 VOS_TIMER_TYPE_SW,
14372 wlan_hdd_restart_timer_cb,
14373 pHddCtx);
14374}
14375/**---------------------------------------------------------------------------
14376 *
14377 * \brief wlan_hdd_restart_deinit
14378 *
14379 * This function cleans up the resources used. An internal function.
14380 *
14381 * \param - pHddCtx
14382 *
14383 * \return - None
14384 *
14385 * --------------------------------------------------------------------------*/
14386
14387static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
14388{
14389
14390 VOS_STATUS vos_status;
14391 /* Block any further calls */
14392 atomic_set(&pHddCtx->isRestartInProgress, 1);
14393 /* Cleanup */
14394 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
14395 if (!VOS_IS_STATUS_SUCCESS(vos_status))
c_hpothu6ff1c3c2013-10-01 19:01:57 +053014396 hddLog(LOGE, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -070014397 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
14398 if (!VOS_IS_STATUS_SUCCESS(vos_status))
c_hpothu6ff1c3c2013-10-01 19:01:57 +053014399 hddLog(LOGE, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -070014400
14401}
14402
14403/**---------------------------------------------------------------------------
14404 *
14405 * \brief wlan_hdd_framework_restart
14406 *
14407 * This function uses a cfg80211 API to start a framework initiated WLAN
14408 * driver module unload/load.
14409 *
14410 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
14411 *
14412 *
14413 * \param - pHddCtx
14414 *
14415 * \return - VOS_STATUS_SUCCESS: Success
14416 * VOS_STATUS_E_EMPTY: Adapter is Empty
14417 * VOS_STATUS_E_NOMEM: No memory
14418
14419 * --------------------------------------------------------------------------*/
14420
14421static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
14422{
14423 VOS_STATUS status = VOS_STATUS_SUCCESS;
14424 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -070014425 int len = (sizeof (struct ieee80211_mgmt));
14426 struct ieee80211_mgmt *mgmt = NULL;
14427
14428 /* Prepare the DEAUTH managment frame with reason code */
14429 mgmt = kzalloc(len, GFP_KERNEL);
14430 if(mgmt == NULL)
14431 {
14432 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
14433 "%s: memory allocation failed (%d bytes)", __func__, len);
14434 return VOS_STATUS_E_NOMEM;
14435 }
14436 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -070014437
14438 /* Iterate over all adapters/devices */
14439 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Hanumantha Reddy Pothulada0fe362015-02-27 18:37:03 +053014440 if ((NULL == pAdapterNode) || (VOS_STATUS_SUCCESS != status))
14441 {
14442 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnsonc135a9a2017-09-19 08:37:24 -070014443 FL("fail to get adapter: %pK %d"), pAdapterNode, status);
Hanumantha Reddy Pothulada0fe362015-02-27 18:37:03 +053014444 goto end;
14445 }
14446
Jeff Johnsone7245742012-09-05 17:12:55 -070014447 do
14448 {
Hanumantha Reddy Pothulada0fe362015-02-27 18:37:03 +053014449 if(pAdapterNode->pAdapter &&
14450 WLAN_HDD_ADAPTER_MAGIC == pAdapterNode->pAdapter->magic)
Jeff Johnsone7245742012-09-05 17:12:55 -070014451 {
14452 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
14453 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
14454 pAdapterNode->pAdapter->dev->name,
14455 pAdapterNode->pAdapter->device_mode,
14456 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -070014457 /*
14458 * CFG80211 event to restart the driver
14459 *
14460 * 'cfg80211_send_unprot_deauth' sends a
14461 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
14462 * of SME(Linux Kernel) state machine.
14463 *
14464 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
14465 * the driver.
14466 *
14467 */
Abhishek Singh00b71972016-01-07 10:51:04 +053014468
Anand N Sunkade9adb1b2015-07-29 09:56:45 +053014469#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
14470 cfg80211_rx_unprot_mlme_mgmt(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len);
14471#else
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -070014472 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Anand N Sunkade9adb1b2015-07-29 09:56:45 +053014473#endif
Jeff Johnsone7245742012-09-05 17:12:55 -070014474 }
14475 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
14476 pAdapterNode = pNext;
14477 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
14478
Hanumantha Reddy Pothulada0fe362015-02-27 18:37:03 +053014479 end:
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -070014480 /* Free the allocated management frame */
14481 kfree(mgmt);
14482
Jeff Johnsone7245742012-09-05 17:12:55 -070014483 /* Retry until we unload or reach max count */
14484 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
14485 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
14486
14487 return status;
14488
14489}
14490/**---------------------------------------------------------------------------
14491 *
14492 * \brief wlan_hdd_restart_timer_cb
14493 *
14494 * Restart timer callback. An internal function.
14495 *
14496 * \param - User data:
14497 *
14498 * \return - None
14499 *
14500 * --------------------------------------------------------------------------*/
14501
14502void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
14503{
14504 hdd_context_t *pHddCtx = usrDataForCallback;
14505 wlan_hdd_framework_restart(pHddCtx);
14506 return;
14507
14508}
14509
14510
14511/**---------------------------------------------------------------------------
14512 *
14513 * \brief wlan_hdd_restart_driver
14514 *
14515 * This function sends an event to supplicant to restart the WLAN driver.
14516 *
14517 * This function is called from vos_wlanRestart.
14518 *
14519 * \param - pHddCtx
14520 *
14521 * \return - VOS_STATUS_SUCCESS: Success
14522 * VOS_STATUS_E_EMPTY: Adapter is Empty
14523 * VOS_STATUS_E_ALREADY: Request already in progress
14524
14525 * --------------------------------------------------------------------------*/
14526VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
14527{
14528 VOS_STATUS status = VOS_STATUS_SUCCESS;
14529
14530 /* A tight check to make sure reentrancy */
14531 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
14532 {
Mihir Shetefd528652014-06-23 19:07:50 +053014533 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnsone7245742012-09-05 17:12:55 -070014534 "%s: WLAN restart is already in progress", __func__);
14535
14536 return VOS_STATUS_E_ALREADY;
14537 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -070014538 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -080014539#ifdef HAVE_WCNSS_RESET_INTR
Siddharth Bhal864e7e82015-04-07 20:07:24 +053014540 wcnss_reset_fiq(TRUE);
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -070014541#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -070014542
Jeff Johnsone7245742012-09-05 17:12:55 -070014543 return status;
14544}
14545
Bhargav Shahd0715912015-10-01 18:17:37 +053014546/**
14547 * hdd_get_total_sessions() - provide total number of active sessions
14548 * @pHddCtx: Valid Global HDD context pointer
14549 *
14550 * This function iterates through pAdaptors and find the number of all active
14551 * sessions. This active sessions includes connected sta, p2p client and number
14552 * of client connected to sap/p2p go.
14553 *
14554 * Return: Total number of active sessions.
14555 */
14556v_U8_t hdd_get_total_sessions(hdd_context_t *pHddCtx)
14557{
14558 v_U8_t active_session = 0;
14559 hdd_station_ctx_t *pHddStaCtx;
14560 hdd_adapter_list_node_t *pAdapterNode, *pNext;
14561 hdd_adapter_t *pAdapter;
14562 VOS_STATUS status;
14563
14564 status = hdd_get_front_adapter(pHddCtx, &pAdapterNode);
14565 while (NULL != pAdapterNode && VOS_STATUS_SUCCESS == status) {
14566 pAdapter = pAdapterNode->pAdapter;
14567 switch (pAdapter->device_mode) {
14568 case VOS_STA_MODE:
14569 case VOS_P2P_CLIENT_MODE:
14570 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14571 if(eConnectionState_Associated == pHddStaCtx->conn_info.connState)
14572 active_session += 1;
14573 break;
14574 case VOS_STA_SAP_MODE:
14575 case VOS_P2P_GO_MODE:
14576 active_session += hdd_softap_get_connected_sta(pAdapter);
14577 break;
14578 default:
14579 break;
14580 }
14581
14582 status = hdd_get_next_adapter(pHddCtx, pAdapterNode, &pNext);
14583 pAdapterNode = pNext;
14584 }
14585
14586 return active_session;
14587}
14588
14589/**
14590 * hdd_set_delack_value() - Set delack value
14591 * @pHddCtx: Valid Global HDD context pointer
14592 * @next_rx_level: Value to set for delack
14593 *
14594 * This function compare present value and next value of delack. If the both
14595 * are diffrent then it sets next value .
14596 *
14597 * Return: void.
14598 */
14599void hdd_set_delack_value(hdd_context_t *pHddCtx, v_U32_t next_rx_level)
14600{
14601 if (pHddCtx->cur_rx_level != next_rx_level) {
14602 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_DEBUG,
14603 "%s: TCP DELACK trigger level %d",
14604 __func__, next_rx_level);
14605 mutex_lock(&pHddCtx->cur_rx_level_lock);
14606 pHddCtx->cur_rx_level = next_rx_level;
14607 mutex_unlock(&pHddCtx->cur_rx_level_lock);
14608 wlan_hdd_send_svc_nlink_msg(WLAN_SVC_WLAN_TP_IND, &next_rx_level,
14609 sizeof(next_rx_level));
14610 }
14611}
14612
14613/**
14614 * hdd_set_default_stop_delack_timer() - Start delack timer
14615 * @pHddCtx: Valid Global HDD context pointer
14616 *
14617 * This function stop delack timer and set delack value to default..
14618 *
14619 * Return: void.
14620 */
14621
14622void hdd_set_default_stop_delack_timer(hdd_context_t *pHddCtx)
14623{
14624 if (VOS_TIMER_STATE_RUNNING !=
14625 vos_timer_getCurrentState(&pHddCtx->delack_timer)) {
14626 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_DEBUG,
14627 "%s: Can not stop timer", __func__);
14628 return;
14629 }
14630
14631 vos_timer_stop(&pHddCtx->delack_timer);
14632 hdd_set_delack_value(pHddCtx, TP_IND_LOW);
14633}
14634
14635/**
14636 * hdd_start_delack_timer() - Start delack timer
14637 * @pHddCtx: Valid Global HDD context pointer
14638 *
14639 * This function starts the delack timer for tcpDelAckComputeInterval time
14640 * interval.The default timer value is 2 second.
14641 *
14642 * Return: void.
14643 */
14644void hdd_start_delack_timer(hdd_context_t *pHddCtx)
14645{
14646 if (VOS_TIMER_STATE_RUNNING ==
14647 vos_timer_getCurrentState(&pHddCtx->delack_timer)) {
14648 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_DEBUG,
14649 "%s: Timer is already running", __func__);
14650 return;
14651 }
14652
14653 vos_timer_start(&pHddCtx->delack_timer,
14654 pHddCtx->cfg_ini->tcpDelAckComputeInterval);
14655}
14656
14657/**
14658 * hdd_update_prev_rx_packet_count() - Update previous rx packet count
14659 * @pHddCtx: Valid Global HDD context pointer
14660 *
14661 * This function updates the prev_rx_packets count from the corresponding
14662 * pAdapter states. This prev_rx_packets will diffed with the packet count
14663 * at the end of delack timer. That can give number of RX packet is spacific
14664 * time.
14665 *
14666 * Return: void.
14667 */
14668void hdd_update_prev_rx_packet_count(hdd_context_t *pHddCtx)
14669{
14670 hdd_adapter_list_node_t *pAdapterNode, *pNext;
14671 hdd_adapter_t *pAdapter;
14672 VOS_STATUS status;
14673
14674 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
14675 while (NULL != pAdapterNode && VOS_STATUS_SUCCESS == status) {
14676 pAdapter = pAdapterNode->pAdapter;
14677 pAdapter->prev_rx_packets = pAdapter->stats.rx_packets;
14678 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
14679 pAdapterNode = pNext;
14680 }
14681}
14682
14683/**
14684 * hdd_manage_delack_timer() - start\stop delack timer
14685 * @pHddCtx: Valid Global HDD context pointer
14686 *
14687 * This function check the number of concerent session present, it starts the
14688 * delack timer if only one session is present.
14689 * In the case of BT_COEX and TDLS mode it blindly stop delack functionality.
14690 *
14691 * Return: void.
14692 */
14693void hdd_manage_delack_timer(hdd_context_t *pHddCtx)
14694{
14695 uint8_t sessions;
14696
14697 if (!pHddCtx->cfg_ini->enable_delack) {
14698 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_DEBUG,
14699 "%s: TCP DELACK is not enabled", __func__);
14700 return;
14701 }
14702
14703 /* Blindly stop timer of BTCOEX and TDLS Session is up */
14704 if (pHddCtx->mode != 0) {
14705 hdd_set_default_stop_delack_timer(pHddCtx);
14706 return;
14707 }
14708
14709 sessions = hdd_get_total_sessions(pHddCtx);
14710 if (sessions == 1) {
14711 hdd_update_prev_rx_packet_count(pHddCtx);
14712 hdd_start_delack_timer(pHddCtx);
14713 } else {
14714 hdd_set_default_stop_delack_timer(pHddCtx);
14715 }
14716}
14717
Mihir Shetee1093ba2014-01-21 20:13:32 +053014718/**---------------------------------------------------------------------------
14719 *
14720 * \brief wlan_hdd_init_channels
14721 *
14722 * This function is used to initialize the channel list in CSR
14723 *
14724 * This function is called from hdd_wlan_startup
14725 *
14726 * \param - pHddCtx: HDD context
14727 *
14728 * \return - VOS_STATUS_SUCCESS: Success
14729 * VOS_STATUS_E_FAULT: Failure reported by SME
14730
14731 * --------------------------------------------------------------------------*/
14732static VOS_STATUS wlan_hdd_init_channels(hdd_context_t *pHddCtx)
14733{
14734 eHalStatus status;
14735
14736 status = sme_InitChannels(pHddCtx->hHal);
14737 if (HAL_STATUS_SUCCESS(status))
14738 {
14739 return VOS_STATUS_SUCCESS;
14740 }
14741 else
14742 {
14743 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Channel initialization failed(%d)",
14744 __func__, status);
14745 return VOS_STATUS_E_FAULT;
14746 }
14747}
14748
Mihir Shete04206452014-11-20 17:50:58 +053014749#ifdef CONFIG_ENABLE_LINUX_REG
Agarwal Ashish6db9d532014-09-30 18:19:10 +053014750VOS_STATUS wlan_hdd_init_channels_for_cc(hdd_context_t *pHddCtx, driver_load_type init )
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053014751{
14752 eHalStatus status;
14753
Agarwal Ashish6db9d532014-09-30 18:19:10 +053014754 status = sme_InitChannelsForCC(pHddCtx->hHal, init);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053014755 if (HAL_STATUS_SUCCESS(status))
14756 {
14757 return VOS_STATUS_SUCCESS;
14758 }
14759 else
14760 {
14761 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Issue reg hint failed(%d)",
14762 __func__, status);
14763 return VOS_STATUS_E_FAULT;
14764 }
14765}
Mihir Shete04206452014-11-20 17:50:58 +053014766#endif
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -070014767/*
14768 * API to find if there is any STA or P2P-Client is connected
14769 */
14770VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
14771{
14772 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
14773}
Jeff Johnsone7245742012-09-05 17:12:55 -070014774
Mihir Shetee2ae82a2015-03-16 14:08:49 +053014775
14776/*
14777 * API to find if the firmware will send logs using DXE channel
14778 */
14779v_U8_t hdd_is_fw_logging_enabled(void)
14780{
14781 hdd_context_t *pHddCtx;
14782
14783 pHddCtx = vos_get_context(VOS_MODULE_ID_HDD,
14784 vos_get_global_context(VOS_MODULE_ID_HDD, NULL));
14785
Sachin Ahuja084313e2015-05-21 17:57:10 +053014786 return (pHddCtx && pHddCtx->cfg_ini->enableMgmtLogging);
Mihir Shetee2ae82a2015-03-16 14:08:49 +053014787}
14788
Agarwal Ashish57e84372014-12-05 18:26:53 +053014789/*
Mihir Shetebe94ebb2015-05-26 12:07:14 +053014790 * API to find if the firmware will send trace logs using DXE channel
14791 */
14792v_U8_t hdd_is_fw_ev_logging_enabled(void)
14793{
14794 hdd_context_t *pHddCtx;
14795
14796 pHddCtx = vos_get_context(VOS_MODULE_ID_HDD,
14797 vos_get_global_context(VOS_MODULE_ID_HDD, NULL));
14798
14799 return (pHddCtx && pHddCtx->cfg_ini->enableFWLogging);
14800}
14801/*
Agarwal Ashish57e84372014-12-05 18:26:53 +053014802 * API to find if there is any session connected
14803 */
14804VOS_STATUS hdd_is_any_session_connected(hdd_context_t *pHddCtx)
14805{
14806 return sme_is_any_session_connected(pHddCtx->hHal);
14807}
14808
14809
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053014810int wlan_hdd_scan_abort(hdd_adapter_t *pAdapter)
14811{
14812 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14813 hdd_scaninfo_t *pScanInfo = NULL;
Girish Gowli4bf7a632014-06-12 13:42:11 +053014814 long status = 0;
c_hpothua3d45d52015-01-05 14:11:17 +053014815 tSirAbortScanStatus abortScanStatus;
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053014816
14817 pScanInfo = &pHddCtx->scan_info;
Ratnam Rachuric7681132015-06-30 10:35:13 +053014818 INIT_COMPLETION(pScanInfo->abortscan_event_var);
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053014819 if (pScanInfo->mScanPending)
14820 {
c_hpothua3d45d52015-01-05 14:11:17 +053014821 abortScanStatus = hdd_abort_mac_scan(pHddCtx, pScanInfo->sessionId,
14822 eCSR_SCAN_ABORT_DEFAULT);
14823 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
14824 FL("abortScanStatus: %d"), abortScanStatus);
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053014825
c_hpothua3d45d52015-01-05 14:11:17 +053014826 /* If there is active scan command lets wait for the completion else
14827 * there is no need to wait as scan command might be in the SME pending
14828 * command list.
14829 */
14830 if (abortScanStatus == eSIR_ABORT_ACTIVE_SCAN_LIST_NOT_EMPTY)
14831 {
Mukul Sharmab392b642017-08-17 17:45:29 +053014832 status = wait_for_completion_timeout(
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053014833 &pScanInfo->abortscan_event_var,
14834 msecs_to_jiffies(5000));
c_hpothua3d45d52015-01-05 14:11:17 +053014835 if (0 >= status)
14836 {
14837 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Girish Gowli4bf7a632014-06-12 13:42:11 +053014838 "%s: Timeout or Interrupt occurred while waiting for abort"
14839 "scan, status- %ld", __func__, status);
c_hpothua3d45d52015-01-05 14:11:17 +053014840 return -ETIMEDOUT;
14841 }
14842 }
14843 else if (abortScanStatus == eSIR_ABORT_SCAN_FAILURE)
14844 {
14845 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
14846 FL("hdd_abort_mac_scan failed"));
14847 return -VOS_STATUS_E_FAILURE;
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053014848 }
14849 }
Girish Gowli4bf7a632014-06-12 13:42:11 +053014850 return 0;
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053014851}
14852
Abhishek Singh7d624e12015-11-30 14:29:27 +053014853/**
14854 * hdd_indicate_mgmt_frame() - Wrapper to indicate management frame to
14855 * user space
14856 * @frame_ind: Management frame data to be informed.
14857 *
14858 * This function is used to indicate management frame to
14859 * user space
14860 *
14861 * Return: None
14862 *
14863 */
14864void hdd_indicate_mgmt_frame(tSirSmeMgmtFrameInd *frame_ind)
14865{
14866 hdd_context_t *hdd_ctx = NULL;
14867 hdd_adapter_t *adapter = NULL;
14868 v_CONTEXT_t vos_context = NULL;
14869
14870 /* Get the global VOSS context.*/
14871 vos_context = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
14872 if (!vos_context) {
14873 hddLog(LOGE, FL("Global VOS context is Null"));
14874 return;
14875 }
14876 /* Get the HDD context.*/
14877 hdd_ctx =
14878 (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, vos_context );
14879
14880 if (0 != wlan_hdd_validate_context(hdd_ctx))
14881 {
14882 return;
14883 }
14884 adapter = hdd_get_adapter_by_sme_session_id(hdd_ctx,
14885 frame_ind->sessionId);
14886
14887 if ((NULL != adapter) &&
14888 (WLAN_HDD_ADAPTER_MAGIC == adapter->magic))
14889 __hdd_indicate_mgmt_frame(adapter,
14890 frame_ind->frameLen,
14891 frame_ind->frameBuf,
14892 frame_ind->frameType,
14893 frame_ind->rxChan,
14894 frame_ind->rxRssi);
14895 return;
14896
14897}
14898
c_hpothu225aa7c2014-10-22 17:45:13 +053014899VOS_STATUS wlan_hdd_cancel_remain_on_channel(hdd_context_t *pHddCtx)
14900{
14901 hdd_adapter_t *pAdapter;
14902 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
14903 VOS_STATUS vosStatus;
14904
14905 vosStatus = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
14906 while (NULL != pAdapterNode && VOS_STATUS_E_EMPTY != vosStatus)
14907 {
14908 pAdapter = pAdapterNode->pAdapter;
14909 if (NULL != pAdapter)
14910 {
14911 if (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode ||
14912 WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ||
14913 WLAN_HDD_P2P_GO == pAdapter->device_mode)
14914 {
14915 hddLog(LOG1, FL("abort ROC deviceMode: %d"),
14916 pAdapter->device_mode);
14917 if (VOS_STATUS_SUCCESS !=
14918 wlan_hdd_cancel_existing_remain_on_channel(pAdapter))
14919 {
14920 hddLog(LOGE, FL("failed to abort ROC"));
14921 return VOS_STATUS_E_FAILURE;
14922 }
14923 }
14924 }
14925 vosStatus = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
14926 pAdapterNode = pNext;
14927 }
14928 return VOS_STATUS_SUCCESS;
14929}
Mahesh A Saptasagard477b092015-02-06 15:12:16 +053014930
Mihir Shete0be28772015-02-17 18:42:14 +053014931hdd_remain_on_chan_ctx_t *hdd_get_remain_on_channel_ctx(hdd_context_t *pHddCtx)
14932{
14933 hdd_adapter_t *pAdapter;
14934 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
14935 hdd_cfg80211_state_t *cfgState;
14936 hdd_remain_on_chan_ctx_t *pRemainChanCtx = NULL;
14937 VOS_STATUS vosStatus;
14938
14939 vosStatus = hdd_get_front_adapter (pHddCtx, &pAdapterNode);
14940 while (NULL != pAdapterNode && VOS_STATUS_E_EMPTY != vosStatus)
14941 {
14942 pAdapter = pAdapterNode->pAdapter;
14943 if (NULL != pAdapter)
14944 {
14945 cfgState = WLAN_HDD_GET_CFG_STATE_PTR(pAdapter);
14946 pRemainChanCtx = cfgState->remain_on_chan_ctx;
14947 if (pRemainChanCtx)
14948 break;
14949 }
14950 vosStatus = hdd_get_next_adapter (pHddCtx, pAdapterNode, &pNext);
14951 pAdapterNode = pNext;
14952 }
14953 return pRemainChanCtx;
14954}
14955
Padma, Santhosh Kumar778d8382015-03-04 17:41:22 +053014956/**
14957 * wlan_hdd_handle_dfs_chan_scan () - handles disable/enable DFS channels
14958 *
14959 * @pHddCtx: HDD context within host driver
14960 * @dfsScanMode: dfsScanMode passed from ioctl
14961 *
14962 */
14963
14964VOS_STATUS wlan_hdd_handle_dfs_chan_scan(hdd_context_t *pHddCtx,
14965 tANI_U8 dfsScanMode)
14966{
14967 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
14968 hdd_adapter_t *pAdapter;
14969 VOS_STATUS vosStatus;
14970 hdd_station_ctx_t *pHddStaCtx;
14971 eHalStatus status = eHAL_STATUS_SUCCESS;
14972
14973 if(!pHddCtx)
14974 {
14975 hddLog(LOGE, FL("HDD context is Null"));
14976 return eHAL_STATUS_FAILURE;
14977 }
14978
14979 if (pHddCtx->scan_info.mScanPending)
14980 {
14981 hddLog(LOG1, FL("Aborting scan for sessionId: %d"),
14982 pHddCtx->scan_info.sessionId);
14983 hdd_abort_mac_scan(pHddCtx,
14984 pHddCtx->scan_info.sessionId,
14985 eCSR_SCAN_ABORT_DEFAULT);
14986 }
14987
14988 if (!dfsScanMode)
14989 {
14990 vosStatus = hdd_get_front_adapter( pHddCtx, &pAdapterNode);
14991 while ((NULL != pAdapterNode) &&
14992 (VOS_STATUS_SUCCESS == vosStatus))
14993 {
14994 pAdapter = pAdapterNode->pAdapter;
14995
14996 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
14997 {
14998 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14999
15000 if(!pHddStaCtx)
15001 {
15002 hddLog(LOGE, FL("HDD STA context is Null"));
15003 return eHAL_STATUS_FAILURE;
15004 }
15005
15006 /* if STA is already connected on DFS channel,
15007 disconnect immediately*/
15008 if (hdd_connIsConnected(pHddStaCtx) &&
15009 (NV_CHANNEL_DFS ==
15010 vos_nv_getChannelEnabledState(
15011 pHddStaCtx->conn_info.operationChannel)))
15012 {
15013 status = sme_RoamDisconnect(pHddCtx->hHal,
15014 pAdapter->sessionId,
15015 eCSR_DISCONNECT_REASON_UNSPECIFIED);
15016 hddLog(LOG1, FL("Client connected on DFS channel %d,"
15017 "sme_RoamDisconnect returned with status: %d"
15018 "for sessionid: %d"), pHddStaCtx->conn_info.
15019 operationChannel, status, pAdapter->sessionId);
15020 }
15021 }
15022
15023 vosStatus = hdd_get_next_adapter(pHddCtx, pAdapterNode,
15024 &pNext);
15025 pAdapterNode = pNext;
15026 }
15027 }
15028
15029 sme_UpdateDFSScanMode(pHddCtx->hHal, dfsScanMode);
15030 sme_UpdateDFSRoamMode(pHddCtx->hHal,
15031 (dfsScanMode != DFS_CHNL_SCAN_DISABLED));
15032
15033 status = sme_HandleDFSChanScan(pHddCtx->hHal);
15034 if (!HAL_STATUS_SUCCESS(status))
15035 {
15036 hddLog(LOGE,
15037 FL("Failed in sme_HandleDFSChanScan (err=%d)"), status);
15038 return status;
15039 }
15040
15041 return status;
15042}
15043
Nirav Shah7e3c8132015-06-22 23:51:42 +053015044static int hdd_log2_ceil(unsigned value)
15045{
15046 /* need to switch to unsigned math so that negative values
15047 * will right-shift towards 0 instead of -1
15048 */
15049 unsigned tmp = value;
15050 int log2 = -1;
15051
15052 if (value == 0)
15053 return 0;
15054
15055 while (tmp) {
15056 log2++;
15057 tmp >>= 1;
15058 }
15059 if (1U << log2 != value)
15060 log2++;
15061
15062 return log2;
15063}
15064
15065/**
15066 * hdd_sta_id_hash_attach() - initialize sta id to macaddr hash
15067 * @pAdapter: adapter handle
15068 *
15069 * Return: vos status
15070 */
15071VOS_STATUS hdd_sta_id_hash_attach(hdd_adapter_t *pAdapter)
15072{
15073 int hash_elem, log2, i;
15074
15075 spin_lock_bh( &pAdapter->sta_hash_lock);
15076 if (pAdapter->is_sta_id_hash_initialized == VOS_TRUE) {
15077 spin_unlock_bh( &pAdapter->sta_hash_lock);
15078 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
15079 "%s: hash already attached for session id %d",
15080 __func__, pAdapter->sessionId);
15081 return VOS_STATUS_SUCCESS;
15082 }
15083 spin_unlock_bh( &pAdapter->sta_hash_lock);
15084
15085 hash_elem = WLAN_MAX_STA_COUNT;
15086 hash_elem *= HDD_STA_ID_HASH_MULTIPLIER;
15087 log2 = hdd_log2_ceil(hash_elem);
15088 hash_elem = 1 << log2;
15089
15090 pAdapter->sta_id_hash.mask = hash_elem - 1;
15091 pAdapter->sta_id_hash.idx_bits = log2;
15092 pAdapter->sta_id_hash.bins =
15093 vos_mem_malloc(hash_elem *sizeof(hdd_list_t));
15094 if (!pAdapter->sta_id_hash.bins) {
15095 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
15096 "%s: malloc failed for session %d",
15097 __func__, pAdapter->sessionId);
15098 return VOS_STATUS_E_NOMEM;
15099 }
15100
15101 for (i = 0; i < hash_elem; i++)
15102 hdd_list_init(&pAdapter->sta_id_hash.bins[i], WLAN_MAX_STA_COUNT);
15103
15104 spin_lock_bh( &pAdapter->sta_hash_lock);
15105 pAdapter->is_sta_id_hash_initialized = VOS_TRUE;
15106 spin_unlock_bh( &pAdapter->sta_hash_lock);
15107 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
15108 "%s: Station ID Hash attached for session id %d",
15109 __func__, pAdapter->sessionId);
15110
15111 return VOS_STATUS_SUCCESS;
15112}
15113
15114/**
15115 * hdd_sta_id_hash_detach() - deinit sta_id to macaddr hash
15116 * @pAdapter: adapter handle
15117 *
15118 * Return: vos status
15119 */
15120VOS_STATUS hdd_sta_id_hash_detach(hdd_adapter_t *pAdapter)
15121{
15122 int hash_elem, i;
15123 v_SIZE_t size;
15124
15125 spin_lock_bh( &pAdapter->sta_hash_lock);
15126 if (pAdapter->is_sta_id_hash_initialized != VOS_TRUE) {
15127 spin_unlock_bh( &pAdapter->sta_hash_lock);
15128 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
15129 "%s: hash not initialized for session id %d",
15130 __func__, pAdapter->sessionId);
15131 return VOS_STATUS_SUCCESS;
15132 }
15133
15134 pAdapter->is_sta_id_hash_initialized = VOS_FALSE;
15135 spin_unlock_bh( &pAdapter->sta_hash_lock);
15136
15137 hash_elem = 1 << pAdapter->sta_id_hash.idx_bits;
15138
15139 /* free all station info*/
15140 for (i = 0; i < hash_elem; i++) {
15141 hdd_list_size(&pAdapter->sta_id_hash.bins[i], &size);
15142 if (size != 0) {
15143 VOS_STATUS status;
15144 hdd_staid_hash_node_t *sta_info_node = NULL;
15145 hdd_staid_hash_node_t *next_node = NULL;
15146 status = hdd_list_peek_front ( &pAdapter->sta_id_hash.bins[i],
15147 (hdd_list_node_t**) &sta_info_node );
15148
15149 while ( NULL != sta_info_node && VOS_STATUS_SUCCESS == status )
15150 {
15151 status = hdd_list_remove_node( &pAdapter->sta_id_hash.bins[i],
15152 &sta_info_node->node);
15153 vos_mem_free(sta_info_node);
15154
15155 status = hdd_list_peek_next (&pAdapter->sta_id_hash.bins[i],
15156 (hdd_list_node_t*)sta_info_node,
15157 (hdd_list_node_t**)&next_node);
15158 sta_info_node = next_node;
15159 }
15160 }
15161 }
15162
15163 vos_mem_free(pAdapter->sta_id_hash.bins);
15164 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
15165 "%s: Station ID Hash detached for session id %d",
15166 __func__, pAdapter->sessionId);
15167 return VOS_STATUS_SUCCESS;
15168}
15169
15170/**
15171 * hdd_sta_id_hash_calculate_index() - derive index from macaddr
15172 * @pAdapter: adapter handle
15173 * @mac_addr_in: input mac address
15174 *
15175 * Return: index derived from mac address
15176 */
15177int hdd_sta_id_hash_calculate_index(hdd_adapter_t *pAdapter,
15178 v_MACADDR_t *mac_addr_in)
15179{
15180 uint16 index;
15181 struct hdd_align_mac_addr_t * mac_addr =
15182 (struct hdd_align_mac_addr_t *)mac_addr_in;
15183
15184 index = mac_addr->bytes_ab ^
15185 mac_addr->bytes_cd ^ mac_addr->bytes_ef;
15186 index ^= index >> pAdapter->sta_id_hash.idx_bits;
15187 index &= pAdapter->sta_id_hash.mask;
15188 return index;
15189}
15190
15191/**
15192 * hdd_sta_id_hash_add_entry() - add entry in hash
15193 * @pAdapter: adapter handle
15194 * @sta_id: station id
15195 * @mac_addr: mac address
15196 *
15197 * Return: vos status
15198 */
15199VOS_STATUS hdd_sta_id_hash_add_entry(hdd_adapter_t *pAdapter,
15200 v_U8_t sta_id, v_MACADDR_t *mac_addr)
15201{
15202 uint16 index;
15203 hdd_staid_hash_node_t *sta_info_node = NULL;
15204
Nirav Shah7e3c8132015-06-22 23:51:42 +053015205 index = hdd_sta_id_hash_calculate_index(pAdapter, mac_addr);
15206 sta_info_node = vos_mem_malloc(sizeof(hdd_staid_hash_node_t));
15207 if (!sta_info_node) {
Nirav Shah7e3c8132015-06-22 23:51:42 +053015208 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
15209 "%s: malloc failed", __func__);
15210 return VOS_STATUS_E_NOMEM;
15211 }
15212
15213 sta_info_node->sta_id = sta_id;
15214 vos_mem_copy(&sta_info_node->mac_addr, mac_addr, sizeof(v_MACADDR_t));
15215
Nirav Shah303ed5c2015-08-24 10:29:25 +053015216 spin_lock_bh( &pAdapter->sta_hash_lock);
15217 if (pAdapter->is_sta_id_hash_initialized != VOS_TRUE) {
15218 spin_unlock_bh( &pAdapter->sta_hash_lock);
15219 vos_mem_free(sta_info_node);
15220 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
15221 "%s: hash is not initialized for session id %d",
15222 __func__, pAdapter->sessionId);
15223 return VOS_STATUS_E_FAILURE;
15224 }
15225
Nirav Shah7e3c8132015-06-22 23:51:42 +053015226 hdd_list_insert_back ( &pAdapter->sta_id_hash.bins[index],
15227 (hdd_list_node_t*) sta_info_node );
15228 spin_unlock_bh( &pAdapter->sta_hash_lock);
15229 return VOS_STATUS_SUCCESS;
15230}
15231
15232/**
15233 * hdd_sta_id_hash_remove_entry() - remove entry from hash
15234 * @pAdapter: adapter handle
15235 * @sta_id: station id
15236 * @mac_addr: mac address
15237 *
15238 * Return: vos status
15239 */
15240VOS_STATUS hdd_sta_id_hash_remove_entry(hdd_adapter_t *pAdapter,
15241 v_U8_t sta_id, v_MACADDR_t *mac_addr)
15242{
15243 uint16 index;
15244 VOS_STATUS status;
15245 hdd_staid_hash_node_t *sta_info_node = NULL;
15246 hdd_staid_hash_node_t *next_node = NULL;
15247
15248 spin_lock_bh( &pAdapter->sta_hash_lock);
15249 if (pAdapter->is_sta_id_hash_initialized != VOS_TRUE) {
15250 spin_unlock_bh( &pAdapter->sta_hash_lock);
15251 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
15252 "%s: hash is not initialized for session id %d",
15253 __func__, pAdapter->sessionId);
15254 return VOS_STATUS_E_FAILURE;
15255 }
15256
15257 index = hdd_sta_id_hash_calculate_index(pAdapter, mac_addr);
15258 status = hdd_list_peek_front ( &pAdapter->sta_id_hash.bins[index],
15259 (hdd_list_node_t**) &sta_info_node );
15260
15261 while ( NULL != sta_info_node && VOS_STATUS_SUCCESS == status )
15262 {
15263 if (sta_info_node->sta_id == sta_id) {
15264 status = hdd_list_remove_node( &pAdapter->sta_id_hash.bins[index],
15265 &sta_info_node->node);
15266 vos_mem_free(sta_info_node);
15267 break;
15268 }
15269 status = hdd_list_peek_next (&pAdapter->sta_id_hash.bins[index],
15270 (hdd_list_node_t*)sta_info_node, (hdd_list_node_t**)&next_node);
15271 sta_info_node = next_node;
15272 }
15273 spin_unlock_bh( &pAdapter->sta_hash_lock);
15274 return status;
15275}
15276
15277/**
15278 * hdd_sta_id_find_from_mac_addr() - find sta id from mac address
15279 * @pAdapter: adapter handle
15280 * @mac_addr_in: mac address
15281 *
15282 * Return: station id
15283 */
15284int hdd_sta_id_find_from_mac_addr(hdd_adapter_t *pAdapter,
15285 v_MACADDR_t *mac_addr_in)
15286{
15287 uint8 is_found = 0;
15288 uint8 sta_id = HDD_WLAN_INVALID_STA_ID;
15289 uint16 index;
15290 VOS_STATUS status;
15291 hdd_staid_hash_node_t *sta_info_node = NULL;
15292 hdd_staid_hash_node_t *next_node = NULL;
15293
15294 spin_lock_bh( &pAdapter->sta_hash_lock);
15295 if (pAdapter->is_sta_id_hash_initialized != VOS_TRUE) {
15296 spin_unlock_bh( &pAdapter->sta_hash_lock);
Bhargav Shahce3b32c2015-08-10 12:29:24 +053015297 hddLog(VOS_TRACE_LEVEL_INFO,
Nirav Shah7e3c8132015-06-22 23:51:42 +053015298 FL("hash is not initialized for session id %d"),
15299 pAdapter->sessionId);
15300 return HDD_WLAN_INVALID_STA_ID;
15301 }
15302
15303 index = hdd_sta_id_hash_calculate_index(pAdapter, mac_addr_in);
15304 status = hdd_list_peek_front ( &pAdapter->sta_id_hash.bins[index],
15305 (hdd_list_node_t**) &sta_info_node );
15306
15307 while ( NULL != sta_info_node && VOS_STATUS_SUCCESS == status )
15308 {
15309 if (vos_mem_compare(&sta_info_node->mac_addr,
15310 mac_addr_in, sizeof(v_MACADDR_t))) {
15311 is_found = 1;
15312 sta_id = sta_info_node->sta_id;
15313 break;
15314 }
15315 status = hdd_list_peek_next (&pAdapter->sta_id_hash.bins[index],
15316 (hdd_list_node_t*)sta_info_node,
15317 (hdd_list_node_t**)&next_node);
15318 sta_info_node = next_node;
15319 }
15320 spin_unlock_bh( &pAdapter->sta_hash_lock);
15321 return sta_id;
15322}
15323
c_manjeecfd1efb2015-09-25 19:32:34 +053015324/*FW memory dump feature*/
15325/**
15326 * This structure hold information about the /proc file
15327 *
15328 */
15329static struct proc_dir_entry *proc_file, *proc_dir;
15330
15331/**
15332 * memdump_read() - perform read operation in memory dump proc file
15333 *
15334 * @file - handle for the proc file.
15335 * @buf - pointer to user space buffer.
15336 * @count - number of bytes to be read.
15337 * @pos - offset in the from buffer.
15338 *
15339 * This function performs read operation for the memory dump proc file.
15340 *
15341 * Return: number of bytes read on success, error code otherwise.
15342 */
15343static ssize_t memdump_read(struct file *file, char __user *buf,
15344 size_t count, loff_t *pos)
15345{
15346 int status;
15347 hdd_context_t *hdd_ctx = (hdd_context_t *)PDE_DATA(file_inode(file));
15348 size_t ret_count;
c_manjeef1495642015-10-13 18:35:01 +053015349 loff_t bytes_left;
c_manjeecfd1efb2015-09-25 19:32:34 +053015350 ENTER();
15351
15352 hddLog(LOG1, FL("Read req for size:%zu pos:%llu"), count, *pos);
15353 status = wlan_hdd_validate_context(hdd_ctx);
15354 if (0 != status) {
15355 return -EINVAL;
15356 }
15357
15358 if (!wlan_fwr_mem_dump_test_and_set_read_allowed_bit()) {
15359 hddLog(LOGE, FL("Current mem dump request timed out/failed"));
15360 return -EINVAL;
15361 }
15362
15363 /* run fs_read_handler in an atomic context*/
15364 vos_ssr_protect(__func__);
c_manjeef1495642015-10-13 18:35:01 +053015365 ret_count = wlan_fwr_mem_dump_fsread_handler( buf, count, pos, &bytes_left);
15366 if(bytes_left == 0)
c_manjeecfd1efb2015-09-25 19:32:34 +053015367 {
15368 /*Free the fwr mem dump buffer */
15369 wlan_free_fwr_mem_dump_buffer();
15370 wlan_set_fwr_mem_dump_state(FW_MEM_DUMP_IDLE);
c_manjeef1495642015-10-13 18:35:01 +053015371 ret_count=0;
c_manjeecfd1efb2015-09-25 19:32:34 +053015372 }
15373 /*if SSR/unload code is waiting for memdump_read to finish,signal it*/
15374 vos_ssr_unprotect(__func__);
15375 EXIT();
15376 return ret_count;
15377}
15378
15379/**
15380 * struct memdump_fops - file operations for memory dump feature
15381 * @read - read function for memory dump operation.
15382 *
15383 * This structure initialize the file operation handle for memory
15384 * dump feature
15385 */
15386static const struct file_operations memdump_fops = {
15387 read: memdump_read
15388};
15389
15390/*
15391* wlan_hdd_fw_mem_dump_cb : callback for Fw mem dump request
15392* To be passed by HDD to WDA and called upon receiving of response
15393* from firmware
15394* @fwMemDumpReqContext : memory dump request context
15395* @dump_rsp : dump response from HAL
15396* Returns none
15397*/
15398void wlan_hdd_fw_mem_dump_cb(void *fwMemDumpReqContext,
15399 tAniFwrDumpRsp *dump_rsp)
15400{
c_manjeef1495642015-10-13 18:35:01 +053015401 struct hdd_fw_mem_dump_req_ctx *pHddFwMemDumpCtx = (struct hdd_fw_mem_dump_req_ctx *)fwMemDumpReqContext;
c_manjeecfd1efb2015-09-25 19:32:34 +053015402
c_manjeef1495642015-10-13 18:35:01 +053015403 ENTER();
15404 spin_lock(&hdd_context_lock);
15405 if(!pHddFwMemDumpCtx || (FW_MEM_DUMP_MAGIC != pHddFwMemDumpCtx->magic)) {
15406 spin_unlock(&hdd_context_lock);
15407 return;
15408 }
15409 /* report the status to requesting function and free mem.*/
c_manjeecfd1efb2015-09-25 19:32:34 +053015410 if (dump_rsp->dump_status != eHAL_STATUS_SUCCESS) {
c_manjeef1495642015-10-13 18:35:01 +053015411 hddLog(LOGE, FL("fw dump request declined by fwr"));
15412 //set the request completion variable
15413 complete(&(pHddFwMemDumpCtx->req_completion));
c_manjeecfd1efb2015-09-25 19:32:34 +053015414 //Free the allocated fwr dump
15415 wlan_free_fwr_mem_dump_buffer();
15416 wlan_set_fwr_mem_dump_state(FW_MEM_DUMP_IDLE);
c_manjeecfd1efb2015-09-25 19:32:34 +053015417 }
c_manjeef1495642015-10-13 18:35:01 +053015418 else {
15419 hddLog(LOG1, FL("fw dump request accepted by fwr"));
15420 /* register the HDD callback which will be called by SVC */
15421 wlan_set_svc_fw_mem_dump_req_cb((void*)wlan_hdd_fw_mem_dump_req_cb,(void*)pHddFwMemDumpCtx);
15422 }
15423 spin_unlock(&hdd_context_lock);
c_manjeecfd1efb2015-09-25 19:32:34 +053015424 EXIT();
15425
15426}
15427
15428/**
15429 * memdump_procfs_remove() - Remove file/dir under procfs for memory dump
15430 *
15431 * This function removes file/dir under proc file system that was
15432 * processing firmware memory dump
15433 *
15434 * Return: None
15435 */
15436static void memdump_procfs_remove(void)
15437{
15438 remove_proc_entry(PROCFS_MEMDUMP_NAME, proc_dir);
15439 hddLog(LOG1 , FL("/proc/%s/%s removed\n"),
15440 PROCFS_MEMDUMP_DIR, PROCFS_MEMDUMP_NAME);
15441 remove_proc_entry(PROCFS_MEMDUMP_DIR, NULL);
15442 hddLog(LOG1 , FL("/proc/%s removed\n"), PROCFS_MEMDUMP_DIR);
15443}
15444
15445/**
15446 * memdump_procfs_init() - Initialize procfs for memory dump
15447 *
15448 * @vos_ctx - Global vos context.
15449 *
15450 * This function create file under proc file system to be used later for
15451 * processing firmware memory dump
15452 *
15453 * Return: 0 on success, error code otherwise.
15454 */
15455static int memdump_procfs_init(void *vos_ctx)
15456{
15457 hdd_context_t *hdd_ctx;
15458
15459 hdd_ctx = vos_get_context(VOS_MODULE_ID_HDD, vos_ctx);
15460 if (!hdd_ctx) {
15461 hddLog(LOGE , FL("Invalid HDD context"));
15462 return -EINVAL;
15463 }
15464
15465 proc_dir = proc_mkdir(PROCFS_MEMDUMP_DIR, NULL);
15466 if (proc_dir == NULL) {
15467 remove_proc_entry(PROCFS_MEMDUMP_DIR, NULL);
15468 hddLog(LOGE , FL("Error: Could not initialize /proc/%s"),
15469 PROCFS_MEMDUMP_DIR);
15470 return -ENOMEM;
15471 }
15472
15473 proc_file = proc_create_data(PROCFS_MEMDUMP_NAME,
15474 S_IRUSR | S_IWUSR, proc_dir,
15475 &memdump_fops, hdd_ctx);
15476 if (proc_file == NULL) {
15477 remove_proc_entry(PROCFS_MEMDUMP_NAME, proc_dir);
15478 hddLog(LOGE , FL("Error: Could not initialize /proc/%s"),
15479 PROCFS_MEMDUMP_NAME);
15480 return -ENOMEM;
15481 }
15482
15483 hddLog(LOG1 , FL("/proc/%s/%s created"),
15484 PROCFS_MEMDUMP_DIR, PROCFS_MEMDUMP_NAME);
15485
15486 return 0;
15487}
15488
15489/**
15490 * memdump_init() - Initialization function for memory dump feature
15491 *
15492 * This function creates proc file for memdump feature and registers
15493 * HDD callback function with SME.
15494 *
15495 * Return - 0 on success, error otherwise
15496 */
15497int memdump_init(void)
15498{
15499 hdd_context_t *hdd_ctx;
15500 void *vos_ctx;
15501 int status = 0;
15502
15503 vos_ctx = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
15504 if (!vos_ctx) {
15505 hddLog(LOGE, FL("Invalid VOS context"));
15506 return -EINVAL;
15507 }
15508
15509 hdd_ctx = vos_get_context(VOS_MODULE_ID_HDD, vos_ctx);
15510 if (!hdd_ctx) {
15511 hddLog(LOGE , FL("Invalid HDD context"));
15512 return -EINVAL;
15513 }
15514
15515 status = memdump_procfs_init(vos_ctx);
15516 if (status) {
15517 hddLog(LOGE , FL("Failed to create proc file"));
15518 return status;
15519 }
15520
15521 return 0;
15522}
15523
15524/**
15525 * memdump_deinit() - De initialize memdump feature
15526 *
15527 * This function removes proc file created for memdump feature.
15528 *
15529 * Return: None
15530 */
15531int memdump_deinit(void)
15532{
15533 hdd_context_t *hdd_ctx;
15534 void *vos_ctx;
15535
15536 vos_ctx = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
15537 if (!vos_ctx) {
15538 hddLog(LOGE, FL("Invalid VOS context"));
15539 return -EINVAL;
15540 }
15541
15542 hdd_ctx = vos_get_context(VOS_MODULE_ID_HDD, vos_ctx);
15543 if(!hdd_ctx) {
15544 hddLog(LOGE , FL("Invalid HDD context"));
15545 return -EINVAL;
15546 }
15547
15548 memdump_procfs_remove();
15549 return 0;
15550}
15551
15552/**
15553 * wlan_hdd_fw_mem_dump_req(pHddCtx) - common API(cfg80211/ioctl) for requesting fw mem dump to SME
15554 * Return: HAL status
15555 */
15556
15557int wlan_hdd_fw_mem_dump_req(hdd_context_t * pHddCtx)
15558{
15559 tAniFwrDumpReq fw_mem_dump_req={0};
c_manjeef1495642015-10-13 18:35:01 +053015560 struct hdd_fw_mem_dump_req_ctx fw_mem_dump_ctx;
c_manjeecfd1efb2015-09-25 19:32:34 +053015561 eHalStatus status = eHAL_STATUS_FAILURE;
Abhishek Singh4eca9822015-12-09 18:07:34 +053015562 int ret=0, result;
c_manjeecfd1efb2015-09-25 19:32:34 +053015563 ENTER();
c_manjeef1495642015-10-13 18:35:01 +053015564
c_manjeecfd1efb2015-09-25 19:32:34 +053015565 /*Check whether a dump request is already going on
15566 *Caution this function will free previously held memory if new dump request is allowed*/
15567 if (!wlan_fwr_mem_dump_test_and_set_write_allowed_bit()) {
15568 hddLog(LOGE, FL("Fw memdump already in progress"));
15569 return -EBUSY;
15570 }
15571 //Allocate memory for fw mem dump buffer
15572 ret = wlan_fwr_mem_dump_buffer_allocation();
15573 if(ret == -EFAULT)
15574 {
15575 hddLog(LOGE, FL("Fwr mem dump not supported by FW"));
15576 return ret;
15577 }
15578 if (0 != ret) {
15579 hddLog(LOGE, FL("Fwr mem Allocation failed"));
15580 return -ENOMEM;
15581 }
c_manjeef1495642015-10-13 18:35:01 +053015582 init_completion(&fw_mem_dump_ctx.req_completion);
15583 fw_mem_dump_ctx.magic = FW_MEM_DUMP_MAGIC;
15584 fw_mem_dump_ctx.status = false;
15585
c_manjeecfd1efb2015-09-25 19:32:34 +053015586 fw_mem_dump_req.fwMemDumpReqCallback = wlan_hdd_fw_mem_dump_cb;
c_manjeef1495642015-10-13 18:35:01 +053015587 fw_mem_dump_req.fwMemDumpReqContext = &fw_mem_dump_ctx;
c_manjeecfd1efb2015-09-25 19:32:34 +053015588 status = sme_FwMemDumpReq(pHddCtx->hHal, &fw_mem_dump_req);
15589 if(eHAL_STATUS_SUCCESS != status)
15590 {
15591 hddLog(VOS_TRACE_LEVEL_ERROR,
15592 "%s: fw_mem_dump_req failed ", __func__);
15593 wlan_free_fwr_mem_dump_buffer();
c_manjeef1495642015-10-13 18:35:01 +053015594 ret = -EFAULT;
15595 goto cleanup;
c_manjeecfd1efb2015-09-25 19:32:34 +053015596 }
c_manjeef1495642015-10-13 18:35:01 +053015597 /*wait for fw mem dump completion to send event to userspace*/
Abhishek Singh4eca9822015-12-09 18:07:34 +053015598 result =
15599 wait_for_completion_timeout(&fw_mem_dump_ctx.req_completion,
15600 msecs_to_jiffies(FW_MEM_DUMP_TIMEOUT_MS));
15601 if (0 >= result )
c_manjeef1495642015-10-13 18:35:01 +053015602 {
15603 hddLog(VOS_TRACE_LEVEL_ERROR,
Abhishek Singh4eca9822015-12-09 18:07:34 +053015604 "%s: fw_mem_dump_req timeout %d ", __func__,result);
15605 ret = -ETIMEDOUT;
c_manjeef1495642015-10-13 18:35:01 +053015606 }
15607cleanup:
15608 spin_lock(&hdd_context_lock);
15609 fw_mem_dump_ctx.magic = 0;
Abhishek Singh4eca9822015-12-09 18:07:34 +053015610 if(!ret && !fw_mem_dump_ctx.status)
15611 ret = -EFAULT;
c_manjeef1495642015-10-13 18:35:01 +053015612 spin_unlock(&hdd_context_lock);
c_manjeecfd1efb2015-09-25 19:32:34 +053015613
c_manjeef1495642015-10-13 18:35:01 +053015614 EXIT();
Abhishek Singh4eca9822015-12-09 18:07:34 +053015615 return ret;
c_manjeef1495642015-10-13 18:35:01 +053015616}
15617
15618/**
15619 * HDD callback which will be called by SVC to indicate mem dump completion.
15620 */
15621void wlan_hdd_fw_mem_dump_req_cb(struct hdd_fw_mem_dump_req_ctx* pHddFwMemDumpCtx)
15622{
15623 if (!pHddFwMemDumpCtx) {
15624 hddLog(VOS_TRACE_LEVEL_ERROR,
15625 "%s: HDD context not valid ", __func__);
15626 return;
15627 }
15628 spin_lock(&hdd_context_lock);
15629 /* check the req magic and set status */
15630 if (pHddFwMemDumpCtx->magic == FW_MEM_DUMP_MAGIC)
15631 {
15632 pHddFwMemDumpCtx->status = true;
15633 //signal the completion
15634 complete(&(pHddFwMemDumpCtx->req_completion));
15635 }
15636 else
15637 {
15638 hddLog(VOS_TRACE_LEVEL_ERROR,
15639 "%s: fw mem dump request possible timeout ", __func__);
15640 }
15641 spin_unlock(&hdd_context_lock);
c_manjeecfd1efb2015-09-25 19:32:34 +053015642}
15643
Mahesh A Saptasagar67ab9222015-10-21 15:38:41 +053015644void hdd_initialize_adapter_common(hdd_adapter_t *pAdapter)
15645{
15646 if (NULL == pAdapter)
15647 {
15648 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: pAdapter is NULL ", __func__);
15649 return;
15650 }
15651 init_completion(&pAdapter->session_open_comp_var);
15652 init_completion(&pAdapter->session_close_comp_var);
15653 init_completion(&pAdapter->disconnect_comp_var);
15654 init_completion(&pAdapter->linkup_event_var);
15655 init_completion(&pAdapter->cancel_rem_on_chan_var);
15656 init_completion(&pAdapter->rem_on_chan_ready_event);
15657 init_completion(&pAdapter->pno_comp_var);
15658#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
15659 init_completion(&pAdapter->offchannel_tx_event);
15660#endif
15661 init_completion(&pAdapter->tx_action_cnf_event);
15662#ifdef FEATURE_WLAN_TDLS
15663 init_completion(&pAdapter->tdls_add_station_comp);
15664 init_completion(&pAdapter->tdls_del_station_comp);
15665 init_completion(&pAdapter->tdls_mgmt_comp);
15666 init_completion(&pAdapter->tdls_link_establish_req_comp);
15667#endif
15668
15669#ifdef WLAN_FEATURE_RMC
15670 init_completion(&pAdapter->ibss_peer_info_comp);
15671#endif /* WLAN_FEATURE_RMC */
15672 init_completion(&pAdapter->ula_complete);
15673 init_completion(&pAdapter->change_country_code);
15674
15675#ifdef FEATURE_WLAN_BATCH_SCAN
15676 init_completion(&pAdapter->hdd_set_batch_scan_req_var);
15677 init_completion(&pAdapter->hdd_get_batch_scan_req_var);
15678#endif
Kapil Gupta2b44acb2016-12-30 16:49:51 +053015679 init_completion(&pAdapter->wlan_suspend_comp_var);
Mahesh A Saptasagar67ab9222015-10-21 15:38:41 +053015680
15681 return;
15682}
c_manjeecfd1efb2015-09-25 19:32:34 +053015683
Anurag Chouhan0b29de02016-12-16 13:18:40 +053015684#ifdef MDNS_OFFLOAD
15685
15686/**
15687 * hdd_mdns_enable_offload_done() - mdns enable offload response api
15688 * @padapter: holds adapter
15689 * @status: response status
15690 *
15691 * Return - None
15692 */
15693void hdd_mdns_enable_offload_done(void *padapter, VOS_STATUS status)
15694{
15695 hdd_adapter_t* adapter = (hdd_adapter_t*) padapter;
15696
15697 ENTER();
15698
15699 if (NULL == adapter)
15700 {
15701 hddLog(VOS_TRACE_LEVEL_ERROR,
15702 "%s: adapter is NULL",__func__);
15703 return;
15704 }
15705
15706 adapter->mdns_status.mdns_enable_status = status;
15707 vos_event_set(&adapter->mdns_status.vos_event);
15708 return;
15709}
15710
15711/**
15712 * hdd_mdns_fqdn_offload_done() - mdns fqdn offload response api
15713 * @padapter: holds adapter
15714 * @status: responce status
15715 *
15716 * Return - None
15717 */
15718void hdd_mdns_fqdn_offload_done(void *padapter, VOS_STATUS status)
15719{
15720 hdd_adapter_t* adapter = (hdd_adapter_t*) padapter;
15721
15722 ENTER();
15723
15724 if (NULL == adapter)
15725 {
15726 hddLog(VOS_TRACE_LEVEL_ERROR,
15727 "%s: adapter is NULL",__func__);
15728 return;
15729 }
15730
15731 adapter->mdns_status.mdns_fqdn_status = status;
15732 return;
15733}
15734
15735/**
15736 * hdd_mdns_resp_offload_done() - mdns resp offload response api
15737 * @padapter: holds adapter
15738 * @status: responce status
15739 *
15740 * Return - None
15741 */
15742void hdd_mdns_resp_offload_done(void *padapter, VOS_STATUS status)
15743{
15744 hdd_adapter_t* adapter = (hdd_adapter_t*) padapter;
15745
15746 ENTER();
15747
15748 if (NULL == adapter)
15749 {
15750 hddLog(VOS_TRACE_LEVEL_ERROR,
15751 "%s: adapter is NULL",__func__);
15752 return;
15753 }
15754
15755 adapter->mdns_status.mdns_resp_status = status;
15756 return;
15757}
15758
15759/**
15760 * wlan_hdd_mdns_process_response_dname() - Process mDNS domain name
15761 * @response: Pointer to a struct hdd_mdns_resp_info
15762 * @resp_info: Pointer to a struct tSirMDNSResponseInfo
15763 *
15764 * This function will pack the whole domain name without compression. It will
15765 * add the leading len for each field and add zero length octet to terminate
15766 * the domain name.
15767 *
15768 * Return: Return boolean. TRUE for success, FALSE for fail.
15769 */
15770static bool
15771wlan_hdd_mdns_process_response_dname(struct hdd_mdns_resp_info *response,
15772 sir_mdns_resp_info resp_info)
15773{
15774 uint8_t num;
15775 uint16_t idx;
15776 uint8_t len = 0;
15777
15778 if ((response == NULL) || (response->data == NULL) ||
15779 (response->offset == NULL)) {
15780 hddLog(LOGE, FL("Either data or offset in response is NULL!"));
15781 return FALSE;
15782 }
15783
15784 if ((resp_info == NULL) ||
15785 (resp_info->resp_len >= MAX_MDNS_RESP_LEN)) {
15786 hddLog(LOGE, FL("resp_len exceeds %d!"), MAX_MDNS_RESP_LEN);
15787 return FALSE;
15788 }
15789
15790 for (num = 0; num < response->num_entries; num++) {
15791 response->offset[num] =
15792 resp_info->resp_len + MDNS_HEADER_LEN;
15793 idx = num * MAX_LEN_DOMAINNAME_FIELD;
15794 len = strlen((char *)&response->data[idx]);
15795 if ((resp_info->resp_len + len + 1) >= MAX_MDNS_RESP_LEN) {
15796 hddLog(LOGE, FL("resp_len exceeds %d!"),
15797 MAX_MDNS_RESP_LEN);
15798 return FALSE;
15799 }
15800 resp_info->resp_data[resp_info->resp_len] = len;
15801 resp_info->resp_len++;
15802 vos_mem_copy(&resp_info->resp_data[resp_info->resp_len],
15803 &response->data[idx], len);
15804 resp_info->resp_len += len;
15805 }
15806
15807 /* The domain name terminates with the zero length octet */
15808 if (num == response->num_entries) {
15809 if (resp_info->resp_len >= MAX_MDNS_RESP_LEN) {
15810 hddLog(LOGE, FL("resp_len exceeds %d!"),
15811 MAX_MDNS_RESP_LEN);
15812 return FALSE;
15813 }
15814 resp_info->resp_data[resp_info->resp_len] = 0;
15815 resp_info->resp_len++;
15816 }
15817
15818 return TRUE;
15819}
15820
15821/**
15822 * wlan_hdd_mdns_format_response_u16() - Form uint16_t response data
15823 * @value: The uint16_t value is formed to the struct tSirMDNSResponseInfo
15824 * @resp_info: Pointer to a struct tSirMDNSResponseInfo
15825 *
15826 * Return: None
15827 */
15828static void wlan_hdd_mdns_format_response_u16(uint16_t value,
15829 sir_mdns_resp_info resp_info)
15830{
15831 uint8_t val_u8;
15832
15833 if ((resp_info == NULL) || (resp_info->resp_data == NULL))
15834 return;
15835 val_u8 = (value & 0xff00) >> 8;
15836 resp_info->resp_data[resp_info->resp_len++] = val_u8;
15837 val_u8 = value & 0xff;
15838 resp_info->resp_data[resp_info->resp_len++] = val_u8;
15839}
15840
15841/**
15842 * wlan_hdd_mdns_format_response_u32() - Form uint32_t response data
15843 * @value: The uint32_t value is formed to the struct tSirMDNSResponseInfo
15844 * @resp_info: Pointer to a struct tSirMDNSResponseInfo
15845 *
15846 * Return: None
15847 */
15848static void wlan_hdd_mdns_format_response_u32(uint32_t value,
15849 sir_mdns_resp_info resp_info)
15850{
15851 uint8_t val_u8;
15852
15853 if ((resp_info == NULL) || (resp_info->resp_data == NULL))
15854 return;
15855 val_u8 = (value & 0xff000000) >> 24;
15856 resp_info->resp_data[resp_info->resp_len++] = val_u8;
15857 val_u8 = (value & 0xff0000) >> 16;
15858 resp_info->resp_data[resp_info->resp_len++] = val_u8;
15859 val_u8 = (value & 0xff00) >> 8;
15860 resp_info->resp_data[resp_info->resp_len++] = val_u8;
15861 val_u8 = value & 0xff;
15862 resp_info->resp_data[resp_info->resp_len++] = val_u8;
15863}
15864
15865/**
15866 * wlan_hdd_mdns_process_response_misc() - Process misc info in mDNS response
15867 * @resp_type: Response type for mDNS
15868 * @resp_info: Pointer to a struct tSirMDNSResponseInfo
15869 *
15870 * This function will pack the response type, class and TTL (Time To Live).
15871 *
15872 * Return: Return boolean. TRUE for success, FALSE for fail.
15873 */
15874static bool wlan_hdd_mdns_process_response_misc(uint16_t resp_type,
15875 sir_mdns_resp_info resp_info)
15876{
15877 uint16_t len;
15878
15879 if (resp_info == NULL) {
15880 hddLog(LOGE, FL("resp_info is NULL!"));
15881 return FALSE;
15882 }
15883
15884 len = resp_info->resp_len + (2 * sizeof(uint16_t) + sizeof(uint32_t));
15885 if (len >= MAX_MDNS_RESP_LEN) {
15886 hddLog(LOGE, FL("resp_len exceeds %d!"), MAX_MDNS_RESP_LEN);
15887 return FALSE;
15888 }
15889
15890 /* Fill Type, Class, TTL */
15891 wlan_hdd_mdns_format_response_u16(resp_type, resp_info);
15892 wlan_hdd_mdns_format_response_u16(MDNS_CLASS, resp_info);
15893 wlan_hdd_mdns_format_response_u32(MDNS_TTL, resp_info);
15894
15895 return TRUE;
15896}
15897
15898/**
15899 * wlan_hdd_mdns_compress_data() - Compress the domain name in mDNS response
15900 * @resp_info: Pointer to a struct tSirMDNSResponseInfo
15901 * @response_dst: The response which domain name is compressed.
15902 * @response_src: The response which domain name is matched with response_dst.
15903 * Its offset is used for data compression.
15904 * @num_matched: The number of matched entries between response_dst and
15905 * response_src
15906 *
15907 * This function will form the different fields of domain name in response_dst
15908 * if any. Then use the offset of the matched domain name in response_src to
15909 * compress the matched domain name.
15910 *
15911 * Return: Return boolean. TRUE for success, FALSE for fail.
15912 */
15913static bool
15914wlan_hdd_mdns_compress_data(sir_mdns_resp_info resp_info,
15915 struct hdd_mdns_resp_info *response_dst,
15916 struct hdd_mdns_resp_info *response_src,
15917 uint8_t num_matched)
15918{
15919 uint8_t num, num_diff;
15920 uint16_t value, idx;
15921 uint8_t len = 0;
15922
15923 if ((response_src == NULL) || (response_dst == NULL) ||
15924 (resp_info == NULL)) {
15925 hddLog(LOGE, FL("response info is NULL!"));
15926 return FALSE;
15927 }
15928
15929 if (response_dst->num_entries < num_matched) {
15930 hddLog(LOGE, FL("num_entries is less than num_matched!"));
15931 return FALSE;
15932 }
15933
15934 if (resp_info->resp_len >= MAX_MDNS_RESP_LEN) {
15935 hddLog(LOGE, FL("resp_len exceeds %d!"), MAX_MDNS_RESP_LEN);
15936 return FALSE;
15937 }
15938
15939 num_diff = response_dst->num_entries - num_matched;
15940 if ((num_diff > 0) && (response_dst->data == NULL)) {
15941 hddLog(LOGE, FL("response_dst->data is NULL!"));
15942 return FALSE;
15943 }
15944
15945 /*
15946 * Handle the unmatched string at the beginning
15947 * Store the length of octets and the octets
15948 */
15949 for (num = 0; num < num_diff; num++) {
15950 response_dst->offset[num] =
15951 resp_info->resp_len + MDNS_HEADER_LEN;
15952 idx = num * MAX_LEN_DOMAINNAME_FIELD;
15953 len = strlen((char *)&response_dst->data[idx]);
15954 if ((resp_info->resp_len + len + 1) >= MAX_MDNS_RESP_LEN) {
15955 hddLog(LOGE, FL("resp_len exceeds %d!"),
15956 MAX_MDNS_RESP_LEN);
15957 return FALSE;
15958 }
15959 resp_info->resp_data[resp_info->resp_len] = len;
15960 resp_info->resp_len++;
15961 vos_mem_copy(&resp_info->resp_data[resp_info->resp_len],
15962 &response_dst->data[idx], len);
15963 resp_info->resp_len += len;
15964 }
15965 /*
15966 * Handle the matched string from the end
15967 * Just keep the offset and mask the leading two bit
15968 */
15969 if (response_src->num_entries >= num_matched) {
15970 num_diff = response_src->num_entries - num_matched;
15971 value = response_src->offset[num_diff];
15972 if (value > 0) {
15973 value |= 0xc000;
15974 if ((resp_info->resp_len + sizeof(uint16_t)) >=
15975 MAX_MDNS_RESP_LEN) {
15976 hddLog(LOGE, FL("resp_len exceeds %d!"),
15977 MAX_MDNS_RESP_LEN);
15978 return FALSE;
15979 }
15980 wlan_hdd_mdns_format_response_u16(value, resp_info);
15981 return TRUE;
15982 }
15983 }
15984 return FALSE;
15985}
15986
15987/**
15988 * wlan_hdd_mdns_reset_response() - Reset the response info
15989 * @response: The response which info is reset.
15990 *
15991 * Return: None
15992 */
15993static void wlan_hdd_mdns_reset_response(struct hdd_mdns_resp_info *response)
15994{
15995 if (response == NULL)
15996 return;
15997 response->num_entries = 0;
15998 response->data = NULL;
15999 response->offset = NULL;
16000}
16001
16002/**
16003 * wlan_hdd_mdns_init_response() - Initialize the response info
16004 * @response: The response which info is initiatized.
16005 * @resp_dname: The domain name string which might be tokenized.
16006 *
16007 * This function will allocate the memory for both response->data and
16008 * response->offset. Besides, it will also tokenize the domain name to some
16009 * entries and fill response->num_entries with the num of entries.
16010 *
16011 * Return: Return boolean. TRUE for success, FALSE for fail.
16012 */
16013static bool wlan_hdd_mdns_init_response(struct hdd_mdns_resp_info *response,
16014 uint8_t *resp_dname, char separator)
16015{
16016 uint16_t size;
16017
16018 if ((resp_dname == NULL) || (response == NULL)) {
16019 hddLog(LOGE, FL("resp_dname or response is NULL!"));
16020 return FALSE;
16021 }
16022
16023 size = MAX_NUM_FIELD_DOMAINNAME * MAX_LEN_DOMAINNAME_FIELD;
16024 response->data = vos_mem_malloc(size);
16025 if (response->data) {
16026 vos_mem_zero(response->data, size);
16027 if (VOS_STATUS_SUCCESS !=
16028 hdd_string_to_string_array((char *)resp_dname,
16029 response->data,
16030 separator,
16031 &response->num_entries,
16032 MAX_NUM_FIELD_DOMAINNAME,
16033 MAX_LEN_DOMAINNAME_FIELD)) {
16034 hddLog(LOGE, FL("hdd_string_to_string_array fail!"));
16035 goto err_init_resp;
16036 }
16037
16038 if ((response->num_entries > 0) &&
16039 (strlen((char *)&response->data[0]) > 0)) {
16040 size = sizeof(uint16_t) * response->num_entries;
16041 response->offset = vos_mem_malloc(size);
16042 if (response->offset) {
16043 vos_mem_zero(response->offset, size);
16044 return TRUE;
16045 }
16046 }
16047 }
16048
16049err_init_resp:
16050 if (response->data)
16051 vos_mem_free(response->data);
16052 wlan_hdd_mdns_reset_response(response);
16053 return FALSE;
16054}
16055
16056/**
16057 * wlan_hdd_mdns_find_entries_from_end() - Find the matched entries
16058 * @response1: The response info is used to be compared.
16059 * @response2: The response info is used to be compared.
16060 *
16061 * This function will find the matched entries from the end.
16062 *
16063 * Return: Return the number of the matched entries.
16064 */
16065static uint8_t
16066wlan_hdd_mdns_find_entries_from_end(struct hdd_mdns_resp_info *response1,
16067 struct hdd_mdns_resp_info *response2)
16068{
16069 uint8_t min, len1, i;
16070 uint16_t num1, num2;
16071 uint8_t num_matched = 0;
16072
16073 min = VOS_MIN(response1->num_entries, response2->num_entries);
16074
16075 for (i = 1; i <= min; i++) {
16076 num1 = (response1->num_entries - i);
16077 num1 *= MAX_LEN_DOMAINNAME_FIELD;
16078 num2 = (response2->num_entries - i);
16079 num2 *= MAX_LEN_DOMAINNAME_FIELD;
16080 len1 = strlen((char *)&response1->data[num1]);
16081
16082 if ((len1 == 0) ||
16083 (len1 != strlen((char *)&response2->data[num2])))
16084 break;
16085 if (memcmp(&response1->data[num1],
16086 &response2->data[num2], len1))
16087 break;
16088 else
16089 num_matched++;
16090 }
16091
16092 return num_matched;
16093}
16094
16095/**
16096 * wlan_hdd_mdns_find_max() - Find the maximum number of the matched entries
16097 * @matchedlist: Pointer to the array of struct hdd_mdns_resp_matched
16098 * @numlist: The number of the elements in the array matchedlist.
16099 *
16100 * Find the max number of the matched entries among the array matchedlist.
16101 *
16102 * Return: None
16103 */
16104static void wlan_hdd_mdns_find_max(struct hdd_mdns_resp_matched *matchedlist,
16105 uint8_t numlist)
16106{
16107 int j;
16108 struct hdd_mdns_resp_matched tmp;
16109
16110 /* At least two values are used for sorting */
16111 if ((numlist < 2) || (matchedlist == NULL)) {
16112 hddLog(LOGE, FL("At least two values are used for sorting!"));
16113 return;
16114 }
16115
16116 for (j = 0; j < numlist-1; j++) {
16117 if (matchedlist[j].num_matched >
16118 matchedlist[j+1].num_matched) {
16119 vos_mem_copy(&tmp, &matchedlist[j],
16120 sizeof(struct hdd_mdns_resp_matched));
16121 vos_mem_copy(&matchedlist[j], &matchedlist[j+1],
16122 sizeof(struct hdd_mdns_resp_matched));
16123 vos_mem_copy(&matchedlist[j+1], &tmp,
16124 sizeof(struct hdd_mdns_resp_matched));
16125 }
16126 }
16127}
16128
16129/**
16130 * wlan_hdd_mdns_pack_response_type_a() - Pack Type A response
16131 * @ini_config: Pointer to the struct hdd_config_t
16132 * @resp_info: Pointer to the struct tSirMDNSResponseInfo
16133 * @resptype_a: Pointer to the struct hdd_mdns_resp_info of Type A
16134 *
16135 * Type A response include QName, response type, class, TTL and Ipv4.
16136 *
16137 * Return: Return boolean. TRUE for success, FALSE for fail.
16138 */
16139static bool
16140wlan_hdd_mdns_pack_response_type_a(hdd_config_t *ini_config,
16141 sir_mdns_resp_info resp_info,
16142 struct hdd_mdns_resp_info *resptype_a)
16143{
16144 uint16_t value;
16145 uint32_t len;
16146
16147 ENTER();
16148 if ((ini_config == NULL) || (resp_info == NULL) ||
16149 (resptype_a == NULL)) {
16150 hddLog(LOGE, FL("ini_config or response info is NULL!"));
16151 return FALSE;
16152 }
16153
16154 /* No Type A response */
16155 if (strlen((char *)ini_config->mdns_resp_type_a) <= 0)
16156 return TRUE;
16157
16158 /* Wrong response is assigned, just ignore this response */
16159 if (!wlan_hdd_mdns_init_response(resptype_a,
16160 ini_config->mdns_resp_type_a, '.'))
16161 return TRUE;
16162
16163 /* Process response domain name */
16164 if (!wlan_hdd_mdns_process_response_dname(resptype_a, resp_info)) {
16165 hddLog(LOGE, FL("Fail to process mDNS response (%d)!"),
16166 MDNS_TYPE_A);
16167 return FALSE;
16168 }
16169
16170 /* Process response Type, Class, TTL */
16171 if (!wlan_hdd_mdns_process_response_misc(MDNS_TYPE_A, resp_info)) {
16172 hddLog(LOGE, FL("Fail to process mDNS misc response (%d)!"),
16173 MDNS_TYPE_A);
16174 return FALSE;
16175 }
16176
16177 /* Process response RDLength, RData */
16178 len = sizeof(uint16_t) + sizeof(uint32_t);
16179 len += resp_info->resp_len;
16180 if (len >= MAX_MDNS_RESP_LEN) {
16181 hddLog(LOGE, FL("resp_len exceeds %d!"), MAX_MDNS_RESP_LEN);
16182 return FALSE;
16183 }
16184 value = sizeof(uint32_t);
16185 wlan_hdd_mdns_format_response_u16(value, resp_info);
16186 wlan_hdd_mdns_format_response_u32(ini_config->mdns_resp_type_a_ipv4,
16187 resp_info);
16188
16189 EXIT();
16190 return TRUE;
16191}
16192
16193/**
16194 * wlan_hdd_mdns_pack_response_type_txt() - Pack Type Txt response
16195 * @ini_config: Pointer to the struct hdd_config_t
16196 * @resp_info: Pointer to the struct tSirMDNSResponseInfo
16197 * @resptype_txt: Pointer to the struct hdd_mdns_resp_info of Type txt
16198 * @resptype_a: Pointer to the struct hdd_mdns_resp_info of Type A
16199 *
16200 * Type Txt response include QName, response type, class, TTL and text content.
16201 * Also, it will find the matched QName from resptype_A and compress the data.
16202 *
16203 * Return: Return boolean. TRUE for success, FALSE for fail.
16204 */
16205static bool
16206wlan_hdd_mdns_pack_response_type_txt(hdd_config_t *ini_config,
16207 sir_mdns_resp_info resp_info,
16208 struct hdd_mdns_resp_info *resptype_txt,
16209 struct hdd_mdns_resp_info *resptype_a)
16210{
16211 uint8_t num_matched;
16212 uint8_t num;
16213 uint16_t idx;
16214 uint16_t value = 0;
16215 uint32_t len;
16216 uint32_t total_len;
16217 bool status;
16218 struct hdd_mdns_resp_info resptype_content;
16219
16220 ENTER();
16221
16222 if ((ini_config == NULL) || (resp_info == NULL) ||
16223 (resptype_txt == NULL)) {
16224 hddLog(LOGE, FL("ini_config or response info is NULL!"));
16225 return FALSE;
16226 }
16227
16228 /* No Type Txt response */
16229 if (strlen((char *)ini_config->mdns_resp_type_txt) <= 0)
16230 return TRUE;
16231
16232 /* Wrong response is assigned, just ignore this response */
16233 if (!wlan_hdd_mdns_init_response(resptype_txt,
16234 ini_config->mdns_resp_type_txt, '.'))
16235 return TRUE;
16236
16237 /*
16238 * For data compression
16239 * Check if any strings are matched with Type A response
16240 */
16241 if (resptype_a && (resptype_a->num_entries > 0)) {
16242 num_matched = wlan_hdd_mdns_find_entries_from_end(resptype_txt,
16243 resptype_a);
16244 if (num_matched > 0) {
16245 if (!wlan_hdd_mdns_compress_data(resp_info,
16246 resptype_txt, resptype_a, num_matched)) {
16247 hddLog(LOGE, FL("Fail to compress mDNS "
16248 "response (%d)!"), MDNS_TYPE_TXT);
16249 return FALSE;
16250 }
16251 } else {
16252 /*
16253 * num_matched is zero. Error!
16254 * At least ".local" is needed.
16255 */
16256 hddLog(LOGE, FL("No matched string! Fail to pack mDNS "
16257 "response (%d)!"), MDNS_TYPE_TXT);
16258 return FALSE;
16259 }
16260 } else {
16261 /* no TypeA response, so show the whole data */
16262 if (!wlan_hdd_mdns_process_response_dname(resptype_txt,
16263 resp_info)) {
16264 hddLog(LOGE, FL("Fail to process mDNS response (%d)!"),
16265 MDNS_TYPE_TXT);
16266 return FALSE;
16267 }
16268 }
16269
16270 /* Process response Type, Class, TTL */
16271 if (!wlan_hdd_mdns_process_response_misc(MDNS_TYPE_TXT, resp_info)) {
16272 hddLog(LOGE, FL("Fail to process mDNS misc response (%d)!"),
16273 MDNS_TYPE_TXT);
16274 return FALSE;
16275 }
16276
16277 /*
16278 * Process response RDLength, RData.
16279 * TypeTxt RData include len.
16280 */
16281 status = wlan_hdd_mdns_init_response(&resptype_content,
16282 ini_config->mdns_resp_type_txt_content,
16283 '/');
16284 if (status == FALSE) {
16285 hddLog(LOGE, FL("wlan_hdd_mdns_init_response FAIL"));
16286 return FALSE;
16287 }
16288
16289 for (num = 0; num < resptype_content.num_entries; num++) {
16290 idx = num * MAX_LEN_DOMAINNAME_FIELD;
16291 value += strlen((char *)&resptype_content.data[idx]);
16292 }
16293
16294 /* content len is uint16_t */
16295 total_len = sizeof(uint16_t);
16296 total_len += resp_info->resp_len + value +
16297 resptype_content.num_entries;
16298
16299 if (total_len >= MAX_MDNS_RESP_LEN) {
16300 hddLog(LOGE, FL("resp_len exceeds %d!"), MAX_MDNS_RESP_LEN);
16301 return FALSE;
16302 }
16303 wlan_hdd_mdns_format_response_u16(value + resptype_content.num_entries,
16304 resp_info);
16305
16306 for (num = 0; num < resptype_content.num_entries; num++) {
16307 idx = num * MAX_LEN_DOMAINNAME_FIELD;
16308 len = strlen((char *)&resptype_content.data[idx]);
16309 resp_info->resp_data[resp_info->resp_len] = len;
16310 resp_info->resp_len++;
16311
16312 vos_mem_copy(&resp_info->resp_data[resp_info->resp_len],
16313 &resptype_content.data[idx], len);
16314
16315 resp_info->resp_len += len;
16316 hddLog(LOG1, FL("index = %d, len = %d, str = %s"),
16317 num, len, &resptype_content.data[idx]);
16318 }
16319
16320 EXIT();
16321 return TRUE;
16322}
16323
16324/**
16325 * wlan_hdd_mdns_pack_response_type_ptr_dname() - Pack Type PTR domain name
16326 * @ini_config: Pointer to the struct hdd_config_t
16327 * @resp_info: Pointer to the struct tSirMDNSResponseInfo
16328 * @resptype_ptr_dn: Pointer to the struct hdd_mdns_resp_info of Type Ptr
16329 * domain name
16330 * @resptype_ptr: Pointer to the struct hdd_mdns_resp_info of Type Ptr
16331 * @resptype_txt: Pointer to the struct hdd_mdns_resp_info of Type Txt
16332 * @resptype_a: Pointer to the struct hdd_mdns_resp_info of Type A
16333 *
16334 * The Type Ptr response include Type PTR domain name in its data field.
16335 * Also, it will find the matched QName from the existing resptype_ptr,
16336 * resptype_txt, resptype_a and then compress the data.
16337 *
16338 * Return: Return boolean. TRUE for success, FALSE for fail.
16339 */
16340static bool
16341wlan_hdd_mdns_pack_response_type_ptr_dname(hdd_config_t *ini_config,
16342 sir_mdns_resp_info resp_info,
16343 struct hdd_mdns_resp_info *resptype_ptr_dn,
16344 struct hdd_mdns_resp_info *resptype_ptr,
16345 struct hdd_mdns_resp_info *resptype_txt,
16346 struct hdd_mdns_resp_info *resptype_a)
16347{
16348 uint8_t num_matched, numlist, size;
16349 struct hdd_mdns_resp_matched matchedlist[MAX_MDNS_RESP_TYPE-1];
16350 struct hdd_mdns_resp_info *resp;
16351
16352 if ((ini_config == NULL) || (resp_info == NULL) ||
16353 (resptype_ptr == NULL) || (resptype_ptr_dn == NULL)) {
16354 hddLog(LOGE, FL("ini_config or response info is NULL!"));
16355 return FALSE;
16356 }
16357
16358 /* No Type Ptr domain name response */
16359 if (strlen((char *)ini_config->mdns_resp_type_ptr_dname) <= 0)
16360 return TRUE;
16361
16362 /* Wrong response is assigned, just ignore this response */
16363 if (!wlan_hdd_mdns_init_response(resptype_ptr_dn,
16364 ini_config->mdns_resp_type_ptr_dname, '.'))
16365 return TRUE;
16366
16367 /*
16368 * For data compression
16369 * Check if any strings are matched with previous
16370 * response.
16371 */
16372 numlist = 0;
16373 size = (MAX_MDNS_RESP_TYPE-1);
16374 size *= sizeof(struct hdd_mdns_resp_matched);
16375 vos_mem_zero(matchedlist, size);
16376 num_matched = wlan_hdd_mdns_find_entries_from_end(resptype_ptr_dn,
16377 resptype_ptr);
16378 if (num_matched > 0) {
16379 matchedlist[numlist].num_matched = num_matched;
16380 matchedlist[numlist].type = MDNS_TYPE_PTR;
16381 numlist++;
16382 }
16383 if (resptype_txt && (resptype_txt->num_entries > 0)) {
16384 num_matched = wlan_hdd_mdns_find_entries_from_end(
16385 resptype_ptr_dn, resptype_txt);
16386 if (num_matched > 0) {
16387 matchedlist[numlist].num_matched = num_matched;
16388 matchedlist[numlist].type = MDNS_TYPE_TXT;
16389 numlist++;
16390 }
16391 }
16392 if (resptype_a && (resptype_a->num_entries > 0)) {
16393 num_matched = wlan_hdd_mdns_find_entries_from_end(
16394 resptype_ptr_dn,resptype_a);
16395 if (num_matched > 0) {
16396 matchedlist[numlist].num_matched = num_matched;
16397 matchedlist[numlist].type = MDNS_TYPE_A;
16398 numlist++;
16399 }
16400 }
16401 if (numlist > 0) {
16402 if (numlist > 1)
16403 wlan_hdd_mdns_find_max(matchedlist, numlist);
16404 resp = NULL;
16405 switch (matchedlist[numlist-1].type) {
16406 case MDNS_TYPE_A:
16407 resp = resptype_a;
16408 break;
16409 case MDNS_TYPE_TXT:
16410 resp = resptype_txt;
16411 break;
16412 case MDNS_TYPE_PTR:
16413 resp = resptype_ptr;
16414 break;
16415 default:
16416 hddLog(LOGE, FL("Fail to compress mDNS response "
16417 "(%d)!"), MDNS_TYPE_PTR_DNAME);
16418 return FALSE;
16419 }
16420 num_matched = matchedlist[numlist-1].num_matched;
16421 if (!wlan_hdd_mdns_compress_data(resp_info, resptype_ptr_dn,
16422 resp, num_matched)) {
16423 hddLog(LOGE, FL("Fail to compress mDNS response "
16424 "(%d)!"), MDNS_TYPE_PTR_DNAME);
16425 return FALSE;
16426 }
16427 } else {
16428 /* num = 0 -> no matched string */
16429 if (!wlan_hdd_mdns_process_response_dname(resptype_ptr_dn,
16430 resp_info)) {
16431 hddLog(LOGE, FL("Fail to process mDNS response (%d)!"),
16432 MDNS_TYPE_PTR_DNAME);
16433 return FALSE;
16434 }
16435 }
16436
16437 return TRUE;
16438}
16439
16440/**
16441 * wlan_hdd_mdns_pack_response_type_ptr() - Pack Type PTR response
16442 * @ini_config: Pointer to the struct hdd_config_t
16443 * @resp_info: Pointer to the struct tSirMDNSResponseInfo
16444 * @resptype_ptr: Pointer to the struct hdd_mdns_resp_info of Type Ptr
16445 * @resptype_ptr_dn: Pointer to the struct hdd_mdns_resp_info of Type Ptr
16446 * domain name
16447 * @resptype_txt: Pointer to the struct hdd_mdns_resp_info of Type Txt
16448 * @resptype_a: Pointer to the struct hdd_mdns_resp_info of Type A
16449 *
16450 * The Type Ptr response include QName, response type, class, TTL and
16451 * Type PTR domain name. Also, it will find the matched QName from the
16452 * existing resptype_txt, resptype_a and then compress the data.
16453 *
16454 * Return: Return boolean. TRUE for success, FALSE for fail.
16455 */
16456static bool
16457wlan_hdd_mdns_pack_response_type_ptr(hdd_config_t *ini_config,
16458 sir_mdns_resp_info resp_info,
16459 struct hdd_mdns_resp_info *resptype_ptr,
16460 struct hdd_mdns_resp_info *resptype_ptr_dn,
16461 struct hdd_mdns_resp_info *resptype_txt,
16462 struct hdd_mdns_resp_info *resptype_a)
16463{
16464 uint8_t num_matched, num_matched1;
16465 uint16_t value;
16466 uint8_t val_u8;
16467 uint32_t offset_data_len, len;
16468
16469 ENTER();
16470 if ((ini_config == NULL) || (resp_info == NULL) ||
16471 (resptype_ptr == NULL) || (resptype_ptr_dn == NULL)) {
16472 hddLog(LOGE, FL("ini_config or response info is NULL!"));
16473 return FALSE;
16474 }
16475
16476 /* No Type Ptr response */
16477 if (strlen((char *)ini_config->mdns_resp_type_ptr) <= 0)
16478 return TRUE;
16479
16480 /* Wrong response is assigned, just ignore this response */
16481 if (!wlan_hdd_mdns_init_response(resptype_ptr,
16482 ini_config->mdns_resp_type_ptr, '.'))
16483 return TRUE;
16484
16485 /*
16486 * For data compression
16487 * Check if any strings are matched with Type A response
16488 */
16489 num_matched = 0;
16490 num_matched1 = 0;
16491 if (resptype_a && (resptype_a->num_entries > 0)) {
16492 num_matched = wlan_hdd_mdns_find_entries_from_end(resptype_ptr,
16493 resptype_a);
16494 }
16495 if (resptype_txt && (resptype_txt->num_entries > 0)) {
16496 num_matched1 = wlan_hdd_mdns_find_entries_from_end(
16497 resptype_ptr, resptype_txt);
16498 }
16499 if ((num_matched != num_matched1) ||
16500 ((num_matched > 0) && (num_matched1 > 0))) {
16501 if (num_matched >= num_matched1) {
16502 if (!wlan_hdd_mdns_compress_data(resp_info,
16503 resptype_ptr, resptype_a, num_matched)) {
16504 hddLog(LOGE, FL("Fail to compress mDNS "
16505 "response (%d)!"), MDNS_TYPE_PTR);
16506 return FALSE;
16507 }
16508 } else {
16509 /* num_matched is less than num_matched1 */
16510 if (!wlan_hdd_mdns_compress_data(resp_info,
16511 resptype_ptr, resptype_txt, num_matched1)) {
16512 hddLog(LOGE, FL("Fail to compress mDNS "
16513 "response (%d)!"), MDNS_TYPE_PTR);
16514 return FALSE;
16515 }
16516 }
16517 } else {
16518 /*
16519 * Both num_matched and num_matched1 are zero.
16520 * no TypeA & TypeTxt
16521 */
16522 if (!wlan_hdd_mdns_process_response_dname(resptype_ptr,
16523 resp_info)) {
16524 hddLog(LOGE, FL("Fail to process mDNS response (%d)!"),
16525 MDNS_TYPE_PTR);
16526 return FALSE;
16527 }
16528 }
16529
16530 /* Process response Type, Class, TTL */
16531 if (!wlan_hdd_mdns_process_response_misc(MDNS_TYPE_PTR, resp_info)) {
16532 hddLog(LOGE, FL("Fail to process mDNS misc response (%d)!"),
16533 MDNS_TYPE_PTR);
16534 return FALSE;
16535 }
16536
16537 /*
16538 * Process response RDLength, RData (Ptr domain name)
16539 * Save the offset of RData length
16540 */
16541 offset_data_len = resp_info->resp_len;
16542 resp_info->resp_len += sizeof(uint16_t);
16543
16544 if (!wlan_hdd_mdns_pack_response_type_ptr_dname(ini_config, resp_info,
16545 resptype_ptr_dn, resptype_ptr,
16546 resptype_txt, resptype_a)) {
16547 return FALSE;
16548 }
16549 /* Set the RData length */
16550 len = offset_data_len + sizeof(uint16_t);
16551 if ((resptype_ptr_dn->num_entries > 0) &&
16552 (resp_info->resp_len > len)) {
16553 value = resp_info->resp_len - len;
16554 val_u8 = (value & 0xff00) >> 8;
16555 resp_info->resp_data[offset_data_len] = val_u8;
16556 val_u8 = value & 0xff;
16557 resp_info->resp_data[offset_data_len+1] = val_u8;
16558 } else {
16559 hddLog(LOGE, FL("Fail to process mDNS response (%d)!"),
16560 MDNS_TYPE_PTR);
16561 return FALSE;
16562 }
16563
16564 EXIT();
16565 return TRUE;
16566}
16567
16568/**
16569 * wlan_hdd_mdns_pack_response_type_srv_target()- Pack Type Service Target
16570 * @ini_config: Pointer to the struct hdd_config_t
16571 * @resp_info: Pointer to the struct tSirMDNSResponseInfo
16572 * @resptype_srv_tgt: Pointer to the struct hdd_mdns_resp_info of Type Srv
16573 * target
16574 * @resptype_srv: Pointer to the struct hdd_mdns_resp_info of Type Srv
16575 * @resptype_ptr: Pointer to the struct hdd_mdns_resp_info of Type Ptr
16576 * @resptype_ptr_dn: Pointer to the struct hdd_mdns_resp_info of Type Ptr
16577 * domain name
16578 * @resptype_txt: Pointer to the struct hdd_mdns_resp_info of Type Txt
16579 * @resptype_a: Pointer to the struct hdd_mdns_resp_info of Type A
16580 *
16581 * The Type service target is one of the data field in the Type SRV response.
16582 * Also, it will find the matched QName from the existing resptype_srv,
16583 * resptype_ptr, resptype_ptr_dn, resptype_txt, resptype_a and then compress
16584 * the data.
16585 *
16586 * Return: Return boolean. TRUE for success, FALSE for fail.
16587 */
16588static bool
16589wlan_hdd_mdns_pack_response_type_srv_target(hdd_config_t *ini_config,
16590 sir_mdns_resp_info resp_info,
16591 struct hdd_mdns_resp_info *resptype_srv_tgt,
16592 struct hdd_mdns_resp_info *resptype_srv,
16593 struct hdd_mdns_resp_info *resptype_ptr,
16594 struct hdd_mdns_resp_info *resptype_ptr_dn,
16595 struct hdd_mdns_resp_info *resptype_txt,
16596 struct hdd_mdns_resp_info *resptype_a)
16597{
16598 uint8_t num_matched, num, size;
16599 struct hdd_mdns_resp_matched matchedlist[MAX_MDNS_RESP_TYPE-1];
16600 struct hdd_mdns_resp_info *resp;
16601
16602 if ((ini_config == NULL) || (resp_info == NULL) ||
16603 (resptype_srv == NULL) || (resptype_srv_tgt == NULL)) {
16604 hddLog(LOGE, FL("ini_config or response info is NULL!"));
16605 return FALSE;
16606 }
16607
16608 /* No Type Srv Target response */
16609 if (strlen((char *)ini_config->mdns_resp_type_srv_target) <= 0)
16610 return TRUE;
16611
16612 /* Wrong response is assigned, just ignore this response */
16613 if (!wlan_hdd_mdns_init_response(resptype_srv_tgt,
16614 ini_config->mdns_resp_type_srv_target, '.'))
16615 return TRUE;
16616
16617 /*
16618 * For data compression
16619 * Check if any strings are matched with previous response.
16620 */
16621 num = 0;
16622 size = (MAX_MDNS_RESP_TYPE-1);
16623 size *= sizeof(struct hdd_mdns_resp_matched);
16624 vos_mem_zero(matchedlist, size);
16625 num_matched = wlan_hdd_mdns_find_entries_from_end(resptype_srv_tgt,
16626 resptype_srv);
16627 if (num_matched > 0) {
16628 matchedlist[num].num_matched = num_matched;
16629 matchedlist[num].type = MDNS_TYPE_SRV;
16630 num++;
16631 }
16632 if (resptype_ptr && (resptype_ptr->num_entries > 0)) {
16633 if (resptype_ptr_dn && (resptype_ptr_dn->num_entries > 0)) {
16634 num_matched = wlan_hdd_mdns_find_entries_from_end(
16635 resptype_srv_tgt, resptype_ptr_dn);
16636 if (num_matched > 0) {
16637 matchedlist[num].num_matched = num_matched;
16638 matchedlist[num].type = MDNS_TYPE_PTR_DNAME;
16639 num++;
16640 }
16641 }
16642 num_matched = wlan_hdd_mdns_find_entries_from_end(
16643 resptype_srv_tgt, resptype_ptr);
16644 if (num_matched > 0) {
16645 matchedlist[num].num_matched = num_matched;
16646 matchedlist[num].type = MDNS_TYPE_PTR;
16647 num++;
16648 }
16649 }
16650 if (resptype_txt && (resptype_txt->num_entries > 0)) {
16651 num_matched = wlan_hdd_mdns_find_entries_from_end(
16652 resptype_srv_tgt, resptype_txt);
16653 if (num_matched > 0) {
16654 matchedlist[num].num_matched = num_matched;
16655 matchedlist[num].type = MDNS_TYPE_TXT;
16656 num++;
16657 }
16658 }
16659 if (resptype_a && (resptype_a->num_entries > 0)) {
16660 num_matched = wlan_hdd_mdns_find_entries_from_end(
16661 resptype_srv_tgt, resptype_a);
16662 if (num_matched > 0) {
16663 matchedlist[num].num_matched = num_matched;
16664 matchedlist[num].type = MDNS_TYPE_A;
16665 num++;
16666 }
16667 }
16668 if (num > 0) {
16669 if (num > 1)
16670 wlan_hdd_mdns_find_max(matchedlist, num);
16671 resp = NULL;
16672 switch (matchedlist[num-1].type) {
16673 case MDNS_TYPE_A:
16674 resp = resptype_a;
16675 break;
16676 case MDNS_TYPE_TXT:
16677 resp = resptype_txt;
16678 break;
16679 case MDNS_TYPE_PTR:
16680 resp = resptype_ptr;
16681 break;
16682 case MDNS_TYPE_PTR_DNAME:
16683 resp = resptype_ptr_dn;
16684 break;
16685 case MDNS_TYPE_SRV:
16686 resp = resptype_srv;
16687 break;
16688 default:
16689 hddLog(LOGE, FL("Fail to compress mDNS response "
16690 "(%d)!"), MDNS_TYPE_SRV_TARGET);
16691 return FALSE;
16692 }
16693 num_matched = matchedlist[num-1].num_matched;
16694 if (!wlan_hdd_mdns_compress_data(resp_info, resptype_srv_tgt,
16695 resp, num_matched)) {
16696 hddLog(LOGE, FL("Fail to compress mDNS response "
16697 "(%d)!"), MDNS_TYPE_SRV_TARGET);
16698 return FALSE;
16699 }
16700 } else {
16701 /* num = 0 -> no matched string */
16702 if (!wlan_hdd_mdns_process_response_dname(resptype_srv_tgt,
16703 resp_info)) {
16704 hddLog(LOGE, FL("Fail to process mDNS response (%d)!"),
16705 MDNS_TYPE_SRV_TARGET);
16706 return FALSE;
16707 }
16708 }
16709
16710 return TRUE;
16711}
16712
16713/**
16714 * wlan_hdd_mdns_pack_response_type_srv()- Pack Type Service response
16715 * @ini_config: Pointer to the struct hdd_config_t
16716 * @resp_info: Pointer to the struct tSirMDNSResponseInfo
16717 * @resptype_srv: Pointer to the struct hdd_mdns_resp_info of Type Srv
16718 * @resptype_srv_tgt: Pointer to the struct hdd_mdns_resp_info of Type Srv
16719 * target
16720 * @resptype_ptr: Pointer to the struct hdd_mdns_resp_info of Type Ptr
16721 * @resptype_ptr_dn: Pointer to the struct hdd_mdns_resp_info of Type Ptr
16722 * domain name
16723 * @resptype_txt: Pointer to the struct hdd_mdns_resp_info of Type Txt
16724 * @resptype_a: Pointer to the struct hdd_mdns_resp_info of Type A
16725 *
16726 * The Type SRV (Service) response include QName, response type, class, TTL
16727 * and four kinds of data fields. Also, it will find the matched QName from
16728 * the existing resptype_ptr, resptype_ptr_dn, resptype_txt, resptype_a and
16729 * then compress the data.
16730 *
16731 * Return: Return boolean. TRUE for success, FALSE for fail.
16732 */
16733static bool
16734wlan_hdd_mdns_pack_response_type_srv(hdd_config_t *ini_config,
16735 sir_mdns_resp_info resp_info,
16736 struct hdd_mdns_resp_info *resptype_srv,
16737 struct hdd_mdns_resp_info *resptype_srv_tgt,
16738 struct hdd_mdns_resp_info *resptype_ptr,
16739 struct hdd_mdns_resp_info *resptype_ptr_dn,
16740 struct hdd_mdns_resp_info *resptype_txt,
16741 struct hdd_mdns_resp_info *resptype_a)
16742{
16743 uint8_t num_matched, num, size;
16744 uint16_t value;
16745 uint8_t val_u8;
16746 uint32_t offset_data_len, len;
16747 struct hdd_mdns_resp_info *resp;
16748 struct hdd_mdns_resp_matched matchedlist[MAX_MDNS_RESP_TYPE-1];
16749
16750 ENTER();
16751
16752 if ((ini_config == NULL) || (resp_info == NULL) ||
16753 (resptype_srv == NULL) || (resptype_srv_tgt == NULL)) {
16754 hddLog(LOGE, FL("ini_config or response info is NULL!"));
16755 return FALSE;
16756 }
16757
16758 /* No Type Srv response */
16759 if (strlen((char *)ini_config->mdns_resp_type_srv) <= 0)
16760 return TRUE;
16761
16762 /* Wrong response is assigned, just ignore this response */
16763 if (!wlan_hdd_mdns_init_response(resptype_srv,
16764 ini_config->mdns_resp_type_srv, '.'))
16765 return TRUE;
16766
16767 /*
16768 * For data compression
16769 * Check if any strings are matched with Type A response
16770 */
16771 num = 0;
16772 size = (MAX_MDNS_RESP_TYPE-1);
16773 size *= sizeof(struct hdd_mdns_resp_matched);
16774 vos_mem_zero(matchedlist, size);
16775 if (resptype_ptr && (resptype_ptr->num_entries > 0)) {
16776 if (resptype_ptr_dn && (resptype_ptr_dn->num_entries > 0)) {
16777 num_matched = wlan_hdd_mdns_find_entries_from_end(
16778 resptype_srv,
16779 resptype_ptr_dn);
16780 if (num_matched > 0) {
16781 matchedlist[num].num_matched = num_matched;
16782 matchedlist[num].type = MDNS_TYPE_PTR_DNAME;
16783 num++;
16784 }
16785 }
16786 num_matched = wlan_hdd_mdns_find_entries_from_end(resptype_srv,
16787 resptype_ptr);
16788 if (num_matched > 0) {
16789 matchedlist[num].num_matched = num_matched;
16790 matchedlist[num].type = MDNS_TYPE_PTR;
16791 num++;
16792 }
16793 }
16794 if (resptype_txt && (resptype_txt->num_entries > 0)) {
16795 num_matched = wlan_hdd_mdns_find_entries_from_end(resptype_srv,
16796 resptype_txt);
16797 if (num_matched > 0) {
16798 matchedlist[num].num_matched =num_matched;
16799 matchedlist[num].type = MDNS_TYPE_TXT;
16800 num++;
16801 }
16802 }
16803 if (resptype_a && (resptype_a->num_entries > 0)) {
16804 num_matched = wlan_hdd_mdns_find_entries_from_end(resptype_srv,
16805 resptype_a);
16806 if (num_matched > 0) {
16807 matchedlist[num].num_matched = num_matched;
16808 matchedlist[num].type = MDNS_TYPE_A;
16809 num++;
16810 }
16811 }
16812 if (num > 0) {
16813 if (num > 1)
16814 wlan_hdd_mdns_find_max(matchedlist, num);
16815 resp = NULL;
16816 switch (matchedlist[num-1].type) {
16817 case MDNS_TYPE_A:
16818 resp = resptype_a;
16819 break;
16820 case MDNS_TYPE_TXT:
16821 resp = resptype_txt;
16822 break;
16823 case MDNS_TYPE_PTR:
16824 resp = resptype_ptr;
16825 break;
16826 case MDNS_TYPE_PTR_DNAME:
16827 resp = resptype_ptr_dn;
16828 break;
16829 default:
16830 hddLog(LOGE, FL("Fail to compress mDNS response "
16831 "(%d)!"), MDNS_TYPE_SRV);
16832 return FALSE;
16833 }
16834 num_matched = matchedlist[num-1].num_matched;
16835 if (!wlan_hdd_mdns_compress_data(resp_info, resptype_srv,
16836 resp, num_matched)) {
16837 hddLog(LOGE, FL("Fail to compress mDNS response "
16838 "(%d)!"), MDNS_TYPE_SRV);
16839 return FALSE;
16840 }
16841 } else {
16842 /* num = 0 -> no matched string */
16843 if (!wlan_hdd_mdns_process_response_dname(resptype_srv,
16844 resp_info)) {
16845 hddLog(LOGE, FL("Fail to process mDNS response (%d)!"),
16846 MDNS_TYPE_SRV);
16847 return FALSE;
16848 }
16849 }
16850
16851 /* Process response Type, Class, TTL */
16852 if (!wlan_hdd_mdns_process_response_misc(MDNS_TYPE_SRV, resp_info)) {
16853 hddLog(LOGE, FL("Fail to process mDNS misc response (%d)!"),
16854 MDNS_TYPE_SRV);
16855 return FALSE;
16856 }
16857
16858 /*
16859 * Process response RDLength, RData (Srv target name)
16860 * Save the offset of RData length
16861 */
16862 offset_data_len = resp_info->resp_len;
16863 resp_info->resp_len += sizeof(uint16_t);
16864
16865 len = resp_info->resp_len + (3 * sizeof(uint16_t));
16866 if (len >= MAX_MDNS_RESP_LEN) {
16867 hddLog(LOGE, FL("resp_len exceeds %d!"), MAX_MDNS_RESP_LEN);
16868 return FALSE;
16869 }
16870
16871 /* set Srv Priority */
16872 value = ini_config->mdns_resp_type_srv_priority;
16873 wlan_hdd_mdns_format_response_u16(value, resp_info);
16874 /* set Srv Weight */
16875 value = ini_config->mdns_resp_type_srv_weight;
16876 wlan_hdd_mdns_format_response_u16(value, resp_info);
16877 /* set Srv Port */
16878 value = ini_config->mdns_resp_type_srv_port;
16879 wlan_hdd_mdns_format_response_u16(value, resp_info);
16880
16881 if (!wlan_hdd_mdns_pack_response_type_srv_target(ini_config, resp_info,
16882 resptype_srv_tgt, resptype_srv,
16883 resptype_ptr, resptype_ptr_dn,
16884 resptype_txt, resptype_a)) {
16885 return FALSE;
16886 }
16887 /* Set the RData length */
16888 len = offset_data_len + sizeof(uint16_t);
16889 if ((resptype_srv_tgt->num_entries > 0) &&
16890 (resp_info->resp_len > len)) {
16891 value = resp_info->resp_len - len;
16892 val_u8 = (value & 0xff00) >> 8;
16893 resp_info->resp_data[offset_data_len] = val_u8;
16894 val_u8 = value & 0xff;
16895 resp_info->resp_data[offset_data_len+1] = val_u8;
16896 } else {
16897 hddLog(LOGE, FL("Fail to process mDNS response (%d)!"),
16898 MDNS_TYPE_SRV);
16899 return FALSE;
16900 }
16901
16902 EXIT();
16903 return TRUE;
16904}
16905
16906/**
16907 * wlan_hdd_mdns_free_mem() - Free the allocated memory
16908 * @response: Pointer to the struct hdd_mdns_resp_info
16909 *
16910 * Return: None
16911 */
16912static void wlan_hdd_mdns_free_mem(struct hdd_mdns_resp_info *response)
16913{
16914 if (response && response->data)
16915 vos_mem_free(response->data);
16916 if (response && response->offset)
16917 vos_mem_free(response->offset);
16918}
16919
16920/**
16921 * wlan_hdd_mdns_pack_response() - Pack mDNS response
16922 * @ini_config: Pointer to the struct hdd_config_t
16923 * @resp_info: Pointer to the struct tSirMDNSResponseInfo
16924 *
16925 * This function will pack four types of responses (Type A, Type Txt, Type Ptr
16926 * and Type Service). Each response contains QName, response type, class, TTL
16927 * and data fields.
16928 *
16929 * Return: Return boolean. TRUE for success, FALSE for fail.
16930 */
16931static bool wlan_hdd_mdns_pack_response(hdd_config_t *ini_config,
16932 sir_mdns_resp_info resp_info)
16933{
16934 struct hdd_mdns_resp_info resptype_a, resptype_txt;
16935 struct hdd_mdns_resp_info resptype_ptr, resptype_ptr_dn;
16936 struct hdd_mdns_resp_info resptype_srv, resptype_srv_tgt;
16937 uint32_t num_res_records = 0;
16938 bool status = FALSE;
16939
16940 ENTER();
16941
16942 wlan_hdd_mdns_reset_response(&resptype_a);
16943 wlan_hdd_mdns_reset_response(&resptype_txt);
16944 wlan_hdd_mdns_reset_response(&resptype_ptr);
16945 wlan_hdd_mdns_reset_response(&resptype_ptr_dn);
16946 wlan_hdd_mdns_reset_response(&resptype_srv);
16947 wlan_hdd_mdns_reset_response(&resptype_srv_tgt);
16948
16949 resp_info->resp_len = 0;
16950
16951 /* Process Type A response */
16952 if (!wlan_hdd_mdns_pack_response_type_a(ini_config, resp_info,
16953 &resptype_a))
16954 goto err_resptype_a;
16955
16956 if ((resptype_a.num_entries > 0) &&
16957 (strlen((char *)&resptype_a.data[0]) > 0))
16958 num_res_records++;
16959
16960 /* Process Type TXT response */
16961 if (!wlan_hdd_mdns_pack_response_type_txt(ini_config, resp_info,
16962 &resptype_txt, &resptype_a))
16963 goto err_resptype_txt;
16964
16965 if ((resptype_txt.num_entries > 0) &&
16966 (strlen((char *)&resptype_txt.data[0]) > 0))
16967 num_res_records++;
16968
16969 /* Process Type PTR response */
16970 if (!wlan_hdd_mdns_pack_response_type_ptr(ini_config, resp_info,
16971 &resptype_ptr, &resptype_ptr_dn,
16972 &resptype_txt, &resptype_a))
16973 goto err_resptype_ptr;
16974
16975 if ((resptype_ptr.num_entries > 0) &&
16976 (strlen((char *)&resptype_ptr.data[0]) > 0))
16977 num_res_records++;
16978
16979 /* Process Type SRV response */
16980 if (!wlan_hdd_mdns_pack_response_type_srv(ini_config, resp_info,
16981 &resptype_srv, &resptype_srv_tgt,
16982 &resptype_ptr, &resptype_ptr_dn,
16983 &resptype_txt, &resptype_a))
16984 goto err_resptype_srv;
16985
16986 if ((resptype_srv.num_entries > 0) &&
16987 (strlen((char *)&resptype_srv.data[0]) > 0))
16988 num_res_records++;
16989
16990 resp_info->resourceRecord_count = num_res_records;
16991 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
16992 "%s: Pack mDNS response data successfully!", __func__);
16993 status = TRUE;
16994
16995err_resptype_srv:
16996 wlan_hdd_mdns_free_mem(&resptype_srv);
16997 wlan_hdd_mdns_free_mem(&resptype_srv_tgt);
16998
16999err_resptype_ptr:
17000 wlan_hdd_mdns_free_mem(&resptype_ptr);
17001 wlan_hdd_mdns_free_mem(&resptype_ptr_dn);
17002
17003err_resptype_txt:
17004 wlan_hdd_mdns_free_mem(&resptype_txt);
17005
17006err_resptype_a:
17007 wlan_hdd_mdns_free_mem(&resptype_a);
17008
17009 EXIT();
17010 return status;
17011}
17012
17013/**
17014 * wlan_hdd_set_mdns_offload() - Enable mDNS offload
17015 * @hostapd_adapter: Pointer to the struct hdd_adapter_t
17016 *
17017 * This function will set FQDN/unique FQDN (full qualified domain name)
17018 * and the mDNS response. Then send them to SME.
17019 *
17020 * Return: Return boolean. TRUE for success, FALSE for fail.
17021 */
17022bool wlan_hdd_set_mdns_offload(hdd_adapter_t *hostapd_adapter)
17023{
17024 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(hostapd_adapter);
17025 sir_mdns_offload_info mdns_offload_info;
17026 sir_mdns_fqdn_info mdns_fqdn_info;
17027 sir_mdns_resp_info mdns_resp_info;
17028 uint32_t fqdn_len, ufqdn_len;
17029
17030 ENTER();
17031
17032 /* 1. Prepare the MDNS fqdn request to send to SME */
17033 fqdn_len = strlen(hdd_ctx->cfg_ini->mdns_fqdn);
17034 ufqdn_len = strlen(hdd_ctx->cfg_ini->mdns_uniquefqdn);
17035 if ((fqdn_len == 0) && (ufqdn_len == 0)) {
17036 hddLog(LOGE, FL("No mDNS FQDN or UFQDN is assigned fqdn_len %d,"
17037 "ufqdn_len %d!"), fqdn_len, ufqdn_len);
17038 return FALSE;
17039 }
17040
17041 mdns_fqdn_info = vos_mem_malloc(sizeof(*mdns_fqdn_info));
17042 if (NULL == mdns_fqdn_info) {
17043 hddLog(LOGE, FL("could not allocate tSirMDNSFqdnInfo!"));
17044 return FALSE;
17045 }
17046 /* MDNS fqdn request */
17047 if (fqdn_len > 0) {
17048 vos_mem_zero(mdns_fqdn_info, sizeof(*mdns_fqdn_info));
17049 mdns_fqdn_info->bss_idx = hostapd_adapter->sessionId;
17050 mdns_fqdn_info->fqdn_type = MDNS_FQDN_TYPE_GENERAL;
17051 mdns_fqdn_info->fqdn_len = fqdn_len;
17052 mdns_fqdn_info->mdns_fqdn_callback = hdd_mdns_fqdn_offload_done;
17053 mdns_fqdn_info->mdns_fqdn_cb_context = hostapd_adapter;
17054 vos_mem_copy(mdns_fqdn_info->fqdn_data,
17055 hdd_ctx->cfg_ini->mdns_fqdn,
17056 mdns_fqdn_info->fqdn_len);
17057
17058 if (eHAL_STATUS_SUCCESS !=
17059 sme_set_mdns_fqdn(hdd_ctx->hHal, mdns_fqdn_info)) {
17060 hddLog(LOGE, FL("sme_set_mdns_fqdn fail!"));
17061 vos_mem_free(mdns_fqdn_info);
17062 return FALSE;
17063 }
17064 }
17065 /* MDNS unique fqdn request */
17066 if (ufqdn_len > 0) {
17067 vos_mem_zero(mdns_fqdn_info, sizeof(*mdns_fqdn_info));
17068 mdns_fqdn_info->bss_idx = hostapd_adapter->sessionId;
17069 mdns_fqdn_info->fqdn_type = MDNS_FQDN_TYPE_UNIQUE;
17070 mdns_fqdn_info->fqdn_len = ufqdn_len;
17071 mdns_fqdn_info->mdns_fqdn_callback = hdd_mdns_fqdn_offload_done;
17072 mdns_fqdn_info->mdns_fqdn_cb_context = hostapd_adapter;
17073 vos_mem_copy(mdns_fqdn_info->fqdn_data,
17074 hdd_ctx->cfg_ini->mdns_uniquefqdn,
17075 mdns_fqdn_info->fqdn_len);
17076 if (eHAL_STATUS_SUCCESS !=
17077 sme_set_mdns_fqdn(hdd_ctx->hHal, mdns_fqdn_info)) {
17078 hddLog(LOGE, FL("sme_set_mdns_fqdn fail!"));
17079 vos_mem_free(mdns_fqdn_info);
17080 return FALSE;
17081 }
17082 }
17083 vos_mem_free(mdns_fqdn_info);
17084
17085 /* 2. Prepare the MDNS response request to send to SME */
17086 mdns_resp_info = vos_mem_malloc(sizeof(*mdns_resp_info));
17087 if (NULL == mdns_resp_info) {
17088 hddLog(LOGE, FL("could not allocate tSirMDNSResponseInfo!"));
17089 return FALSE;
17090 }
17091
17092 vos_mem_zero(mdns_resp_info, sizeof(*mdns_resp_info));
17093 mdns_resp_info->bss_idx = hostapd_adapter->sessionId;
17094 mdns_resp_info->mdns_resp_callback = hdd_mdns_resp_offload_done;
17095 mdns_resp_info->mdns_resp_cb_context = hostapd_adapter;
17096 if (!wlan_hdd_mdns_pack_response(hdd_ctx->cfg_ini, mdns_resp_info)) {
17097 hddLog(LOGE, FL("wlan_hdd_pack_mdns_response fail!"));
17098 vos_mem_free(mdns_resp_info);
17099 return FALSE;
17100 }
17101 if (eHAL_STATUS_SUCCESS !=
17102 sme_set_mdns_resp(hdd_ctx->hHal, mdns_resp_info)) {
17103 hddLog(LOGE, FL("sme_set_mdns_resp fail!"));
17104 vos_mem_free(mdns_resp_info);
17105 return FALSE;
17106 }
17107 vos_mem_free(mdns_resp_info);
17108
17109 /* 3. Prepare the MDNS Enable request to send to SME */
17110 mdns_offload_info = vos_mem_malloc(sizeof(*mdns_offload_info));
17111 if (NULL == mdns_offload_info) {
17112 hddLog(LOGE, FL("could not allocate tSirMDNSOffloadInfo!"));
17113 return FALSE;
17114 }
17115
17116 vos_mem_zero(mdns_offload_info, sizeof(*mdns_offload_info));
17117
17118 mdns_offload_info->bss_idx = hostapd_adapter->sessionId;
17119 mdns_offload_info->enable = hdd_ctx->cfg_ini->enable_mdns_offload;
17120 mdns_offload_info->mdns_enable_callback = hdd_mdns_enable_offload_done;
17121 mdns_offload_info->mdns_enable_cb_context = hostapd_adapter;
17122 if (eHAL_STATUS_SUCCESS !=
17123 sme_set_mdns_offload(hdd_ctx->hHal, mdns_offload_info)) {
17124 hddLog(LOGE, FL("sme_set_mdns_offload fail!"));
17125 vos_mem_free(mdns_offload_info);
17126 return FALSE;
17127 }
17128
17129 vos_mem_free(mdns_offload_info);
17130 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
17131 "%s: enable mDNS offload successfully!", __func__);
17132 return TRUE;
17133}
Manjeet Singh3ed79242017-01-11 19:04:32 +053017134
17135
Anurag Chouhan0b29de02016-12-16 13:18:40 +053017136#endif /* MDNS_OFFLOAD */
c_manjeecfd1efb2015-09-25 19:32:34 +053017137
Hanumanth Reddy Pothulad864f312017-01-18 16:16:08 +053017138/**
17139 * wlan_hdd_start_sap() - This function starts bss of SAP.
17140 * @ap_adapter: SAP adapter
17141 *
17142 * This function will process the starting of sap adapter.
17143 *
17144 * Return: void.
17145 */
17146void wlan_hdd_start_sap(hdd_adapter_t *ap_adapter)
17147{
17148 hdd_ap_ctx_t *hdd_ap_ctx;
17149 hdd_hostapd_state_t *hostapd_state;
17150 VOS_STATUS vos_status;
17151 hdd_context_t *hdd_ctx;
17152 tsap_Config_t *pConfig;
17153
17154 if (NULL == ap_adapter) {
17155 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
17156 FL("ap_adapter is NULL here"));
17157 return;
17158 }
17159
17160 hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter);
17161 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
17162 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
17163 pConfig = &ap_adapter->sessionCtx.ap.sapConfig;
17164
17165 mutex_lock(&hdd_ctx->sap_lock);
17166 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags))
17167 goto end;
17168
17169 if (0 != wlan_hdd_cfg80211_update_apies(ap_adapter)) {
17170 hddLog(LOGE, FL("SAP Not able to set AP IEs"));
17171 goto end;
17172 }
17173
17174 vos_event_reset(&hostapd_state->vosEvent);
17175 if (WLANSAP_StartBss(hdd_ctx->pvosContext, hdd_hostapd_SAPEventCB,
17176 &hdd_ap_ctx->sapConfig, (v_PVOID_t)ap_adapter->dev)
17177 != VOS_STATUS_SUCCESS) {
17178 goto end;
17179 }
17180
17181 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
17182 FL("Waiting for SAP to start"));
17183 vos_status = vos_wait_single_event(&hostapd_state->vosEvent, 10000);
17184 if (!VOS_IS_STATUS_SUCCESS(vos_status)) {
17185 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
17186 FL("SAP Start failed"));
17187 goto end;
17188 }
17189 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
17190 FL("SAP Start Success"));
17191 set_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
17192
17193 wlan_hdd_incr_active_session(hdd_ctx, ap_adapter->device_mode);
17194 hostapd_state->bCommit = TRUE;
17195
17196end:
17197 mutex_unlock(&hdd_ctx->sap_lock);
17198 return;
17199}
17200
Manjeet Singh3ed79242017-01-11 19:04:32 +053017201#ifdef WLAN_FEATURE_TSF
17202
17203/**
17204 * hdd_tsf_cb() - handle tsf request callback
17205 *
17206 * @pcb_cxt: pointer to the hdd_contex
17207 * @ptsf: pointer to struct stsf
17208 *
17209 * Based on the request sent .
17210 *
17211 * Return: Describe the execute result of this routine
17212 */
17213static int hdd_tsf_cb(void *pcb_ctx, struct stsf *ptsf)
17214{
17215 hdd_context_t *hddctx;
17216 int status;
17217 hdd_adapter_t* adapter = (hdd_adapter_t*)pcb_ctx;
17218
17219 if (pcb_ctx == NULL || ptsf == NULL) {
17220 hddLog(VOS_TRACE_LEVEL_ERROR,
17221 FL("HDD context is not valid"));
17222 return -EINVAL;
17223 }
17224
17225 hddctx = (hdd_context_t *)pcb_ctx;
17226 status = wlan_hdd_validate_context(hddctx);
17227 if (0 != status)
17228 return -EINVAL;
17229
17230 if (NULL == adapter) {
17231 hddLog(VOS_TRACE_LEVEL_ERROR,
17232 FL("failed to find adapter"));
17233 return -EINVAL;
17234 }
17235
17236 hddLog(VOS_TRACE_LEVEL_INFO,
17237 FL("tsf cb handle event, device_mode is %d"),
17238 adapter->device_mode);
17239
17240 /* copy the return value to hdd_tsf_ctx in adapter*/
17241 if (ptsf->tsf_req_status) {
17242
17243 vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
17244 adapter->tsf_cap_ctx.tsf_get_state = TSF_NOT_RETURNED_BY_FW;
17245 adapter->tsf_cap_ctx.tsf_capture_state = TSF_IDLE;
17246 vos_event_set (&adapter->tsf_cap_ctx.tsf_capture_done_event);
17247 vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
17248
17249 hddLog(VOS_TRACE_LEVEL_ERROR, FL("tsf req failure :%d"),
17250 ptsf->tsf_req_status);
17251 return ptsf->tsf_req_status;
17252 }
17253 /* If this is a get request.Store the tsf values in adapter. */
17254 if (!ptsf->set_tsf_req) {
17255 vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
17256 adapter->tsf_cap_ctx.tsf_low = ptsf->tsf_low;
17257 adapter->tsf_cap_ctx.tsf_high = ptsf->tsf_high;
17258 adapter->tsf_cap_ctx.tsf_get_state = TSF_RETURN;
17259 adapter->tsf_cap_ctx.tsf_capture_state = TSF_IDLE;
17260 vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
17261
17262 hddLog(VOS_TRACE_LEVEL_INFO,
17263 FL("hdd_get_tsf_cb sta=%u, tsf_low=%u, tsf_high=%u"),
17264 adapter->sessionId, ptsf->tsf_low, ptsf->tsf_high);
17265 }
17266 else {
17267 vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
17268 adapter->tsf_cap_ctx.tsf_capture_state = TSF_CAP_STATE;
17269 adapter->tsf_cap_ctx.tsf_get_state = TSF_CURRENT_IN_CAP_STATE;
17270 vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
17271 }
17272 vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
17273 vos_event_set (&adapter->tsf_cap_ctx.tsf_capture_done_event);
17274 vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
17275
17276 /* free allocated mem */
17277 vos_mem_free(ptsf);
17278
17279 return 0;
17280}
17281
17282/**
17283 * hdd_capture_tsf() - capture tsf
17284 *
17285 * @adapter: pointer to adapter
17286 * @buf: pointer to upper layer buf
17287 * @len : the length of buf
17288 *
17289 * This function returns tsf value to uplayer.
17290 *
17291 * Return: Describe the execute result of this routine
17292 */
17293int hdd_capture_tsf(hdd_adapter_t *adapter, uint32_t *buf, int len)
17294{
17295 int ret = 0;
17296 hdd_station_ctx_t *hdd_sta_ctx;
17297 hdd_context_t *hdd_ctx;
17298 tSirCapTsfParams cap_tsf_params;
17299 VOS_STATUS status;
17300
17301 if (adapter == NULL || buf == NULL) {
17302 hddLog(VOS_TRACE_LEVEL_ERROR,
17303 FL("invalid pointer"));
17304 return -EINVAL;
17305 }
17306 if (len != 1)
17307 return -EINVAL;
17308
17309 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
17310
17311 if (wlan_hdd_validate_context(hdd_ctx)) {
17312 hddLog(VOS_TRACE_LEVEL_ERROR,
17313 FL("invalid hdd ctx"));
17314 return -EINVAL;
17315 }
17316 if (adapter->device_mode == WLAN_HDD_INFRA_STATION ||
17317 adapter->device_mode == WLAN_HDD_P2P_CLIENT) {
17318 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
17319 if (hdd_sta_ctx->conn_info.connState !=
17320 eConnectionState_Associated) {
17321
17322 hddLog(VOS_TRACE_LEVEL_INFO,
17323 FL("failed to cap tsf, not connect with ap"));
17324 buf[0] = TSF_STA_NOT_CONNECTED_NO_TSF;
17325 return ret;
17326 }
17327 }
17328 if ((adapter->device_mode == WLAN_HDD_SOFTAP ||
17329 adapter->device_mode == WLAN_HDD_P2P_GO) &&
17330 !(test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags))) {
17331 hddLog(VOS_TRACE_LEVEL_INFO,
17332 FL("Soft AP / P2p GO not beaconing"));
17333 buf[0] = TSF_SAP_NOT_STARTED_NO_TSF;
17334 return ret;
17335 }
17336 if (adapter->tsf_cap_ctx.tsf_capture_state == TSF_CAP_STATE) {
17337 hddLog(VOS_TRACE_LEVEL_INFO,
17338 FL("current in capture state, pls reset"));
17339 buf[0] = TSF_CURRENT_IN_CAP_STATE;
17340 } else {
17341 hddLog(VOS_TRACE_LEVEL_INFO, FL("ioctl issue cap tsf cmd"));
17342 buf[0] = TSF_RETURN;
17343 cap_tsf_params.session_id = adapter->sessionId;
17344 cap_tsf_params.tsf_rsp_cb_func = hdd_tsf_cb;
17345 cap_tsf_params.tsf_rsp_cb_ctx = adapter;
17346
17347 vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
17348 adapter->tsf_cap_ctx.tsf_capture_state = TSF_CAP_STATE;
17349 adapter->tsf_cap_ctx.tsf_get_state = TSF_CURRENT_IN_CAP_STATE;
17350 vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
17351
17352 ret = sme_capture_tsf_req(hdd_ctx->hHal, cap_tsf_params);
17353
17354 if (ret != VOS_STATUS_SUCCESS) {
17355 hddLog(VOS_TRACE_LEVEL_ERROR, FL("capture fail"));
17356 buf[0] = TSF_CAPTURE_FAIL;
17357 vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
17358 adapter->tsf_cap_ctx.tsf_capture_state = TSF_IDLE;
17359 vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
17360 return -EINVAL;
17361 }
17362 /* wait till we get a response from fw */
17363 status = vos_wait_single_event(&adapter->tsf_cap_ctx.
17364 tsf_capture_done_event,
17365 HDD_TSF_CAP_REQ_TIMEOUT);
17366
17367 if (!VOS_IS_STATUS_SUCCESS(status)) {
17368 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
17369 ("capture tsf vos wait for single_event failed!! %d"),
17370 adapter->tsf_cap_ctx.tsf_get_state);
17371
17372 vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
17373 adapter->tsf_cap_ctx.tsf_capture_state = TSF_IDLE;
17374 vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
17375
17376 return -EINVAL;
17377 }
17378 }
17379 buf[0] = TSF_RETURN;
17380 hddLog(VOS_TRACE_LEVEL_INFO,
17381 FL("ioctl return cap tsf cmd, ret = %d"), ret);
17382 return ret;
17383}
17384
17385/**
17386 * hdd_indicate_tsf() - return tsf to uplayer
17387 *
17388 * @adapter: pointer to adapter
17389 * @buf: pointer to uplayer buf
17390 * @len : the length of buf
17391 *
17392 * This function returns tsf value to uplayer.
17393 *
17394 * Return: Describe the execute result of this routine
17395 */
17396int hdd_indicate_tsf(hdd_adapter_t *adapter, uint32_t *buf, int len)
17397{
17398 int ret = 0;
17399 hdd_station_ctx_t *hdd_sta_ctx;
17400 hdd_context_t *hdd_ctx;
17401 tSirCapTsfParams cap_tsf_params;
17402 VOS_STATUS status;
17403
17404 if (adapter == NULL || buf == NULL) {
17405 hddLog(VOS_TRACE_LEVEL_ERROR,
17406 FL("invalid pointer"));
17407 return -EINVAL;
17408 }
17409 if (len != 3)
17410 return -EINVAL;
17411
17412 buf [1] = 0;
17413 buf [2] = 0;
17414 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
17415
17416 if (wlan_hdd_validate_context(hdd_ctx)) {
17417 hddLog(VOS_TRACE_LEVEL_ERROR,
17418 FL("invalid hdd ctx"));
17419 return -EINVAL;
17420 }
17421 if (adapter->device_mode == WLAN_HDD_INFRA_STATION ||
17422 adapter->device_mode == WLAN_HDD_P2P_CLIENT) {
17423 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
17424 if (hdd_sta_ctx->conn_info.connState !=
17425 eConnectionState_Associated) {
17426
17427 hddLog(VOS_TRACE_LEVEL_INFO,
17428 FL("failed to cap tsf, not connect with ap"));
17429 buf[0] = TSF_STA_NOT_CONNECTED_NO_TSF;
17430 return ret;
17431 }
17432 }
17433 if ((adapter->device_mode == WLAN_HDD_SOFTAP ||
17434 adapter->device_mode == WLAN_HDD_P2P_GO) &&
17435 !(test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags))) {
17436 hddLog(VOS_TRACE_LEVEL_INFO,
17437 FL("Soft AP / P2p GO not beaconing"));
17438 buf[0] = TSF_SAP_NOT_STARTED_NO_TSF;
17439 return ret;
17440 }
17441
17442 if (adapter->tsf_cap_ctx.tsf_capture_state != TSF_CAP_STATE ||
17443 adapter->tsf_cap_ctx.tsf_get_state != TSF_CURRENT_IN_CAP_STATE ) {
17444 hddLog(VOS_TRACE_LEVEL_INFO,
17445 FL("Not in capture state,Enter capture state first"));
17446 buf[0] = TSF_GET_FAIL;
17447 } else {
17448 hddLog(VOS_TRACE_LEVEL_INFO, FL("ioctl issue cap tsf cmd"));
17449 cap_tsf_params.session_id = adapter->sessionId;
17450 cap_tsf_params.tsf_rsp_cb_func = hdd_tsf_cb;
17451 cap_tsf_params.tsf_rsp_cb_ctx = adapter;
17452
17453 ret = sme_get_tsf_req(hdd_ctx->hHal, cap_tsf_params);
17454
17455 if (ret != VOS_STATUS_SUCCESS) {
17456 hddLog(VOS_TRACE_LEVEL_ERROR, FL("capture fail"));
17457 buf[0] = TSF_CAPTURE_FAIL;
17458 vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
17459 adapter->tsf_cap_ctx.tsf_capture_state = TSF_IDLE;
17460 vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
17461 return -EINVAL;
17462 }
17463 /* wait till we get a response from fw */
17464 status = vos_wait_single_event(&adapter->tsf_cap_ctx.
17465 tsf_capture_done_event,
17466 HDD_TSF_GET_REQ_TIMEOUT);
17467
17468 if (!VOS_IS_STATUS_SUCCESS(status)) {
17469 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
17470 ("capture tsf vos wait for single_event failed!! %d"),
17471 status);
17472
17473 vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
17474 adapter->tsf_cap_ctx.tsf_capture_state = TSF_IDLE;
17475 vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
17476 return status;
17477 }
17478 buf[1] = adapter->tsf_cap_ctx.tsf_low;
17479 buf[2] = adapter->tsf_cap_ctx.tsf_high;
17480
17481 hddLog(VOS_TRACE_LEVEL_INFO,
17482 FL("get tsf cmd,status=%u, tsf_low=%u, tsf_high=%u"),
17483 buf[0], buf[1], buf[2]);
17484 }
17485 hddLog(VOS_TRACE_LEVEL_INFO,
17486 FL("ioctl return cap tsf cmd, ret = %d"), ret);
17487 return ret;
17488}
17489
17490void wlan_hdd_tsf_init(hdd_adapter_t *adapter)
17491{
17492
17493 if (adapter == NULL) {
17494 hddLog(VOS_TRACE_LEVEL_ERROR,
17495 FL("TSF init on a null adapter!"));
17496 return;
17497 }
17498
17499 adapter->tsf_cap_ctx.tsf_get_state = TSF_RETURN;
17500 adapter->tsf_cap_ctx.tsf_capture_state = TSF_IDLE;
17501 vos_event_init(&adapter->tsf_cap_ctx.tsf_capture_done_event);
17502 vos_spin_lock_init(&adapter->tsf_cap_ctx.tsf_lock);
17503 adapter->tsf_cap_ctx.tsf_high = 0;
17504 adapter->tsf_cap_ctx.tsf_low = 0;
17505}
17506
17507#endif
17508
Jeff Johnson295189b2012-06-20 16:38:30 -070017509//Register the module init/exit functions
17510module_init(hdd_module_init);
17511module_exit(hdd_module_exit);
17512
17513MODULE_LICENSE("Dual BSD/GPL");
17514MODULE_AUTHOR("Qualcomm Atheros, Inc.");
17515MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
17516
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070017517module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
17518 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -070017519
Jeff Johnson76052702013-04-16 13:55:05 -070017520module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -070017521 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Arif Hussain66559122013-11-21 10:11:40 -080017522
17523module_param(enable_dfs_chan_scan, int,
17524 S_IRUSR | S_IRGRP | S_IROTH);
17525
17526module_param(enable_11d, int,
17527 S_IRUSR | S_IRGRP | S_IROTH);
17528
17529module_param(country_code, charp,
17530 S_IRUSR | S_IRGRP | S_IROTH);