blob: 6dc22da0ec2a36a3e81bf0d4e7248fe7204b7b04 [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Abhishek Singh8a3e4dc2017-01-02 10:39:18 +05302 * Copyright (c) 2012-2017 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,
1743 "%s: pBatchScanRsp is %p pReq %p", __func__, pBatchScanRsp, pReq);
1744 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,
1767 "%s: pScanList is %p", __func__, pScanList);
1768 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,
1794 "%s: pApMetaInfo is %p", __func__, pApMetaInfo);
1795 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 Sirasanagandlaf740b1e2017-08-23 18:07:01 +05303625 ret = hdd_drv_cmd_validate(command, SIZE_OF_SETROAMMODE);
3626 if (ret)
3627 goto exit;
3628
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07003629 /* Move pointer to ahead of SETROAMMODE<delimiter> */
3630 value = value + SIZE_OF_SETROAMMODE + 1;
3631
3632 /* Convert the value from ascii to integer */
3633 ret = kstrtou8(value, SIZE_OF_SETROAMMODE, &roamMode);
3634 if (ret < 0)
3635 {
3636 /* If the input value is greater than max value of datatype, then also
3637 kstrtou8 fails */
3638 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3639 "%s: kstrtou8 failed range [%d - %d]", __func__,
3640 CFG_LFR_FEATURE_ENABLED_MIN,
3641 CFG_LFR_FEATURE_ENABLED_MAX);
3642 ret = -EINVAL;
3643 goto exit;
3644 }
3645 if ((roamMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
3646 (roamMode > CFG_LFR_FEATURE_ENABLED_MAX))
3647 {
3648 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3649 "Roam Mode value %d is out of range"
3650 " (Min: %d Max: %d)", roamMode,
3651 CFG_LFR_FEATURE_ENABLED_MIN,
3652 CFG_LFR_FEATURE_ENABLED_MAX);
3653 ret = -EINVAL;
3654 goto exit;
3655 }
3656
3657 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3658 "%s: Received Command to Set Roam Mode = %d", __func__, roamMode);
3659 /*
3660 * Note that
3661 * SETROAMMODE 0 is to enable LFR while
3662 * SETROAMMODE 1 is to disable LFR, but
3663 * NotifyIsFastRoamIniFeatureEnabled 0/1 is to enable/disable.
3664 * So, we have to invert the value to call sme_UpdateIsFastRoamIniFeatureEnabled.
3665 */
3666 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
3667 roamMode = CFG_LFR_FEATURE_ENABLED_MAX; /* Roam enable */
3668 else
3669 roamMode = CFG_LFR_FEATURE_ENABLED_MIN; /* Roam disable */
3670
3671 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = roamMode;
3672 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), roamMode);
3673 }
3674 /* GETROAMMODE */
Mahesh A Saptasagarec7d1092015-04-02 13:41:34 +05303675 else if (strncmp(command, "GETROAMMODE", SIZE_OF_GETROAMMODE) == 0)
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07003676 {
3677 tANI_BOOLEAN roamMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
3678 char extra[32];
3679 tANI_U8 len = 0;
3680
3681 /*
3682 * roamMode value shall be inverted because the sementics is different.
3683 */
3684 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
3685 roamMode = CFG_LFR_FEATURE_ENABLED_MAX;
3686 else
3687 roamMode = CFG_LFR_FEATURE_ENABLED_MIN;
3688
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003689 len = scnprintf(extra, sizeof(extra), "%s %d", command, roamMode);
Ratnam Rachuri28693eb2015-07-17 13:23:42 +05303690 len = VOS_MIN(priv_data.total_len, len + 1);
3691 if (copy_to_user(priv_data.buf, &extra, len)) {
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07003692 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3693 "%s: failed to copy data to user buffer", __func__);
3694 ret = -EFAULT;
3695 goto exit;
3696 }
3697 }
3698#endif
Srinivas Girigowdade697412013-02-14 16:31:48 -08003699#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003700#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -08003701 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
3702 {
3703 tANI_U8 *value = command;
3704 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
3705
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05303706 ret = hdd_drv_cmd_validate(command, 12);
3707 if (ret)
3708 goto exit;
3709
Srinivas Girigowdade697412013-02-14 16:31:48 -08003710 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
3711 value = value + 13;
3712 /* Convert the value from ascii to integer */
3713 ret = kstrtou8(value, 10, &roamRssiDiff);
3714 if (ret < 0)
3715 {
3716 /* If the input value is greater than max value of datatype, then also
3717 kstrtou8 fails */
3718 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3719 "%s: kstrtou8 failed range [%d - %d]", __func__,
3720 CFG_ROAM_RSSI_DIFF_MIN,
3721 CFG_ROAM_RSSI_DIFF_MAX);
3722 ret = -EINVAL;
3723 goto exit;
3724 }
3725
3726 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
3727 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
3728 {
3729 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3730 "Roam rssi diff value %d is out of range"
3731 " (Min: %d Max: %d)", roamRssiDiff,
3732 CFG_ROAM_RSSI_DIFF_MIN,
3733 CFG_ROAM_RSSI_DIFF_MAX);
3734 ret = -EINVAL;
3735 goto exit;
3736 }
3737
3738 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3739 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
3740
3741 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
3742 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
3743 }
Mahesh A Saptasagarec7d1092015-04-02 13:41:34 +05303744 else if (strncmp(command, "GETROAMDELTA", 12) == 0)
Srinivas Girigowdade697412013-02-14 16:31:48 -08003745 {
3746 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
3747 char extra[32];
3748 tANI_U8 len = 0;
3749
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303750 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3751 TRACE_CODE_HDD_GETROAMDELTA_IOCTL,
3752 pAdapter->sessionId, roamRssiDiff));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003753 len = scnprintf(extra, sizeof(extra), "%s %d",
3754 command, roamRssiDiff);
Ratnam Rachuri22a3b402015-07-17 13:21:49 +05303755 len = VOS_MIN(priv_data.total_len, len + 1);
3756 if (copy_to_user(priv_data.buf, &extra, len)) {
Srinivas Girigowdade697412013-02-14 16:31:48 -08003757 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3758 "%s: failed to copy data to user buffer", __func__);
3759 ret = -EFAULT;
3760 goto exit;
3761 }
3762 }
3763#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003764#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -08003765 else if (strncmp(command, "GETBAND", 7) == 0)
3766 {
3767 int band = -1;
3768 char extra[32];
3769 tANI_U8 len = 0;
3770 hdd_getBand_helper(pHddCtx, &band);
3771
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303772 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3773 TRACE_CODE_HDD_GETBAND_IOCTL,
3774 pAdapter->sessionId, band));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003775 len = scnprintf(extra, sizeof(extra), "%s %d", command, band);
Ratnam Rachuri52139592015-07-17 13:17:29 +05303776 len = VOS_MIN(priv_data.total_len, len + 1);
3777 if (copy_to_user(priv_data.buf, &extra, len)) {
Srinivas Girigowdade697412013-02-14 16:31:48 -08003778 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3779 "%s: failed to copy data to user buffer", __func__);
3780 ret = -EFAULT;
3781 goto exit;
3782 }
3783 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08003784 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
3785 {
3786 tANI_U8 *value = command;
3787 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
3788 tANI_U8 numChannels = 0;
3789 eHalStatus status = eHAL_STATUS_SUCCESS;
3790
3791 status = hdd_parse_channellist(value, ChannelList, &numChannels);
3792 if (eHAL_STATUS_SUCCESS != status)
3793 {
3794 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3795 "%s: Failed to parse channel list information", __func__);
3796 ret = -EINVAL;
3797 goto exit;
3798 }
3799
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303800 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3801 TRACE_CODE_HDD_SETROAMSCANCHANNELS_IOCTL,
3802 pAdapter->sessionId, numChannels));
Srinivas Girigowdade697412013-02-14 16:31:48 -08003803 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
3804 {
3805 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3806 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
3807 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
3808 ret = -EINVAL;
3809 goto exit;
3810 }
3811 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
3812 numChannels);
3813 if (eHAL_STATUS_SUCCESS != status)
3814 {
3815 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3816 "%s: Failed to update channel list information", __func__);
3817 ret = -EINVAL;
3818 goto exit;
3819 }
3820 }
3821 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
3822 {
3823 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
3824 tANI_U8 numChannels = 0;
Jeff Johnson51b67782013-04-05 12:35:41 -07003825 tANI_U8 j = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08003826 char extra[128] = {0};
Jeff Johnson51b67782013-04-05 12:35:41 -07003827 int len;
Srinivas Girigowdade697412013-02-14 16:31:48 -08003828
3829 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
3830 ChannelList, &numChannels ))
3831 {
3832 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3833 "%s: failed to get roam scan channel list", __func__);
3834 ret = -EFAULT;
3835 goto exit;
3836 }
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303837 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3838 TRACE_CODE_HDD_GETROAMSCANCHANNELS_IOCTL,
3839 pAdapter->sessionId, numChannels));
Srinivas Girigowdade697412013-02-14 16:31:48 -08003840 /* output channel list is of the format
3841 [Number of roam scan channels][Channel1][Channel2]... */
3842 /* copy the number of channels in the 0th index */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003843 len = scnprintf(extra, sizeof(extra), "%s %d", command, numChannels);
Sushant Kaushika08ca192015-09-16 15:52:04 +05303844 for (j = 0; (j < numChannels) && len <= sizeof(extra); j++)
Srinivas Girigowdade697412013-02-14 16:31:48 -08003845 {
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003846 len += scnprintf(extra + len, sizeof(extra) - len, " %d",
3847 ChannelList[j]);
Srinivas Girigowdade697412013-02-14 16:31:48 -08003848 }
3849
Sushant Kaushikc9b8be52015-07-15 16:41:27 +05303850 len = VOS_MIN(priv_data.total_len, len + 1);
3851 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdade697412013-02-14 16:31:48 -08003852 {
3853 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3854 "%s: failed to copy data to user buffer", __func__);
3855 ret = -EFAULT;
3856 goto exit;
3857 }
3858 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003859 else if (strncmp(command, "GETCCXMODE", 10) == 0)
3860 {
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003861 tANI_BOOLEAN eseMode = sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003862 char extra[32];
3863 tANI_U8 len = 0;
3864
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003865 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003866 then this operation is not permitted (return FAILURE) */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003867 if (eseMode &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003868 hdd_is_okc_mode_enabled(pHddCtx) &&
3869 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
3870 {
3871 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003872 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003873 " hence this operation is not permitted!", __func__);
3874 ret = -EPERM;
3875 goto exit;
3876 }
3877
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003878 len = scnprintf(extra, sizeof(extra), "%s %d",
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003879 "GETCCXMODE", eseMode);
Sushant Kaushikf8abd352015-07-15 16:37:49 +05303880 len = VOS_MIN(priv_data.total_len, len + 1);
3881 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003882 {
3883 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3884 "%s: failed to copy data to user buffer", __func__);
3885 ret = -EFAULT;
3886 goto exit;
3887 }
3888 }
3889 else if (strncmp(command, "GETOKCMODE", 10) == 0)
3890 {
3891 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
3892 char extra[32];
3893 tANI_U8 len = 0;
3894
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003895 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003896 then this operation is not permitted (return FAILURE) */
3897 if (okcMode &&
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003898 sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003899 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
3900 {
3901 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003902 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003903 " hence this operation is not permitted!", __func__);
3904 ret = -EPERM;
3905 goto exit;
3906 }
3907
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003908 len = scnprintf(extra, sizeof(extra), "%s %d",
3909 "GETOKCMODE", okcMode);
Sushant Kaushikbc2fb5c2015-07-15 16:43:16 +05303910 len = VOS_MIN(priv_data.total_len, len + 1);
3911 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003912 {
3913 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3914 "%s: failed to copy data to user buffer", __func__);
3915 ret = -EFAULT;
3916 goto exit;
3917 }
3918 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003919 else if (strncmp(command, "GETFASTROAM", 11) == 0)
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003920 {
3921 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
3922 char extra[32];
3923 tANI_U8 len = 0;
3924
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003925 len = scnprintf(extra, sizeof(extra), "%s %d",
3926 "GETFASTROAM", lfrMode);
Sushant Kaushik4da7ec92015-07-15 16:39:32 +05303927 len = VOS_MIN(priv_data.total_len, len + 1);
3928 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003929 {
3930 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3931 "%s: failed to copy data to user buffer", __func__);
3932 ret = -EFAULT;
3933 goto exit;
3934 }
3935 }
3936 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
3937 {
3938 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
3939 char extra[32];
3940 tANI_U8 len = 0;
3941
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003942 len = scnprintf(extra, sizeof(extra), "%s %d",
3943 "GETFASTTRANSITION", ft);
Sushant Kaushik231a4452015-07-15 16:23:56 +05303944 len = VOS_MIN(priv_data.total_len, len + 1);
3945 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003946 {
3947 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3948 "%s: failed to copy data to user buffer", __func__);
3949 ret = -EFAULT;
3950 goto exit;
3951 }
3952 }
3953 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
3954 {
3955 tANI_U8 *value = command;
3956 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
3957
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05303958 ret = hdd_drv_cmd_validate(command, 25);
3959 if (ret)
3960 goto exit;
3961
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003962 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
3963 value = value + 26;
3964 /* Convert the value from ascii to integer */
3965 ret = kstrtou8(value, 10, &minTime);
3966 if (ret < 0)
3967 {
3968 /* If the input value is greater than max value of datatype, then also
3969 kstrtou8 fails */
3970 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3971 "%s: kstrtou8 failed range [%d - %d]", __func__,
3972 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
3973 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
3974 ret = -EINVAL;
3975 goto exit;
3976 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003977 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
3978 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
3979 {
3980 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3981 "scan min channel time value %d is out of range"
3982 " (Min: %d Max: %d)", minTime,
3983 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
3984 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
3985 ret = -EINVAL;
3986 goto exit;
3987 }
3988
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303989 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3990 TRACE_CODE_HDD_SETROAMSCANCHANNELMINTIME_IOCTL,
3991 pAdapter->sessionId, minTime));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003992 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3993 "%s: Received Command to change channel min time = %d", __func__, minTime);
3994
3995 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
3996 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
3997 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003998 else if (strncmp(command, "SENDACTIONFRAME", 15) == 0)
3999 {
4000 tANI_U8 *value = command;
4001 tANI_U8 channel = 0;
4002 tANI_U8 dwellTime = 0;
4003 tANI_U8 bufLen = 0;
4004 tANI_U8 *buf = NULL;
4005 tSirMacAddr targetApBssid;
4006 eHalStatus status = eHAL_STATUS_SUCCESS;
4007 struct ieee80211_channel chan;
4008 tANI_U8 finalLen = 0;
4009 tANI_U8 *finalBuf = NULL;
4010 tANI_U8 temp = 0;
4011 u64 cookie;
4012 hdd_station_ctx_t *pHddStaCtx = NULL;
4013 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4014
4015 /* if not associated, no need to send action frame */
4016 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
4017 {
4018 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
4019 ret = -EINVAL;
4020 goto exit;
4021 }
4022
4023 status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel,
4024 &dwellTime, &buf, &bufLen);
4025 if (eHAL_STATUS_SUCCESS != status)
4026 {
4027 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4028 "%s: Failed to parse send action frame data", __func__);
4029 ret = -EINVAL;
4030 goto exit;
4031 }
4032
4033 /* if the target bssid is different from currently associated AP,
4034 then no need to send action frame */
4035 if (VOS_TRUE != vos_mem_compare(targetApBssid,
4036 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
4037 {
4038 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__);
4039 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07004040 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08004041 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004042 goto exit;
4043 }
4044
4045 /* if the channel number is different from operating channel then
4046 no need to send action frame */
4047 if (channel != pHddStaCtx->conn_info.operationChannel)
4048 {
4049 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4050 "%s: channel(%d) is different from operating channel(%d)",
4051 __func__, channel, pHddStaCtx->conn_info.operationChannel);
4052 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07004053 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08004054 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004055 goto exit;
4056 }
4057 chan.center_freq = sme_ChnToFreq(channel);
4058
4059 finalLen = bufLen + 24;
4060 finalBuf = vos_mem_malloc(finalLen);
4061 if (NULL == finalBuf)
4062 {
4063 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__);
4064 ret = -ENOMEM;
Jeff Johnson11c33152013-04-16 17:52:40 -07004065 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08004066 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004067 goto exit;
4068 }
4069 vos_mem_zero(finalBuf, finalLen);
4070
4071 /* Fill subtype */
4072 temp = SIR_MAC_MGMT_ACTION << 4;
4073 vos_mem_copy(finalBuf + 0, &temp, sizeof(temp));
4074
4075 /* Fill type */
4076 temp = SIR_MAC_MGMT_FRAME;
4077 vos_mem_copy(finalBuf + 2, &temp, sizeof(temp));
4078
4079 /* Fill destination address (bssid of the AP) */
4080 vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid));
4081
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07004082 /* Fill source address (STA mac address) */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004083 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
4084
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07004085 /* Fill BSSID (AP mac address) */
4086 vos_mem_copy(finalBuf + 16, targetApBssid, sizeof(targetApBssid));
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004087
4088 /* Fill received buffer from 24th address */
4089 vos_mem_copy(finalBuf + 24, buf, bufLen);
4090
Jeff Johnson11c33152013-04-16 17:52:40 -07004091 /* done with the parsed buffer */
4092 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08004093 buf = NULL;
Jeff Johnson11c33152013-04-16 17:52:40 -07004094
Anand N Sunkade9adb1b2015-07-29 09:56:45 +05304095#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0))
4096 params.chan = &chan;
4097 params.offchan = 0;
4098 params.wait = dwellTime;
4099 params.buf = finalBuf;
4100 params.len = finalLen;
4101 params.no_cck = 1;
4102 params.dont_wait_for_ack = 1;
4103 ret = wlan_hdd_mgmt_tx(NULL, &pAdapter->wdev, &params, &cookie);
4104#else
DARAM SUDHA39eede62014-02-12 11:16:40 +05304105 wlan_hdd_mgmt_tx( NULL,
Yue Maf49ba872013-08-19 12:04:25 -07004106#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
4107 &(pAdapter->wdev),
4108#else
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07004109 pAdapter->dev,
Yue Maf49ba872013-08-19 12:04:25 -07004110#endif
4111 &chan, 0,
4112#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
4113 NL80211_CHAN_HT20, 1,
4114#endif
4115 dwellTime, finalBuf, finalLen, 1,
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004116 1, &cookie );
Anand N Sunkade9adb1b2015-07-29 09:56:45 +05304117#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0)*/
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004118 vos_mem_free(finalBuf);
4119 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004120 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
4121 {
4122 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
4123 char extra[32];
4124 tANI_U8 len = 0;
4125
4126 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004127 len = scnprintf(extra, sizeof(extra), "%s %d",
4128 "GETROAMSCANCHANNELMINTIME", val);
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05304129 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
4130 TRACE_CODE_HDD_GETROAMSCANCHANNELMINTIME_IOCTL,
4131 pAdapter->sessionId, val));
Sushant Kaushikbb8c52c2015-07-15 16:36:23 +05304132 len = VOS_MIN(priv_data.total_len, len + 1);
4133 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004134 {
4135 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4136 "%s: failed to copy data to user buffer", __func__);
4137 ret = -EFAULT;
4138 goto exit;
4139 }
4140 }
4141 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
4142 {
4143 tANI_U8 *value = command;
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07004144 tANI_U16 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004145
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304146 ret = hdd_drv_cmd_validate(command, 18);
4147 if (ret)
4148 goto exit;
4149
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004150 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
4151 value = value + 19;
4152 /* Convert the value from ascii to integer */
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07004153 ret = kstrtou16(value, 10, &maxTime);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004154 if (ret < 0)
4155 {
4156 /* If the input value is greater than max value of datatype, then also
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07004157 kstrtou16 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004158 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07004159 "%s: kstrtou16 failed range [%d - %d]", __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004160 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
4161 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
4162 ret = -EINVAL;
4163 goto exit;
4164 }
4165
4166 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
4167 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
4168 {
4169 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4170 "lfr mode value %d is out of range"
4171 " (Min: %d Max: %d)", maxTime,
4172 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
4173 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
4174 ret = -EINVAL;
4175 goto exit;
4176 }
4177
4178 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4179 "%s: Received Command to change channel max time = %d", __func__, maxTime);
4180
4181 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
4182 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
4183 }
4184 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
4185 {
4186 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
4187 char extra[32];
4188 tANI_U8 len = 0;
4189
4190 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004191 len = scnprintf(extra, sizeof(extra), "%s %d",
4192 "GETSCANCHANNELTIME", val);
Ratheesh S Pacbfa932015-07-16 15:27:18 +05304193 len = VOS_MIN(priv_data.total_len, len + 1);
4194 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004195 {
4196 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4197 "%s: failed to copy data to user buffer", __func__);
4198 ret = -EFAULT;
4199 goto exit;
4200 }
4201 }
4202 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
4203 {
4204 tANI_U8 *value = command;
4205 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
4206
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304207 ret = hdd_drv_cmd_validate(command, 15);
4208 if (ret)
4209 goto exit;
4210
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004211 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
4212 value = value + 16;
4213 /* Convert the value from ascii to integer */
4214 ret = kstrtou16(value, 10, &val);
4215 if (ret < 0)
4216 {
4217 /* If the input value is greater than max value of datatype, then also
4218 kstrtou16 fails */
4219 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4220 "%s: kstrtou16 failed range [%d - %d]", __func__,
4221 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
4222 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
4223 ret = -EINVAL;
4224 goto exit;
4225 }
4226
4227 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
4228 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
4229 {
4230 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4231 "scan home time value %d is out of range"
4232 " (Min: %d Max: %d)", val,
4233 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
4234 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
4235 ret = -EINVAL;
4236 goto exit;
4237 }
4238
4239 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4240 "%s: Received Command to change scan home time = %d", __func__, val);
4241
4242 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
4243 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
4244 }
4245 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
4246 {
4247 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
4248 char extra[32];
4249 tANI_U8 len = 0;
4250
4251 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004252 len = scnprintf(extra, sizeof(extra), "%s %d",
4253 "GETSCANHOMETIME", val);
Ratheesh S P728d7c62015-07-16 15:38:58 +05304254 len = VOS_MIN(priv_data.total_len, len + 1);
4255 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004256 {
4257 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4258 "%s: failed to copy data to user buffer", __func__);
4259 ret = -EFAULT;
4260 goto exit;
4261 }
4262 }
4263 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
4264 {
4265 tANI_U8 *value = command;
4266 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
4267
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304268 ret = hdd_drv_cmd_validate(command, 16);
4269 if (ret)
4270 goto exit;
4271
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004272 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
4273 value = value + 17;
4274 /* Convert the value from ascii to integer */
4275 ret = kstrtou8(value, 10, &val);
4276 if (ret < 0)
4277 {
4278 /* If the input value is greater than max value of datatype, then also
4279 kstrtou8 fails */
4280 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4281 "%s: kstrtou8 failed range [%d - %d]", __func__,
4282 CFG_ROAM_INTRA_BAND_MIN,
4283 CFG_ROAM_INTRA_BAND_MAX);
4284 ret = -EINVAL;
4285 goto exit;
4286 }
4287
4288 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
4289 (val > CFG_ROAM_INTRA_BAND_MAX))
4290 {
4291 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4292 "intra band mode value %d is out of range"
4293 " (Min: %d Max: %d)", val,
4294 CFG_ROAM_INTRA_BAND_MIN,
4295 CFG_ROAM_INTRA_BAND_MAX);
4296 ret = -EINVAL;
4297 goto exit;
4298 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004299 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4300 "%s: Received Command to change intra band = %d", __func__, val);
4301
4302 pHddCtx->cfg_ini->nRoamIntraBand = val;
4303 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
4304 }
4305 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
4306 {
4307 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
4308 char extra[32];
4309 tANI_U8 len = 0;
4310
4311 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004312 len = scnprintf(extra, sizeof(extra), "%s %d",
4313 "GETROAMINTRABAND", val);
Ratheesh S P2dd2a3e2015-07-16 15:34:23 +05304314 len = VOS_MIN(priv_data.total_len, len + 1);
4315 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004316 {
4317 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4318 "%s: failed to copy data to user buffer", __func__);
4319 ret = -EFAULT;
4320 goto exit;
4321 }
4322 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004323 else if (strncmp(command, "SETSCANNPROBES", 14) == 0)
4324 {
4325 tANI_U8 *value = command;
4326 tANI_U8 nProbes = CFG_ROAM_SCAN_N_PROBES_DEFAULT;
4327
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304328 ret = hdd_drv_cmd_validate(command, 14);
4329 if (ret)
4330 goto exit;
4331
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004332 /* Move pointer to ahead of SETSCANNPROBES<delimiter> */
4333 value = value + 15;
4334 /* Convert the value from ascii to integer */
4335 ret = kstrtou8(value, 10, &nProbes);
4336 if (ret < 0)
4337 {
4338 /* If the input value is greater than max value of datatype, then also
4339 kstrtou8 fails */
4340 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4341 "%s: kstrtou8 failed range [%d - %d]", __func__,
4342 CFG_ROAM_SCAN_N_PROBES_MIN,
4343 CFG_ROAM_SCAN_N_PROBES_MAX);
4344 ret = -EINVAL;
4345 goto exit;
4346 }
4347
4348 if ((nProbes < CFG_ROAM_SCAN_N_PROBES_MIN) ||
4349 (nProbes > CFG_ROAM_SCAN_N_PROBES_MAX))
4350 {
4351 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4352 "NProbes value %d is out of range"
4353 " (Min: %d Max: %d)", nProbes,
4354 CFG_ROAM_SCAN_N_PROBES_MIN,
4355 CFG_ROAM_SCAN_N_PROBES_MAX);
4356 ret = -EINVAL;
4357 goto exit;
4358 }
4359
4360 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4361 "%s: Received Command to Set nProbes = %d", __func__, nProbes);
4362
4363 pHddCtx->cfg_ini->nProbes = nProbes;
4364 sme_UpdateRoamScanNProbes((tHalHandle)(pHddCtx->hHal), nProbes);
4365 }
Mahesh A Saptasagarec7d1092015-04-02 13:41:34 +05304366 else if (strncmp(command, "GETSCANNPROBES", 14) == 0)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004367 {
4368 tANI_U8 val = sme_getRoamScanNProbes((tHalHandle)(pHddCtx->hHal));
4369 char extra[32];
4370 tANI_U8 len = 0;
4371
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004372 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Ratnam Rachuri6da525d2015-08-07 13:55:54 +05304373 len = VOS_MIN(priv_data.total_len, len + 1);
4374 if (copy_to_user(priv_data.buf, &extra, len)) {
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004375 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4376 "%s: failed to copy data to user buffer", __func__);
4377 ret = -EFAULT;
4378 goto exit;
4379 }
4380 }
4381 else if (strncmp(command, "SETSCANHOMEAWAYTIME", 19) == 0)
4382 {
4383 tANI_U8 *value = command;
4384 tANI_U16 homeAwayTime = CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT;
4385
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304386 ret = hdd_drv_cmd_validate(command, 19);
4387 if (ret)
4388 goto exit;
4389
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004390 /* Move pointer to ahead of SETSCANHOMEAWAYTIME<delimiter> */
4391 /* input value is in units of msec */
4392 value = value + 20;
4393 /* Convert the value from ascii to integer */
4394 ret = kstrtou16(value, 10, &homeAwayTime);
4395 if (ret < 0)
4396 {
4397 /* If the input value is greater than max value of datatype, then also
4398 kstrtou8 fails */
4399 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4400 "%s: kstrtou8 failed range [%d - %d]", __func__,
4401 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
4402 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
4403 ret = -EINVAL;
4404 goto exit;
4405 }
4406
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004407 if ((homeAwayTime < CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN) ||
4408 (homeAwayTime > CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX))
4409 {
4410 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4411 "homeAwayTime value %d is out of range"
4412 " (Min: %d Max: %d)", homeAwayTime,
4413 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
4414 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
4415 ret = -EINVAL;
4416 goto exit;
4417 }
4418
4419 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4420 "%s: Received Command to Set scan away time = %d", __func__, homeAwayTime);
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07004421 if (pHddCtx->cfg_ini->nRoamScanHomeAwayTime != homeAwayTime)
4422 {
4423 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
4424 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_TRUE);
4425 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004426 }
Mahesh A Saptasagarec7d1092015-04-02 13:41:34 +05304427 else if (strncmp(command, "GETSCANHOMEAWAYTIME", 19) == 0)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004428 {
4429 tANI_U16 val = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
4430 char extra[32];
4431 tANI_U8 len = 0;
4432
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004433 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Ratnam Rachuri51a5ad12015-08-07 14:06:37 +05304434 len = VOS_MIN(priv_data.total_len, len + 1);
4435 if (copy_to_user(priv_data.buf, &extra, len)) {
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004436 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4437 "%s: failed to copy data to user buffer", __func__);
4438 ret = -EFAULT;
4439 goto exit;
4440 }
4441 }
4442 else if (strncmp(command, "REASSOC", 7) == 0)
4443 {
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304444 ret = hdd_drv_cmd_validate(command, 7);
4445 if (ret)
4446 goto exit;
4447
4448 ret = hdd_parse_reassoc(pAdapter, command, priv_data.total_len);
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05304449 if (!ret)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004450 goto exit;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004451 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07004452 else if (strncmp(command, "SETWESMODE", 10) == 0)
4453 {
4454 tANI_U8 *value = command;
4455 tANI_BOOLEAN wesMode = CFG_ENABLE_WES_MODE_NAME_DEFAULT;
4456
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304457 ret = hdd_drv_cmd_validate(command, 10);
4458 if (ret)
4459 goto exit;
4460
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07004461 /* Move pointer to ahead of SETWESMODE<delimiter> */
4462 value = value + 11;
4463 /* Convert the value from ascii to integer */
4464 ret = kstrtou8(value, 10, &wesMode);
4465 if (ret < 0)
4466 {
4467 /* If the input value is greater than max value of datatype, then also
4468 kstrtou8 fails */
4469 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4470 "%s: kstrtou8 failed range [%d - %d]", __func__,
4471 CFG_ENABLE_WES_MODE_NAME_MIN,
4472 CFG_ENABLE_WES_MODE_NAME_MAX);
4473 ret = -EINVAL;
4474 goto exit;
4475 }
4476
4477 if ((wesMode < CFG_ENABLE_WES_MODE_NAME_MIN) ||
4478 (wesMode > CFG_ENABLE_WES_MODE_NAME_MAX))
4479 {
4480 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4481 "WES Mode value %d is out of range"
4482 " (Min: %d Max: %d)", wesMode,
4483 CFG_ENABLE_WES_MODE_NAME_MIN,
4484 CFG_ENABLE_WES_MODE_NAME_MAX);
4485 ret = -EINVAL;
4486 goto exit;
4487 }
4488 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4489 "%s: Received Command to Set WES Mode rssi diff = %d", __func__, wesMode);
4490
4491 pHddCtx->cfg_ini->isWESModeEnabled = wesMode;
4492 sme_UpdateWESMode((tHalHandle)(pHddCtx->hHal), wesMode);
4493 }
Mahesh A Saptasagarec7d1092015-04-02 13:41:34 +05304494 else if (strncmp(command, "GETWESMODE", 10) == 0)
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07004495 {
4496 tANI_BOOLEAN wesMode = sme_GetWESMode((tHalHandle)(pHddCtx->hHal));
4497 char extra[32];
4498 tANI_U8 len = 0;
4499
Arif Hussain826d9412013-11-12 16:44:54 -08004500 len = scnprintf(extra, sizeof(extra), "%s %d", command, wesMode);
Ratnam Rachuri8fe90c62015-08-07 14:03:26 +05304501 len = VOS_MIN(priv_data.total_len, len + 1);
4502 if (copy_to_user(priv_data.buf, &extra, len)) {
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07004503 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4504 "%s: failed to copy data to user buffer", __func__);
4505 ret = -EFAULT;
4506 goto exit;
4507 }
4508 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004509#endif /* WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_ESE || FEATURE_WLAN_LFR */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004510#ifdef FEATURE_WLAN_LFR
4511 else if (strncmp(command, "SETFASTROAM", 11) == 0)
4512 {
4513 tANI_U8 *value = command;
4514 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
4515
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304516 ret = hdd_drv_cmd_validate(command, 11);
4517 if (ret)
4518 goto exit;
4519
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004520 /* Move pointer to ahead of SETFASTROAM<delimiter> */
4521 value = value + 12;
4522 /* Convert the value from ascii to integer */
4523 ret = kstrtou8(value, 10, &lfrMode);
4524 if (ret < 0)
4525 {
4526 /* If the input value is greater than max value of datatype, then also
4527 kstrtou8 fails */
4528 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4529 "%s: kstrtou8 failed range [%d - %d]", __func__,
4530 CFG_LFR_FEATURE_ENABLED_MIN,
4531 CFG_LFR_FEATURE_ENABLED_MAX);
4532 ret = -EINVAL;
4533 goto exit;
4534 }
4535
4536 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
4537 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
4538 {
4539 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4540 "lfr mode value %d is out of range"
4541 " (Min: %d Max: %d)", lfrMode,
4542 CFG_LFR_FEATURE_ENABLED_MIN,
4543 CFG_LFR_FEATURE_ENABLED_MAX);
4544 ret = -EINVAL;
4545 goto exit;
4546 }
4547
4548 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4549 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
4550
4551 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
4552 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
4553 }
4554#endif
4555#ifdef WLAN_FEATURE_VOWIFI_11R
4556 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
4557 {
4558 tANI_U8 *value = command;
4559 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
4560
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304561 ret = hdd_drv_cmd_validate(command, 17);
4562 if (ret)
4563 goto exit;
4564
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004565 /* Move pointer to ahead of SETFASTROAM<delimiter> */
4566 value = value + 18;
4567 /* Convert the value from ascii to integer */
4568 ret = kstrtou8(value, 10, &ft);
4569 if (ret < 0)
4570 {
4571 /* If the input value is greater than max value of datatype, then also
4572 kstrtou8 fails */
4573 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4574 "%s: kstrtou8 failed range [%d - %d]", __func__,
4575 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
4576 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
4577 ret = -EINVAL;
4578 goto exit;
4579 }
4580
4581 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
4582 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
4583 {
4584 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4585 "ft mode value %d is out of range"
4586 " (Min: %d Max: %d)", ft,
4587 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
4588 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
4589 ret = -EINVAL;
4590 goto exit;
4591 }
4592
4593 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4594 "%s: Received Command to change ft mode = %d", __func__, ft);
4595
4596 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
4597 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
4598 }
Padma, Santhosh Kumar778d8382015-03-04 17:41:22 +05304599 else if (strncmp(command, "SETDFSSCANMODE", 14) == 0)
4600 {
4601 tANI_U8 *value = command;
4602 tANI_U8 dfsScanMode = DFS_CHNL_SCAN_ENABLED_NORMAL;
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05304603
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304604 ret = hdd_drv_cmd_validate(command, 14);
4605 if (ret)
4606 goto exit;
4607
Padma, Santhosh Kumar778d8382015-03-04 17:41:22 +05304608 /* Move pointer to ahead of SETDFSSCANMODE<delimiter> */
4609 value = value + 15;
4610 /* Convert the value from ascii to integer */
4611 ret = kstrtou8(value, 10, &dfsScanMode);
4612 if (ret < 0)
4613 {
4614 /* If the input value is greater than max value of
4615 datatype, then also kstrtou8 fails
4616 */
4617 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4618 "%s: kstrtou8 failed range [%d - %d]", __func__,
4619 CFG_ENABLE_DFS_CHNL_SCAN_MIN,
4620 CFG_ENABLE_DFS_CHNL_SCAN_MAX);
4621 ret = -EINVAL;
4622 goto exit;
4623 }
4624
4625 if ((dfsScanMode < CFG_ENABLE_DFS_CHNL_SCAN_MIN) ||
4626 (dfsScanMode > CFG_ENABLE_DFS_CHNL_SCAN_MAX))
4627 {
4628 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4629 "dfsScanMode value %d is out of range"
4630 " (Min: %d Max: %d)", dfsScanMode,
4631 CFG_ENABLE_DFS_CHNL_SCAN_MIN,
4632 CFG_ENABLE_DFS_CHNL_SCAN_MAX);
4633 ret = -EINVAL;
4634 goto exit;
4635 }
4636 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4637 "%s: Received Command to Set DFS Scan Mode = %d",
4638 __func__, dfsScanMode);
4639
4640 ret = wlan_hdd_handle_dfs_chan_scan(pHddCtx, dfsScanMode);
4641 }
4642 else if (strncmp(command, "GETDFSSCANMODE", 14) == 0)
4643 {
4644 tANI_U8 dfsScanMode = sme_GetDFSScanMode(pHddCtx->hHal);
4645 char extra[32];
4646 tANI_U8 len = 0;
4647
4648 len = scnprintf(extra, sizeof(extra), "%s %d", command, dfsScanMode);
Ratheesh S P767224e2015-07-16 15:35:51 +05304649 len = VOS_MIN(priv_data.total_len, len + 1);
4650 if (copy_to_user(priv_data.buf, &extra, len))
Padma, Santhosh Kumar778d8382015-03-04 17:41:22 +05304651 {
4652 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4653 "%s: failed to copy data to user buffer", __func__);
4654 ret = -EFAULT;
4655 goto exit;
4656 }
4657 }
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05304658 else if (strncmp(command, "FASTREASSOC", 11) == 0)
4659 {
Selvaraj, Sridhar3714c4d2016-06-22 15:19:12 +05304660 ret = wlan_hdd_handle_fastreassoc(pAdapter, command);
4661 if (!ret)
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05304662 goto exit;
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05304663 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004664#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004665#ifdef FEATURE_WLAN_ESE
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004666 else if (strncmp(command, "SETCCXMODE", 10) == 0)
4667 {
4668 tANI_U8 *value = command;
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004669 tANI_U8 eseMode = CFG_ESE_FEATURE_ENABLED_DEFAULT;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004670
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304671 ret = hdd_drv_cmd_validate(command, 10);
4672 if (ret)
4673 goto exit;
4674
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004675 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07004676 then this operation is not permitted (return FAILURE) */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004677 if (sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07004678 hdd_is_okc_mode_enabled(pHddCtx) &&
4679 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
4680 {
4681 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004682 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07004683 " hence this operation is not permitted!", __func__);
4684 ret = -EPERM;
4685 goto exit;
4686 }
4687
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004688 /* Move pointer to ahead of SETCCXMODE<delimiter> */
4689 value = value + 11;
4690 /* Convert the value from ascii to integer */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004691 ret = kstrtou8(value, 10, &eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004692 if (ret < 0)
4693 {
4694 /* If the input value is greater than max value of datatype, then also
4695 kstrtou8 fails */
4696 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4697 "%s: kstrtou8 failed range [%d - %d]", __func__,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004698 CFG_ESE_FEATURE_ENABLED_MIN,
4699 CFG_ESE_FEATURE_ENABLED_MAX);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004700 ret = -EINVAL;
4701 goto exit;
4702 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004703 if ((eseMode < CFG_ESE_FEATURE_ENABLED_MIN) ||
4704 (eseMode > CFG_ESE_FEATURE_ENABLED_MAX))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004705 {
4706 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004707 "Ese mode value %d is out of range"
4708 " (Min: %d Max: %d)", eseMode,
4709 CFG_ESE_FEATURE_ENABLED_MIN,
4710 CFG_ESE_FEATURE_ENABLED_MAX);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004711 ret = -EINVAL;
4712 goto exit;
4713 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004714 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004715 "%s: Received Command to change ese mode = %d", __func__, eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004716
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004717 pHddCtx->cfg_ini->isEseIniFeatureEnabled = eseMode;
4718 sme_UpdateIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal), eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004719 }
4720#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004721 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
4722 {
4723 tANI_U8 *value = command;
4724 tANI_BOOLEAN roamScanControl = 0;
4725
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304726 ret = hdd_drv_cmd_validate(command, 18);
4727 if (ret)
4728 goto exit;
4729
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004730 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
4731 value = value + 19;
4732 /* Convert the value from ascii to integer */
4733 ret = kstrtou8(value, 10, &roamScanControl);
4734 if (ret < 0)
4735 {
4736 /* If the input value is greater than max value of datatype, then also
4737 kstrtou8 fails */
4738 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4739 "%s: kstrtou8 failed ", __func__);
4740 ret = -EINVAL;
4741 goto exit;
4742 }
4743
4744 if (0 != roamScanControl)
4745 {
4746 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4747 "roam scan control invalid value = %d",
4748 roamScanControl);
4749 ret = -EINVAL;
4750 goto exit;
4751 }
4752 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4753 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
4754
4755 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
4756 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004757#ifdef FEATURE_WLAN_OKC
4758 else if (strncmp(command, "SETOKCMODE", 10) == 0)
4759 {
4760 tANI_U8 *value = command;
4761 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
4762
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304763 ret = hdd_drv_cmd_validate(command, 10);
4764 if (ret)
4765 goto exit;
4766
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004767 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07004768 then this operation is not permitted (return FAILURE) */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004769 if (sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07004770 hdd_is_okc_mode_enabled(pHddCtx) &&
4771 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
4772 {
4773 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004774 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07004775 " hence this operation is not permitted!", __func__);
4776 ret = -EPERM;
4777 goto exit;
4778 }
4779
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004780 /* Move pointer to ahead of SETOKCMODE<delimiter> */
4781 value = value + 11;
4782 /* Convert the value from ascii to integer */
4783 ret = kstrtou8(value, 10, &okcMode);
4784 if (ret < 0)
4785 {
4786 /* If the input value is greater than max value of datatype, then also
4787 kstrtou8 fails */
4788 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4789 "%s: kstrtou8 failed range [%d - %d]", __func__,
4790 CFG_OKC_FEATURE_ENABLED_MIN,
4791 CFG_OKC_FEATURE_ENABLED_MAX);
4792 ret = -EINVAL;
4793 goto exit;
4794 }
4795
4796 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
4797 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
4798 {
4799 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4800 "Okc mode value %d is out of range"
4801 " (Min: %d Max: %d)", okcMode,
4802 CFG_OKC_FEATURE_ENABLED_MIN,
4803 CFG_OKC_FEATURE_ENABLED_MAX);
4804 ret = -EINVAL;
4805 goto exit;
4806 }
4807
4808 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4809 "%s: Received Command to change okc mode = %d", __func__, okcMode);
4810
4811 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
4812 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07004813#endif /* FEATURE_WLAN_OKC */
Mahesh A Saptasagarec7d1092015-04-02 13:41:34 +05304814 else if (strncmp(command, "GETROAMSCANCONTROL", 18) == 0)
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004815 {
4816 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
4817 char extra[32];
4818 tANI_U8 len = 0;
4819
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004820 len = scnprintf(extra, sizeof(extra), "%s %d",
4821 command, roamScanControl);
Ratnam Rachuri083ada82015-08-07 14:01:05 +05304822 len = VOS_MIN(priv_data.total_len, len + 1);
4823 if (copy_to_user(priv_data.buf, &extra, len)) {
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004824 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4825 "%s: failed to copy data to user buffer", __func__);
4826 ret = -EFAULT;
4827 goto exit;
4828 }
4829 }
Gopichand Nakkala227c7f32013-06-26 22:44:57 +05304830#ifdef WLAN_FEATURE_PACKET_FILTERING
4831 else if (strncmp(command, "ENABLE_PKTFILTER_IPV6", 21) == 0)
4832 {
4833 tANI_U8 filterType = 0;
4834 tANI_U8 *value = command;
4835
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304836 ret = hdd_drv_cmd_validate(command, 21);
4837 if (ret)
4838 goto exit;
4839
Gopichand Nakkala227c7f32013-06-26 22:44:57 +05304840 /* Move pointer to ahead of ENABLE_PKTFILTER_IPV6<delimiter> */
4841 value = value + 22;
4842
4843 /* Convert the value from ascii to integer */
4844 ret = kstrtou8(value, 10, &filterType);
4845 if (ret < 0)
4846 {
4847 /* If the input value is greater than max value of datatype,
4848 * then also kstrtou8 fails
4849 */
4850 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4851 "%s: kstrtou8 failed range ", __func__);
4852 ret = -EINVAL;
4853 goto exit;
4854 }
4855
4856 if (filterType != 0 && filterType != 1)
4857 {
4858 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4859 "%s: Accepted Values are 0 and 1 ", __func__);
4860 ret = -EINVAL;
4861 goto exit;
4862 }
4863 wlan_hdd_setIPv6Filter(WLAN_HDD_GET_CTX(pAdapter), filterType,
4864 pAdapter->sessionId);
4865 }
4866#endif
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05304867 else if (strncmp(command, "BTCOEXMODE", 10) == 0 )
4868 {
Kiet Lamad161252014-07-22 11:23:32 -07004869 char *dhcpPhase;
Satyanarayana Dash1faea4f2014-09-22 16:21:04 +05304870 int ret;
4871
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304872 ret = hdd_drv_cmd_validate(command, 10);
4873 if (ret)
4874 goto exit;
4875
Kiet Lamad161252014-07-22 11:23:32 -07004876 dhcpPhase = command + 11;
4877 if ('1' == *dhcpPhase)
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05304878 {
Deepthi Gowribfd17132014-11-14 17:59:04 +05304879 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Kiet Lamad161252014-07-22 11:23:32 -07004880 FL("send DHCP START indication"));
c_hpothu9b781ba2013-12-30 20:57:45 +05304881
4882 pHddCtx->btCoexModeSet = TRUE;
Kiet Lamad161252014-07-22 11:23:32 -07004883
Satyanarayana Dash1faea4f2014-09-22 16:21:04 +05304884 ret = wlan_hdd_scan_abort(pAdapter);
4885 if (ret < 0)
4886 {
4887 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4888 FL("failed to abort existing scan %d"), ret);
4889 }
4890
Kiet Lamad161252014-07-22 11:23:32 -07004891 sme_DHCPStartInd(pHddCtx->hHal, pAdapter->device_mode,
4892 pAdapter->sessionId);
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05304893 }
Kiet Lamad161252014-07-22 11:23:32 -07004894 else if ('2' == *dhcpPhase)
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05304895 {
Deepthi Gowribfd17132014-11-14 17:59:04 +05304896 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Kiet Lamad161252014-07-22 11:23:32 -07004897 FL("send DHCP STOP indication"));
c_hpothu9b781ba2013-12-30 20:57:45 +05304898
4899 pHddCtx->btCoexModeSet = FALSE;
Kiet Lamad161252014-07-22 11:23:32 -07004900
4901 sme_DHCPStopInd(pHddCtx->hHal, pAdapter->device_mode,
4902 pAdapter->sessionId);
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05304903 }
4904 }
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07004905 else if (strncmp(command, "SCAN-ACTIVE", 11) == 0)
4906 {
Abhishek Singh58749d62016-02-03 15:27:20 +05304907 hddLog(LOG1,
4908 FL("making default scan to ACTIVE"));
c_hpothudbefd3e2014-04-28 15:59:47 +05304909 pHddCtx->scan_info.scan_mode = eSIR_ACTIVE_SCAN;
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07004910 }
4911 else if (strncmp(command, "SCAN-PASSIVE", 12) == 0)
4912 {
Abhishek Singh58749d62016-02-03 15:27:20 +05304913 hddLog(LOG1,
4914 FL("making default scan to PASSIVE"));
c_hpothudbefd3e2014-04-28 15:59:47 +05304915 pHddCtx->scan_info.scan_mode = eSIR_PASSIVE_SCAN;
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07004916 }
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05304917 else if (strncmp(command, "GETDWELLTIME", 12) == 0)
4918 {
4919 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
4920 char extra[32];
4921 tANI_U8 len = 0;
4922
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05304923 memset(extra, 0, sizeof(extra));
4924 ret = hdd_get_dwell_time(pCfg, command, extra, sizeof(extra), &len);
Ratnam Rachuri12d5d462015-08-07 14:10:23 +05304925 len = VOS_MIN(priv_data.total_len, len + 1);
4926 if (ret != 0 || copy_to_user(priv_data.buf, &extra, len)) {
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05304927 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4928 "%s: failed to copy data to user buffer", __func__);
4929 ret = -EFAULT;
4930 goto exit;
4931 }
4932 ret = len;
4933 }
4934 else if (strncmp(command, "SETDWELLTIME", 12) == 0)
4935 {
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05304936 ret = hdd_set_dwell_time(pAdapter, command);
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05304937 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07004938 else if ( strncasecmp(command, "MIRACAST", 8) == 0 )
4939 {
4940 tANI_U8 filterType = 0;
4941 tANI_U8 *value;
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304942
4943 ret = hdd_drv_cmd_validate(command, 8);
4944 if (ret)
4945 goto exit;
4946
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07004947 value = command + 9;
4948
4949 /* Convert the value from ascii to integer */
4950 ret = kstrtou8(value, 10, &filterType);
4951 if (ret < 0)
4952 {
4953 /* If the input value is greater than max value of datatype,
4954 * then also kstrtou8 fails
4955 */
4956 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4957 "%s: kstrtou8 failed range ", __func__);
4958 ret = -EINVAL;
4959 goto exit;
4960 }
4961 if ((filterType < WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL ) ||
4962 (filterType > WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL))
4963 {
4964 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4965 "%s: Accepted Values are 0 to 2. 0-Disabled, 1-Source,"
4966 " 2-Sink ", __func__);
4967 ret = -EINVAL;
4968 goto exit;
4969 }
4970 //Filtertype value should be either 0-Disabled, 1-Source, 2-sink
4971 pHddCtx->drvr_miracast = filterType;
Kaushik, Sushant96122442014-10-21 16:40:18 +05304972 pScanInfo = &pHddCtx->scan_info;
4973 if (filterType && pScanInfo != NULL &&
4974 pHddCtx->scan_info.mScanPending)
4975 {
4976 /*Miracast Session started. Abort Scan */
4977 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4978 "%s, Aborting Scan For Miracast",__func__);
4979 hdd_abort_mac_scan(pHddCtx, pScanInfo->sessionId,
4980 eCSR_SCAN_ABORT_DEFAULT);
4981 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07004982 hdd_tx_rx_pkt_cnt_stat_timer_handler(pHddCtx);
Ganesh Kondabattini8f6e3b32014-08-25 16:07:54 +05304983 sme_SetMiracastMode(pHddCtx->hHal, pHddCtx->drvr_miracast);
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07004984 }
Leo Chang614d2072013-08-22 14:59:44 -07004985 else if (strncmp(command, "SETMCRATE", 9) == 0)
4986 {
Leo Chang614d2072013-08-22 14:59:44 -07004987 tANI_U8 *value = command;
4988 int targetRate;
Leo Chang1f98cbd2013-10-17 15:03:52 -07004989 tSirRateUpdateInd *rateUpdate;
4990 eHalStatus status;
Leo Chang614d2072013-08-22 14:59:44 -07004991
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05304992 ret = hdd_drv_cmd_validate(command, 9);
4993 if (ret)
4994 goto exit;
4995
Leo Chang614d2072013-08-22 14:59:44 -07004996 /* Only valid for SAP mode */
4997 if (WLAN_HDD_SOFTAP != pAdapter->device_mode)
4998 {
4999 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5000 "%s: SAP mode is not running", __func__);
5001 ret = -EFAULT;
5002 goto exit;
5003 }
5004
5005 /* Move pointer to ahead of SETMCRATE<delimiter> */
5006 /* input value is in units of hundred kbps */
5007 value = value + 10;
5008 /* Convert the value from ascii to integer, decimal base */
5009 ret = kstrtouint(value, 10, &targetRate);
5010
Leo Chang1f98cbd2013-10-17 15:03:52 -07005011 rateUpdate = (tSirRateUpdateInd *)vos_mem_malloc(sizeof(tSirRateUpdateInd));
5012 if (NULL == rateUpdate)
Leo Chang614d2072013-08-22 14:59:44 -07005013 {
Leo Chang1f98cbd2013-10-17 15:03:52 -07005014 hddLog(VOS_TRACE_LEVEL_ERROR,
5015 "%s: SETMCRATE indication alloc fail", __func__);
5016 ret = -EFAULT;
5017 goto exit;
5018 }
5019 vos_mem_zero(rateUpdate, sizeof(tSirRateUpdateInd ));
5020
5021 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5022 "MC Target rate %d", targetRate);
5023 /* Ignore unicast */
5024 rateUpdate->ucastDataRate = -1;
5025 rateUpdate->mcastDataRate24GHz = targetRate;
5026 rateUpdate->mcastDataRate5GHz = targetRate;
5027 rateUpdate->mcastDataRate24GHzTxFlag = 0;
5028 rateUpdate->mcastDataRate5GHzTxFlag = 0;
5029 status = sme_SendRateUpdateInd(pHddCtx->hHal, rateUpdate);
5030 if (eHAL_STATUS_SUCCESS != status)
5031 {
5032 hddLog(VOS_TRACE_LEVEL_ERROR,
5033 "%s: SET_MC_RATE failed", __func__);
5034 vos_mem_free(rateUpdate);
5035 ret = -EFAULT;
5036 goto exit;
Leo Chang614d2072013-08-22 14:59:44 -07005037 }
5038 }
jge35567202017-06-21 16:39:38 +08005039 else if (strncmp(command, "MAXTXPOWER", 10) == 0)
5040 {
5041 int status;
5042 int txPower;
5043 eHalStatus smeStatus;
5044 tANI_U8 *value = command;
5045 tSirMacAddr bssid = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
5046 tSirMacAddr selfMac = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
5047
5048 status = hdd_parse_setmaxtxpower_command(value, &txPower);
5049 if (status)
5050 {
5051 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5052 "Invalid MAXTXPOWER command ");
5053 ret = -EINVAL;
5054 goto exit;
5055 }
5056
5057 hddLog(VOS_TRACE_LEVEL_INFO, "max tx power %d selfMac: "
5058 MAC_ADDRESS_STR " bssId: " MAC_ADDRESS_STR " ",
5059 txPower, MAC_ADDR_ARRAY(selfMac),
5060 MAC_ADDR_ARRAY(bssid));
5061 smeStatus = sme_SetMaxTxPower((tHalHandle)(pHddCtx->hHal),
5062 bssid, selfMac, txPower) ;
5063 if( smeStatus != eHAL_STATUS_SUCCESS )
5064 {
5065 hddLog(VOS_TRACE_LEVEL_ERROR, "%s:Set max tx power failed",
5066 __func__);
5067 ret = -EINVAL;
5068 goto exit;
5069 }
5070
5071 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Set max tx power success",
5072 __func__);
5073 }
Rajeev79dbe4c2013-10-05 11:03:42 +05305074#ifdef FEATURE_WLAN_BATCH_SCAN
Rajeev Kumar8b373292014-01-08 20:36:55 -08005075 else if (strncmp(command, "WLS_BATCHING", 12) == 0)
Rajeev79dbe4c2013-10-05 11:03:42 +05305076 {
Rajeev Kumar8b373292014-01-08 20:36:55 -08005077 ret = hdd_handle_batch_scan_ioctl(pAdapter, &priv_data, command);
Rajeev79dbe4c2013-10-05 11:03:42 +05305078 }
5079#endif
Abhishek Singh00b71972016-01-07 10:51:04 +05305080#ifdef WLAN_FEATURE_RMC
5081 else if ((strncasecmp(command, "SETIBSSBEACONOUIDATA", 20) == 0) &&
5082 (WLAN_HDD_IBSS == pAdapter->device_mode))
5083 {
5084 int i = 0;
5085 tANI_U8 *ibss_ie;
5086 tANI_U32 command_len;
5087 tANI_U8 *value = command;
5088 tHalHandle hHal = pHddCtx->hHal;
5089 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
5090 tANI_U32 ibss_ie_length;
5091 tANI_U32 len, present;
5092 tANI_U8 *addIE;
5093 tANI_U8 *addIEData;
5094
5095 hddLog(LOG1,
5096 FL(" received command %s"),((char *) value));
5097 /* validate argument of command */
5098 if (strlen(value) <= 21)
5099 {
5100 hddLog(LOGE,
5101 FL("No arguements in command length %zu"), strlen(value));
5102 ret = -EFAULT;
5103 goto exit;
5104 }
5105
5106 /* moving to arguments of commands */
5107 value = value + 21;
5108 command_len = strlen(value);
5109
5110 /* oui_data can't be less than 3 bytes */
5111 if (command_len <= (2 * WLAN_HDD_IBSS_MIN_OUI_DATA_LENGTH))
5112 {
5113 hddLog(LOGE,
5114 FL("Invalid SETIBSSBEACONOUIDATA command length %d"),
5115 command_len);
5116 ret = -EFAULT;
5117 goto exit;
5118 }
5119 ibss_ie = vos_mem_malloc(command_len);
5120 if (!ibss_ie) {
5121 hddLog(LOGE,
5122 FL("Could not allocate memory for command length %d"),
5123 command_len);
5124 ret = -ENOMEM;
5125 goto exit;
5126 }
5127 vos_mem_zero(ibss_ie, command_len);
5128
5129 ibss_ie_length = hdd_parse_set_ibss_oui_data_command(value, ibss_ie,
5130 command_len);
5131 if (ibss_ie_length < (2 * WLAN_HDD_IBSS_MIN_OUI_DATA_LENGTH)) {
5132 hddLog(LOGE, FL("Could not parse command %s return length %d"),
5133 value, ibss_ie_length);
5134 ret = -EFAULT;
5135 vos_mem_free(ibss_ie);
5136 goto exit;
5137 }
5138
5139 hddLog(LOG1, FL("ibss_ie length %d ibss_ie:"), ibss_ie_length);
5140 while (i < ibss_ie_length)
5141 hddLog(LOG1, FL("0x%x"), ibss_ie[i++]);
5142
5143 /* Populate Vendor IE in Beacon */
5144 if ((ccmCfgGetInt(hHal,
5145 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
5146 &present)) != eHAL_STATUS_SUCCESS)
5147 {
5148 hddLog(LOGE,
5149 FL("unable to ftch WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG"));
5150 ret = -EFAULT;
5151 vos_mem_free(ibss_ie);
5152 goto exit;
5153 }
5154
5155 addIE = vos_mem_malloc(WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN);
5156 if (!addIE) {
5157 hddLog(LOGE,
5158 FL("Could not allocate memory for command length %d"),
5159 command_len);
5160 vos_mem_free(ibss_ie);
5161 ret = -ENOMEM;
5162 goto exit;
5163 }
5164 vos_mem_zero(addIE, WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN);
5165
5166 if (present)
5167 {
5168 if ((wlan_cfgGetStrLen(pMac,
5169 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, &len)) != eSIR_SUCCESS)
5170 {
5171 hddLog(LOGE,
5172 FL("unable to fetch WNI_CFG_PROBE_RSP_BCN_ADDNIE_LEN"));
5173 ret = -EFAULT;
5174 vos_mem_free(ibss_ie);
5175 vos_mem_free(addIE);
5176 goto exit;
5177 }
5178
5179 if (len <= WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN && len &&
5180 ((len + ibss_ie_length) <=
5181 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN))
5182 {
5183 if ((ccmCfgGetStr(hHal,
5184 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, addIE, &len))
5185 != eHAL_STATUS_SUCCESS)
5186 {
5187 hddLog(LOGE,
5188 FL("unable to fetch WNI_PROBE_RSP_BCN_ADDNIE_DATA"));
5189 ret = -EFAULT;
5190 vos_mem_free(ibss_ie);
5191 vos_mem_free(addIE);
5192 goto exit;
5193 }
5194 else
5195 {
5196 /* Curruntly only WPA IE is added before Vendor IE
5197 * so we can blindly place the Vendor IE after WPA
5198 * IE. If no WPA IE found replace all with Vendor IE.
5199 */
5200 len = hdd_find_ibss_wpa_ie_pos(addIE, len);
5201 }
5202 }
5203 else
5204 {
5205 hddLog(LOGE,
5206 FL("IE len exceed limit len %d,ibss_ie_length %d "),
5207 len, ibss_ie_length);
5208 ret = -EFAULT;
5209 vos_mem_free(addIE);
5210 vos_mem_free(ibss_ie);
5211 goto exit;
5212 }
5213 }
5214 else {
5215 len = 0;
5216 }
5217
5218 vos_mem_copy (addIE + len , ibss_ie, ibss_ie_length);
5219 len += ibss_ie_length;
5220
5221 if (ccmCfgSetStr(hHal,
5222 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, addIE, len, NULL,
5223 eANI_BOOLEAN_FALSE) != eHAL_STATUS_SUCCESS)
5224 {
5225 hddLog(LOGE,
5226 FL("unable to set WNI_CFG_PRBE_RSP_BCN_ADDNIE_DATA"));
5227 ret = -EFAULT;
5228 vos_mem_free(ibss_ie);
5229 vos_mem_free(addIE);
5230 goto exit;
5231 }
5232 vos_mem_free(addIE);
5233 if (ccmCfgSetInt(hHal,
5234 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 1,NULL,
5235 eANI_BOOLEAN_FALSE) != eHAL_STATUS_SUCCESS)
5236 {
5237 hddLog(LOGE,
5238 FL("unble to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG"));
5239 ret = -EFAULT;
5240 vos_mem_free(ibss_ie);
5241 goto exit;
5242 }
5243
5244 /* Populate Vendor IE in probe resp */
5245 if ((ccmCfgGetInt(hHal,
5246 WNI_CFG_PROBE_RSP_ADDNIE_FLAG,
5247 &present)) != eHAL_STATUS_SUCCESS)
5248 {
5249 hddLog(LOGE,
5250 FL("unable to fetch WNI_CFG_PROBE_RSP_ADDNIE_FLAG"));
5251 ret = -EFAULT;
5252 vos_mem_free(ibss_ie);
5253 goto exit;
5254 }
5255
5256 addIEData = vos_mem_malloc(WNI_CFG_PROBE_RSP_ADDNIE_DATA1_LEN);
5257 if (!addIEData) {
5258 hddLog(LOGE,
5259 FL("Could not allocate memory for command length %d"),
5260 command_len);
5261 vos_mem_free(ibss_ie);
5262 ret = -ENOMEM;
5263 goto exit;
5264 }
5265 vos_mem_zero(addIEData, WNI_CFG_PROBE_RSP_ADDNIE_DATA1_LEN);
5266
5267 if (present) {
5268 if (eSIR_SUCCESS != wlan_cfgGetStrLen(pMac,
5269 WNI_CFG_PROBE_RSP_ADDNIE_DATA1, &len)) {
5270 hddLog(LOGE,
5271 FL("unable to fetch WNI_CFG_PROBE_RSP_ADDNIE_DATA1"));
5272 ret = -EFAULT;
5273 vos_mem_free(ibss_ie);
5274 vos_mem_free(addIEData);
5275 goto exit;
5276 }
5277 if (len < WNI_CFG_PROBE_RSP_ADDNIE_DATA1_LEN && len &&
5278 (ibss_ie_length + len) <=
5279 WNI_CFG_PROBE_RSP_ADDNIE_DATA1_LEN) {
5280
5281 if ((ccmCfgGetStr(hHal,
5282 WNI_CFG_PROBE_RSP_ADDNIE_DATA1, addIEData, &len))
5283 != eHAL_STATUS_SUCCESS) {
5284 hddLog(LOGE,
5285 FL("unable 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 else {
5292 /* Curruntly only WPA IE is added before Vendor IE
5293 * so we can blindly place the Vendor IE after WPA
5294 * IE. If no WPA IE found replace all with Vendor IE.
5295 */
5296 len = hdd_find_ibss_wpa_ie_pos(addIEData, len);
5297 }
5298 }
5299 else
5300 {
5301 hddLog(LOGE,
5302 FL("IE len exceed limit len %d,ibss_ie_length %d "),
5303 len, ibss_ie_length);
5304 ret = -EFAULT;
5305 vos_mem_free(addIEData);
5306 vos_mem_free(ibss_ie);
5307 goto exit;
5308 }
5309 } /* probe rsp ADD IE present */
5310 else {
5311 /* probe rsp add IE is not present */
5312 len = 0;
5313 }
5314
5315 vos_mem_copy(addIEData +len , ibss_ie, ibss_ie_length);
5316 len += ibss_ie_length;
5317
5318 vos_mem_free(ibss_ie);
5319
5320 if (ccmCfgSetStr(hHal,
5321 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,
5322 (tANI_U8*)(addIEData),
5323 len, NULL,
5324 eANI_BOOLEAN_FALSE)
5325 == eHAL_STATUS_FAILURE) {
5326 hddLog(LOGE,
5327 FL("unable to copy to WNI_CFG_PROBE_RSP_ADDNIE_DATA1"));
5328 ret = -EFAULT;
5329 vos_mem_free(addIEData);
5330 goto exit;
5331 }
5332 vos_mem_free(addIEData);
5333 if (ccmCfgSetInt(WLAN_HDD_GET_HAL_CTX(pAdapter),
5334 WNI_CFG_PROBE_RSP_ADDNIE_FLAG, 1,NULL,
5335 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
5336 {
5337 hddLog(LOGE,
5338 FL("unable to copy WNI_CFG_PROBE_RSP_ADDNIE_FLAG"));
5339 ret = -EFAULT;
5340 goto exit;
5341 }
5342 }
5343 else if (strncasecmp(command, "SETRMCENABLE", 12) == 0)
5344 {
5345 tANI_U8 *value = command;
5346 tANI_U8 ucRmcEnable = 0;
5347 int status;
5348
5349 if ((WLAN_HDD_IBSS != pAdapter->device_mode) &&
5350 (WLAN_HDD_SOFTAP != pAdapter->device_mode))
5351 {
5352 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5353 "Received SETRMCENABLE command in invalid mode %d "
5354 "SETRMCENABLE command is only allowed in IBSS or SOFTAP mode",
5355 pAdapter->device_mode);
5356 ret = -EINVAL;
5357 goto exit;
5358 }
5359
5360 status = hdd_parse_setrmcenable_command(value, &ucRmcEnable);
5361 if (status)
5362 {
5363 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5364 "Invalid SETRMCENABLE command ");
5365 ret = -EINVAL;
5366 goto exit;
5367 }
5368
5369 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5370 "%s: ucRmcEnable %d ", __func__, ucRmcEnable);
5371
5372 if (TRUE == ucRmcEnable)
5373 {
5374 status = sme_EnableRMC( (tHalHandle)(pHddCtx->hHal),
5375 pAdapter->sessionId );
5376 }
5377 else if(FALSE == ucRmcEnable)
5378 {
5379 status = sme_DisableRMC( (tHalHandle)(pHddCtx->hHal),
5380 pAdapter->sessionId );
5381 }
5382 else
5383 {
5384 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5385 "Invalid SETRMCENABLE command %d", ucRmcEnable);
5386 ret = -EINVAL;
5387 goto exit;
5388 }
5389
5390 if (VOS_STATUS_SUCCESS != status)
5391 {
5392 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5393 "%s: SETRMC %d failed status %d", __func__, ucRmcEnable,
5394 status);
5395 ret = -EINVAL;
5396 goto exit;
5397 }
5398 }
5399 else if (strncasecmp(command, "SETRMCACTIONPERIOD", 18) == 0)
5400 {
5401 tANI_U8 *value = command;
5402 tANI_U32 uActionPeriod = 0;
5403 int status;
5404
5405 if ((WLAN_HDD_IBSS != pAdapter->device_mode) &&
5406 (WLAN_HDD_SOFTAP != pAdapter->device_mode))
5407 {
5408 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5409 "Received SETRMC command in invalid mode %d "
5410 "SETRMC command is only allowed in IBSS or SOFTAP mode",
5411 pAdapter->device_mode);
5412 ret = -EINVAL;
5413 goto exit;
5414 }
5415
5416 status = hdd_parse_setrmcactionperiod_command(value, &uActionPeriod);
5417 if (status)
5418 {
5419 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5420 "Invalid SETRMCACTIONPERIOD command ");
5421 ret = -EINVAL;
5422 goto exit;
5423 }
5424
5425 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5426 "%s: uActionPeriod %d ", __func__, uActionPeriod);
5427
5428 if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY,
5429 uActionPeriod, NULL, eANI_BOOLEAN_FALSE))
5430 {
5431 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5432 "%s: Could not set SETRMCACTIONPERIOD %d", __func__, uActionPeriod);
5433 ret = -EINVAL;
5434 goto exit;
5435 }
5436
5437 }
5438 else if (strncasecmp(command, "GETIBSSPEERINFOALL", 18) == 0)
5439 {
5440 /* Peer Info All Command */
5441 int status = eHAL_STATUS_SUCCESS;
5442 hdd_station_ctx_t *pHddStaCtx = NULL;
5443 char *extra = NULL;
5444 int idx = 0, length = 0;
5445 v_MACADDR_t *macAddr;
5446 v_U32_t txRateMbps = 0, numOfBytestoPrint = 0;
5447
5448 if (WLAN_HDD_IBSS == pAdapter->device_mode)
5449 {
5450 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5451 }
5452 else
5453 {
5454 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5455 "%s: pAdapter is not valid for this device mode",
5456 __func__);
5457 ret = -EINVAL;
5458 goto exit;
5459 }
5460
5461 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5462 "%s: Received GETIBSSPEERINFOALL Command", __func__);
5463
5464
5465 /* Handle the command */
5466 status = hdd_cfg80211_get_ibss_peer_info_all(pAdapter);
5467 if (VOS_STATUS_SUCCESS == status)
5468 {
5469 /* The variable extra needed to be allocated on the heap since
5470 * amount of memory required to copy the data for 32 devices
5471 * exceeds the size of 1024 bytes of default stack size. On
5472 * 64 bit devices, the default max stack size of 2048 bytes
5473 */
5474 extra = kmalloc(WLAN_MAX_BUF_SIZE, GFP_KERNEL);
5475
5476 if (NULL == extra)
5477 {
5478 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5479 "%s:kmalloc failed", __func__);
5480 ret = -EINVAL;
5481 goto exit;
5482 }
5483
5484 /* Copy number of stations */
5485 length = scnprintf( extra, WLAN_MAX_BUF_SIZE, "%d ",
5486 pHddStaCtx->ibss_peer_info.numIBSSPeers);
5487 numOfBytestoPrint = length;
5488 for (idx = 0; idx < pHddStaCtx->ibss_peer_info.numIBSSPeers; idx++)
5489 {
5490 macAddr =
5491 hdd_wlan_get_ibss_mac_addr_from_staid(pAdapter,
5492 pHddStaCtx->ibss_peer_info.ibssPeerList[idx].staIdx);
5493 if (NULL != macAddr)
5494 {
5495 txRateMbps =
5496 ((pHddStaCtx->ibss_peer_info.ibssPeerList[idx].txRate)*500*1000)/1000000;
5497
5498 length += scnprintf( (extra + length), WLAN_MAX_BUF_SIZE - length,
5499 "%02x:%02x:%02x:%02x:%02x:%02x %d %d ",
5500 macAddr->bytes[0], macAddr->bytes[1], macAddr->bytes[2],
5501 macAddr->bytes[3], macAddr->bytes[4], macAddr->bytes[5],
5502 (int)txRateMbps,
5503 (int)pHddStaCtx->ibss_peer_info.ibssPeerList[idx].rssi);
5504 }
5505 else
5506 {
5507 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5508 "%s: MAC ADDR is NULL for staIdx: %d", __func__,
5509 pHddStaCtx->ibss_peer_info.ibssPeerList[idx].staIdx);
5510 }
5511
5512 /*
5513 * VOS_TRACE() macro has limitation of 512 bytes for the print
5514 * buffer. Hence printing the data in two chunks. The first chunk
5515 * will have the data for 16 devices and the second chunk will
5516 * have the rest.
5517 */
5518 if (idx < NUM_OF_STA_DATA_TO_PRINT)
5519 {
5520 numOfBytestoPrint = length;
5521 }
5522 }
5523
5524 /*
5525 * Copy the data back into buffer, if the data to copy is
5526 * morethan 512 bytes than we will split the data and do
5527 * it in two shots
5528 */
5529 if (copy_to_user(priv_data.buf, extra, numOfBytestoPrint))
5530 {
5531 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5532 "%s: Copy into user data buffer failed ", __func__);
5533 ret = -EFAULT;
5534 kfree(extra);
5535 goto exit;
5536 }
5537 priv_data.buf[numOfBytestoPrint] = '\0';
5538 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED,
5539 "%s", priv_data.buf);
5540
5541 if (length > numOfBytestoPrint)
5542 {
5543 if (copy_to_user(priv_data.buf + numOfBytestoPrint,
5544 extra + numOfBytestoPrint,
5545 length - numOfBytestoPrint + 1))
5546 {
5547 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5548 "%s: Copy into user data buffer failed ", __func__);
5549 ret = -EFAULT;
5550 kfree(extra);
5551 goto exit;
5552 }
5553 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED,
5554 "%s", &priv_data.buf[numOfBytestoPrint]);
5555 }
5556
5557 /* Free temporary buffer */
5558 kfree(extra);
5559 }
5560
5561 else
5562 {
5563 /* Command failed, log error */
5564 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5565 "%s: GETIBSSPEERINFOALL command failed with status code %d",
5566 __func__, status);
5567 ret = -EINVAL;
5568 goto exit;
5569 }
5570 ret = 0;
5571 }
5572 else if(strncasecmp(command, "GETIBSSPEERINFO", 15) == 0)
5573 {
5574 /* Peer Info <Peer Addr> command */
5575 tANI_U8 *value = command;
5576 VOS_STATUS status;
5577 hdd_station_ctx_t *pHddStaCtx = NULL;
5578 char extra[128] = { 0 };
5579 v_U32_t length = 0;
5580 v_U8_t staIdx = 0;
5581 v_U32_t txRateMbps = 0;
5582 v_MACADDR_t peerMacAddr;
5583
5584 if (WLAN_HDD_IBSS == pAdapter->device_mode)
5585 {
5586 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5587 }
5588 else
5589 {
5590 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5591 "%s: pAdapter is not valid for this device mode",
5592 __func__);
5593 ret = -EINVAL;
5594 goto exit;
5595 }
5596
5597 /* if there are no peers, no need to continue with the command */
5598 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5599 "%s: Received GETIBSSPEERINFO Command", __func__);
5600
5601 if (eConnectionState_IbssConnected != pHddStaCtx->conn_info.connState)
5602 {
5603 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5604 "%s:No IBSS Peers coalesced", __func__);
5605 ret = -EINVAL;
5606 goto exit;
5607 }
5608
5609 /* Parse the incoming command buffer */
5610 status = hdd_parse_get_ibss_peer_info(value, &peerMacAddr);
5611 if (VOS_STATUS_SUCCESS != status)
5612 {
5613 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5614 "%s: Invalid GETIBSSPEERINFO command", __func__);
5615 ret = -EINVAL;
5616 goto exit;
5617 }
5618
5619 /* Get station index for the peer mac address */
5620 hdd_Ibss_GetStaId(pHddStaCtx, &peerMacAddr, &staIdx);
5621
5622 if (staIdx > HDD_MAX_NUM_IBSS_STA)
5623 {
5624 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5625 "%s: Invalid StaIdx %d returned", __func__, staIdx);
5626 ret = -EINVAL;
5627 goto exit;
5628 }
5629
5630 /* Handle the command */
5631 status = hdd_cfg80211_get_ibss_peer_info(pAdapter, staIdx);
5632 if (VOS_STATUS_SUCCESS == status)
5633 {
5634 v_U32_t txRate = pHddStaCtx->ibss_peer_info.ibssPeerList[0].txRate;
5635 txRateMbps = (txRate * 500 * 1000)/1000000;
5636
5637 length = scnprintf( extra, sizeof(extra), "%d %d", (int)txRateMbps,
5638 (int)pHddStaCtx->ibss_peer_info.ibssPeerList[0].rssi);
5639
5640 /* Copy the data back into buffer */
5641 if (copy_to_user(priv_data.buf, &extra, length+ 1))
5642 {
5643 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5644 "%s: copy data to user buffer failed GETIBSSPEERINFO command",
5645 __func__);
5646 ret = -EFAULT;
5647 goto exit;
5648 }
5649 }
5650 else
5651 {
5652 /* Command failed, log error */
5653 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5654 "%s: GETIBSSPEERINFO command failed with status code %d",
5655 __func__, status);
5656 ret = -EINVAL;
5657 goto exit;
5658 }
5659
5660 /* Success ! */
5661 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED,
5662 "%s", priv_data.buf);
5663 ret = 0;
5664 }
5665 else if (strncasecmp(command, "SETRMCTXRATE", 12) == 0)
5666 {
5667 tANI_U8 *value = command;
5668 tANI_U32 uRate = 0;
5669 tTxrateinfoflags txFlags = 0;
5670 tSirRateUpdateInd *rateUpdateParams;
5671 int status;
5672
5673 if ((WLAN_HDD_IBSS != pAdapter->device_mode) &&
5674 (WLAN_HDD_SOFTAP != pAdapter->device_mode))
5675 {
5676 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5677 "Received SETRMCTXRATE command in invalid mode %d "
5678 "SETRMC command is only allowed in IBSS or SOFTAP mode",
5679 pAdapter->device_mode);
5680 ret = -EINVAL;
5681 goto exit;
5682 }
5683
5684 status = hdd_parse_setrmcrate_command(value, &uRate, &txFlags);
5685 if (status)
5686 {
5687 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5688 "Invalid SETRMCTXRATE command ");
5689 ret = -EINVAL;
5690 goto exit;
5691 }
5692
5693 rateUpdateParams = vos_mem_malloc(sizeof(tSirRateUpdateInd));
5694 if (NULL == rateUpdateParams)
5695 {
5696 ret = -EINVAL;
5697 goto exit;
5698 }
5699
5700 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5701 "%s: uRate %d ", __func__, uRate);
5702
5703 vos_mem_zero(rateUpdateParams, sizeof(tSirRateUpdateInd ));
5704
5705 /* -1 implies ignore this param */
5706 rateUpdateParams->ucastDataRate = -1;
5707
5708 /*
5709 * Fill the user specifieed RMC rate param
5710 * and the derived tx flags.
5711 */
5712 rateUpdateParams->rmcDataRate = uRate;
5713 rateUpdateParams->rmcDataRateTxFlag = txFlags;
5714
5715 status = sme_SendRateUpdateInd((tHalHandle)(pHddCtx->hHal), rateUpdateParams);
5716 }
5717 else if (strncasecmp(command, "SETIBSSTXFAILEVENT", 18) == 0 )
5718 {
5719 char *value;
5720 tANI_U8 tx_fail_count = 0;
5721 tANI_U16 pid = 0;
5722
5723 value = command;
5724
5725 ret = hdd_ParseIBSSTXFailEventParams(value, &tx_fail_count, &pid);
5726
5727 if (0 != ret)
5728 {
5729 hddLog(VOS_TRACE_LEVEL_INFO,
5730 "%s: Failed to parse SETIBSSTXFAILEVENT arguments",
5731 __func__);
5732 goto exit;
5733 }
5734
5735 hddLog(VOS_TRACE_LEVEL_INFO, "%s: tx_fail_cnt=%hhu, pid=%hu",
5736 __func__, tx_fail_count, pid);
5737
5738 if (0 == tx_fail_count)
5739 {
5740 // Disable TX Fail Indication
5741 if (eHAL_STATUS_SUCCESS ==
5742 sme_TXFailMonitorStartStopInd(pHddCtx->hHal,
5743 tx_fail_count,
5744 NULL))
5745 {
5746 cesium_pid = 0;
5747 }
5748 else
5749 {
5750 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5751 "%s: failed to disable TX Fail Event ", __func__);
5752 ret = -EINVAL;
5753 }
5754 }
5755 else
5756 {
5757 if (eHAL_STATUS_SUCCESS ==
5758 sme_TXFailMonitorStartStopInd(pHddCtx->hHal,
5759 tx_fail_count,
5760 (void*)hdd_tx_fail_ind_callback))
5761 {
5762 cesium_pid = pid;
5763 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5764 "%s: Registered Cesium pid %u", __func__,
5765 cesium_pid);
5766 }
5767 else
5768 {
5769 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5770 "%s: Failed to enable TX Fail Monitoring", __func__);
5771 ret = -EINVAL;
5772 }
5773 }
5774 }
5775
5776#endif /* WLAN_FEATURE_RMC */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08005777#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07005778 else if (strncmp(command, "SETCCXROAMSCANCHANNELS", 22) == 0)
5779 {
5780 tANI_U8 *value = command;
5781 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
5782 tANI_U8 numChannels = 0;
5783 eHalStatus status = eHAL_STATUS_SUCCESS;
5784
5785 status = hdd_parse_channellist(value, ChannelList, &numChannels);
5786 if (eHAL_STATUS_SUCCESS != status)
5787 {
5788 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5789 "%s: Failed to parse channel list information", __func__);
5790 ret = -EINVAL;
5791 goto exit;
5792 }
5793
5794 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
5795 {
5796 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5797 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
5798 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
5799 ret = -EINVAL;
5800 goto exit;
5801 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08005802 status = sme_SetEseRoamScanChannelList((tHalHandle)(pHddCtx->hHal),
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07005803 ChannelList,
5804 numChannels);
5805 if (eHAL_STATUS_SUCCESS != status)
5806 {
5807 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5808 "%s: Failed to update channel list information", __func__);
5809 ret = -EINVAL;
5810 goto exit;
5811 }
5812 }
5813 else if (strncmp(command, "GETTSMSTATS", 11) == 0)
5814 {
5815 tANI_U8 *value = command;
5816 char extra[128] = {0};
5817 int len = 0;
5818 tANI_U8 tid = 0;
5819 hdd_station_ctx_t *pHddStaCtx = NULL;
5820 tAniTrafStrmMetrics tsmMetrics;
5821 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5822
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05305823 ret = hdd_drv_cmd_validate(command, 11);
5824 if (ret)
5825 goto exit;
5826
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07005827 /* if not associated, return error */
5828 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
5829 {
5830 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:Not associated!",__func__);
5831 ret = -EINVAL;
5832 goto exit;
5833 }
5834
5835 /* Move pointer to ahead of GETTSMSTATS<delimiter> */
5836 value = value + 12;
5837 /* Convert the value from ascii to integer */
5838 ret = kstrtou8(value, 10, &tid);
5839 if (ret < 0)
5840 {
5841 /* If the input value is greater than max value of datatype, then also
5842 kstrtou8 fails */
5843 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5844 "%s: kstrtou8 failed range [%d - %d]", __func__,
5845 TID_MIN_VALUE,
5846 TID_MAX_VALUE);
5847 ret = -EINVAL;
5848 goto exit;
5849 }
5850
5851 if ((tid < TID_MIN_VALUE) || (tid > TID_MAX_VALUE))
5852 {
5853 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5854 "tid value %d is out of range"
5855 " (Min: %d Max: %d)", tid,
5856 TID_MIN_VALUE,
5857 TID_MAX_VALUE);
5858 ret = -EINVAL;
5859 goto exit;
5860 }
5861
5862 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5863 "%s: Received Command to get tsm stats tid = %d", __func__, tid);
5864
5865 if (VOS_STATUS_SUCCESS != hdd_get_tsm_stats(pAdapter, tid, &tsmMetrics))
5866 {
5867 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5868 "%s: failed to get tsm stats", __func__);
5869 ret = -EFAULT;
5870 goto exit;
5871 }
5872
5873 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5874 "UplinkPktQueueDly(%d)\n"
5875 "UplinkPktQueueDlyHist[0](%d)\n"
5876 "UplinkPktQueueDlyHist[1](%d)\n"
5877 "UplinkPktQueueDlyHist[2](%d)\n"
5878 "UplinkPktQueueDlyHist[3](%d)\n"
Arun Kumar Khandavallie8768212014-02-17 16:43:34 +05305879 "UplinkPktTxDly(%u)\n"
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07005880 "UplinkPktLoss(%d)\n"
5881 "UplinkPktCount(%d)\n"
5882 "RoamingCount(%d)\n"
5883 "RoamingDly(%d)", tsmMetrics.UplinkPktQueueDly,
5884 tsmMetrics.UplinkPktQueueDlyHist[0],
5885 tsmMetrics.UplinkPktQueueDlyHist[1],
5886 tsmMetrics.UplinkPktQueueDlyHist[2],
5887 tsmMetrics.UplinkPktQueueDlyHist[3],
5888 tsmMetrics.UplinkPktTxDly, tsmMetrics.UplinkPktLoss,
5889 tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount, tsmMetrics.RoamingDly);
5890
5891 /* Output TSM stats is of the format
5892 GETTSMSTATS [PktQueueDly] [PktQueueDlyHist[0]]:[PktQueueDlyHist[1]] ...[RoamingDly]
5893 eg., GETTSMSTATS 10 1:0:0:161 20 1 17 8 39800 */
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08005894 len = scnprintf(extra, sizeof(extra), "%s %d %d:%d:%d:%d %u %d %d %d %d", command,
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07005895 tsmMetrics.UplinkPktQueueDly, tsmMetrics.UplinkPktQueueDlyHist[0],
5896 tsmMetrics.UplinkPktQueueDlyHist[1], tsmMetrics.UplinkPktQueueDlyHist[2],
5897 tsmMetrics.UplinkPktQueueDlyHist[3], tsmMetrics.UplinkPktTxDly,
5898 tsmMetrics.UplinkPktLoss, tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount,
5899 tsmMetrics.RoamingDly);
5900
Ratnam Rachurid53009c2015-08-07 13:59:00 +05305901 len = VOS_MIN(priv_data.total_len, len + 1);
5902 if (copy_to_user(priv_data.buf, &extra, len)) {
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07005903 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5904 "%s: failed to copy data to user buffer", __func__);
5905 ret = -EFAULT;
5906 goto exit;
5907 }
5908 }
5909 else if (strncmp(command, "SETCCKMIE", 9) == 0)
5910 {
5911 tANI_U8 *value = command;
5912 tANI_U8 *cckmIe = NULL;
5913 tANI_U8 cckmIeLen = 0;
5914 eHalStatus status = eHAL_STATUS_SUCCESS;
5915
5916 status = hdd_parse_get_cckm_ie(value, &cckmIe, &cckmIeLen);
5917 if (eHAL_STATUS_SUCCESS != status)
5918 {
5919 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5920 "%s: Failed to parse cckm ie data", __func__);
5921 ret = -EINVAL;
5922 goto exit;
5923 }
5924
5925 if (cckmIeLen > DOT11F_IE_RSN_MAX_LEN)
5926 {
5927 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5928 "%s: CCKM Ie input length is more than max[%d]", __func__,
5929 DOT11F_IE_RSN_MAX_LEN);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08005930 vos_mem_free(cckmIe);
5931 cckmIe = NULL;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07005932 ret = -EINVAL;
5933 goto exit;
5934 }
5935 sme_SetCCKMIe((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, cckmIe, cckmIeLen);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08005936 vos_mem_free(cckmIe);
5937 cckmIe = NULL;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07005938 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08005939 else if (strncmp(command, "CCXBEACONREQ", 12) == 0)
5940 {
5941 tANI_U8 *value = command;
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08005942 tCsrEseBeaconReq eseBcnReq;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08005943 eHalStatus status = eHAL_STATUS_SUCCESS;
Srinivas Girigowda0c6d7fe2014-05-28 18:18:10 -07005944
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08005945 status = hdd_parse_ese_beacon_req(value, &eseBcnReq);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08005946 if (eHAL_STATUS_SUCCESS != status)
5947 {
5948 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08005949 "%s: Failed to parse ese beacon req", __func__);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08005950 ret = -EINVAL;
5951 goto exit;
5952 }
Srinivas Girigowda0c6d7fe2014-05-28 18:18:10 -07005953 if (!hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))) {
5954 hddLog(VOS_TRACE_LEVEL_INFO, FL("Not associated"));
5955 hdd_indicateEseBcnReportNoResults (pAdapter,
5956 eseBcnReq.bcnReq[0].measurementToken,
5957 0x02, //BIT(1) set for measurement done
5958 0); // no BSS
5959 goto exit;
5960 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08005961
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08005962 status = sme_SetEseBeaconRequest((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, &eseBcnReq);
5963 if (eHAL_STATUS_SUCCESS != status)
5964 {
5965 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5966 "%s: sme_SetEseBeaconRequest failed (%d)", __func__, status);
5967 ret = -EINVAL;
5968 goto exit;
5969 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08005970 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08005971#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
c_hpothu92367912014-05-01 15:18:17 +05305972 else if (strncmp(command, "GETBCNMISSRATE", 14) == 0)
5973 {
5974 eHalStatus status;
5975 char buf[32], len;
5976 long waitRet;
5977 bcnMissRateContext_t getBcnMissRateCtx;
5978
5979 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5980
5981 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
5982 {
5983 hddLog(VOS_TRACE_LEVEL_WARN,
5984 FL("GETBCNMISSRATE: STA is not in connected state"));
5985 ret = -1;
5986 goto exit;
5987 }
5988
5989 init_completion(&(getBcnMissRateCtx.completion));
5990 getBcnMissRateCtx.magic = BCN_MISS_RATE_CONTEXT_MAGIC;
5991
5992 status = sme_getBcnMissRate((tHalHandle)(pHddCtx->hHal),
5993 pAdapter->sessionId,
5994 (void *)getBcnMissRateCB,
5995 (void *)(&getBcnMissRateCtx));
5996 if( eHAL_STATUS_SUCCESS != status)
5997 {
5998 hddLog(VOS_TRACE_LEVEL_INFO,
5999 FL("GETBCNMISSRATE: fail to post WDA cmd"));
6000 ret = -EINVAL;
6001 goto exit;
6002 }
6003
6004 waitRet = wait_for_completion_interruptible_timeout
6005 (&getBcnMissRateCtx.completion, BCN_MISS_RATE_TIME);
6006 if(waitRet <= 0)
6007 {
6008 hddLog(VOS_TRACE_LEVEL_ERROR,
6009 FL("failed to wait on bcnMissRateComp %d"), ret);
6010
6011 //Make magic number to zero so that callback is not called.
6012 spin_lock(&hdd_context_lock);
6013 getBcnMissRateCtx.magic = 0x0;
6014 spin_unlock(&hdd_context_lock);
6015 ret = -EINVAL;
6016 goto exit;
6017 }
6018
6019 hddLog(VOS_TRACE_LEVEL_INFO,
6020 FL("GETBCNMISSRATE: bcnMissRate: %d"), gbcnMissRate);
6021
6022 len = snprintf(buf, sizeof(buf), "GETBCNMISSRATE %d", gbcnMissRate);
6023 if (copy_to_user(priv_data.buf, &buf, len + 1))
6024 {
6025 hddLog(VOS_TRACE_LEVEL_ERROR,
6026 "%s: failed to copy data to user buffer", __func__);
6027 ret = -EFAULT;
6028 goto exit;
6029 }
6030 ret = len;
6031 }
Atul Mittal87ec2422014-09-24 13:12:50 +05306032#ifdef FEATURE_WLAN_TDLS
6033 else if (strncmp(command, "TDLSSECONDARYCHANNELOFFSET", 26) == 0) {
6034 tANI_U8 *value = command;
6035 int set_value;
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05306036
6037 ret = hdd_drv_cmd_validate(command, 26);
6038 if (ret)
6039 goto exit;
6040
Atul Mittal87ec2422014-09-24 13:12:50 +05306041 /* Move pointer to ahead of TDLSOFFCH*/
6042 value += 26;
c_manjeebbc40212015-12-08 13:52:59 +05306043 if (!(sscanf(value, "%d", &set_value))) {
6044 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6045 FL("No input identified"));
6046 ret = -EINVAL;
6047 goto exit;
6048 }
6049
Atul Mittal87ec2422014-09-24 13:12:50 +05306050 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6051 "%s: Tdls offchannel offset:%d",
6052 __func__, set_value);
6053 ret = iw_set_tdlssecoffchanneloffset(pHddCtx, set_value);
6054 if (ret < 0)
6055 {
6056 ret = -EINVAL;
6057 goto exit;
6058 }
6059
6060 } else if (strncmp(command, "TDLSOFFCHANNELMODE", 18) == 0) {
6061 tANI_U8 *value = command;
6062 int set_value;
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05306063
6064 ret = hdd_drv_cmd_validate(command, 18);
6065 if (ret)
6066 goto exit;
6067
Atul Mittal87ec2422014-09-24 13:12:50 +05306068 /* Move pointer to ahead of tdlsoffchnmode*/
6069 value += 18;
c_manjee82323892015-12-08 12:40:34 +05306070 ret = sscanf(value, "%d", &set_value);
6071 if (ret != 1) {
6072 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6073 FL("No input identified"));
6074 ret = -EINVAL;
6075 goto exit;
6076 }
Atul Mittal87ec2422014-09-24 13:12:50 +05306077 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6078 "%s: Tdls offchannel mode:%d",
6079 __func__, set_value);
6080 ret = iw_set_tdlsoffchannelmode(pAdapter, set_value);
6081 if (ret < 0)
6082 {
6083 ret = -EINVAL;
6084 goto exit;
6085 }
6086 } else if (strncmp(command, "TDLSOFFCHANNEL", 14) == 0) {
6087 tANI_U8 *value = command;
6088 int set_value;
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05306089
6090 ret = hdd_drv_cmd_validate(command, 14);
6091 if (ret)
6092 goto exit;
6093
Atul Mittal87ec2422014-09-24 13:12:50 +05306094 /* Move pointer to ahead of TDLSOFFCH*/
6095 value += 14;
c_manjeef6ccaf52015-12-08 11:52:11 +05306096 ret = sscanf(value, "%d", &set_value);
6097 if (ret != 1) {
6098 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6099 "Wrong value is given for hdd_set_tdls_offchannel");
6100 ret = -EINVAL;
6101 goto exit;
6102 }
6103
Atul Mittal87ec2422014-09-24 13:12:50 +05306104 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6105 "%s: Tdls offchannel num: %d",
6106 __func__, set_value);
6107 ret = iw_set_tdlsoffchannel(pHddCtx, set_value);
6108 if (ret < 0)
6109 {
6110 ret = -EINVAL;
6111 goto exit;
6112 }
6113 }
6114#endif
Satyanarayana Dash72806012014-12-02 14:30:08 +05306115 else if (strncmp(command, "GETFWSTATS", 10) == 0)
6116 {
6117 eHalStatus status;
6118 char *buf = NULL;
6119 char len;
6120 long waitRet;
6121 fwStatsContext_t fwStatsCtx;
Abhishek Singh08aa7762014-12-16 13:59:03 +05306122 tSirFwStatsResult *fwStatsRsp = &(pAdapter->fwStatsRsp);
Satyanarayana Dash72806012014-12-02 14:30:08 +05306123 tANI_U8 *ptr = command;
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05306124 int stats;
Satyanarayana Dash72806012014-12-02 14:30:08 +05306125
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05306126 ret = hdd_drv_cmd_validate(command, 10);
6127 if (ret)
6128 goto exit;
6129
6130 stats = *(ptr + 11) - '0';
Satyanarayana Dash72806012014-12-02 14:30:08 +05306131 hddLog(VOS_TRACE_LEVEL_INFO, FL("stats = %d "),stats);
6132 if (!IS_FEATURE_FW_STATS_ENABLE)
6133 {
6134 hddLog(VOS_TRACE_LEVEL_INFO,
6135 FL("Get Firmware stats feature not supported"));
6136 ret = -EINVAL;
6137 goto exit;
6138 }
6139
6140 if (FW_STATS_MAX <= stats || 0 >= stats)
6141 {
6142 hddLog(VOS_TRACE_LEVEL_INFO,
6143 FL(" stats %d not supported"),stats);
6144 ret = -EINVAL;
6145 goto exit;
6146 }
6147
6148 init_completion(&(fwStatsCtx.completion));
6149 fwStatsCtx.magic = FW_STATS_CONTEXT_MAGIC;
6150 fwStatsCtx.pAdapter = pAdapter;
6151 fwStatsRsp->type = 0;
6152 status = sme_GetFwStats( (tHalHandle)pHddCtx->hHal, stats,
Abhishek Singh08aa7762014-12-16 13:59:03 +05306153 &fwStatsCtx, hdd_FWStatisCB);
Satyanarayana Dash72806012014-12-02 14:30:08 +05306154 if (eHAL_STATUS_SUCCESS != status)
6155 {
6156 hddLog(VOS_TRACE_LEVEL_ERROR,
6157 FL(" fail to post WDA cmd status = %d"), status);
6158 ret = -EINVAL;
6159 goto exit;
6160 }
6161 waitRet = wait_for_completion_timeout
6162 (&(fwStatsCtx.completion), FW_STATE_WAIT_TIME);
6163 if (waitRet <= 0)
6164 {
6165 hddLog(VOS_TRACE_LEVEL_ERROR,
6166 FL("failed to wait on GwtFwstats"));
6167 //Make magic number to zero so that callback is not executed.
6168 spin_lock(&hdd_context_lock);
6169 fwStatsCtx.magic = 0x0;
6170 spin_unlock(&hdd_context_lock);
6171 ret = -EINVAL;
6172 goto exit;
6173 }
6174 if (fwStatsRsp->type)
6175 {
6176 buf = kmalloc(FW_STATE_RSP_LEN, GFP_KERNEL);
6177 if (!buf)
6178 {
6179 hddLog(VOS_TRACE_LEVEL_ERROR,
6180 FL(" failed to allocate memory"));
6181 ret = -ENOMEM;
6182 goto exit;
6183 }
6184 switch( fwStatsRsp->type )
6185 {
6186 case FW_UBSP_STATS:
6187 {
6188 len = snprintf(buf, FW_STATE_RSP_LEN,
6189 "GETFWSTATS: ubsp_enter_cnt %d ubsp_jump_ddr_cnt %d",
Abhishek Singh08aa7762014-12-16 13:59:03 +05306190 fwStatsRsp->fwStatsData.ubspStats.ubsp_enter_cnt,
6191 fwStatsRsp->fwStatsData.ubspStats.ubsp_jump_ddr_cnt);
Satyanarayana Dash72806012014-12-02 14:30:08 +05306192 }
6193 break;
6194 default:
6195 {
6196 hddLog(VOS_TRACE_LEVEL_ERROR, FL( "No handling for stats type %d"),fwStatsRsp->type);
6197 ret = -EFAULT;
6198 kfree(buf);
6199 goto exit;
6200 }
6201 }
6202 if (copy_to_user(priv_data.buf, buf, len + 1))
6203 {
6204 hddLog(VOS_TRACE_LEVEL_ERROR,
6205 FL(" failed to copy data to user buffer"));
6206 ret = -EFAULT;
6207 kfree(buf);
6208 goto exit;
6209 }
6210 ret = len;
6211 kfree(buf);
6212 }
6213 else
6214 {
6215 hddLog(VOS_TRACE_LEVEL_ERROR,
6216 FL("failed to fetch the stats"));
6217 ret = -EFAULT;
6218 goto exit;
6219 }
6220
6221 }
Agarwal Ashish8bd53ae2015-06-12 18:03:45 +05306222 else if (strncasecmp(command, "SET_FCC_CHANNEL", 15) == 0)
6223 {
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05306224 ret = hdd_drv_cmd_validate(command, 15);
6225 if (ret)
6226 goto exit;
6227
Agarwal Ashish8bd53ae2015-06-12 18:03:45 +05306228 /*
6229 * this command wld be called by user-space when it detects WLAN
6230 * ON after airplane mode is set. When APM is set, WLAN turns off.
6231 * But it can be turned back on. Otherwise; when APM is turned back
6232 * off, WLAN wld turn back on. So at that point the command is
6233 * expected to come down. 0 means disable, 1 means enable. The
6234 * constraint is removed when parameter 1 is set or different
6235 * country code is set
6236 */
6237 ret = hdd_cmd_setFccChannel(pHddCtx, command, 15);
6238 }
Mahesh A Saptasagarbeca12c2015-09-07 16:21:06 +05306239 else if (strncasecmp(command, "DISABLE_CA_EVENT", 16) == 0)
6240 {
Rajeev Kumar Sirasanagandlaf740b1e2017-08-23 18:07:01 +05306241 ret = hdd_drv_cmd_validate(command, 16);
6242 if (ret)
6243 goto exit;
6244
Mahesh A Saptasagarbeca12c2015-09-07 16:21:06 +05306245 ret = hdd_enable_disable_ca_event(pHddCtx, command, 16);
6246 }
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07006247 else {
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05306248 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
6249 TRACE_CODE_HDD_UNSUPPORTED_IOCTL,
6250 pAdapter->sessionId, 0));
Satyanarayana Dash72806012014-12-02 14:30:08 +05306251 hddLog( VOS_TRACE_LEVEL_WARN, FL("Unsupported GUI command %s"),
6252 command);
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07006253 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006254 }
6255exit:
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05306256 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07006257 if (command)
6258 {
6259 kfree(command);
6260 }
6261 return ret;
6262}
6263
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07006264#ifdef CONFIG_COMPAT
6265static int hdd_driver_compat_ioctl(hdd_adapter_t *pAdapter, struct ifreq *ifr)
6266{
6267 struct {
6268 compat_uptr_t buf;
6269 int used_len;
6270 int total_len;
6271 } compat_priv_data;
6272 hdd_priv_data_t priv_data;
6273 int ret = 0;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006274
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07006275 /*
6276 * Note that pAdapter and ifr have already been verified by caller,
6277 * and HDD context has also been validated
6278 */
6279 if (copy_from_user(&compat_priv_data, ifr->ifr_data,
6280 sizeof(compat_priv_data))) {
6281 ret = -EFAULT;
6282 goto exit;
6283 }
6284 priv_data.buf = compat_ptr(compat_priv_data.buf);
6285 priv_data.used_len = compat_priv_data.used_len;
6286 priv_data.total_len = compat_priv_data.total_len;
6287 ret = hdd_driver_command(pAdapter, &priv_data);
6288 exit:
6289 return ret;
6290}
6291#else /* CONFIG_COMPAT */
6292static int hdd_driver_compat_ioctl(hdd_adapter_t *pAdapter, struct ifreq *ifr)
6293{
6294 /* will never be invoked */
6295 return 0;
6296}
6297#endif /* CONFIG_COMPAT */
6298
6299static int hdd_driver_ioctl(hdd_adapter_t *pAdapter, struct ifreq *ifr)
6300{
6301 hdd_priv_data_t priv_data;
6302 int ret = 0;
6303
6304 /*
6305 * Note that pAdapter and ifr have already been verified by caller,
6306 * and HDD context has also been validated
6307 */
6308 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(priv_data))) {
6309 ret = -EFAULT;
6310 } else {
6311 ret = hdd_driver_command(pAdapter, &priv_data);
6312 }
6313 return ret;
6314}
6315
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05306316int __hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07006317{
6318 hdd_adapter_t *pAdapter;
6319 hdd_context_t *pHddCtx;
6320 int ret;
6321
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05306322 ENTER();
6323
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07006324 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6325 if (NULL == pAdapter) {
6326 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6327 "%s: HDD adapter context is Null", __func__);
6328 ret = -ENODEV;
6329 goto exit;
6330 }
6331 if (dev != pAdapter->dev) {
6332 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6333 "%s: HDD adapter/dev inconsistency", __func__);
6334 ret = -ENODEV;
6335 goto exit;
6336 }
6337
6338 if ((!ifr) || (!ifr->ifr_data)) {
6339 ret = -EINVAL;
6340 goto exit;
6341 }
6342
6343 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6344 ret = wlan_hdd_validate_context(pHddCtx);
6345 if (ret) {
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07006346 ret = -EBUSY;
6347 goto exit;
6348 }
6349
6350 switch (cmd) {
6351 case (SIOCDEVPRIVATE + 1):
6352 if (is_compat_task())
6353 ret = hdd_driver_compat_ioctl(pAdapter, ifr);
6354 else
6355 ret = hdd_driver_ioctl(pAdapter, ifr);
6356 break;
6357 default:
6358 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unknown ioctl %d",
6359 __func__, cmd);
6360 ret = -EINVAL;
6361 break;
6362 }
6363 exit:
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05306364 EXIT();
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07006365 return ret;
6366}
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006367
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05306368int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
6369{
6370 int ret;
6371
6372 vos_ssr_protect(__func__);
6373 ret = __hdd_ioctl(dev, ifr, cmd);
6374 vos_ssr_unprotect(__func__);
6375
6376 return ret;
6377}
6378
Katya Nigame7b69a82015-04-28 15:24:06 +05306379int hdd_mon_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
6380{
6381 return 0;
6382}
6383
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006384#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006385/**---------------------------------------------------------------------------
6386
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006387 \brief hdd_parse_ese_beacon_req() - Parse ese beacon request
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006388
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006389 This function parses the ese beacon request passed in the format
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006390 CCXBEACONREQ<space><Number of fields><space><Measurement token>
6391 <space>Channel 1<space>Scan Mode <space>Meas Duration<space>Channel N
6392 <space>Scan Mode N<space>Meas Duration N
6393 if the Number of bcn req fields (N) does not match with the actual number of fields passed
6394 then take N.
6395 <Meas Token><Channel><Scan Mode> and <Meas Duration> are treated as one pair
6396 For example, CCXBEACONREQ 2 1 1 1 30 2 44 0 40.
6397 This function does not take care of removing duplicate channels from the list
6398
6399 \param - pValue Pointer to data
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006400 \param - pEseBcnReq output pointer to store parsed ie information
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006401
6402 \return - 0 for success non-zero for failure
6403
6404 --------------------------------------------------------------------------*/
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006405static VOS_STATUS hdd_parse_ese_beacon_req(tANI_U8 *pValue,
6406 tCsrEseBeaconReq *pEseBcnReq)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006407{
6408 tANI_U8 *inPtr = pValue;
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306409 uint8_t input = 0;
6410 uint32_t tempInt = 0;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006411 int j = 0, i = 0, v = 0;
6412 char buf[32];
6413
6414 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
6415 /*no argument after the command*/
6416 if (NULL == inPtr)
6417 {
6418 return -EINVAL;
6419 }
6420 /*no space after the command*/
6421 else if (SPACE_ASCII_VALUE != *inPtr)
6422 {
6423 return -EINVAL;
6424 }
6425
6426 /*removing empty spaces*/
6427 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
6428
6429 /*no argument followed by spaces*/
6430 if ('\0' == *inPtr) return -EINVAL;
6431
6432 /*getting the first argument ie measurement token*/
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08006433 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006434 if (1 != v) return -EINVAL;
6435
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306436 v = kstrtos8(buf, 10, &input);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006437 if ( v < 0) return -EINVAL;
6438
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306439 input = VOS_MIN(input, SIR_ESE_MAX_MEAS_IE_REQS);
6440 pEseBcnReq->numBcnReqIe = input;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006441
Srinivas Girigowda725a88e2016-03-31 19:24:25 +05306442 hddLog(LOG1, "Number of Bcn Req Ie fields: %d", pEseBcnReq->numBcnReqIe);
6443
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006444
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006445 for (j = 0; j < (pEseBcnReq->numBcnReqIe); j++)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006446 {
6447 for (i = 0; i < 4; i++)
6448 {
6449 /*inPtr pointing to the beginning of first space after number of ie fields*/
6450 inPtr = strpbrk( inPtr, " " );
6451 /*no ie data after the number of ie fields argument*/
6452 if (NULL == inPtr) return -EINVAL;
6453
6454 /*removing empty space*/
6455 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
6456
6457 /*no ie data after the number of ie fields argument and spaces*/
6458 if ( '\0' == *inPtr ) return -EINVAL;
6459
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08006460 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006461 if (1 != v) return -EINVAL;
6462
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306463 v = kstrtou32(buf, 10, &tempInt);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006464 if (v < 0) return -EINVAL;
6465
6466 switch (i)
6467 {
6468 case 0: /* Measurement token */
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306469 if (!tempInt)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006470 {
6471 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306472 "Invalid Measurement Token: %u", tempInt);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006473 return -EINVAL;
6474 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006475 pEseBcnReq->bcnReq[j].measurementToken = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006476 break;
6477
6478 case 1: /* Channel number */
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306479 if ((!tempInt) ||
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006480 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
6481 {
6482 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306483 "Invalid Channel Number: %u", tempInt);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006484 return -EINVAL;
6485 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006486 pEseBcnReq->bcnReq[j].channel = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006487 break;
6488
6489 case 2: /* Scan mode */
Varun Reddy Yeturu0b18d5a2013-12-04 11:42:23 -08006490 if ((tempInt < eSIR_PASSIVE_SCAN) || (tempInt > eSIR_BEACON_TABLE))
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006491 {
6492 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306493 "Invalid Scan Mode(%u) Expected{0|1|2}", tempInt);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006494 return -EINVAL;
6495 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006496 pEseBcnReq->bcnReq[j].scanMode= tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006497 break;
6498
6499 case 3: /* Measurement duration */
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306500 if (((!tempInt) && (pEseBcnReq->bcnReq[j].scanMode != eSIR_BEACON_TABLE)) ||
6501 ((pEseBcnReq->bcnReq[j].scanMode == eSIR_BEACON_TABLE)))
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006502 {
6503 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306504 "Invalid Measurement Duration: %u", tempInt);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006505 return -EINVAL;
6506 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006507 pEseBcnReq->bcnReq[j].measurementDuration = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006508 break;
6509 }
6510 }
6511 }
6512
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006513 for (j = 0; j < pEseBcnReq->numBcnReqIe; j++)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006514 {
6515 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arun Kumar Khandavallie8768212014-02-17 16:43:34 +05306516 "Index(%d) Measurement Token(%u)Channel(%u) Scan Mode(%u) Measurement Duration(%u)\n",
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006517 j,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006518 pEseBcnReq->bcnReq[j].measurementToken,
6519 pEseBcnReq->bcnReq[j].channel,
6520 pEseBcnReq->bcnReq[j].scanMode,
6521 pEseBcnReq->bcnReq[j].measurementDuration);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006522 }
6523
6524 return VOS_STATUS_SUCCESS;
6525}
6526
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006527static void hdd_GetTsmStatsCB( tAniTrafStrmMetrics tsmMetrics, const tANI_U32 staId, void *pContext )
6528{
6529 struct statsContext *pStatsContext = NULL;
6530 hdd_adapter_t *pAdapter = NULL;
6531
6532 if (NULL == pContext)
6533 {
6534 hddLog(VOS_TRACE_LEVEL_ERROR,
6535 "%s: Bad param, pContext [%p]",
6536 __func__, pContext);
6537 return;
6538 }
6539
Jeff Johnson72a40512013-12-19 10:14:15 -08006540 /* there is a race condition that exists between this callback
6541 function and the caller since the caller could time out either
6542 before or while this code is executing. we use a spinlock to
6543 serialize these actions */
6544 spin_lock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006545
6546 pStatsContext = pContext;
6547 pAdapter = pStatsContext->pAdapter;
6548 if ((NULL == pAdapter) || (STATS_CONTEXT_MAGIC != pStatsContext->magic))
6549 {
6550 /* the caller presumably timed out so there is nothing we can do */
Jeff Johnson72a40512013-12-19 10:14:15 -08006551 spin_unlock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006552 hddLog(VOS_TRACE_LEVEL_WARN,
6553 "%s: Invalid context, pAdapter [%p] magic [%08x]",
6554 __func__, pAdapter, pStatsContext->magic);
6555 return;
6556 }
6557
Jeff Johnson72a40512013-12-19 10:14:15 -08006558 /* context is valid so caller is still waiting */
6559
6560 /* paranoia: invalidate the magic */
6561 pStatsContext->magic = 0;
6562
6563 /* copy over the tsm stats */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006564 pAdapter->tsmStats.UplinkPktQueueDly = tsmMetrics.UplinkPktQueueDly;
6565 vos_mem_copy(pAdapter->tsmStats.UplinkPktQueueDlyHist,
6566 tsmMetrics.UplinkPktQueueDlyHist,
6567 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
6568 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
6569 pAdapter->tsmStats.UplinkPktTxDly = tsmMetrics.UplinkPktTxDly;
6570 pAdapter->tsmStats.UplinkPktLoss = tsmMetrics.UplinkPktLoss;
6571 pAdapter->tsmStats.UplinkPktCount = tsmMetrics.UplinkPktCount;
6572 pAdapter->tsmStats.RoamingCount = tsmMetrics.RoamingCount;
6573 pAdapter->tsmStats.RoamingDly = tsmMetrics.RoamingDly;
6574
Jeff Johnson72a40512013-12-19 10:14:15 -08006575 /* notify the caller */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006576 complete(&pStatsContext->completion);
Jeff Johnson72a40512013-12-19 10:14:15 -08006577
6578 /* serialization is complete */
6579 spin_unlock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006580}
6581
6582
6583
6584static VOS_STATUS hdd_get_tsm_stats(hdd_adapter_t *pAdapter, const tANI_U8 tid,
6585 tAniTrafStrmMetrics* pTsmMetrics)
6586{
6587 hdd_station_ctx_t *pHddStaCtx = NULL;
6588 eHalStatus hstatus;
Jeff Johnson72a40512013-12-19 10:14:15 -08006589 VOS_STATUS vstatus = VOS_STATUS_SUCCESS;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006590 long lrc;
6591 struct statsContext context;
6592 hdd_context_t *pHddCtx = NULL;
6593
6594 if (NULL == pAdapter)
6595 {
6596 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: pAdapter is NULL", __func__);
6597 return VOS_STATUS_E_FAULT;
6598 }
6599
6600 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6601 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6602
6603 /* we are connected prepare our callback context */
6604 init_completion(&context.completion);
6605 context.pAdapter = pAdapter;
6606 context.magic = STATS_CONTEXT_MAGIC;
6607
6608 /* query tsm stats */
6609 hstatus = sme_GetTsmStats(pHddCtx->hHal, hdd_GetTsmStatsCB,
6610 pHddStaCtx->conn_info.staId[ 0 ],
6611 pHddStaCtx->conn_info.bssId,
6612 &context, pHddCtx->pvosContext, tid);
6613
6614 if (eHAL_STATUS_SUCCESS != hstatus)
6615 {
Jeff Johnson72a40512013-12-19 10:14:15 -08006616 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unable to retrieve statistics",
6617 __func__);
6618 vstatus = VOS_STATUS_E_FAULT;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006619 }
6620 else
6621 {
6622 /* request was sent -- wait for the response */
6623 lrc = wait_for_completion_interruptible_timeout(&context.completion,
6624 msecs_to_jiffies(WLAN_WAIT_TIME_STATS));
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006625 if (lrc <= 0)
6626 {
6627 hddLog(VOS_TRACE_LEVEL_ERROR,
6628 "%s: SME %s while retrieving statistics",
6629 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson72a40512013-12-19 10:14:15 -08006630 vstatus = VOS_STATUS_E_TIMEOUT;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006631 }
6632 }
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006633
Jeff Johnson72a40512013-12-19 10:14:15 -08006634 /* either we never sent a request, we sent a request and received a
6635 response or we sent a request and timed out. if we never sent a
6636 request or if we sent a request and got a response, we want to
6637 clear the magic out of paranoia. if we timed out there is a
6638 race condition such that the callback function could be
6639 executing at the same time we are. of primary concern is if the
6640 callback function had already verified the "magic" but had not
6641 yet set the completion variable when a timeout occurred. we
6642 serialize these activities by invalidating the magic while
6643 holding a shared spinlock which will cause us to block if the
6644 callback is currently executing */
6645 spin_lock(&hdd_context_lock);
6646 context.magic = 0;
6647 spin_unlock(&hdd_context_lock);
6648
6649 if (VOS_STATUS_SUCCESS == vstatus)
6650 {
6651 pTsmMetrics->UplinkPktQueueDly = pAdapter->tsmStats.UplinkPktQueueDly;
6652 vos_mem_copy(pTsmMetrics->UplinkPktQueueDlyHist,
6653 pAdapter->tsmStats.UplinkPktQueueDlyHist,
6654 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
6655 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
6656 pTsmMetrics->UplinkPktTxDly = pAdapter->tsmStats.UplinkPktTxDly;
6657 pTsmMetrics->UplinkPktLoss = pAdapter->tsmStats.UplinkPktLoss;
6658 pTsmMetrics->UplinkPktCount = pAdapter->tsmStats.UplinkPktCount;
6659 pTsmMetrics->RoamingCount = pAdapter->tsmStats.RoamingCount;
6660 pTsmMetrics->RoamingDly = pAdapter->tsmStats.RoamingDly;
6661 }
6662 return vstatus;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006663}
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006664#endif /*FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006665
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006666#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -08006667void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
6668{
6669 eCsrBand band = -1;
6670 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
6671 switch (band)
6672 {
6673 case eCSR_BAND_ALL:
6674 *pBand = WLAN_HDD_UI_BAND_AUTO;
6675 break;
6676
6677 case eCSR_BAND_24:
6678 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
6679 break;
6680
6681 case eCSR_BAND_5G:
6682 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
6683 break;
6684
6685 default:
6686 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
6687 *pBand = -1;
6688 break;
6689 }
6690}
6691
6692/**---------------------------------------------------------------------------
6693
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006694 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
6695
6696 This function parses the send action frame data passed in the format
6697 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
6698
Srinivas Girigowda56076852013-08-20 14:00:50 -07006699 \param - pValue Pointer to input data
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006700 \param - pTargetApBssid Pointer to target Ap bssid
6701 \param - pChannel Pointer to the Target AP channel
6702 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
6703 \param - pBuf Pointer to data
6704 \param - pBufLen Pointer to data length
6705
6706 \return - 0 for success non-zero for failure
6707
6708 --------------------------------------------------------------------------*/
6709VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
6710 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
6711{
6712 tANI_U8 *inPtr = pValue;
6713 tANI_U8 *dataEnd;
6714 int tempInt;
6715 int j = 0;
6716 int i = 0;
6717 int v = 0;
6718 tANI_U8 tempBuf[32];
6719 tANI_U8 tempByte = 0;
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08006720 /* 12 hexa decimal digits, 5 ':' and '\0' */
6721 tANI_U8 macAddress[18];
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006722
6723 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
6724 /*no argument after the command*/
6725 if (NULL == inPtr)
6726 {
6727 return -EINVAL;
6728 }
6729
6730 /*no space after the command*/
6731 else if (SPACE_ASCII_VALUE != *inPtr)
6732 {
6733 return -EINVAL;
6734 }
6735
6736 /*removing empty spaces*/
6737 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
6738
6739 /*no argument followed by spaces*/
6740 if ('\0' == *inPtr)
6741 {
6742 return -EINVAL;
6743 }
6744
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07006745 v = sscanf(inPtr, "%17s", macAddress);
6746 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006747 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07006748 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6749 "Invalid MAC address or All hex inputs are not read (%d)", v);
6750 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006751 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07006752
6753 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
6754 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
6755 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
6756 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
6757 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
6758 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006759
6760 /* point to the next argument */
6761 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
6762 /*no argument after the command*/
6763 if (NULL == inPtr) return -EINVAL;
6764
6765 /*removing empty spaces*/
6766 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
6767
6768 /*no argument followed by spaces*/
6769 if ('\0' == *inPtr)
6770 {
6771 return -EINVAL;
6772 }
6773
6774 /*getting the next argument ie the channel number */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08006775 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07006776 if (1 != v) return -EINVAL;
6777
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006778 v = kstrtos32(tempBuf, 10, &tempInt);
Agarwal Ashish353b3a82014-04-08 14:55:11 +05306779 if ( v < 0 || tempInt <= 0 || tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX )
Kiet Lambe150c22013-11-21 16:30:32 +05306780 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006781
6782 *pChannel = tempInt;
6783
6784 /* point to the next argument */
6785 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
6786 /*no argument after the command*/
6787 if (NULL == inPtr) return -EINVAL;
6788 /*removing empty spaces*/
6789 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
6790
6791 /*no argument followed by spaces*/
6792 if ('\0' == *inPtr)
6793 {
6794 return -EINVAL;
6795 }
6796
6797 /*getting the next argument ie the dwell time */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08006798 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07006799 if (1 != v) return -EINVAL;
6800
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006801 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda5a6e0672014-01-09 14:42:57 -08006802 if ( v < 0 || tempInt < 0) return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006803
6804 *pDwellTime = tempInt;
6805
6806 /* point to the next argument */
6807 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
6808 /*no argument after the command*/
6809 if (NULL == inPtr) return -EINVAL;
6810 /*removing empty spaces*/
6811 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
6812
6813 /*no argument followed by spaces*/
6814 if ('\0' == *inPtr)
6815 {
6816 return -EINVAL;
6817 }
6818
6819 /* find the length of data */
6820 dataEnd = inPtr;
6821 while(('\0' != *dataEnd) )
6822 {
6823 dataEnd++;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006824 }
Kiet Lambe150c22013-11-21 16:30:32 +05306825 *pBufLen = dataEnd - inPtr ;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006826 if ( *pBufLen <= 0) return -EINVAL;
6827
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07006828 /* Allocate the number of bytes based on the number of input characters
6829 whether it is even or odd.
6830 if the number of input characters are even, then we need N/2 byte.
6831 if the number of input characters are odd, then we need do (N+1)/2 to
6832 compensate rounding off.
6833 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
6834 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
6835 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006836 if (NULL == *pBuf)
6837 {
6838 hddLog(VOS_TRACE_LEVEL_FATAL,
6839 "%s: vos_mem_alloc failed ", __func__);
6840 return -EINVAL;
6841 }
6842
6843 /* the buffer received from the upper layer is character buffer,
6844 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
6845 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
6846 and f0 in 3rd location */
6847 for (i = 0, j = 0; j < *pBufLen; j += 2)
6848 {
Kiet Lambe150c22013-11-21 16:30:32 +05306849 if( j+1 == *pBufLen)
6850 {
6851 tempByte = hdd_parse_hex(inPtr[j]);
6852 }
6853 else
6854 {
6855 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
6856 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006857 (*pBuf)[i++] = tempByte;
6858 }
6859 *pBufLen = i;
6860 return VOS_STATUS_SUCCESS;
6861}
6862
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006863/**---------------------------------------------------------------------------
6864
Srinivas Girigowdade697412013-02-14 16:31:48 -08006865 \brief hdd_parse_channellist() - HDD Parse channel list
6866
6867 This function parses the channel list passed in the format
6868 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07006869 if the Number of channels (N) does not match with the actual number of channels passed
6870 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
6871 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
6872 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
6873 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08006874
6875 \param - pValue Pointer to input channel list
6876 \param - ChannelList Pointer to local output array to record channel list
6877 \param - pNumChannels Pointer to number of roam scan channels
6878
6879 \return - 0 for success non-zero for failure
6880
6881 --------------------------------------------------------------------------*/
6882VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
6883{
6884 tANI_U8 *inPtr = pValue;
6885 int tempInt;
6886 int j = 0;
6887 int v = 0;
6888 char buf[32];
6889
6890 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
6891 /*no argument after the command*/
6892 if (NULL == inPtr)
6893 {
6894 return -EINVAL;
6895 }
6896
6897 /*no space after the command*/
6898 else if (SPACE_ASCII_VALUE != *inPtr)
6899 {
6900 return -EINVAL;
6901 }
6902
6903 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07006904 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08006905
6906 /*no argument followed by spaces*/
6907 if ('\0' == *inPtr)
6908 {
6909 return -EINVAL;
6910 }
6911
6912 /*getting the first argument ie the number of channels*/
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08006913 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07006914 if (1 != v) return -EINVAL;
6915
Srinivas Girigowdade697412013-02-14 16:31:48 -08006916 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07006917 if ((v < 0) ||
6918 (tempInt <= 0) ||
6919 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
6920 {
6921 return -EINVAL;
6922 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08006923
6924 *pNumChannels = tempInt;
6925
6926 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
6927 "Number of channels are: %d", *pNumChannels);
6928
6929 for (j = 0; j < (*pNumChannels); j++)
6930 {
6931 /*inPtr pointing to the beginning of first space after number of channels*/
6932 inPtr = strpbrk( inPtr, " " );
6933 /*no channel list after the number of channels argument*/
6934 if (NULL == inPtr)
6935 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07006936 if (0 != j)
6937 {
6938 *pNumChannels = j;
6939 return VOS_STATUS_SUCCESS;
6940 }
6941 else
6942 {
6943 return -EINVAL;
6944 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08006945 }
6946
6947 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07006948 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08006949
6950 /*no channel list after the number of channels argument and spaces*/
6951 if ( '\0' == *inPtr )
6952 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07006953 if (0 != j)
6954 {
6955 *pNumChannels = j;
6956 return VOS_STATUS_SUCCESS;
6957 }
6958 else
6959 {
6960 return -EINVAL;
6961 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08006962 }
6963
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08006964 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07006965 if (1 != v) return -EINVAL;
6966
Srinivas Girigowdade697412013-02-14 16:31:48 -08006967 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07006968 if ((v < 0) ||
6969 (tempInt <= 0) ||
6970 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
6971 {
6972 return -EINVAL;
6973 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08006974 pChannelList[j] = tempInt;
6975
6976 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
6977 "Channel %d added to preferred channel list",
6978 pChannelList[j] );
6979 }
6980
Srinivas Girigowdade697412013-02-14 16:31:48 -08006981 return VOS_STATUS_SUCCESS;
6982}
6983
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07006984
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05306985/**
6986 * hdd_parse_reassoc_command_v1_data() - HDD Parse reassoc command data
6987 * This function parses the reasoc command data passed in the format
6988 * REASSOC<space><bssid><space><channel>
6989 *
6990 * @pValue: Pointer to input data (its a NUL terminated string)
6991 * @pTargetApBssid: Pointer to target Ap bssid
6992 * @pChannel: Pointer to the Target AP channel
6993 *
6994 * Return: 0 for success non-zero for failure
6995 */
6996static int hdd_parse_reassoc_command_v1_data(const tANI_U8 *pValue,
6997 tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07006998{
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05306999 const tANI_U8 *inPtr = pValue;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07007000 int tempInt;
7001 int v = 0;
7002 tANI_U8 tempBuf[32];
Kiet Lamaa8e15a2014-02-11 23:30:06 -08007003 /* 12 hexa decimal digits, 5 ':' and '\0' */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08007004 tANI_U8 macAddress[18];
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07007005
7006 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
7007 /*no argument after the command*/
7008 if (NULL == inPtr)
7009 {
7010 return -EINVAL;
7011 }
7012
7013 /*no space after the command*/
7014 else if (SPACE_ASCII_VALUE != *inPtr)
7015 {
7016 return -EINVAL;
7017 }
7018
7019 /*removing empty spaces*/
7020 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
7021
7022 /*no argument followed by spaces*/
7023 if ('\0' == *inPtr)
7024 {
7025 return -EINVAL;
7026 }
7027
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07007028 v = sscanf(inPtr, "%17s", macAddress);
7029 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07007030 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07007031 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7032 "Invalid MAC address or All hex inputs are not read (%d)", v);
7033 return -EINVAL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07007034 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07007035
7036 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
7037 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
7038 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
7039 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
7040 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
7041 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07007042
7043 /* point to the next argument */
7044 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
7045 /*no argument after the command*/
7046 if (NULL == inPtr) return -EINVAL;
7047
7048 /*removing empty spaces*/
7049 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
7050
7051 /*no argument followed by spaces*/
7052 if ('\0' == *inPtr)
7053 {
7054 return -EINVAL;
7055 }
7056
7057 /*getting the next argument ie the channel number */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08007058 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07007059 if (1 != v) return -EINVAL;
7060
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07007061 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07007062 if ((v < 0) ||
Padma, Santhosh Kumar0fa809b2014-11-13 14:56:56 +05307063 (tempInt < 0) ||
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07007064 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
7065 {
7066 return -EINVAL;
7067 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07007068
7069 *pChannel = tempInt;
7070 return VOS_STATUS_SUCCESS;
7071}
7072
7073#endif
7074
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08007075#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07007076/**---------------------------------------------------------------------------
7077
7078 \brief hdd_parse_get_cckm_ie() - HDD Parse and fetch the CCKM IE
7079
7080 This function parses the SETCCKM IE command
7081 SETCCKMIE<space><ie data>
7082
7083 \param - pValue Pointer to input data
7084 \param - pCckmIe Pointer to output cckm Ie
7085 \param - pCckmIeLen Pointer to output cckm ie length
7086
7087 \return - 0 for success non-zero for failure
7088
7089 --------------------------------------------------------------------------*/
7090VOS_STATUS hdd_parse_get_cckm_ie(tANI_U8 *pValue, tANI_U8 **pCckmIe,
7091 tANI_U8 *pCckmIeLen)
7092{
7093 tANI_U8 *inPtr = pValue;
7094 tANI_U8 *dataEnd;
7095 int j = 0;
7096 int i = 0;
7097 tANI_U8 tempByte = 0;
7098
7099 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
7100 /*no argument after the command*/
7101 if (NULL == inPtr)
7102 {
7103 return -EINVAL;
7104 }
7105
7106 /*no space after the command*/
7107 else if (SPACE_ASCII_VALUE != *inPtr)
7108 {
7109 return -EINVAL;
7110 }
7111
7112 /*removing empty spaces*/
7113 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
7114
7115 /*no argument followed by spaces*/
7116 if ('\0' == *inPtr)
7117 {
7118 return -EINVAL;
7119 }
7120
7121 /* find the length of data */
7122 dataEnd = inPtr;
7123 while(('\0' != *dataEnd) )
7124 {
7125 dataEnd++;
7126 ++(*pCckmIeLen);
7127 }
7128 if ( *pCckmIeLen <= 0) return -EINVAL;
7129
7130 /* Allocate the number of bytes based on the number of input characters
7131 whether it is even or odd.
7132 if the number of input characters are even, then we need N/2 byte.
7133 if the number of input characters are odd, then we need do (N+1)/2 to
7134 compensate rounding off.
7135 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
7136 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
7137 *pCckmIe = vos_mem_malloc((*pCckmIeLen + 1)/2);
7138 if (NULL == *pCckmIe)
7139 {
7140 hddLog(VOS_TRACE_LEVEL_FATAL,
7141 "%s: vos_mem_alloc failed ", __func__);
7142 return -EINVAL;
7143 }
7144 vos_mem_zero(*pCckmIe, (*pCckmIeLen + 1)/2);
7145 /* the buffer received from the upper layer is character buffer,
7146 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
7147 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
7148 and f0 in 3rd location */
7149 for (i = 0, j = 0; j < *pCckmIeLen; j += 2)
7150 {
7151 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
7152 (*pCckmIe)[i++] = tempByte;
7153 }
7154 *pCckmIeLen = i;
7155
7156 return VOS_STATUS_SUCCESS;
7157}
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08007158#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07007159
Jeff Johnson295189b2012-06-20 16:38:30 -07007160/**---------------------------------------------------------------------------
7161
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07007162 \brief hdd_is_valid_mac_address() - Validate MAC address
7163
7164 This function validates whether the given MAC address is valid or not
7165 Expected MAC address is of the format XX:XX:XX:XX:XX:XX
7166 where X is the hexa decimal digit character and separated by ':'
7167 This algorithm works even if MAC address is not separated by ':'
7168
7169 This code checks given input string mac contains exactly 12 hexadecimal digits.
7170 and a separator colon : appears in the input string only after
7171 an even number of hex digits.
7172
7173 \param - pMacAddr pointer to the input MAC address
7174 \return - 1 for valid and 0 for invalid
7175
7176 --------------------------------------------------------------------------*/
7177
7178v_BOOL_t hdd_is_valid_mac_address(const tANI_U8 *pMacAddr)
7179{
7180 int xdigit = 0;
7181 int separator = 0;
7182 while (*pMacAddr)
7183 {
7184 if (isxdigit(*pMacAddr))
7185 {
7186 xdigit++;
7187 }
7188 else if (':' == *pMacAddr)
7189 {
7190 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
7191 break;
7192
7193 ++separator;
7194 }
7195 else
7196 {
7197 separator = -1;
7198 /* Invalid MAC found */
7199 return 0;
7200 }
7201 ++pMacAddr;
7202 }
7203 return (xdigit == 12 && (separator == 5 || separator == 0));
7204}
7205
7206/**---------------------------------------------------------------------------
7207
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307208 \brief __hdd_open() - HDD Open function
Jeff Johnson295189b2012-06-20 16:38:30 -07007209
7210 \param - dev Pointer to net_device structure
7211
7212 \return - 0 for success non-zero for failure
7213
7214 --------------------------------------------------------------------------*/
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307215int __hdd_open(struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07007216{
7217 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7218 hdd_context_t *pHddCtx;
7219 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7220 VOS_STATUS status;
7221 v_BOOL_t in_standby = TRUE;
7222
7223 if (NULL == pAdapter)
7224 {
7225 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Agarwal Ashish971c2882013-10-30 20:11:12 +05307226 "%s: pAdapter is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007227 return -ENODEV;
7228 }
7229
7230 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05307231 MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_OPEN_REQUEST,
7232 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson295189b2012-06-20 16:38:30 -07007233 if (NULL == pHddCtx)
7234 {
7235 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007236 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007237 return -ENODEV;
7238 }
7239
7240 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7241 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
7242 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07007243 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
7244 {
7245 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307246 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07007247 in_standby = FALSE;
7248 break;
7249 }
7250 else
7251 {
7252 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7253 pAdapterNode = pNext;
7254 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007255 }
7256
7257 if (TRUE == in_standby)
7258 {
7259 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
7260 {
7261 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
7262 "wlan out of power save", __func__);
7263 return -EINVAL;
7264 }
7265 }
7266
Jeff Johnson6a81ca42013-04-05 10:37:08 -07007267 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07007268 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
7269 {
7270 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007271 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007272 /* Enable TX queues only when we are connected */
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05307273 hddLog(VOS_TRACE_LEVEL_INFO, FL("Enabling queues"));
Jeff Johnson295189b2012-06-20 16:38:30 -07007274 netif_tx_start_all_queues(dev);
7275 }
7276
7277 return 0;
7278}
7279
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307280/**---------------------------------------------------------------------------
7281
7282 \brief hdd_open() - Wrapper function for __hdd_open to protect it from SSR
7283
7284 This is called in response to ifconfig up
7285
7286 \param - dev Pointer to net_device structure
7287
7288 \return - 0 for success non-zero for failure
7289
7290 --------------------------------------------------------------------------*/
7291int hdd_open(struct net_device *dev)
7292{
7293 int ret;
7294
7295 vos_ssr_protect(__func__);
7296 ret = __hdd_open(dev);
7297 vos_ssr_unprotect(__func__);
7298
7299 return ret;
7300}
7301
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +05307302int __hdd_mon_open (struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07007303{
7304 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7305
7306 if(pAdapter == NULL) {
7307 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007308 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007309 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007310 }
7311
Jeff Johnson295189b2012-06-20 16:38:30 -07007312 return 0;
7313}
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +05307314
7315int hdd_mon_open (struct net_device *dev)
7316{
7317 int ret;
7318
7319 vos_ssr_protect(__func__);
7320 ret = __hdd_mon_open(dev);
7321 vos_ssr_unprotect(__func__);
7322
7323 return ret;
7324}
7325
Katya Nigame7b69a82015-04-28 15:24:06 +05307326int hdd_mon_stop(struct net_device *dev)
7327{
7328 return 0;
7329}
7330
Jeff Johnson295189b2012-06-20 16:38:30 -07007331/**---------------------------------------------------------------------------
7332
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307333 \brief __hdd_stop() - HDD stop function
Jeff Johnson295189b2012-06-20 16:38:30 -07007334
7335 \param - dev Pointer to net_device structure
7336
7337 \return - 0 for success non-zero for failure
7338
7339 --------------------------------------------------------------------------*/
7340
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307341int __hdd_stop (struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07007342{
Vinay Krishna Eranna90f43532014-10-27 16:45:54 +05307343 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07007344 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7345 hdd_context_t *pHddCtx;
7346 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7347 VOS_STATUS status;
7348 v_BOOL_t enter_standby = TRUE;
7349
7350 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07007351 if (NULL == pAdapter)
7352 {
7353 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Agarwal Ashish971c2882013-10-30 20:11:12 +05307354 "%s: pAdapter is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007355 return -ENODEV;
7356 }
Sachin Ahuja9b4958f2015-01-15 21:37:00 +05307357 MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_STOP_REQUEST,
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05307358 pAdapter->sessionId, pAdapter->device_mode));
Vinay Krishna Eranna90f43532014-10-27 16:45:54 +05307359
7360 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7361 ret = wlan_hdd_validate_context(pHddCtx);
7362 if (ret)
Jeff Johnson295189b2012-06-20 16:38:30 -07007363 {
Vinay Krishna Eranna90f43532014-10-27 16:45:54 +05307364 return ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07007365 }
7366
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307367 /* Nothing to be done if the interface is not opened */
7368 if (VOS_FALSE == test_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags))
7369 {
7370 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7371 "%s: NETDEV Interface is not OPENED", __func__);
7372 return -ENODEV;
7373 }
7374
7375 /* Make sure the interface is marked as closed */
Jeff Johnson6a81ca42013-04-05 10:37:08 -07007376 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07007377 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307378
7379 /* Disable TX on the interface, after this hard_start_xmit() will not
7380 * be called on that interface
7381 */
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05307382 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
Jeff Johnson295189b2012-06-20 16:38:30 -07007383 netif_tx_disable(pAdapter->dev);
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307384
7385 /* Mark the interface status as "down" for outside world */
Jeff Johnson295189b2012-06-20 16:38:30 -07007386 netif_carrier_off(pAdapter->dev);
7387
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307388 /* The interface is marked as down for outside world (aka kernel)
7389 * But the driver is pretty much alive inside. The driver needs to
7390 * tear down the existing connection on the netdev (session)
7391 * cleanup the data pipes and wait until the control plane is stabilized
7392 * for this interface. The call also needs to wait until the above
7393 * mentioned actions are completed before returning to the caller.
7394 * Notice that the hdd_stop_adapter is requested not to close the session
7395 * That is intentional to be able to scan if it is a STA/P2P interface
7396 */
7397 hdd_stop_adapter(pHddCtx, pAdapter, VOS_FALSE);
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05307398#ifdef FEATURE_WLAN_TDLS
7399 mutex_lock(&pHddCtx->tdls_lock);
7400#endif
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307401 /* DeInit the adapter. This ensures datapath cleanup as well */
c_hpothu002231a2015-02-05 14:58:51 +05307402 hdd_deinit_adapter(pHddCtx, pAdapter, TRUE);
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05307403#ifdef FEATURE_WLAN_TDLS
7404 mutex_unlock(&pHddCtx->tdls_lock);
7405#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007406 /* SoftAP ifaces should never go in power save mode
7407 making sure same here. */
7408 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
7409 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07007410 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07007411 )
7412 {
7413 /* SoftAP mode, so return from here */
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307414 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
7415 "%s: In SAP MODE", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007416 EXIT();
7417 return 0;
7418 }
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307419 /* Find if any iface is up. If any iface is up then can't put device to
7420 * sleep/power save mode
7421 */
Jeff Johnson295189b2012-06-20 16:38:30 -07007422 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7423 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
7424 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07007425 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
7426 {
7427 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307428 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07007429 enter_standby = FALSE;
7430 break;
7431 }
7432 else
7433 {
7434 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7435 pAdapterNode = pNext;
7436 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007437 }
7438
7439 if (TRUE == enter_standby)
7440 {
7441 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
7442 "entering standby", __func__);
7443 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
7444 {
7445 /*log and return success*/
7446 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
7447 "wlan in power save", __func__);
7448 }
7449 }
7450
7451 EXIT();
7452 return 0;
7453}
7454
7455/**---------------------------------------------------------------------------
7456
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307457 \brief hdd_stop() - wrapper_function for __hdd_stop to protect it from SSR
Jeff Johnson295189b2012-06-20 16:38:30 -07007458
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307459 This is called in response to ifconfig down
7460
7461 \param - dev Pointer to net_device structure
7462
7463 \return - 0 for success non-zero for failure
7464-----------------------------------------------------------------------------*/
7465int hdd_stop (struct net_device *dev)
7466{
7467 int ret;
7468
7469 vos_ssr_protect(__func__);
7470 ret = __hdd_stop(dev);
7471 vos_ssr_unprotect(__func__);
7472
7473 return ret;
7474}
7475
7476/**---------------------------------------------------------------------------
7477
7478 \brief __hdd_uninit() - HDD uninit function
Jeff Johnson295189b2012-06-20 16:38:30 -07007479
7480 \param - dev Pointer to net_device structure
7481
7482 \return - void
7483
7484 --------------------------------------------------------------------------*/
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307485static void __hdd_uninit (struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07007486{
7487 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05307488 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07007489 ENTER();
7490
7491 do
7492 {
7493 if (NULL == pAdapter)
7494 {
7495 hddLog(VOS_TRACE_LEVEL_FATAL,
7496 "%s: NULL pAdapter", __func__);
7497 break;
7498 }
7499
7500 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
7501 {
7502 hddLog(VOS_TRACE_LEVEL_FATAL,
7503 "%s: Invalid magic", __func__);
7504 break;
7505 }
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05307506 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7507 if (NULL == pHddCtx)
Jeff Johnson295189b2012-06-20 16:38:30 -07007508 {
7509 hddLog(VOS_TRACE_LEVEL_FATAL,
7510 "%s: NULL pHddCtx", __func__);
7511 break;
7512 }
7513
7514 if (dev != pAdapter->dev)
7515 {
7516 hddLog(VOS_TRACE_LEVEL_FATAL,
7517 "%s: Invalid device reference", __func__);
7518 /* we haven't validated all cases so let this go for now */
7519 }
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05307520#ifdef FEATURE_WLAN_TDLS
7521 mutex_lock(&pHddCtx->tdls_lock);
7522#endif
c_hpothu002231a2015-02-05 14:58:51 +05307523 hdd_deinit_adapter(pHddCtx, pAdapter, TRUE);
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05307524#ifdef FEATURE_WLAN_TDLS
7525 mutex_unlock(&pHddCtx->tdls_lock);
7526#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007527
7528 /* after uninit our adapter structure will no longer be valid */
7529 pAdapter->dev = NULL;
7530 pAdapter->magic = 0;
Manjeet Singh47ee8472016-04-11 11:57:18 +05307531 pAdapter->pHddCtx = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007532 } while (0);
7533
7534 EXIT();
7535}
7536
7537/**---------------------------------------------------------------------------
7538
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307539 \brief hdd_uninit() - Wrapper function to protect __hdd_uninit from SSR
7540
7541 This is called during the netdev unregister to uninitialize all data
7542associated with the device
7543
7544 \param - dev Pointer to net_device structure
7545
7546 \return - void
7547
7548 --------------------------------------------------------------------------*/
7549static void hdd_uninit (struct net_device *dev)
7550{
7551 vos_ssr_protect(__func__);
7552 __hdd_uninit(dev);
7553 vos_ssr_unprotect(__func__);
7554}
7555
7556/**---------------------------------------------------------------------------
7557
Jeff Johnson295189b2012-06-20 16:38:30 -07007558 \brief hdd_release_firmware() -
7559
7560 This function calls the release firmware API to free the firmware buffer.
7561
7562 \param - pFileName Pointer to the File Name.
7563 pCtx - Pointer to the adapter .
7564
7565
7566 \return - 0 for success, non zero for failure
7567
7568 --------------------------------------------------------------------------*/
7569
7570VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
7571{
7572 VOS_STATUS status = VOS_STATUS_SUCCESS;
7573 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
7574 ENTER();
7575
7576
7577 if (!strcmp(WLAN_FW_FILE, pFileName)) {
7578
7579 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
7580
7581 if(pHddCtx->fw) {
7582 release_firmware(pHddCtx->fw);
7583 pHddCtx->fw = NULL;
7584 }
7585 else
7586 status = VOS_STATUS_E_FAILURE;
7587 }
7588 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
7589 if(pHddCtx->nv) {
7590 release_firmware(pHddCtx->nv);
7591 pHddCtx->nv = NULL;
7592 }
7593 else
7594 status = VOS_STATUS_E_FAILURE;
7595
7596 }
7597
7598 EXIT();
7599 return status;
7600}
7601
7602/**---------------------------------------------------------------------------
7603
7604 \brief hdd_request_firmware() -
7605
7606 This function reads the firmware file using the request firmware
7607 API and returns the the firmware data and the firmware file size.
7608
7609 \param - pfileName - Pointer to the file name.
7610 - pCtx - Pointer to the adapter .
7611 - ppfw_data - Pointer to the pointer of the firmware data.
7612 - pSize - Pointer to the file size.
7613
7614 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
7615
7616 --------------------------------------------------------------------------*/
7617
7618
7619VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
7620{
7621 int status;
7622 VOS_STATUS retval = VOS_STATUS_SUCCESS;
7623 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
7624 ENTER();
7625
7626 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
7627
7628 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
7629
7630 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
7631 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
7632 __func__, pfileName);
7633 retval = VOS_STATUS_E_FAILURE;
7634 }
7635
7636 else {
7637 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
7638 *pSize = pHddCtx->fw->size;
7639 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
7640 __func__, *pSize);
7641 }
7642 }
7643 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
7644
7645 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
7646
7647 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
7648 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
7649 __func__, pfileName);
7650 retval = VOS_STATUS_E_FAILURE;
7651 }
7652
7653 else {
7654 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
7655 *pSize = pHddCtx->nv->size;
7656 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
7657 __func__, *pSize);
7658 }
7659 }
7660
7661 EXIT();
7662 return retval;
7663}
7664/**---------------------------------------------------------------------------
7665 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
7666
7667 This is the function invoked by SME to inform the result of a full power
7668 request issued by HDD
7669
7670 \param - callbackcontext - Pointer to cookie
7671 status - result of request
7672
7673 \return - None
7674
7675--------------------------------------------------------------------------*/
7676void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
7677{
7678 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
7679
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07007680 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07007681 if(&pHddCtx->full_pwr_comp_var)
7682 {
7683 complete(&pHddCtx->full_pwr_comp_var);
7684 }
7685}
7686
Abhishek Singh00b71972016-01-07 10:51:04 +05307687#ifdef WLAN_FEATURE_RMC
7688static void hdd_tx_fail_ind_callback(v_U8_t *MacAddr, v_U8_t seqNo)
7689{
7690 int payload_len;
7691 struct sk_buff *skb;
7692 struct nlmsghdr *nlh;
7693 v_U8_t *data;
7694
7695 payload_len = ETH_ALEN;
7696
7697 if (0 == cesium_pid)
7698 {
7699 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: cesium process not registered",
7700 __func__);
7701 return;
7702 }
7703
7704 if ((skb = nlmsg_new(payload_len,GFP_ATOMIC)) == NULL)
7705 {
7706 hddLog(VOS_TRACE_LEVEL_ERROR,
7707 "%s: nlmsg_new() failed for msg size[%d]",
7708 __func__, NLMSG_SPACE(payload_len));
7709 return;
7710 }
7711
7712 nlh = nlmsg_put(skb, cesium_pid, seqNo, 0, payload_len, NLM_F_REQUEST);
7713
7714 if (NULL == nlh)
7715 {
7716 hddLog(VOS_TRACE_LEVEL_ERROR,
7717 "%s: nlmsg_put() failed for msg size[%d]",
7718 __func__, NLMSG_SPACE(payload_len));
7719
7720 kfree_skb(skb);
7721 return;
7722 }
7723
7724 data = nlmsg_data(nlh);
7725 memcpy(data, MacAddr, ETH_ALEN);
7726
7727 if (nlmsg_unicast(cesium_nl_srv_sock, skb, cesium_pid) < 0)
7728 {
7729 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: nlmsg_unicast() failed for msg size[%d]",
7730 __func__, NLMSG_SPACE(payload_len));
7731 }
7732
7733 return;
7734}
7735
7736/**---------------------------------------------------------------------------
7737 \brief hdd_ParseuserParams - return a pointer to the next argument
7738
7739 \return - status
7740
7741--------------------------------------------------------------------------*/
7742static int hdd_ParseUserParams(tANI_U8 *pValue, tANI_U8 **ppArg)
7743{
7744 tANI_U8 *pVal;
7745
7746 pVal = strchr(pValue, ' ');
7747
7748 if (NULL == pVal)
7749 {
7750 /* no argument remains */
7751 return -EINVAL;
7752 }
7753 else if (SPACE_ASCII_VALUE != *pVal)
7754 {
7755 /* no space after the current argument */
7756 return -EINVAL;
7757 }
7758
7759 pVal++;
7760
7761 /* remove empty spaces */
7762 while ((SPACE_ASCII_VALUE == *pVal) && ('\0' != *pVal))
7763 {
7764 pVal++;
7765 }
7766
7767 /* no argument followed by spaces */
7768 if ('\0' == *pVal)
7769 {
7770 return -EINVAL;
7771 }
7772
7773 *ppArg = pVal;
7774
7775 return 0;
7776}
7777
7778/**----------------------------------------------------------------------------
7779 \brief hdd_ParseIBSSTXFailEventParams - Parse params for SETIBSSTXFAILEVENT
7780
7781 \return - status
7782
7783------------------------------------------------------------------------------*/
7784static int hdd_ParseIBSSTXFailEventParams(tANI_U8 *pValue,
7785 tANI_U8 *tx_fail_count,
7786 tANI_U16 *pid)
7787{
7788 tANI_U8 *param = NULL;
7789 int ret;
7790
7791 ret = hdd_ParseUserParams(pValue, &param);
7792
7793 if (0 == ret && NULL != param)
7794 {
7795 if (1 != sscanf(param, "%hhu", tx_fail_count))
7796 {
7797 ret = -EINVAL;
7798 goto done;
7799 }
7800 }
7801 else
7802 {
7803 goto done;
7804 }
7805
7806 if (0 == *tx_fail_count)
7807 {
7808 *pid = 0;
7809 goto done;
7810 }
7811
7812 pValue = param;
7813 pValue++;
7814
7815 ret = hdd_ParseUserParams(pValue, &param);
7816
7817 if (0 == ret)
7818 {
7819 if (1 != sscanf(param, "%hu", pid))
7820 {
7821 ret = -EINVAL;
7822 goto done;
7823 }
7824 }
7825 else
7826 {
7827 goto done;
7828 }
7829
7830done:
7831 return ret;
7832}
7833
7834static int hdd_open_cesium_nl_sock()
7835{
7836#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
7837 struct netlink_kernel_cfg cfg = {
7838 .groups = WLAN_NLINK_MCAST_GRP_ID,
7839 .input = NULL
7840 };
7841#endif
7842 int ret = 0;
7843
7844#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
7845 cesium_nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_CESIUM,
7846#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0))
7847 THIS_MODULE,
7848#endif
7849 &cfg);
7850#else
7851 cesium_nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_CESIUM,
7852 WLAN_NLINK_MCAST_GRP_ID, NULL, NULL, THIS_MODULE);
7853#endif
7854
7855 if (cesium_nl_srv_sock == NULL)
7856 {
7857 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7858 "NLINK: cesium netlink_kernel_create failed");
7859 ret = -ECONNREFUSED;
7860 }
7861
7862 return ret;
7863}
7864
7865static void hdd_close_cesium_nl_sock()
7866{
7867 if (NULL != cesium_nl_srv_sock)
7868 {
7869 netlink_kernel_release(cesium_nl_srv_sock);
7870 cesium_nl_srv_sock = NULL;
7871 }
7872}
7873#endif /* WLAN_FEATURE_RMC */
Jeff Johnson295189b2012-06-20 16:38:30 -07007874/**---------------------------------------------------------------------------
7875
7876 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
7877
7878 This is the function invoked by SME to inform the result of BMPS
7879 request issued by HDD
7880
7881 \param - callbackcontext - Pointer to cookie
7882 status - result of request
7883
7884 \return - None
7885
7886--------------------------------------------------------------------------*/
7887void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
7888{
7889
7890 struct completion *completion_var = (struct completion*) callbackContext;
7891
Arif Hussain6d2a3322013-11-17 19:50:10 -08007892 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07007893 if(completion_var != NULL)
7894 {
7895 complete(completion_var);
7896 }
7897}
7898
7899/**---------------------------------------------------------------------------
7900
7901 \brief hdd_get_cfg_file_size() -
7902
7903 This function reads the configuration file using the request firmware
7904 API and returns the configuration file size.
7905
7906 \param - pCtx - Pointer to the adapter .
7907 - pFileName - Pointer to the file name.
7908 - pBufSize - Pointer to the buffer size.
7909
7910 \return - 0 for success, non zero for failure
7911
7912 --------------------------------------------------------------------------*/
7913
7914VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
7915{
7916 int status;
7917 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
7918
7919 ENTER();
7920
7921 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
7922
7923 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
7924 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
7925 status = VOS_STATUS_E_FAILURE;
7926 }
7927 else {
7928 *pBufSize = pHddCtx->fw->size;
7929 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
7930 release_firmware(pHddCtx->fw);
7931 pHddCtx->fw = NULL;
7932 }
7933
7934 EXIT();
7935 return VOS_STATUS_SUCCESS;
7936}
7937
7938/**---------------------------------------------------------------------------
7939
7940 \brief hdd_read_cfg_file() -
7941
7942 This function reads the configuration file using the request firmware
7943 API and returns the cfg data and the buffer size of the configuration file.
7944
7945 \param - pCtx - Pointer to the adapter .
7946 - pFileName - Pointer to the file name.
7947 - pBuffer - Pointer to the data buffer.
7948 - pBufSize - Pointer to the buffer size.
7949
7950 \return - 0 for success, non zero for failure
7951
7952 --------------------------------------------------------------------------*/
7953
7954VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
7955 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
7956{
7957 int status;
7958 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
7959
7960 ENTER();
7961
7962 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
7963
7964 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
7965 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
7966 return VOS_STATUS_E_FAILURE;
7967 }
7968 else {
7969 if(*pBufSize != pHddCtx->fw->size) {
7970 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
7971 "file size", __func__);
7972 release_firmware(pHddCtx->fw);
7973 pHddCtx->fw = NULL;
7974 return VOS_STATUS_E_FAILURE;
7975 }
7976 else {
7977 if(pBuffer) {
7978 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
7979 }
7980 release_firmware(pHddCtx->fw);
7981 pHddCtx->fw = NULL;
7982 }
7983 }
7984
7985 EXIT();
7986
7987 return VOS_STATUS_SUCCESS;
7988}
7989
7990/**---------------------------------------------------------------------------
7991
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307992 \brief __hdd_set_mac_address() -
Jeff Johnson295189b2012-06-20 16:38:30 -07007993
7994 This function sets the user specified mac address using
7995 the command ifconfig wlanX hw ether <mac adress>.
7996
7997 \param - dev - Pointer to the net device.
7998 - addr - Pointer to the sockaddr.
7999 \return - 0 for success, non zero for failure
8000
8001 --------------------------------------------------------------------------*/
8002
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05308003static int __hdd_set_mac_address(struct net_device *dev, void *addr)
Jeff Johnson295189b2012-06-20 16:38:30 -07008004{
Mahesh A Saptasagar74088392015-02-05 17:22:09 +05308005 hdd_adapter_t *pAdapter;
8006 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07008007 struct sockaddr *psta_mac_addr = addr;
8008 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
Mahesh A Saptasagar74088392015-02-05 17:22:09 +05308009 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07008010
8011 ENTER();
Mahesh A Saptasagar74088392015-02-05 17:22:09 +05308012 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
8013 if (NULL == pAdapter)
8014 {
8015 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8016 "%s: Adapter is NULL",__func__);
8017 return -EINVAL;
8018 }
8019 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
8020 ret = wlan_hdd_validate_context(pHddCtx);
8021 if (0 != ret)
8022 {
Mahesh A Saptasagar74088392015-02-05 17:22:09 +05308023 return ret;
8024 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008025
8026 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
Jeff Johnson295189b2012-06-20 16:38:30 -07008027 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
8028
8029 EXIT();
8030 return halStatus;
8031}
8032
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05308033/**---------------------------------------------------------------------------
8034
8035 \brief hdd_set_mac_address() -
8036
8037 Wrapper function to protect __hdd_set_mac_address() function from ssr
8038
8039 \param - dev - Pointer to the net device.
8040 - addr - Pointer to the sockaddr.
8041 \return - 0 for success, non zero for failure
8042
8043 --------------------------------------------------------------------------*/
8044static int hdd_set_mac_address(struct net_device *dev, void *addr)
8045{
8046 int ret;
8047
8048 vos_ssr_protect(__func__);
8049 ret = __hdd_set_mac_address(dev, addr);
8050 vos_ssr_unprotect(__func__);
8051
8052 return ret;
8053}
8054
Jeff Johnson295189b2012-06-20 16:38:30 -07008055tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
8056{
8057 int i;
8058 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
8059 {
Abhishek Singheb183782014-02-06 13:37:21 +05308060 if( 0 == ((pHddCtx->cfg_ini->intfAddrMask) & (1 << i)) )
Jeff Johnson295189b2012-06-20 16:38:30 -07008061 break;
8062 }
8063
8064 if( VOS_MAX_CONCURRENCY_PERSONA == i)
8065 return NULL;
8066
8067 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
8068 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
8069}
8070
8071void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
8072{
8073 int i;
8074 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
8075 {
8076 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
8077 {
8078 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
8079 break;
8080 }
8081 }
8082 return;
8083}
8084
8085#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
8086 static struct net_device_ops wlan_drv_ops = {
8087 .ndo_open = hdd_open,
8088 .ndo_stop = hdd_stop,
8089 .ndo_uninit = hdd_uninit,
8090 .ndo_start_xmit = hdd_hard_start_xmit,
8091 .ndo_tx_timeout = hdd_tx_timeout,
8092 .ndo_get_stats = hdd_stats,
8093 .ndo_do_ioctl = hdd_ioctl,
8094 .ndo_set_mac_address = hdd_set_mac_address,
8095 .ndo_select_queue = hdd_select_queue,
8096#ifdef WLAN_FEATURE_PACKET_FILTERING
8097#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
8098 .ndo_set_rx_mode = hdd_set_multicast_list,
8099#else
8100 .ndo_set_multicast_list = hdd_set_multicast_list,
8101#endif //LINUX_VERSION_CODE
8102#endif
8103 };
Jeff Johnson295189b2012-06-20 16:38:30 -07008104 static struct net_device_ops wlan_mon_drv_ops = {
8105 .ndo_open = hdd_mon_open,
Katya Nigame7b69a82015-04-28 15:24:06 +05308106 .ndo_stop = hdd_mon_stop,
Jeff Johnson295189b2012-06-20 16:38:30 -07008107 .ndo_uninit = hdd_uninit,
8108 .ndo_start_xmit = hdd_mon_hard_start_xmit,
8109 .ndo_tx_timeout = hdd_tx_timeout,
8110 .ndo_get_stats = hdd_stats,
Katya Nigame7b69a82015-04-28 15:24:06 +05308111 .ndo_do_ioctl = hdd_mon_ioctl,
Jeff Johnson295189b2012-06-20 16:38:30 -07008112 .ndo_set_mac_address = hdd_set_mac_address,
8113 };
Mahesh A Saptasagar305e2632015-03-04 12:57:33 +05308114
Jeff Johnson295189b2012-06-20 16:38:30 -07008115#endif
8116
8117void hdd_set_station_ops( struct net_device *pWlanDev )
8118{
8119#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
Jeff Johnson295189b2012-06-20 16:38:30 -07008120 pWlanDev->netdev_ops = &wlan_drv_ops;
8121#else
8122 pWlanDev->open = hdd_open;
8123 pWlanDev->stop = hdd_stop;
8124 pWlanDev->uninit = hdd_uninit;
8125 pWlanDev->hard_start_xmit = NULL;
8126 pWlanDev->tx_timeout = hdd_tx_timeout;
8127 pWlanDev->get_stats = hdd_stats;
8128 pWlanDev->do_ioctl = hdd_ioctl;
Jeff Johnson295189b2012-06-20 16:38:30 -07008129 pWlanDev->set_mac_address = hdd_set_mac_address;
8130#endif
8131}
8132
Katya Nigam1fd24402015-02-16 14:52:19 +05308133void hdd_set_ibss_ops( hdd_adapter_t *pAdapter )
8134{
8135 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
8136 wlan_drv_ops.ndo_start_xmit = hdd_ibss_hard_start_xmit;
8137 #else
8138 pAdapter->dev->hard_start_xmit = hdd_ibss_hard_start_xmit;
8139 #endif
8140}
8141
Jeff Johnsoneed415b2013-01-18 16:11:20 -08008142static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07008143{
8144 struct net_device *pWlanDev = NULL;
8145 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07008146 /*
8147 * cfg80211 initialization and registration....
8148 */
Anand N Sunkadc34abbd2015-07-29 09:52:59 +05308149 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name,
8150#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0))
8151 NET_NAME_UNKNOWN,
8152#endif
8153 ether_setup, NUM_TX_QUEUES);
Jeff Johnson295189b2012-06-20 16:38:30 -07008154 if(pWlanDev != NULL)
8155 {
8156
8157 //Save the pointer to the net_device in the HDD adapter
8158 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
8159
Jeff Johnson295189b2012-06-20 16:38:30 -07008160 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
8161
8162 pAdapter->dev = pWlanDev;
8163 pAdapter->pHddCtx = pHddCtx;
8164 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
Agarwal Ashish47d18112014-08-04 19:55:07 +05308165 spin_lock_init(&pAdapter->lock_for_active_session);
Jeff Johnson295189b2012-06-20 16:38:30 -07008166
Rajeev79dbe4c2013-10-05 11:03:42 +05308167#ifdef FEATURE_WLAN_BATCH_SCAN
Rajeev79dbe4c2013-10-05 11:03:42 +05308168 pAdapter->pBatchScanRsp = NULL;
8169 pAdapter->numScanList = 0;
Rajeev Kumar20140c12013-10-21 19:39:02 -07008170 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
Kiet Lamaa8e15a2014-02-11 23:30:06 -08008171 pAdapter->prev_batch_id = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05308172 mutex_init(&pAdapter->hdd_batch_scan_lock);
8173#endif
8174
Jeff Johnson295189b2012-06-20 16:38:30 -07008175 pAdapter->isLinkUpSvcNeeded = FALSE;
8176 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
8177 //Init the net_device structure
8178 strlcpy(pWlanDev->name, name, IFNAMSIZ);
8179
8180 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
8181 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
8182 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
8183 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
8184
8185 hdd_set_station_ops( pAdapter->dev );
8186
8187 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07008188 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
8189 pAdapter->wdev.wiphy = pHddCtx->wiphy;
8190 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07008191 /* set pWlanDev's parent to underlying device */
8192 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
Kumar Anand82c009f2014-05-29 00:29:42 -07008193
8194 hdd_wmm_init( pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07008195 }
8196
8197 return pAdapter;
8198}
8199
8200VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
8201{
8202 struct net_device *pWlanDev = pAdapter->dev;
8203 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
8204 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
8205 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
8206
8207 if( rtnl_lock_held )
8208 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08008209 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07008210 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
8211 {
8212 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
8213 return VOS_STATUS_E_FAILURE;
8214 }
8215 }
8216 if (register_netdevice(pWlanDev))
8217 {
8218 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
8219 return VOS_STATUS_E_FAILURE;
8220 }
8221 }
8222 else
8223 {
8224 if(register_netdev(pWlanDev))
8225 {
8226 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
8227 return VOS_STATUS_E_FAILURE;
8228 }
8229 }
8230 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
8231
8232 return VOS_STATUS_SUCCESS;
8233}
8234
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008235static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07008236{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008237 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07008238
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008239 if (NULL == pAdapter)
8240 {
8241 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
8242 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07008243 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008244
8245 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
8246 {
8247 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
8248 return eHAL_STATUS_NOT_INITIALIZED;
8249 }
8250
8251 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
8252
Sameer Thalappilbee426e2013-10-30 10:30:30 -07008253#ifndef WLAN_OPEN_SOURCE
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008254 /* need to make sure all of our scheduled work has completed.
8255 * This callback is called from MC thread context, so it is safe to
8256 * to call below flush workqueue API from here.
Sameer Thalappilbee426e2013-10-30 10:30:30 -07008257 *
8258 * Even though this is called from MC thread context, if there is a faulty
8259 * work item in the system, that can hang this call forever. So flushing
8260 * this global work queue is not safe; and now we make sure that
8261 * individual work queues are stopped correctly. But the cancel work queue
8262 * is a GPL only API, so the proprietary version of the driver would still
8263 * rely on the global work queue flush.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008264 */
8265 flush_scheduled_work();
Sameer Thalappilbee426e2013-10-30 10:30:30 -07008266#endif
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008267
8268 /* We can be blocked while waiting for scheduled work to be
8269 * flushed, and the adapter structure can potentially be freed, in
8270 * which case the magic will have been reset. So make sure the
8271 * magic is still good, and hence the adapter structure is still
8272 * valid, before signaling completion */
8273 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
8274 {
8275 complete(&pAdapter->session_close_comp_var);
8276 }
8277
Jeff Johnson295189b2012-06-20 16:38:30 -07008278 return eHAL_STATUS_SUCCESS;
8279}
Manjeet Singh47ee8472016-04-11 11:57:18 +05308280/**
8281 * hdd_close_tx_queues() - close tx queues
8282 * @hdd_ctx: hdd global context
8283 *
8284 * Return: None
8285 */
8286static void hdd_close_tx_queues(hdd_context_t *hdd_ctx)
8287{
8288 VOS_STATUS status;
8289 hdd_adapter_t *adapter;
8290 hdd_adapter_list_node_t *adapter_node = NULL, *next_adapter = NULL;
8291 /* Not validating hdd_ctx as it's already done by the caller */
8292 ENTER();
8293 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
8294 while (NULL != adapter_node && VOS_STATUS_SUCCESS == status) {
8295 adapter = adapter_node->pAdapter;
8296 if (adapter && adapter->dev) {
8297 netif_tx_disable (adapter->dev);
8298 netif_carrier_off(adapter->dev);
8299 }
8300 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
8301 &next_adapter);
8302 adapter_node = next_adapter;
8303 }
8304 EXIT();
8305}
Jeff Johnson295189b2012-06-20 16:38:30 -07008306
8307VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
8308{
8309 struct net_device *pWlanDev = pAdapter->dev;
8310 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
8311 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
8312 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
8313 VOS_STATUS status = VOS_STATUS_E_FAILURE;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308314 long rc = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07008315
Nirav Shah7e3c8132015-06-22 23:51:42 +05308316 spin_lock_init( &pAdapter->sta_hash_lock);
8317 pAdapter->is_sta_id_hash_initialized = VOS_FALSE;
8318
Jeff Johnson295189b2012-06-20 16:38:30 -07008319 INIT_COMPLETION(pAdapter->session_open_comp_var);
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07008320 sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07008321 //Open a SME session for future operation
8322 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07008323 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07008324 if ( !HAL_STATUS_SUCCESS( halStatus ) )
8325 {
8326 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07008327 "sme_OpenSession() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07008328 halStatus, halStatus );
8329 status = VOS_STATUS_E_FAILURE;
8330 goto error_sme_open;
8331 }
8332
8333 //Block on a completion variable. Can't wait forever though.
Vinay Krishna Eranna0fe2e7c2014-04-09 21:32:08 +05308334 rc = wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07008335 &pAdapter->session_open_comp_var,
8336 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308337 if (rc <= 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07008338 {
8339 hddLog(VOS_TRACE_LEVEL_FATAL,
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308340 "Session is not opened within timeout period code %ld", rc );
Jeff Johnson295189b2012-06-20 16:38:30 -07008341 status = VOS_STATUS_E_FAILURE;
8342 goto error_sme_open;
8343 }
8344
8345 // Register wireless extensions
8346 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
8347 {
8348 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07008349 "hdd_register_wext() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07008350 halStatus, halStatus );
8351 status = VOS_STATUS_E_FAILURE;
8352 goto error_register_wext;
8353 }
Katya Nigam1fd24402015-02-16 14:52:19 +05308354
Jeff Johnson295189b2012-06-20 16:38:30 -07008355 //Safe to register the hard_start_xmit function again
Katya Nigam1fd24402015-02-16 14:52:19 +05308356 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
8357 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
8358 #else
8359 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
8360 #endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008361
8362 //Set the Connection State to Not Connected
Abhishek Singhf4669da2014-05-26 15:07:49 +05308363 hddLog(VOS_TRACE_LEVEL_INFO,
8364 "%s: Set HDD connState to eConnectionState_NotConnected",
8365 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008366 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
8367
8368 //Set the default operation channel
8369 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
8370
8371 /* Make the default Auth Type as OPEN*/
8372 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
8373
8374 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
8375 {
8376 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07008377 "hdd_init_tx_rx() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07008378 status, status );
8379 goto error_init_txrx;
8380 }
8381
8382 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
8383
8384 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
8385 {
8386 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07008387 "hdd_wmm_adapter_init() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07008388 status, status );
8389 goto error_wmm_init;
8390 }
8391
8392 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
8393
8394 return VOS_STATUS_SUCCESS;
8395
8396error_wmm_init:
8397 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
8398 hdd_deinit_tx_rx(pAdapter);
8399error_init_txrx:
8400 hdd_UnregisterWext(pWlanDev);
8401error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008402 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07008403 {
8404 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008405 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Agrawal Ashish5a3522c2016-03-02 15:08:28 +05308406 pAdapter->sessionId, FALSE, VOS_TRUE,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008407 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07008408 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308409 unsigned long rc;
8410
Jeff Johnson295189b2012-06-20 16:38:30 -07008411 //Block on a completion variable. Can't wait forever though.
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308412 rc = wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07008413 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008414 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308415 if (rc <= 0)
8416 hddLog(VOS_TRACE_LEVEL_ERROR,
8417 FL("Session is not opened within timeout period code %ld"), rc);
Jeff Johnson295189b2012-06-20 16:38:30 -07008418 }
8419}
8420error_sme_open:
8421 return status;
8422}
8423
Jeff Johnson295189b2012-06-20 16:38:30 -07008424void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
8425{
8426 hdd_cfg80211_state_t *cfgState;
8427
8428 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
8429
8430 if( NULL != cfgState->buf )
8431 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308432 long rc;
Jeff Johnson295189b2012-06-20 16:38:30 -07008433 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
8434 rc = wait_for_completion_interruptible_timeout(
8435 &pAdapter->tx_action_cnf_event,
8436 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308437 if (rc <= 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07008438 {
Deepthi Gowri91b3e9c2015-08-25 13:14:58 +05308439 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8440 "%s ERROR: HDD Wait for Action Confirmation Failed!! %ld"
8441 , __func__, rc);
8442
8443 // Inform tx status as FAILURE to upper layer and free cfgState->buf
8444 hdd_sendActionCnf( pAdapter, FALSE );
Jeff Johnson295189b2012-06-20 16:38:30 -07008445 }
8446 }
8447 return;
8448}
Jeff Johnson295189b2012-06-20 16:38:30 -07008449
c_hpothu002231a2015-02-05 14:58:51 +05308450void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
Jeff Johnson295189b2012-06-20 16:38:30 -07008451{
8452 ENTER();
8453 switch ( pAdapter->device_mode )
8454 {
Katya Nigam1fd24402015-02-16 14:52:19 +05308455 case WLAN_HDD_IBSS:
8456 {
8457 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
8458 {
8459 hdd_ibss_deinit_tx_rx( pAdapter );
8460 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
8461 }
8462 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008463 case WLAN_HDD_INFRA_STATION:
8464 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07008465 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07008466 {
8467 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
8468 {
8469 hdd_deinit_tx_rx( pAdapter );
8470 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
8471 }
8472
8473 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
8474 {
8475 hdd_wmm_adapter_close( pAdapter );
8476 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
8477 }
8478
Jeff Johnson295189b2012-06-20 16:38:30 -07008479 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07008480 break;
8481 }
8482
8483 case WLAN_HDD_SOFTAP:
8484 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07008485 {
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05308486
8487 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
8488 {
8489 hdd_wmm_adapter_close( pAdapter );
8490 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
8491 }
8492
Jeff Johnson295189b2012-06-20 16:38:30 -07008493 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07008494
c_hpothu002231a2015-02-05 14:58:51 +05308495 hdd_unregister_hostapd(pAdapter, rtnl_held);
Agrawal Ashisha0584d42016-09-29 13:03:45 +05308496 /* set con_mode to STA only when no SAP concurrency mode */
8497 if (!(hdd_get_concurrency_mode() & (VOS_SAP | VOS_P2P_GO)))
8498 hdd_set_conparam(0);
Jeff Johnson295189b2012-06-20 16:38:30 -07008499 break;
8500 }
8501
8502 case WLAN_HDD_MONITOR:
8503 {
Jeff Johnson295189b2012-06-20 16:38:30 -07008504 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
8505 {
8506 hdd_deinit_tx_rx( pAdapter );
8507 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
8508 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008509 break;
8510 }
8511
8512
8513 default:
8514 break;
8515 }
8516
8517 EXIT();
8518}
8519
8520void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
8521{
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -08008522 struct net_device *pWlanDev = NULL;
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05308523
8524 ENTER();
8525 if (NULL == pAdapter)
8526 {
8527 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8528 "%s: HDD adapter is Null", __func__);
8529 return;
8530 }
8531
8532 pWlanDev = pAdapter->dev;
Jeff Johnson295189b2012-06-20 16:38:30 -07008533
Rajeev79dbe4c2013-10-05 11:03:42 +05308534#ifdef FEATURE_WLAN_BATCH_SCAN
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05308535 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
8536 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Rajeev Kumarf999e582014-01-09 17:33:29 -08008537 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05308538 || (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)
8539 )
8540 {
Rajeev Kumarf999e582014-01-09 17:33:29 -08008541 if (pAdapter)
Rajeev79dbe4c2013-10-05 11:03:42 +05308542 {
Rajeev Kumarf999e582014-01-09 17:33:29 -08008543 if (eHDD_BATCH_SCAN_STATE_STARTED == pAdapter->batchScanState)
8544 {
8545 hdd_deinit_batch_scan(pAdapter);
8546 }
Rajeev79dbe4c2013-10-05 11:03:42 +05308547 }
Rajeev Kumarf999e582014-01-09 17:33:29 -08008548 }
Rajeev79dbe4c2013-10-05 11:03:42 +05308549#endif
8550
Jeff Johnson295189b2012-06-20 16:38:30 -07008551 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
8552 if( rtnl_held )
8553 {
8554 unregister_netdevice(pWlanDev);
8555 }
8556 else
8557 {
8558 unregister_netdev(pWlanDev);
8559 }
8560 // note that the pAdapter is no longer valid at this point
8561 // since the memory has been reclaimed
8562 }
8563
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05308564 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07008565}
8566
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008567void hdd_set_pwrparams(hdd_context_t *pHddCtx)
8568{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308569 VOS_STATUS status;
8570 hdd_adapter_t *pAdapter = NULL;
8571 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008572
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308573 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008574
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308575 /*loop through all adapters.*/
8576 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008577 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308578 pAdapter = pAdapterNode->pAdapter;
8579 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
8580 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008581
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308582 { // we skip this registration for modes other than STA and P2P client modes.
8583 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
8584 pAdapterNode = pNext;
8585 continue;
8586 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008587
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308588 //Apply Dynamic DTIM For P2P
8589 //Only if ignoreDynamicDtimInP2pMode is not set in ini
8590 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
8591 pHddCtx->cfg_ini->enableModulatedDTIM) &&
8592 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
8593 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
8594 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
8595 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
8596 (eConnectionState_Associated ==
8597 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
8598 (pHddCtx->cfg_ini->fIsBmpsEnabled))
8599 {
8600 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008601
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308602 powerRequest.uIgnoreDTIM = 1;
8603 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
8604
8605 if (pHddCtx->cfg_ini->enableModulatedDTIM)
8606 {
8607 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
8608 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
8609 }
8610 else
8611 {
8612 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
8613 }
8614
8615 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
8616 * specified during Enter/Exit BMPS when LCD off*/
8617 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
8618 NULL, eANI_BOOLEAN_FALSE);
8619 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
8620 NULL, eANI_BOOLEAN_FALSE);
8621
8622 /* switch to the DTIM specified in cfg.ini */
8623 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Abhishek Singh1e390cf2015-10-27 13:45:17 +05308624 "Switch to DTIM %d Listen interval %d",
8625 powerRequest.uDTIMPeriod,
8626 powerRequest.uListenInterval);
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308627 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
8628 break;
8629
8630 }
8631
8632 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
8633 pAdapterNode = pNext;
8634 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008635}
8636
8637void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
8638{
8639 /*Switch back to DTIM 1*/
8640 tSirSetPowerParamsReq powerRequest = { 0 };
8641
8642 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
8643 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07008644 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008645
8646 /* Update ignoreDTIM and ListedInterval in CFG with default values */
8647 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
8648 NULL, eANI_BOOLEAN_FALSE);
8649 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
8650 NULL, eANI_BOOLEAN_FALSE);
8651
8652 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8653 "Switch to DTIM%d",powerRequest.uListenInterval);
8654 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
8655
8656}
8657
Jeff Johnson295189b2012-06-20 16:38:30 -07008658VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
8659{
8660 VOS_STATUS status = VOS_STATUS_SUCCESS;
Sushant Kaushik4928e542014-12-29 15:25:54 +05308661 if (WLAN_HDD_IS_UNLOAD_IN_PROGRESS(pHddCtx))
8662 {
8663 hddLog( LOGE, FL("Wlan Unload in progress"));
8664 return VOS_STATUS_E_PERM;
8665 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008666 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
8667 {
8668 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
8669 }
8670
8671 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
8672 {
8673 sme_StartAutoBmpsTimer(pHddCtx->hHal);
8674 }
8675
8676 if (pHddCtx->cfg_ini->fIsImpsEnabled)
8677 {
8678 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
8679 }
8680
8681 return status;
8682}
8683
8684VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
8685{
8686 hdd_adapter_t *pAdapter = NULL;
8687 eHalStatus halStatus;
8688 VOS_STATUS status = VOS_STATUS_E_INVAL;
8689 v_BOOL_t disableBmps = FALSE;
8690 v_BOOL_t disableImps = FALSE;
8691
8692 switch(session_type)
8693 {
8694 case WLAN_HDD_INFRA_STATION:
8695 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07008696 case WLAN_HDD_P2P_CLIENT:
8697 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07008698 //Exit BMPS -> Is Sta/P2P Client is already connected
8699 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
8700 if((NULL != pAdapter)&&
8701 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
8702 {
8703 disableBmps = TRUE;
8704 }
8705
8706 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
8707 if((NULL != pAdapter)&&
8708 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
8709 {
8710 disableBmps = TRUE;
8711 }
8712
8713 //Exit both Bmps and Imps incase of Go/SAP Mode
8714 if((WLAN_HDD_SOFTAP == session_type) ||
8715 (WLAN_HDD_P2P_GO == session_type))
8716 {
8717 disableBmps = TRUE;
8718 disableImps = TRUE;
8719 }
8720
8721 if(TRUE == disableImps)
8722 {
8723 if (pHddCtx->cfg_ini->fIsImpsEnabled)
8724 {
8725 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
8726 }
8727 }
8728
8729 if(TRUE == disableBmps)
8730 {
8731 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
8732 {
8733 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
8734
8735 if(eHAL_STATUS_SUCCESS != halStatus)
8736 {
8737 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08008738 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008739 VOS_ASSERT(0);
8740 return status;
8741 }
8742 }
8743
8744 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
8745 {
8746 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
8747
8748 if(eHAL_STATUS_SUCCESS != halStatus)
8749 {
8750 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08008751 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008752 VOS_ASSERT(0);
8753 return status;
8754 }
8755 }
8756 }
8757
8758 if((TRUE == disableBmps) ||
8759 (TRUE == disableImps))
8760 {
8761 /* Now, get the chip into Full Power now */
8762 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
8763 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
8764 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
8765
8766 if(halStatus != eHAL_STATUS_SUCCESS)
8767 {
8768 if(halStatus == eHAL_STATUS_PMC_PENDING)
8769 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308770 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07008771 //Block on a completion variable. Can't wait forever though
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308772 ret = wait_for_completion_interruptible_timeout(
8773 &pHddCtx->full_pwr_comp_var,
8774 msecs_to_jiffies(1000));
8775 if (ret <= 0)
8776 {
8777 hddLog(VOS_TRACE_LEVEL_ERROR,
8778 "%s: wait on full_pwr_comp_var failed %ld",
8779 __func__, ret);
8780 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008781 }
8782 else
8783 {
8784 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08008785 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008786 VOS_ASSERT(0);
8787 return status;
8788 }
8789 }
8790
8791 status = VOS_STATUS_SUCCESS;
8792 }
8793
8794 break;
8795 }
8796 return status;
8797}
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +05308798
8799void hdd_monPostMsgCb(tANI_U32 *magic, struct completion *cmpVar)
8800{
8801 if (magic == NULL || cmpVar == NULL) {
8802 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8803 FL("invalid arguments %p %p"), magic, cmpVar);
8804 return;
8805 }
8806 if (*magic != MON_MODE_MSG_MAGIC) {
8807 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8808 FL("maic: %x"), *magic);
8809 return;
8810 }
8811
8812 complete(cmpVar);
8813 return;
8814}
8815
Katya Nigame7b69a82015-04-28 15:24:06 +05308816void hdd_init_mon_mode (hdd_adapter_t *pAdapter)
8817 {
8818 hdd_mon_ctx_t *pMonCtx = NULL;
8819 pMonCtx = WLAN_HDD_GET_MONITOR_CTX_PTR(pAdapter);
8820
8821 pMonCtx->state = 0;
8822 pMonCtx->ChannelNo = 1;
8823 pMonCtx->ChannelBW = 20;
Katya Nigamd7d3a1f2015-06-11 14:04:24 +05308824 pMonCtx->crcCheckEnabled = 1;
8825 pMonCtx->typeSubtypeBitmap = 0xFFFF00000000;
8826 pMonCtx->is80211to803ConReq = 1;
Katya Nigame7b69a82015-04-28 15:24:06 +05308827 pMonCtx->numOfMacFilters = 0;
8828 }
8829
Jeff Johnson295189b2012-06-20 16:38:30 -07008830
8831hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08008832 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07008833 tANI_U8 rtnl_held )
8834{
8835 hdd_adapter_t *pAdapter = NULL;
8836 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
8837 VOS_STATUS status = VOS_STATUS_E_FAILURE;
8838 VOS_STATUS exitbmpsStatus;
8839
Arif Hussain6d2a3322013-11-17 19:50:10 -08008840 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d",__func__,iface_name,session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07008841
Nirav Shah436658f2014-02-28 17:05:45 +05308842 if(macAddr == NULL)
8843 {
8844 /* Not received valid macAddr */
8845 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8846 "%s:Unable to add virtual intf: Not able to get"
8847 "valid mac address",__func__);
8848 return NULL;
8849 }
8850
Jeff Johnson295189b2012-06-20 16:38:30 -07008851 //Disable BMPS incase of Concurrency
8852 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
8853
8854 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
8855 {
8856 //Fail to Exit BMPS
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308857 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Exit BMPS", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008858 VOS_ASSERT(0);
8859 return NULL;
8860 }
8861
8862 switch(session_type)
8863 {
8864 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07008865 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07008866 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07008867 {
8868 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
8869
8870 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308871 {
8872 hddLog(VOS_TRACE_LEVEL_FATAL,
8873 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07008874 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308875 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008876
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05308877#ifdef FEATURE_WLAN_TDLS
8878 /* A Mutex Lock is introduced while changing/initializing the mode to
8879 * protect the concurrent access for the Adapters by TDLS module.
8880 */
Rajesh Chauhana34c6e62014-03-25 16:37:58 +05308881 mutex_lock(&pHddCtx->tdls_lock);
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05308882#endif
8883
Jeff Johnsone7245742012-09-05 17:12:55 -07008884 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
8885 NL80211_IFTYPE_P2P_CLIENT:
8886 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07008887
Jeff Johnson295189b2012-06-20 16:38:30 -07008888 pAdapter->device_mode = session_type;
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05308889#ifdef FEATURE_WLAN_TDLS
8890 mutex_unlock(&pHddCtx->tdls_lock);
8891#endif
Sunil Dutt66485cb2013-12-19 19:05:03 +05308892
Mahesh A Saptasagar67ab9222015-10-21 15:38:41 +05308893 hdd_initialize_adapter_common(pAdapter);
Sunil Dutt66485cb2013-12-19 19:05:03 +05308894 status = hdd_init_station_mode( pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07008895 if( VOS_STATUS_SUCCESS != status )
8896 goto err_free_netdev;
8897
8898 status = hdd_register_interface( pAdapter, rtnl_held );
8899 if( VOS_STATUS_SUCCESS != status )
8900 {
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05308901#ifdef FEATURE_WLAN_TDLS
8902 mutex_lock(&pHddCtx->tdls_lock);
8903#endif
c_hpothu002231a2015-02-05 14:58:51 +05308904 hdd_deinit_adapter(pHddCtx, pAdapter, rtnl_held);
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05308905#ifdef FEATURE_WLAN_TDLS
8906 mutex_unlock(&pHddCtx->tdls_lock);
8907#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008908 goto err_free_netdev;
8909 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05308910
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05308911 // Workqueue which gets scheduled in IPv4 notification callback.
Anand N Sunkaddc63c792015-06-03 14:33:24 +05308912 vos_init_work(&pAdapter->ipv4NotifierWorkQueue, hdd_ipv4_notifier_work_queue);
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05308913
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05308914#ifdef WLAN_NS_OFFLOAD
8915 // Workqueue which gets scheduled in IPv6 notification callback.
Anand N Sunkaddc63c792015-06-03 14:33:24 +05308916 vos_init_work(&pAdapter->ipv6NotifierWorkQueue, hdd_ipv6_notifier_work_queue);
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05308917#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008918 //Stop the Interface TX queue.
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05308919 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
Jeff Johnson295189b2012-06-20 16:38:30 -07008920 netif_tx_disable(pAdapter->dev);
8921 //netif_tx_disable(pWlanDev);
8922 netif_carrier_off(pAdapter->dev);
8923
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +05308924 if (WLAN_HDD_P2P_CLIENT == session_type ||
8925 WLAN_HDD_P2P_DEVICE == session_type)
8926 {
8927 /* Initialize the work queue to defer the
8928 * back to back RoC request */
Anand N Sunkaddc63c792015-06-03 14:33:24 +05308929 vos_init_delayed_work(&pAdapter->roc_work,
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +05308930 hdd_p2p_roc_work_queue);
8931 }
8932
Jeff Johnson295189b2012-06-20 16:38:30 -07008933 break;
8934 }
8935
Jeff Johnson295189b2012-06-20 16:38:30 -07008936 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07008937 case WLAN_HDD_SOFTAP:
8938 {
8939 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
8940 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308941 {
8942 hddLog(VOS_TRACE_LEVEL_FATAL,
8943 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07008944 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308945 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008946
Jeff Johnson295189b2012-06-20 16:38:30 -07008947 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
8948 NL80211_IFTYPE_AP:
8949 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07008950 pAdapter->device_mode = session_type;
8951
Mahesh A Saptasagar67ab9222015-10-21 15:38:41 +05308952 hdd_initialize_adapter_common(pAdapter);
Hanumanth Reddy Pothula15bc0fa2017-02-03 17:24:17 +05308953 status = hdd_init_ap_mode(pAdapter, false);
Jeff Johnson295189b2012-06-20 16:38:30 -07008954 if( VOS_STATUS_SUCCESS != status )
8955 goto err_free_netdev;
8956
Nirav Shah7e3c8132015-06-22 23:51:42 +05308957 status = hdd_sta_id_hash_attach(pAdapter);
8958 if (VOS_STATUS_SUCCESS != status)
8959 {
8960 hddLog(VOS_TRACE_LEVEL_FATAL,
8961 FL("failed to attach hash for session %d"), session_type);
8962 hdd_deinit_adapter(pHddCtx, pAdapter, rtnl_held);
8963 goto err_free_netdev;
8964 }
8965
Jeff Johnson295189b2012-06-20 16:38:30 -07008966 status = hdd_register_hostapd( pAdapter, rtnl_held );
8967 if( VOS_STATUS_SUCCESS != status )
8968 {
c_hpothu002231a2015-02-05 14:58:51 +05308969 hdd_deinit_adapter(pHddCtx, pAdapter, rtnl_held);
Jeff Johnson295189b2012-06-20 16:38:30 -07008970 goto err_free_netdev;
8971 }
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05308972 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
Jeff Johnson295189b2012-06-20 16:38:30 -07008973 netif_tx_disable(pAdapter->dev);
8974 netif_carrier_off(pAdapter->dev);
8975
8976 hdd_set_conparam( 1 );
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +05308977
8978 if (WLAN_HDD_P2P_GO == session_type)
8979 {
8980 /* Initialize the work queue to
8981 * defer the back to back RoC request */
8982 INIT_DELAYED_WORK(&pAdapter->roc_work,
8983 hdd_p2p_roc_work_queue);
8984 }
Bhargav Shahd0715912015-10-01 18:17:37 +05308985
Jeff Johnson295189b2012-06-20 16:38:30 -07008986 break;
8987 }
8988 case WLAN_HDD_MONITOR:
8989 {
Jeff Johnson295189b2012-06-20 16:38:30 -07008990 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
8991 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308992 {
8993 hddLog(VOS_TRACE_LEVEL_FATAL,
8994 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07008995 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308996 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008997
Katya Nigame7b69a82015-04-28 15:24:06 +05308998 // Register wireless extensions
8999 if( VOS_STATUS_SUCCESS != (status = hdd_register_wext(pAdapter->dev)))
9000 {
9001 hddLog(VOS_TRACE_LEVEL_FATAL,
9002 "hdd_register_wext() failed with status code %08d [x%08x]",
9003 status, status );
9004 status = VOS_STATUS_E_FAILURE;
9005 }
9006
Jeff Johnson295189b2012-06-20 16:38:30 -07009007 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
9008 pAdapter->device_mode = session_type;
Jeff Johnson295189b2012-06-20 16:38:30 -07009009#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
9010 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
9011#else
9012 pAdapter->dev->open = hdd_mon_open;
9013 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
Katya Nigame7b69a82015-04-28 15:24:06 +05309014 pAdapter->dev->stop = hdd_mon_stop;
9015 pAdapter->dev->do_ioctl = hdd_mon_ioctl;
Jeff Johnson295189b2012-06-20 16:38:30 -07009016#endif
Katya Nigame7b69a82015-04-28 15:24:06 +05309017 status = hdd_register_interface( pAdapter, rtnl_held );
9018 hdd_init_mon_mode( pAdapter );
Mahesh A Saptasagar67ab9222015-10-21 15:38:41 +05309019 hdd_initialize_adapter_common(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07009020 hdd_init_tx_rx( pAdapter );
9021 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
Katya Nigame7b69a82015-04-28 15:24:06 +05309022 //Stop the Interface TX queue.
9023 netif_tx_disable(pAdapter->dev);
9024 netif_carrier_off(pAdapter->dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07009025 }
9026 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07009027 case WLAN_HDD_FTM:
9028 {
9029 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
9030
9031 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309032 {
9033 hddLog(VOS_TRACE_LEVEL_FATAL,
9034 FL("failed to allocate adapter for session %d"), session_type);
9035 return NULL;
9036 }
9037
Jeff Johnson295189b2012-06-20 16:38:30 -07009038 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
9039 * message while loading driver in FTM mode. */
9040 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
9041 pAdapter->device_mode = session_type;
9042 status = hdd_register_interface( pAdapter, rtnl_held );
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05309043
Mahesh A Saptasagar67ab9222015-10-21 15:38:41 +05309044 hdd_initialize_adapter_common(pAdapter);
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05309045 hdd_init_tx_rx( pAdapter );
9046
9047 //Stop the Interface TX queue.
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05309048 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05309049 netif_tx_disable(pAdapter->dev);
9050 netif_carrier_off(pAdapter->dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07009051 }
9052 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07009053 default:
9054 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309055 hddLog(VOS_TRACE_LEVEL_FATAL,"%s Invalid session type %d",
9056 __func__, session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07009057 VOS_ASSERT(0);
9058 return NULL;
9059 }
9060 }
9061
Jeff Johnson295189b2012-06-20 16:38:30 -07009062 if( VOS_STATUS_SUCCESS == status )
9063 {
Mahesh A Saptasagar67ab9222015-10-21 15:38:41 +05309064 //Add it to the hdd's session list.
Jeff Johnson295189b2012-06-20 16:38:30 -07009065 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
9066 if( NULL == pHddAdapterNode )
9067 {
9068 status = VOS_STATUS_E_NOMEM;
9069 }
9070 else
9071 {
9072 pHddAdapterNode->pAdapter = pAdapter;
9073 status = hdd_add_adapter_back ( pHddCtx,
9074 pHddAdapterNode );
9075 }
9076 }
9077
9078 if( VOS_STATUS_SUCCESS != status )
9079 {
9080 if( NULL != pAdapter )
9081 {
9082 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
9083 pAdapter = NULL;
9084 }
9085 if( NULL != pHddAdapterNode )
9086 {
9087 vos_mem_free( pHddAdapterNode );
9088 }
9089
9090 goto resume_bmps;
9091 }
9092
9093 if(VOS_STATUS_SUCCESS == status)
9094 {
9095 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07009096 //Initialize the WoWL service
9097 if(!hdd_init_wowl(pAdapter))
9098 {
9099 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
9100 goto err_free_netdev;
9101 }
Manjeet Singh3ed79242017-01-11 19:04:32 +05309102 //Initialize the TSF capture data
9103 wlan_hdd_tsf_init(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07009104 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009105 return pAdapter;
9106
9107err_free_netdev:
9108 free_netdev(pAdapter->dev);
9109 wlan_hdd_release_intf_addr( pHddCtx,
9110 pAdapter->macAddressCurrent.bytes );
9111
9112resume_bmps:
9113 //If bmps disabled enable it
9114 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
9115 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05309116 if (pHddCtx->hdd_wlan_suspended)
9117 {
9118 hdd_set_pwrparams(pHddCtx);
9119 }
9120 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07009121 }
9122 return NULL;
9123}
9124
9125VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
9126 tANI_U8 rtnl_held )
9127{
9128 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
9129 VOS_STATUS status;
9130
9131 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
9132 if( VOS_STATUS_SUCCESS != status )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309133 {
9134 hddLog(VOS_TRACE_LEVEL_WARN,"%s: adapter list empty %d",
9135 __func__, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07009136 return status;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309137 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009138
9139 while ( pCurrent->pAdapter != pAdapter )
9140 {
9141 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
9142 if( VOS_STATUS_SUCCESS != status )
9143 break;
9144
9145 pCurrent = pNext;
9146 }
9147 pAdapterNode = pCurrent;
9148 if( VOS_STATUS_SUCCESS == status )
9149 {
9150 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
9151 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05309152
9153#ifdef FEATURE_WLAN_TDLS
9154
9155 /* A Mutex Lock is introduced while changing/initializing the mode to
9156 * protect the concurrent access for the Adapters by TDLS module.
9157 */
Rajesh Chauhana34c6e62014-03-25 16:37:58 +05309158 mutex_lock(&pHddCtx->tdls_lock);
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05309159#endif
9160
Jeff Johnson295189b2012-06-20 16:38:30 -07009161 hdd_remove_adapter( pHddCtx, pAdapterNode );
9162 vos_mem_free( pAdapterNode );
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08009163 pAdapterNode = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07009164
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05309165#ifdef FEATURE_WLAN_TDLS
9166 mutex_unlock(&pHddCtx->tdls_lock);
9167#endif
9168
Jeff Johnson295189b2012-06-20 16:38:30 -07009169
9170 /* If there is a single session of STA/P2P client, re-enable BMPS */
Agarwal Ashish51325b52014-06-16 16:50:49 +05309171 if ((!vos_concurrent_open_sessions_running()) &&
9172 ((pHddCtx->no_of_open_sessions[VOS_STA_MODE] >= 1) ||
9173 (pHddCtx->no_of_open_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
Jeff Johnson295189b2012-06-20 16:38:30 -07009174 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05309175 if (pHddCtx->hdd_wlan_suspended)
9176 {
9177 hdd_set_pwrparams(pHddCtx);
9178 }
9179 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07009180 }
9181
9182 return VOS_STATUS_SUCCESS;
9183 }
9184
9185 return VOS_STATUS_E_FAILURE;
9186}
9187
9188VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
9189{
9190 hdd_adapter_list_node_t *pHddAdapterNode;
9191 VOS_STATUS status;
9192
9193 ENTER();
9194
9195 do
9196 {
9197 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
9198 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
9199 {
9200 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
9201 vos_mem_free( pHddAdapterNode );
9202 }
9203 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
9204
9205 EXIT();
9206
9207 return VOS_STATUS_SUCCESS;
9208}
9209
9210void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
9211{
9212 v_U8_t addIE[1] = {0};
9213
9214 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
9215 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
9216 eANI_BOOLEAN_FALSE) )
9217 {
9218 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08009219 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07009220 }
9221
9222 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
9223 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
9224 eANI_BOOLEAN_FALSE) )
9225 {
9226 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08009227 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07009228 }
9229
9230 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
9231 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
9232 eANI_BOOLEAN_FALSE) )
9233 {
9234 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08009235 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07009236 }
9237}
9238
Anurag Chouhan83026002016-12-13 22:46:21 +05309239VOS_STATUS hdd_cleanup_ap_events(hdd_adapter_t *adapter)
9240{
9241#ifdef DHCP_SERVER_OFFLOAD
9242 vos_event_destroy(&adapter->dhcp_status.vos_event);
9243#endif
Anurag Chouhan0b29de02016-12-16 13:18:40 +05309244#ifdef MDNS_OFFLOAD
9245 vos_event_destroy(&adapter->mdns_status.vos_event);
9246#endif
Anurag Chouhan83026002016-12-13 22:46:21 +05309247 return VOS_STATUS_SUCCESS;
9248}
9249
9250
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05309251VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
9252 const v_BOOL_t bCloseSession )
Jeff Johnson295189b2012-06-20 16:38:30 -07009253{
9254 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
9255 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
Kaushik, Sushant4975a572014-10-21 16:07:48 +05309256 hdd_scaninfo_t *pScanInfo = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07009257 union iwreq_data wrqu;
Kaushik, Sushant7005e372014-04-08 11:36:54 +05309258 v_U8_t retry = 0;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309259 long ret;
Nirav Shah7e3c8132015-06-22 23:51:42 +05309260 VOS_STATUS status;
Jeff Johnson295189b2012-06-20 16:38:30 -07009261
Anand N Sunkad26d71b92014-12-24 18:08:22 +05309262 if (pHddCtx->isLogpInProgress) {
9263 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
9264 "%s:LOGP in Progress. Ignore!!!",__func__);
9265 return VOS_STATUS_E_FAILURE;
9266 }
9267
Jeff Johnson295189b2012-06-20 16:38:30 -07009268 ENTER();
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +05309269
Kaushik, Sushant4975a572014-10-21 16:07:48 +05309270 pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07009271 switch(pAdapter->device_mode)
9272 {
Nirav Shah0cf4d892015-11-05 16:27:27 +05309273 case WLAN_HDD_IBSS:
9274 if ( VOS_TRUE == bCloseSession )
9275 {
9276 status = hdd_sta_id_hash_detach(pAdapter);
9277 if (status != VOS_STATUS_SUCCESS)
9278 hddLog(VOS_TRACE_LEVEL_ERROR,
9279 FL("sta id hash detach failed"));
9280 }
9281
Jeff Johnson295189b2012-06-20 16:38:30 -07009282 case WLAN_HDD_INFRA_STATION:
9283 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07009284 case WLAN_HDD_P2P_DEVICE:
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05309285 {
9286 hdd_station_ctx_t *pstation = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Mahesh A Saptasagare4d05d42015-07-02 16:17:20 +05309287#ifdef FEATURE_WLAN_TDLS
9288 mutex_lock(&pHddCtx->tdls_lock);
9289 wlan_hdd_tdls_exit(pAdapter, TRUE);
9290 mutex_unlock(&pHddCtx->tdls_lock);
9291#endif
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05309292 if( hdd_connIsConnected(pstation) ||
9293 (pstation->conn_info.connState == eConnectionState_Connecting) )
Jeff Johnson295189b2012-06-20 16:38:30 -07009294 {
Abhishek Singhe21a5212017-06-09 09:42:58 +05309295 /*
9296 * Indicate sme of disconnect so that in progress connection
9297 * or preauth can be aborted.
9298 */
9299 sme_abortConnection(WLAN_HDD_GET_HAL_CTX(pAdapter),
9300 pAdapter->sessionId);
Abhishek Singh99f17b82017-02-06 16:57:56 +05309301 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07009302 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
9303 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
9304 pAdapter->sessionId,
9305 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
9306 else
9307 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
9308 pAdapter->sessionId,
9309 eCSR_DISCONNECT_REASON_UNSPECIFIED);
Abhishek Singh7b52ed52016-02-11 17:45:54 +05309310 /* Success implies disconnect command got queued up successfully
9311 * Or cmd not queued as scan for SSID is in progress
9312 */
9313 if((eHAL_STATUS_SUCCESS == halStatus) ||
9314 (eHAL_STATUS_CMD_NOT_QUEUED == halStatus))
Jeff Johnson295189b2012-06-20 16:38:30 -07009315 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309316 ret = wait_for_completion_interruptible_timeout(
9317 &pAdapter->disconnect_comp_var,
9318 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Abhishek Singh7b52ed52016-02-11 17:45:54 +05309319 if (ret <= 0 &&
9320 (eHAL_STATUS_CMD_NOT_QUEUED != halStatus))
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309321 {
9322 hddLog(VOS_TRACE_LEVEL_ERROR,
9323 "%s: wait on disconnect_comp_var failed %ld",
9324 __func__, ret);
9325 }
9326 }
9327 else
9328 {
9329 hddLog(LOGE, "%s: failed to post disconnect event to SME",
9330 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009331 }
9332 memset(&wrqu, '\0', sizeof(wrqu));
9333 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
9334 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
9335 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
9336 }
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05309337 else if(pstation->conn_info.connState ==
9338 eConnectionState_Disconnecting)
9339 {
9340 ret = wait_for_completion_interruptible_timeout(
9341 &pAdapter->disconnect_comp_var,
9342 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
9343 if (ret <= 0)
9344 {
9345 hddLog(VOS_TRACE_LEVEL_ERROR,
9346 FL("wait on disconnect_comp_var failed %ld"), ret);
9347 }
9348 }
Sachin Ahuja27dd2402016-08-01 20:30:31 +05309349 if(pScanInfo != NULL && pHddCtx->scan_info.mScanPending)
Jeff Johnson295189b2012-06-20 16:38:30 -07009350 {
Mahesh A Saptasagar0b61dcc2016-02-15 14:23:38 +05309351 wlan_hdd_scan_abort(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07009352 }
Abhishek Singh3ac179b2015-09-21 10:01:34 +05309353 if ((pAdapter->device_mode != WLAN_HDD_INFRA_STATION) &&
9354 (pAdapter->device_mode != WLAN_HDD_IBSS))
Kaushik, Sushant7005e372014-04-08 11:36:54 +05309355 {
9356 while (pAdapter->is_roc_inprogress)
9357 {
9358 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9359 "%s: ROC in progress for session %d!!!",
9360 __func__, pAdapter->sessionId);
9361 // waiting for ROC to expire
9362 msleep(500);
9363 /* In GO present case , if retry exceeds 3,
9364 it means something went wrong. */
9365 if ( retry++ > MAX_WAIT_FOR_ROC_COMPLETION )
9366 {
9367 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9368 "%s: ROC completion is not received.!!!", __func__);
Deepthi Gowri70498252015-01-20 15:56:45 +05309369 if (eHAL_STATUS_SUCCESS !=
9370 sme_CancelRemainOnChannel( WLAN_HDD_GET_HAL_CTX( pAdapter),
9371 pAdapter->sessionId ))
9372 {
9373 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9374 FL("Failed to Cancel Remain on Channel"));
9375 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +05309376 wait_for_completion_interruptible_timeout(
9377 &pAdapter->cancel_rem_on_chan_var,
9378 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
9379 break;
9380 }
9381 }
Anand N Sunkaddc63c792015-06-03 14:33:24 +05309382 vos_flush_delayed_work(&pAdapter->roc_work);
Kaushik, Sushant7005e372014-04-08 11:36:54 +05309383 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05309384#ifdef WLAN_NS_OFFLOAD
Anand N Sunkaddc63c792015-06-03 14:33:24 +05309385 vos_flush_work(&pAdapter->ipv6NotifierWorkQueue);
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05309386#endif
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +05309387
Anand N Sunkaddc63c792015-06-03 14:33:24 +05309388 vos_flush_work(&pAdapter->ipv4NotifierWorkQueue);
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +05309389
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05309390 /* It is possible that the caller of this function does not
9391 * wish to close the session
9392 */
9393 if (VOS_TRUE == bCloseSession &&
9394 test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07009395 {
9396 INIT_COMPLETION(pAdapter->session_close_comp_var);
9397 if (eHAL_STATUS_SUCCESS ==
Agrawal Ashish5a3522c2016-03-02 15:08:28 +05309398 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId, FALSE,
9399 VOS_FALSE, hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07009400 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309401 unsigned long ret;
9402
Jeff Johnson295189b2012-06-20 16:38:30 -07009403 //Block on a completion variable. Can't wait forever though.
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309404 ret = wait_for_completion_timeout(
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05309405 &pAdapter->session_close_comp_var,
9406 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309407 if ( 0 >= ret)
9408 {
9409 hddLog(LOGE, "%s: failure waiting for session_close_comp_var %ld",
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05309410 __func__, ret);
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309411 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009412 }
9413 }
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05309414 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009415 break;
9416
9417 case WLAN_HDD_SOFTAP:
9418 case WLAN_HDD_P2P_GO:
Nirav Shah0cf4d892015-11-05 16:27:27 +05309419 if ( VOS_TRUE == bCloseSession )
9420 {
9421 status = hdd_sta_id_hash_detach(pAdapter);
9422 if (status != VOS_STATUS_SUCCESS)
9423 hddLog(VOS_TRACE_LEVEL_ERROR,
9424 FL("sta id hash detach failed"));
9425 }
9426
Jeff Johnson295189b2012-06-20 16:38:30 -07009427 //Any softap specific cleanup here...
Anurag Chouhan83026002016-12-13 22:46:21 +05309428 hdd_cleanup_ap_events(pAdapter);
Kaushik, Sushant7005e372014-04-08 11:36:54 +05309429 if (pAdapter->device_mode == WLAN_HDD_P2P_GO) {
9430 while (pAdapter->is_roc_inprogress) {
9431 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9432 "%s: ROC in progress for session %d!!!",
9433 __func__, pAdapter->sessionId);
9434 msleep(500);
9435 if ( retry++ > MAX_WAIT_FOR_ROC_COMPLETION ) {
9436 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9437 "%s: ROC completion is not received.!!!", __func__);
9438 WLANSAP_CancelRemainOnChannel(
9439 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
9440 wait_for_completion_interruptible_timeout(
9441 &pAdapter->cancel_rem_on_chan_var,
9442 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
9443 break;
9444 }
9445 }
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +05309446
Anand N Sunkaddc63c792015-06-03 14:33:24 +05309447 vos_flush_delayed_work(&pAdapter->roc_work);
Kaushik, Sushant7005e372014-04-08 11:36:54 +05309448 }
Agrawal Ashish17ef5082016-10-17 18:33:21 +05309449#ifdef SAP_AUTH_OFFLOAD
9450 if (pHddCtx->cfg_ini->enable_sap_auth_offload)
9451 hdd_set_sap_auth_offload(pAdapter, FALSE);
9452#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009453 mutex_lock(&pHddCtx->sap_lock);
9454 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
9455 {
9456 VOS_STATUS status;
9457 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9458
9459 //Stop Bss.
9460 status = WLANSAP_StopBss(pHddCtx->pvosContext);
9461 if (VOS_IS_STATUS_SUCCESS(status))
9462 {
9463 hdd_hostapd_state_t *pHostapdState =
9464 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
9465
9466 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
9467
9468 if (!VOS_IS_STATUS_SUCCESS(status))
9469 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309470 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss %d",
9471 __func__, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07009472 }
9473 }
9474 else
9475 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07009476 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009477 }
9478 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
Agarwal Ashish51325b52014-06-16 16:50:49 +05309479 wlan_hdd_decr_active_session(pHddCtx, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07009480
9481 if (eHAL_STATUS_FAILURE ==
9482 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
9483 0, NULL, eANI_BOOLEAN_FALSE))
9484 {
9485 hddLog(LOGE,
9486 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07009487 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009488 }
9489
9490 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
9491 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
9492 eANI_BOOLEAN_FALSE) )
9493 {
9494 hddLog(LOGE,
9495 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
9496 }
9497
9498 // Reset WNI_CFG_PROBE_RSP Flags
9499 wlan_hdd_reset_prob_rspies(pAdapter);
9500 kfree(pAdapter->sessionCtx.ap.beacon);
9501 pAdapter->sessionCtx.ap.beacon = NULL;
9502 }
9503 mutex_unlock(&pHddCtx->sap_lock);
9504 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07009505
Jeff Johnson295189b2012-06-20 16:38:30 -07009506 case WLAN_HDD_MONITOR:
9507 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07009508
Jeff Johnson295189b2012-06-20 16:38:30 -07009509 default:
9510 break;
9511 }
9512
9513 EXIT();
9514 return VOS_STATUS_SUCCESS;
9515}
9516
Kapil Gupta137ef892016-12-13 19:38:00 +05309517/**
9518 * wlan_hdd_restart_sap() - to restart SAP in driver internally
9519 * @ap_adapter: - Pointer to SAP hdd_adapter_t structure
9520 *
9521 * wlan_hdd_restart_sap first delete SAP and do cleanup.
9522 * After that WLANSAP_StartBss start re-start process of SAP.
9523 *
9524 * Return: None
9525 */
9526static void wlan_hdd_restart_sap(hdd_adapter_t *ap_adapter)
9527{
9528 hdd_ap_ctx_t *pHddApCtx;
9529 hdd_hostapd_state_t *pHostapdState;
9530 VOS_STATUS vos_status;
9531 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(ap_adapter);
9532#ifdef CFG80211_DEL_STA_V2
9533 struct station_del_parameters delStaParams;
9534#endif
9535 tsap_Config_t *pConfig;
9536
9537 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
9538 pConfig = &pHddApCtx->sapConfig;
9539
9540 mutex_lock(&pHddCtx->sap_lock);
9541 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags)) {
9542#ifdef CFG80211_DEL_STA_V2
9543 delStaParams.mac = NULL;
9544 delStaParams.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
9545 delStaParams.reason_code = eCsrForcedDeauthSta;
9546 wlan_hdd_cfg80211_del_station(ap_adapter->wdev.wiphy, ap_adapter->dev,
9547 &delStaParams);
9548#else
9549 wlan_hdd_cfg80211_del_station(ap_adapter->wdev.wiphy, ap_adapter->dev,
9550 NULL);
9551#endif
9552 hdd_cleanup_actionframe(pHddCtx, ap_adapter);
9553
9554 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
9555 vos_event_reset(&pHostapdState->vosEvent);
9556
9557 if (VOS_STATUS_SUCCESS == WLANSAP_StopBss(pHddCtx->pvosContext)) {
9558 vos_status = vos_wait_single_event(&pHostapdState->vosEvent,
9559 10000);
9560 if (!VOS_IS_STATUS_SUCCESS(vos_status)) {
9561 hddLog(LOGE, FL("SAP Stop Failed"));
9562 goto end;
9563 }
9564 }
9565 clear_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
9566 wlan_hdd_decr_active_session(pHddCtx, ap_adapter->device_mode);
9567 hddLog(LOG1, FL("SAP Stop Success"));
9568
9569 if (0 != wlan_hdd_cfg80211_update_apies(ap_adapter)) {
9570 hddLog(LOGE, FL("SAP Not able to set AP IEs"));
9571 goto end;
9572 }
9573
9574 if (WLANSAP_StartBss(pHddCtx->pvosContext, hdd_hostapd_SAPEventCB,
9575 pConfig, (v_PVOID_t)ap_adapter->dev) != VOS_STATUS_SUCCESS) {
9576 hddLog(LOGE, FL("SAP Start Bss fail"));
9577 goto end;
9578 }
9579
9580 hddLog(LOG1, FL("Waiting for SAP to start"));
9581 vos_status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
9582 if (!VOS_IS_STATUS_SUCCESS(vos_status)) {
9583 hddLog(LOGE, FL("SAP Start failed"));
9584 goto end;
9585 }
9586 hddLog(LOG1, FL("SAP Start Success"));
9587 set_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
9588 wlan_hdd_incr_active_session(pHddCtx, ap_adapter->device_mode);
9589 pHostapdState->bCommit = TRUE;
Anurag Chouhanb2951ae2017-03-12 13:41:35 +05309590 if (!VOS_IS_STATUS_SUCCESS(hdd_dhcp_mdns_offload(ap_adapter))) {
9591 hddLog(VOS_TRACE_LEVEL_ERROR, FL("DHCP/MDNS offload Failed!!"));
9592 vos_event_reset(&pHostapdState->vosEvent);
9593 if (VOS_STATUS_SUCCESS == WLANSAP_StopBss(pHddCtx->pvosContext)) {
9594 vos_status = vos_wait_single_event(&pHostapdState->vosEvent,
9595 10000);
9596 if (!VOS_IS_STATUS_SUCCESS(vos_status)) {
9597 hddLog(LOGE, FL("SAP Stop Failed"));
9598 goto end;
9599 }
9600 }
9601 }
Kapil Gupta137ef892016-12-13 19:38:00 +05309602 }
9603end:
9604 mutex_unlock(&pHddCtx->sap_lock);
9605 return;
9606}
9607
9608/**
9609 * __hdd_sap_restart_handle() - to handle restarting of SAP
9610 * @work: name of the work
9611 *
9612 * Purpose of this function is to trigger sap start. this function
9613 * will be called from workqueue.
9614 *
9615 * Return: void.
9616 */
9617static void __hdd_sap_restart_handle(struct work_struct *work)
9618{
9619 hdd_adapter_t *sap_adapter;
9620 hdd_context_t *hdd_ctx = container_of(work,
9621 hdd_context_t,
9622 sap_start_work);
9623 if (0 != wlan_hdd_validate_context(hdd_ctx)) {
9624 vos_ssr_unprotect(__func__);
9625 return;
9626 }
9627 sap_adapter = hdd_get_adapter(hdd_ctx,
9628 WLAN_HDD_SOFTAP);
9629 if (sap_adapter == NULL) {
9630 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9631 FL("sap_adapter is NULL"));
9632 vos_ssr_unprotect(__func__);
9633 return;
9634 }
9635
9636 if (hdd_ctx->is_ch_avoid_in_progress) {
9637 sap_adapter->sessionCtx.ap.sapConfig.channel = AUTO_CHANNEL_SELECT;
9638 wlan_hdd_restart_sap(sap_adapter);
9639 hdd_change_ch_avoidance_status(hdd_ctx, false);
9640 }
Agrawal Ashish574b3e62017-02-09 18:58:34 +05309641 if (hdd_ctx->cfg_ini->enable_sap_auth_offload)
9642 wlan_hdd_restart_sap(sap_adapter);
Kapil Gupta137ef892016-12-13 19:38:00 +05309643}
9644
9645/**
9646 * hdd_sap_restart_handle() - to handle restarting of SAP
9647 * @work: name of the work
9648 *
9649 * Purpose of this function is to trigger sap start. this function
9650 * will be called from workqueue.
9651 *
9652 * Return: void.
9653 */
9654static void hdd_sap_restart_handle(struct work_struct *work)
9655{
9656 vos_ssr_protect(__func__);
9657 __hdd_sap_restart_handle(work);
9658 vos_ssr_unprotect(__func__);
9659}
9660
9661
Jeff Johnson295189b2012-06-20 16:38:30 -07009662VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
9663{
9664 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
9665 VOS_STATUS status;
9666 hdd_adapter_t *pAdapter;
9667
9668 ENTER();
9669
9670 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
9671
9672 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
9673 {
9674 pAdapter = pAdapterNode->pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07009675
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05309676 hdd_stop_adapter( pHddCtx, pAdapter, VOS_TRUE );
Jeff Johnson295189b2012-06-20 16:38:30 -07009677
9678 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
9679 pAdapterNode = pNext;
9680 }
9681
9682 EXIT();
9683
9684 return VOS_STATUS_SUCCESS;
9685}
9686
Rajeev Kumarf999e582014-01-09 17:33:29 -08009687
9688#ifdef FEATURE_WLAN_BATCH_SCAN
9689/**---------------------------------------------------------------------------
9690
9691 \brief hdd_deinit_batch_scan () - This function cleans up batch scan data
9692 structures
9693
9694 \param - pAdapter Pointer to HDD adapter
9695
9696 \return - None
9697
9698 --------------------------------------------------------------------------*/
9699void hdd_deinit_batch_scan(hdd_adapter_t *pAdapter)
9700{
9701 tHddBatchScanRsp *pNode;
9702 tHddBatchScanRsp *pPrev;
9703
Siddharth Bhalb3e9b792014-02-24 15:14:16 +05309704 if (NULL == pAdapter)
Rajeev Kumarf999e582014-01-09 17:33:29 -08009705 {
Siddharth Bhalb3e9b792014-02-24 15:14:16 +05309706 hddLog(VOS_TRACE_LEVEL_ERROR,
9707 "%s: Adapter context is Null", __func__);
9708 return;
9709 }
9710
9711 pNode = pAdapter->pBatchScanRsp;
9712 while (pNode)
9713 {
9714 pPrev = pNode;
9715 pNode = pNode->pNext;
9716 vos_mem_free((v_VOID_t * )pPrev);
Rajeev Kumarf999e582014-01-09 17:33:29 -08009717 }
9718
9719 pAdapter->pBatchScanRsp = NULL;
9720 pAdapter->numScanList = 0;
9721 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
9722 pAdapter->prev_batch_id = 0;
9723
9724 return;
9725}
9726#endif
9727
9728
Jeff Johnson295189b2012-06-20 16:38:30 -07009729VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
9730{
9731 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
9732 VOS_STATUS status;
9733 hdd_adapter_t *pAdapter;
9734
9735 ENTER();
9736
9737 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
9738
9739 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
9740 {
9741 pAdapter = pAdapterNode->pAdapter;
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05309742 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
Jeff Johnson295189b2012-06-20 16:38:30 -07009743 netif_tx_disable(pAdapter->dev);
Hanumanth Reddy Pothulad864f312017-01-18 16:16:08 +05309744
9745 if (pHddCtx->cfg_ini->sap_internal_restart &&
9746 pAdapter->device_mode == WLAN_HDD_SOFTAP) {
9747 hddLog(LOG1, FL("driver supports sap restart"));
9748 vos_flush_work(&pHddCtx->sap_start_work);
9749 hdd_sap_indicate_disconnect_for_sta(pAdapter);
9750 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Hanumanth Reddy Pothula15bc0fa2017-02-03 17:24:17 +05309751 hdd_softap_deinit_tx_rx(pAdapter, true);
9752 hdd_sap_destroy_timers(pAdapter);
Hanumanth Reddy Pothulad864f312017-01-18 16:16:08 +05309753 } else {
9754 netif_carrier_off(pAdapter->dev);
9755 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009756
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07009757 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
9758
Jeff Johnson295189b2012-06-20 16:38:30 -07009759 hdd_deinit_tx_rx(pAdapter);
Agarwal Ashish6267caa2014-08-06 19:16:21 +05309760
Katya Nigam1fd24402015-02-16 14:52:19 +05309761 if(pAdapter->device_mode == WLAN_HDD_IBSS )
9762 hdd_ibss_deinit_tx_rx(pAdapter);
9763
Nirav Shah7e3c8132015-06-22 23:51:42 +05309764 status = hdd_sta_id_hash_detach(pAdapter);
9765 if (status != VOS_STATUS_SUCCESS)
9766 hddLog(VOS_TRACE_LEVEL_ERROR,
9767 FL("sta id hash detach failed for session id %d"),
9768 pAdapter->sessionId);
9769
Agarwal Ashish6267caa2014-08-06 19:16:21 +05309770 wlan_hdd_decr_active_session(pHddCtx, pAdapter->device_mode);
9771
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05309772 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
9773 {
9774 hdd_wmm_adapter_close( pAdapter );
9775 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
9776 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009777
Siddharth Bhal2db319d2014-12-03 12:37:18 +05309778 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
9779 {
9780 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
9781 }
9782
Rajeev Kumarf999e582014-01-09 17:33:29 -08009783#ifdef FEATURE_WLAN_BATCH_SCAN
9784 if (eHDD_BATCH_SCAN_STATE_STARTED == pAdapter->batchScanState)
9785 {
9786 hdd_deinit_batch_scan(pAdapter);
9787 }
9788#endif
9789
Mahesh A Saptasagarf5b8eff2015-01-31 01:07:07 +05309790#ifdef FEATURE_WLAN_TDLS
9791 mutex_lock(&pHddCtx->tdls_lock);
Pradeep Reddy POTTETI2d4d5c42015-03-03 14:34:19 +05309792 wlan_hdd_tdls_exit(pAdapter, TRUE);
Mahesh A Saptasagarf5b8eff2015-01-31 01:07:07 +05309793 mutex_unlock(&pHddCtx->tdls_lock);
9794#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009795 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
9796 pAdapterNode = pNext;
9797 }
9798
9799 EXIT();
9800
9801 return VOS_STATUS_SUCCESS;
9802}
9803
Abhishek Singhbbe0b2a2016-12-05 11:57:36 +05309804/**
Abhishek Singh5a597e62016-12-05 15:16:30 +05309805 * hdd_get_bss_entry() - Get the bss entry matching the chan, bssid and ssid
9806 * @wiphy: wiphy
9807 * @channel: channel of the BSS to find
9808 * @bssid: bssid of the BSS to find
9809 * @ssid: ssid of the BSS to find
9810 * @ssid_len: ssid len of of the BSS to find
9811 *
9812 * The API is a wrapper to get bss from kernel matching the chan,
9813 * bssid and ssid
9814 *
9815 * Return: Void
9816 */
9817#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) \
9818 && !defined(WITH_BACKPORTS) && !defined(IEEE80211_PRIVACY)
9819
9820struct cfg80211_bss* hdd_get_bss_entry(struct wiphy *wiphy,
9821 struct ieee80211_channel *channel,
9822 const u8 *bssid,
9823 const u8 *ssid, size_t ssid_len)
9824{
9825 return cfg80211_get_bss(wiphy, channel, bssid,
9826 ssid, ssid_len,
9827 WLAN_CAPABILITY_ESS,
9828 WLAN_CAPABILITY_ESS);
9829}
9830#else
9831struct cfg80211_bss* hdd_get_bss_entry(struct wiphy *wiphy,
9832 struct ieee80211_channel *channel,
9833 const u8 *bssid,
9834 const u8 *ssid, size_t ssid_len)
9835{
9836 return cfg80211_get_bss(wiphy, channel, bssid,
9837 ssid, ssid_len,
9838 IEEE80211_BSS_TYPE_ESS,
9839 IEEE80211_PRIVACY_ANY);
9840}
9841#endif
9842
9843/**
Abhishek Singhbbe0b2a2016-12-05 11:57:36 +05309844 * hdd_connect_result() - API to send connection status to supplicant
9845 * @dev: network device
9846 * @bssid: bssid to which we want to associate
9847 * @roam_info: information about connected bss
9848 * @req_ie: Request Information Element
9849 * @req_ie_len: len of the req IE
9850 * @resp_ie: Response IE
9851 * @resp_ie_len: len of ht response IE
9852 * @status: status
9853 * @gfp: Kernel Flag
9854 *
9855 * The API is a wrapper to send connection status to supplicant
9856 *
9857 * Return: Void
9858 */
9859#if defined CFG80211_CONNECT_BSS
9860void hdd_connect_result(struct net_device *dev,
9861 const u8 *bssid,
9862 tCsrRoamInfo *roam_info,
9863 const u8 *req_ie,
9864 size_t req_ie_len,
9865 const u8 *resp_ie,
9866 size_t resp_ie_len,
9867 u16 status,
9868 gfp_t gfp)
9869{
9870 hdd_adapter_t *padapter = (hdd_adapter_t *) netdev_priv(dev);
9871 struct cfg80211_bss *bss = NULL;
9872
9873 if (WLAN_STATUS_SUCCESS == status) {
9874 struct ieee80211_channel *chan;
9875 int freq;
9876 int chan_no = roam_info->pBssDesc->channelId;;
9877
9878 if (chan_no <= 14)
9879 freq = ieee80211_channel_to_frequency(chan_no,
9880 IEEE80211_BAND_2GHZ);
9881 else
9882 freq = ieee80211_channel_to_frequency(chan_no,
9883 IEEE80211_BAND_5GHZ);
9884
9885 chan = ieee80211_get_channel(padapter->wdev.wiphy, freq);
Abhishek Singh5a597e62016-12-05 15:16:30 +05309886 bss = hdd_get_bss_entry(padapter->wdev.wiphy,
9887 chan, bssid,
9888 roam_info->u.pConnectedProfile->SSID.ssId,
9889 roam_info->u.pConnectedProfile->SSID.length);
Abhishek Singhbbe0b2a2016-12-05 11:57:36 +05309890 }
9891
9892 cfg80211_connect_bss(dev, bssid, bss, req_ie, req_ie_len,
9893 resp_ie, resp_ie_len, status, gfp);
9894}
9895#else
9896void hdd_connect_result(struct net_device *dev,
9897 const u8 *bssid,
9898 tCsrRoamInfo *roam_info,
9899 const u8 *req_ie,
9900 size_t req_ie_len,
9901 const u8 * resp_ie,
9902 size_t resp_ie_len,
9903 u16 status,
9904 gfp_t gfp)
9905{
9906 cfg80211_connect_result(dev, bssid, req_ie, req_ie_len,
9907 resp_ie, resp_ie_len, status, gfp);
9908}
9909#endif
9910
Jeff Johnson295189b2012-06-20 16:38:30 -07009911VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
9912{
9913 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
9914 VOS_STATUS status;
9915 hdd_adapter_t *pAdapter;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05309916 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -07009917
9918 ENTER();
9919
9920 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
9921
9922 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
9923 {
9924 pAdapter = pAdapterNode->pAdapter;
9925
Kumar Anand82c009f2014-05-29 00:29:42 -07009926 hdd_wmm_init( pAdapter );
9927
Jeff Johnson295189b2012-06-20 16:38:30 -07009928 switch(pAdapter->device_mode)
9929 {
9930 case WLAN_HDD_INFRA_STATION:
9931 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07009932 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05309933
9934 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
9935
Jeff Johnson295189b2012-06-20 16:38:30 -07009936 hdd_init_station_mode(pAdapter);
9937 /* Open the gates for HDD to receive Wext commands */
9938 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07009939 pHddCtx->scan_info.mScanPending = FALSE;
9940 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07009941
9942 //Trigger the initial scan
Mukul Sharmae74e42c2015-08-06 23:55:49 +05309943 if (!pHddCtx->isLogpInProgress)
9944 hdd_wlan_initial_scan(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07009945
9946 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05309947 if (eConnectionState_Associated == connState ||
9948 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -07009949 {
9950 union iwreq_data wrqu;
9951 memset(&wrqu, '\0', sizeof(wrqu));
9952 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
9953 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
9954 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07009955 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07009956
Jeff Johnson295189b2012-06-20 16:38:30 -07009957 /* indicate disconnected event to nl80211 */
Mahesh A Saptasagar9ff4bcc2016-06-01 17:17:50 +05309958 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, false,
Mahesh A Saptasagarb5a15142016-05-25 11:27:43 +05309959 WLAN_REASON_UNSPECIFIED);
Jeff Johnson295189b2012-06-20 16:38:30 -07009960 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05309961 else if (eConnectionState_Connecting == connState)
9962 {
9963 /*
9964 * Indicate connect failure to supplicant if we were in the
9965 * process of connecting
9966 */
Abhishek Singhbbe0b2a2016-12-05 11:57:36 +05309967 hdd_connect_result(pAdapter->dev, NULL, NULL,
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05309968 NULL, 0, NULL, 0,
9969 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
9970 GFP_KERNEL);
9971 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009972 break;
9973
9974 case WLAN_HDD_SOFTAP:
Hanumanth Reddy Pothulad864f312017-01-18 16:16:08 +05309975 if (pHddCtx->cfg_ini->sap_internal_restart) {
Hanumanth Reddy Pothula15bc0fa2017-02-03 17:24:17 +05309976 hdd_init_ap_mode(pAdapter, true);
Hanumanth Reddy Pothulad864f312017-01-18 16:16:08 +05309977 status = hdd_sta_id_hash_attach(pAdapter);
9978 if (VOS_STATUS_SUCCESS != status)
9979 {
9980 hddLog(VOS_TRACE_LEVEL_FATAL,
9981 FL("failed to attach hash for"));
9982 }
9983 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009984 break;
9985
9986 case WLAN_HDD_P2P_GO:
Sameer Thalappiledf0d792013-08-09 14:31:03 -07009987 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send stop ap to supplicant",
Jeff Johnson295189b2012-06-20 16:38:30 -07009988 __func__);
Sameer Thalappiledf0d792013-08-09 14:31:03 -07009989 cfg80211_ap_stopped(pAdapter->dev, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07009990 break;
9991
9992 case WLAN_HDD_MONITOR:
9993 /* monitor interface start */
9994 break;
9995 default:
9996 break;
9997 }
9998
9999 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10000 pAdapterNode = pNext;
10001 }
10002
10003 EXIT();
10004
10005 return VOS_STATUS_SUCCESS;
10006}
10007
10008VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
10009{
10010 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
10011 hdd_adapter_t *pAdapter;
10012 VOS_STATUS status;
10013 v_U32_t roamId;
c_hpothu6ff1c3c2013-10-01 19:01:57 +053010014 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -070010015
10016 ENTER();
10017
10018 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10019
10020 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
10021 {
10022 pAdapter = pAdapterNode->pAdapter;
10023
10024 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
10025 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
10026 {
10027 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10028 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10029
Abhishek Singhf4669da2014-05-26 15:07:49 +053010030 hddLog(VOS_TRACE_LEVEL_INFO,
10031 "%s: Set HDD connState to eConnectionState_NotConnected",
10032 __func__);
Ganesh Kondabattini04338412015-09-14 15:39:09 +053010033 spin_lock_bh(&pAdapter->lock_for_active_session);
10034 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState)
10035 {
10036 wlan_hdd_decr_active_session(pHddCtx, pAdapter->device_mode);
10037 }
Jeff Johnson295189b2012-06-20 16:38:30 -070010038 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
Ganesh Kondabattini04338412015-09-14 15:39:09 +053010039 spin_unlock_bh(&pAdapter->lock_for_active_session);
Jeff Johnson295189b2012-06-20 16:38:30 -070010040 init_completion(&pAdapter->disconnect_comp_var);
10041 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
10042 eCSR_DISCONNECT_REASON_UNSPECIFIED);
10043
c_hpothu6ff1c3c2013-10-01 19:01:57 +053010044 ret = wait_for_completion_interruptible_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -070010045 &pAdapter->disconnect_comp_var,
10046 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +053010047 if (0 >= ret)
10048 hddLog(LOGE, "%s: failure waiting for disconnect_comp_var %ld",
10049 __func__, ret);
Jeff Johnson295189b2012-06-20 16:38:30 -070010050
10051 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
10052 pHddCtx->isAmpAllowed = VOS_FALSE;
10053 sme_RoamConnect(pHddCtx->hHal,
10054 pAdapter->sessionId, &(pWextState->roamProfile),
10055 &roamId);
10056 }
10057
10058 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10059 pAdapterNode = pNext;
10060 }
10061
10062 EXIT();
10063
10064 return VOS_STATUS_SUCCESS;
10065}
10066
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -070010067void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
10068{
10069 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
10070 VOS_STATUS status;
10071 hdd_adapter_t *pAdapter;
10072 hdd_station_ctx_t *pHddStaCtx;
10073 hdd_ap_ctx_t *pHddApCtx;
10074 hdd_hostapd_state_t * pHostapdState;
10075 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
10076 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
10077 const char *p2pMode = "DEV";
10078 const char *ccMode = "Standalone";
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -070010079
10080 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10081 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
10082 {
10083 pAdapter = pAdapterNode->pAdapter;
10084 switch (pAdapter->device_mode) {
10085 case WLAN_HDD_INFRA_STATION:
10086 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10087 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
10088 staChannel = pHddStaCtx->conn_info.operationChannel;
10089 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
10090 }
10091 break;
10092 case WLAN_HDD_P2P_CLIENT:
10093 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10094 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
10095 p2pChannel = pHddStaCtx->conn_info.operationChannel;
10096 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
10097 p2pMode = "CLI";
10098 }
10099 break;
10100 case WLAN_HDD_P2P_GO:
10101 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
10102 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
10103 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
10104 p2pChannel = pHddApCtx->operatingChannel;
10105 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
10106 }
10107 p2pMode = "GO";
10108 break;
10109 case WLAN_HDD_SOFTAP:
10110 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
10111 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
10112 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
10113 apChannel = pHddApCtx->operatingChannel;
10114 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
10115 }
10116 break;
10117 default:
10118 break;
10119 }
10120 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10121 pAdapterNode = pNext;
10122 }
10123 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
10124 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
10125 }
SaidiReddy Yenugaa8b32f92016-07-27 19:29:18 +053010126 hddLog(VOS_TRACE_LEVEL_INFO, "wlan(%d) " MAC_ADDRESS_STR " %s",
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -070010127 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
10128 if (p2pChannel > 0) {
Sushant Kaushikdc3184b2015-10-09 12:00:21 +053010129 hddLog(VOS_TRACE_LEVEL_ERROR, "p2p-%s(%d) " MAC_ADDRESS_STR,
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -070010130 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
10131 }
10132 if (apChannel > 0) {
Sushant Kaushikdc3184b2015-10-09 12:00:21 +053010133 hddLog(VOS_TRACE_LEVEL_ERROR, "AP(%d) " MAC_ADDRESS_STR,
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -070010134 apChannel, MAC_ADDR_ARRAY(apBssid));
10135 }
10136
10137 if (p2pChannel > 0 && apChannel > 0) {
10138 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
10139 }
10140}
10141
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -070010142bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -070010143{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -070010144 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -070010145}
10146
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -070010147/* Once SSR is disabled then it cannot be set. */
10148void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -070010149{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -070010150 if (HDD_SSR_DISABLED == isSsrRequired)
10151 return;
10152
Jeff Johnson295189b2012-06-20 16:38:30 -070010153 isSsrRequired = value;
10154}
10155
Hema Aparna Medicharla6b4d4f32015-06-23 04:09:12 +053010156void hdd_set_pre_close( hdd_context_t *pHddCtx)
10157{
10158 sme_PreClose(pHddCtx->hHal);
10159}
10160
Jeff Johnson295189b2012-06-20 16:38:30 -070010161VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
10162 hdd_adapter_list_node_t** ppAdapterNode)
10163{
10164 VOS_STATUS status;
Mukul Sharmaae1266d2015-06-26 15:29:53 +053010165 spin_lock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010166 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
10167 (hdd_list_node_t**) ppAdapterNode );
Mukul Sharmaae1266d2015-06-26 15:29:53 +053010168 spin_unlock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010169 return status;
10170}
10171
10172VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
10173 hdd_adapter_list_node_t* pAdapterNode,
10174 hdd_adapter_list_node_t** pNextAdapterNode)
10175{
10176 VOS_STATUS status;
Mukul Sharmaae1266d2015-06-26 15:29:53 +053010177 spin_lock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010178 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
10179 (hdd_list_node_t*) pAdapterNode,
10180 (hdd_list_node_t**)pNextAdapterNode );
10181
Mukul Sharmaae1266d2015-06-26 15:29:53 +053010182 spin_unlock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010183 return status;
10184}
10185
10186VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
10187 hdd_adapter_list_node_t* pAdapterNode)
10188{
10189 VOS_STATUS status;
Mukul Sharmaae1266d2015-06-26 15:29:53 +053010190 spin_lock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010191 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
10192 &pAdapterNode->node );
Mukul Sharmaae1266d2015-06-26 15:29:53 +053010193 spin_unlock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010194 return status;
10195}
10196
10197VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
10198 hdd_adapter_list_node_t** ppAdapterNode)
10199{
10200 VOS_STATUS status;
Mukul Sharmaae1266d2015-06-26 15:29:53 +053010201 spin_lock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010202 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
10203 (hdd_list_node_t**) ppAdapterNode );
Mukul Sharmaae1266d2015-06-26 15:29:53 +053010204 spin_unlock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010205 return status;
10206}
10207
10208VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
10209 hdd_adapter_list_node_t* pAdapterNode)
10210{
10211 VOS_STATUS status;
Mukul Sharmaae1266d2015-06-26 15:29:53 +053010212 spin_lock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010213 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
10214 (hdd_list_node_t*) pAdapterNode );
Mukul Sharmaae1266d2015-06-26 15:29:53 +053010215 spin_unlock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010216 return status;
10217}
10218
10219VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
10220 hdd_adapter_list_node_t* pAdapterNode)
10221{
10222 VOS_STATUS status;
Mukul Sharmaae1266d2015-06-26 15:29:53 +053010223 spin_lock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010224 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
10225 (hdd_list_node_t*) pAdapterNode );
Mukul Sharmaae1266d2015-06-26 15:29:53 +053010226 spin_unlock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010227 return status;
10228}
10229
10230hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
10231 tSirMacAddr macAddr )
10232{
10233 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
10234 hdd_adapter_t *pAdapter;
10235 VOS_STATUS status;
10236
10237 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10238
10239 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
10240 {
10241 pAdapter = pAdapterNode->pAdapter;
10242
10243 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
10244 macAddr, sizeof(tSirMacAddr) ) )
10245 {
10246 return pAdapter;
10247 }
10248 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10249 pAdapterNode = pNext;
10250 }
10251
10252 return NULL;
10253
10254}
10255
10256hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
10257{
10258 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
10259 hdd_adapter_t *pAdapter;
10260 VOS_STATUS status;
10261
10262 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10263
10264 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
10265 {
10266 pAdapter = pAdapterNode->pAdapter;
10267
10268 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
10269 IFNAMSIZ ) )
10270 {
10271 return pAdapter;
10272 }
10273 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10274 pAdapterNode = pNext;
10275 }
10276
10277 return NULL;
10278
10279}
10280
Ganesh Kondabattinicbfdc392015-09-11 19:12:59 +053010281hdd_adapter_t *hdd_get_adapter_by_sme_session_id( hdd_context_t *pHddCtx,
10282 tANI_U32 sme_session_id )
10283{
10284 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
10285 hdd_adapter_t *pAdapter;
10286 VOS_STATUS vos_status;
10287
10288
10289 vos_status = hdd_get_front_adapter( pHddCtx, &pAdapterNode);
10290
10291 while ((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == vos_status))
10292 {
10293 pAdapter = pAdapterNode->pAdapter;
10294
10295 if (pAdapter->sessionId == sme_session_id)
10296 return pAdapter;
10297
10298 vos_status = hdd_get_next_adapter(pHddCtx, pAdapterNode, &pNext);
10299 pAdapterNode = pNext;
10300 }
10301
10302 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
10303 "%s: sme_session_id %d does not exist with host",
10304 __func__, sme_session_id);
10305
10306 return NULL;
10307}
10308
Jeff Johnson295189b2012-06-20 16:38:30 -070010309hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
10310{
10311 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
10312 hdd_adapter_t *pAdapter;
10313 VOS_STATUS status;
10314
10315 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10316
10317 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
10318 {
10319 pAdapter = pAdapterNode->pAdapter;
10320
10321 if( pAdapter && (mode == pAdapter->device_mode) )
10322 {
10323 return pAdapter;
10324 }
10325 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10326 pAdapterNode = pNext;
10327 }
10328
10329 return NULL;
10330
10331}
10332
10333//Remove this function later
10334hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
10335{
10336 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
10337 hdd_adapter_t *pAdapter;
10338 VOS_STATUS status;
10339
10340 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10341
10342 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
10343 {
10344 pAdapter = pAdapterNode->pAdapter;
10345
10346 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
10347 {
10348 return pAdapter;
10349 }
10350
10351 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10352 pAdapterNode = pNext;
10353 }
10354
10355 return NULL;
10356
10357}
10358
Jeff Johnson295189b2012-06-20 16:38:30 -070010359/**---------------------------------------------------------------------------
10360
Mahesh A Saptasgar64534612014-09-23 13:13:33 +053010361 \brief hdd_get_operating_channel() -
Jeff Johnson295189b2012-06-20 16:38:30 -070010362
10363 This API returns the operating channel of the requested device mode
10364
10365 \param - pHddCtx - Pointer to the HDD context.
10366 - mode - Device mode for which operating channel is required
10367 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
10368 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
10369 \return - channel number. "0" id the requested device is not found OR it is not connected.
10370 --------------------------------------------------------------------------*/
10371v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
10372{
10373 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
10374 VOS_STATUS status;
10375 hdd_adapter_t *pAdapter;
10376 v_U8_t operatingChannel = 0;
10377
10378 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10379
10380 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
10381 {
10382 pAdapter = pAdapterNode->pAdapter;
10383
10384 if( mode == pAdapter->device_mode )
10385 {
10386 switch(pAdapter->device_mode)
10387 {
10388 case WLAN_HDD_INFRA_STATION:
10389 case WLAN_HDD_P2P_CLIENT:
10390 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
10391 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
10392 break;
10393 case WLAN_HDD_SOFTAP:
10394 case WLAN_HDD_P2P_GO:
10395 /*softap connection info */
10396 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
10397 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
10398 break;
10399 default:
10400 break;
10401 }
10402
10403 break; //Found the device of interest. break the loop
10404 }
10405
10406 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10407 pAdapterNode = pNext;
10408 }
10409 return operatingChannel;
10410}
10411
10412#ifdef WLAN_FEATURE_PACKET_FILTERING
10413/**---------------------------------------------------------------------------
10414
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +053010415 \brief __hdd_set_multicast_list() -
Jeff Johnson295189b2012-06-20 16:38:30 -070010416
10417 This used to set the multicast address list.
10418
10419 \param - dev - Pointer to the WLAN device.
10420 - skb - Pointer to OS packet (sk_buff).
Mahesh A Saptasagar74088392015-02-05 17:22:09 +053010421 \return - success/fail
Jeff Johnson295189b2012-06-20 16:38:30 -070010422
10423 --------------------------------------------------------------------------*/
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +053010424static void __hdd_set_multicast_list(struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -070010425{
Mahesh A Saptasagar74088392015-02-05 17:22:09 +053010426 hdd_adapter_t *pAdapter;
10427 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -070010428 int mc_count;
Mahesh A Saptasagar74088392015-02-05 17:22:09 +053010429 int i = 0, ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -070010430 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +053010431
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +053010432 ENTER();
10433
Mahesh A Saptasagar74088392015-02-05 17:22:09 +053010434 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Gopichand Nakkala0f276812013-02-24 14:45:51 +053010435 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -070010436 {
10437 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +053010438 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -070010439 return;
10440 }
Mahesh A Saptasagar74088392015-02-05 17:22:09 +053010441 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10442 ret = wlan_hdd_validate_context(pHddCtx);
10443 if (0 != ret)
10444 {
Mahesh A Saptasagar74088392015-02-05 17:22:09 +053010445 return;
10446 }
Jeff Johnson295189b2012-06-20 16:38:30 -070010447 if (dev->flags & IFF_ALLMULTI)
10448 {
10449 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070010450 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +053010451 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -070010452 }
Mahesh A Saptasagar74088392015-02-05 17:22:09 +053010453 else
Jeff Johnson295189b2012-06-20 16:38:30 -070010454 {
10455 mc_count = netdev_mc_count(dev);
10456 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070010457 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -070010458 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
10459 {
10460 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070010461 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +053010462 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -070010463 return;
10464 }
10465
Gopichand Nakkala0f276812013-02-24 14:45:51 +053010466 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -070010467
10468 netdev_for_each_mc_addr(ha, dev) {
10469 if (i == mc_count)
10470 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +053010471 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
10472 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
Arif Hussain6d2a3322013-11-17 19:50:10 -080010473 hddLog(VOS_TRACE_LEVEL_INFO, "%s: mlist[%d] = "MAC_ADDRESS_STR,
Mahesh A Saptasagar74088392015-02-05 17:22:09 +053010474 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +053010475 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -070010476 i++;
10477 }
10478 }
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +053010479
Ganesh Kondabattinifb37e652015-10-09 15:46:47 +053010480 if (pHddCtx->hdd_wlan_suspended)
10481 {
10482 /*
10483 * Configure the Mcast address list to FW
10484 * If wlan is already in suspend mode
10485 */
10486 wlan_hdd_set_mc_addr_list(pAdapter, TRUE);
10487 }
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +053010488 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -070010489 return;
10490}
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +053010491
10492static void hdd_set_multicast_list(struct net_device *dev)
10493{
10494 vos_ssr_protect(__func__);
10495 __hdd_set_multicast_list(dev);
10496 vos_ssr_unprotect(__func__);
10497}
Jeff Johnson295189b2012-06-20 16:38:30 -070010498#endif
10499
10500/**---------------------------------------------------------------------------
10501
10502 \brief hdd_select_queue() -
10503
10504 This function is registered with the Linux OS for network
10505 core to decide which queue to use first.
10506
10507 \param - dev - Pointer to the WLAN device.
10508 - skb - Pointer to OS packet (sk_buff).
10509 \return - ac, Queue Index/access category corresponding to UP in IP header
10510
10511 --------------------------------------------------------------------------*/
10512v_U16_t hdd_select_queue(struct net_device *dev,
Anand N Sunkade9adb1b2015-07-29 09:56:45 +053010513 struct sk_buff *skb
10514#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0))
10515 , void *accel_priv
10516#endif
10517#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0))
10518 , select_queue_fallback_t fallback
10519#endif
10520)
Jeff Johnson295189b2012-06-20 16:38:30 -070010521{
10522 return hdd_wmm_select_queue(dev, skb);
10523}
10524
10525
10526/**---------------------------------------------------------------------------
10527
10528 \brief hdd_wlan_initial_scan() -
10529
10530 This function triggers the initial scan
10531
10532 \param - pAdapter - Pointer to the HDD adapter.
10533
10534 --------------------------------------------------------------------------*/
10535void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
10536{
10537 tCsrScanRequest scanReq;
10538 tCsrChannelInfo channelInfo;
10539 eHalStatus halStatus;
Jeff Johnson02797792013-10-26 19:17:13 -070010540 tANI_U32 scanId;
Jeff Johnson295189b2012-06-20 16:38:30 -070010541 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10542
10543 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
10544 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
10545 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
10546
10547 if(sme_Is11dSupported(pHddCtx->hHal))
10548 {
10549 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
10550 if ( HAL_STATUS_SUCCESS( halStatus ) )
10551 {
10552 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
10553 if( !scanReq.ChannelInfo.ChannelList )
10554 {
10555 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
10556 vos_mem_free(channelInfo.ChannelList);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -080010557 channelInfo.ChannelList = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -070010558 return;
10559 }
10560 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
10561 channelInfo.numOfChannels);
10562 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
10563 vos_mem_free(channelInfo.ChannelList);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -080010564 channelInfo.ChannelList = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -070010565 }
10566
10567 scanReq.scanType = eSIR_PASSIVE_SCAN;
10568 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
10569 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
10570 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
10571 }
10572 else
10573 {
10574 scanReq.scanType = eSIR_ACTIVE_SCAN;
10575 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
10576 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
10577 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
10578 }
10579
10580 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
10581 if ( !HAL_STATUS_SUCCESS( halStatus ) )
10582 {
10583 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
10584 __func__, halStatus );
10585 }
10586
10587 if(sme_Is11dSupported(pHddCtx->hHal))
10588 vos_mem_free(scanReq.ChannelInfo.ChannelList);
10589}
10590
Jeff Johnson295189b2012-06-20 16:38:30 -070010591/**---------------------------------------------------------------------------
10592
10593 \brief hdd_full_power_callback() - HDD full power callback function
10594
10595 This is the function invoked by SME to inform the result of a full power
10596 request issued by HDD
10597
10598 \param - callbackcontext - Pointer to cookie
10599 \param - status - result of request
10600
10601 \return - None
10602
10603 --------------------------------------------------------------------------*/
10604static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
10605{
Jeff Johnson72a40512013-12-19 10:14:15 -080010606 struct statsContext *pContext = callbackContext;
Jeff Johnson295189b2012-06-20 16:38:30 -070010607
10608 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +053010609 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -070010610
10611 if (NULL == callbackContext)
10612 {
10613 hddLog(VOS_TRACE_LEVEL_ERROR,
10614 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070010615 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -070010616 return;
10617 }
10618
Jeff Johnson72a40512013-12-19 10:14:15 -080010619 /* there is a race condition that exists between this callback
10620 function and the caller since the caller could time out either
10621 before or while this code is executing. we use a spinlock to
10622 serialize these actions */
10623 spin_lock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010624
10625 if (POWER_CONTEXT_MAGIC != pContext->magic)
10626 {
10627 /* the caller presumably timed out so there is nothing we can do */
Jeff Johnson72a40512013-12-19 10:14:15 -080010628 spin_unlock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010629 hddLog(VOS_TRACE_LEVEL_WARN,
10630 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070010631 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -070010632 return;
10633 }
10634
Jeff Johnson72a40512013-12-19 10:14:15 -080010635 /* context is valid so caller is still waiting */
10636
10637 /* paranoia: invalidate the magic */
10638 pContext->magic = 0;
10639
10640 /* notify the caller */
Jeff Johnson295189b2012-06-20 16:38:30 -070010641 complete(&pContext->completion);
Jeff Johnson72a40512013-12-19 10:14:15 -080010642
10643 /* serialization is complete */
10644 spin_unlock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010645}
10646
Katya Nigamf0511f62015-05-05 16:40:57 +053010647void wlan_hdd_mon_set_typesubtype( hdd_mon_ctx_t *pMonCtx,int type)
10648{
10649 pMonCtx->typeSubtypeBitmap = 0;
10650 if( type%10 ) /* Management Packets */
10651 pMonCtx->typeSubtypeBitmap |= 0xFFFF;
10652 type/=10;
10653 if( type%10 ) /* Control Packets */
10654 pMonCtx->typeSubtypeBitmap |= 0xFFFF0000;
10655 type/=10;
10656 if( type%10 ) /* Data Packets */
10657 pMonCtx->typeSubtypeBitmap |= 0xFFFF00000000;
10658}
10659
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053010660VOS_STATUS wlan_hdd_mon_postMsg(tANI_U32 *magic, struct completion *cmpVar,
10661 hdd_mon_ctx_t *pMonCtx , void* callback)
Katya Nigamf0511f62015-05-05 16:40:57 +053010662{
10663 vos_msg_t monMsg;
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053010664 tSirMonModeReq *pMonModeReq;
Katya Nigamf0511f62015-05-05 16:40:57 +053010665
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053010666 if (MON_MODE_START == pMonCtx->state)
10667 monMsg.type = WDA_MON_START_REQ;
10668 else if (MON_MODE_STOP == pMonCtx->state)
10669 monMsg.type = WDA_MON_STOP_REQ;
10670 else {
10671 hddLog(VOS_TRACE_LEVEL_ERROR,
10672 FL("invalid monitor state %d"), pMonCtx->state);
Katya Nigamf0511f62015-05-05 16:40:57 +053010673 return VOS_STATUS_E_FAILURE;
10674 }
10675
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053010676 pMonModeReq = vos_mem_malloc(sizeof(tSirMonModeReq));
10677 if (pMonModeReq == NULL) {
10678 hddLog(VOS_TRACE_LEVEL_ERROR,
10679 FL("fail to allocate memory for monitor mode req"));
10680 return VOS_STATUS_E_FAILURE;
10681 }
Katya Nigamf0511f62015-05-05 16:40:57 +053010682
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053010683 pMonModeReq->magic = magic;
10684 pMonModeReq->cmpVar = cmpVar;
10685 pMonModeReq->data = pMonCtx;
10686 pMonModeReq->callback = callback;
Katya Nigamf0511f62015-05-05 16:40:57 +053010687
Katya Nigamf0511f62015-05-05 16:40:57 +053010688 monMsg.reserved = 0;
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053010689 monMsg.bodyptr = pMonModeReq;
Katya Nigamf0511f62015-05-05 16:40:57 +053010690 monMsg.bodyval = 0;
10691
10692 if (VOS_STATUS_SUCCESS != vos_mq_post_message(
10693 VOS_MODULE_ID_WDA,(vos_msg_t *)&monMsg)) {
10694 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: : Failed to post Msg to HAL",__func__);
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053010695 vos_mem_free(pMonModeReq);
Katya Nigamf0511f62015-05-05 16:40:57 +053010696 }
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053010697 return VOS_STATUS_SUCCESS;
Katya Nigamf0511f62015-05-05 16:40:57 +053010698}
10699
Katya Nigame7b69a82015-04-28 15:24:06 +053010700void wlan_hdd_mon_close(hdd_context_t *pHddCtx)
10701{
10702 VOS_STATUS vosStatus;
10703 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053010704 long ret;
10705 hdd_mon_ctx_t *pMonCtx = NULL;
10706 v_U32_t magic;
10707 struct completion cmpVar;
Hanumantha Reddy Pothulac99bc062015-09-08 14:59:26 +053010708
Katya Nigame7b69a82015-04-28 15:24:06 +053010709 hdd_adapter_t *pAdapter = hdd_get_adapter(pHddCtx,WLAN_HDD_MONITOR);
10710 if(pAdapter == NULL || pVosContext == NULL)
10711 {
10712 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:pAdapter is NULL",__func__);
10713 return ;
10714 }
Katya Nigamf0511f62015-05-05 16:40:57 +053010715
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053010716 pMonCtx = WLAN_HDD_GET_MONITOR_CTX_PTR(pAdapter);
10717 if (pMonCtx!= NULL && pMonCtx->state == MON_MODE_START) {
10718 pMonCtx->state = MON_MODE_STOP;
10719 magic = MON_MODE_MSG_MAGIC;
10720 init_completion(&cmpVar);
10721 if (VOS_STATUS_SUCCESS !=
10722 wlan_hdd_mon_postMsg(&magic, &cmpVar,
10723 pMonCtx, hdd_monPostMsgCb)) {
10724 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
10725 FL("failed to post MON MODE REQ"));
10726 pMonCtx->state = MON_MODE_START;
10727 magic = 0;
10728 return;
10729 }
10730 ret = wait_for_completion_timeout(&cmpVar, MON_MODE_MSG_TIMEOUT);
10731 magic = 0;
10732 if (ret <= 0 ) {
10733 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
10734 FL("timeout on monitor mode completion %ld"), ret);
10735 }
10736 }
10737
Katya Nigame7b69a82015-04-28 15:24:06 +053010738 hdd_UnregisterWext(pAdapter->dev);
10739
10740 vos_mon_stop( pVosContext );
10741
10742 vosStatus = vos_sched_close( pVosContext );
10743 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
10744 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
10745 "%s: Failed to close VOSS Scheduler",__func__);
10746 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
10747 }
10748
10749 vosStatus = vos_nv_close();
10750 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
10751 {
10752 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
10753 "%s: Failed to close NV", __func__);
10754 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
10755 }
10756
10757 vos_close(pVosContext);
10758
10759 #ifdef WLAN_KD_READY_NOTIFIER
10760 nl_srv_exit(pHddCtx->ptt_pid);
10761 #else
10762 nl_srv_exit();
10763 #endif
10764
Katya Nigame7b69a82015-04-28 15:24:06 +053010765 hdd_close_all_adapters( pHddCtx );
Katya Nigame7b69a82015-04-28 15:24:06 +053010766}
Agrawal Ashish33ec71e2015-11-26 20:20:58 +053010767/**
10768 * hdd_wlan_free_wiphy_channels - free Channel pointer for wiphy
10769 * @ wiphy: the wiphy to validate against
10770 *
10771 * Return: void
10772 */
10773void hdd_wlan_free_wiphy_channels(struct wiphy *wiphy)
10774{
10775 int i =0;
10776 for (i = 0; i < IEEE80211_NUM_BANDS; i++)
10777 {
10778 if (NULL != wiphy->bands[i] &&
10779 (NULL != wiphy->bands[i]->channels))
10780 {
10781 vos_mem_free(wiphy->bands[i]->channels);
10782 wiphy->bands[i]->channels = NULL;
10783 }
10784 }
10785}
Jeff Johnson295189b2012-06-20 16:38:30 -070010786/**---------------------------------------------------------------------------
10787
10788 \brief hdd_wlan_exit() - HDD WLAN exit function
10789
10790 This is the driver exit point (invoked during rmmod)
10791
10792 \param - pHddCtx - Pointer to the HDD Context
10793
10794 \return - None
10795
10796 --------------------------------------------------------------------------*/
10797void hdd_wlan_exit(hdd_context_t *pHddCtx)
10798{
10799 eHalStatus halStatus;
10800 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
10801 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +053010802 struct wiphy *wiphy = pHddCtx->wiphy;
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -080010803 hdd_adapter_t* pAdapter = NULL;
Jeff Johnson72a40512013-12-19 10:14:15 -080010804 struct statsContext powerContext;
Jeff Johnson295189b2012-06-20 16:38:30 -070010805 long lrc;
c_hpothu5ab05e92014-06-13 17:34:05 +053010806 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -070010807
10808 ENTER();
10809
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053010810
Katya Nigame7b69a82015-04-28 15:24:06 +053010811 if (VOS_MONITOR_MODE == hdd_get_conparam())
10812 {
10813 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: MONITOR MODE",__func__);
10814 wlan_hdd_mon_close(pHddCtx);
Hanumantha Reddy Pothulac99bc062015-09-08 14:59:26 +053010815 goto free_hdd_ctx;
Katya Nigame7b69a82015-04-28 15:24:06 +053010816 }
10817 else if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -080010818 {
10819 // Unloading, restart logic is no more required.
10820 wlan_hdd_restart_deinit(pHddCtx);
Jeff Johnsone7245742012-09-05 17:12:55 -070010821
Agarwal Ashishb20e0ff2014-12-17 22:50:19 +053010822#ifdef FEATURE_WLAN_TDLS
10823 /* At the time of driver unloading; if tdls connection is present;
10824 * hdd_rx_packet_cbk calls wlan_hdd_tdls_find_peer.
10825 * wlan_hdd_tdls_find_peer always checks for valid context;
10826 * as load/unload in progress there can be a race condition.
10827 * hdd_rx_packet_cbk calls wlan_hdd_tdls_find_peer only
10828 * when tdls state is enabled.
10829 * As soon as driver set load/unload flag; tdls flag also needs
10830 * to be disabled so that hdd_rx_packet_cbk won't call
10831 * wlan_hdd_tdls_find_peer.
10832 */
Masti, Narayanraddi20494af2015-12-17 20:56:42 +053010833 wlan_hdd_tdls_set_mode(pHddCtx, eTDLS_SUPPORT_DISABLED, FALSE,
10834 HDD_SET_TDLS_MODE_SOURCE_USER);
Agarwal Ashishb20e0ff2014-12-17 22:50:19 +053010835#endif
10836
c_hpothu5ab05e92014-06-13 17:34:05 +053010837 vosStatus = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10838 while (NULL != pAdapterNode && VOS_STATUS_E_EMPTY != vosStatus)
Jeff Johnson295189b2012-06-20 16:38:30 -070010839 {
c_hpothu5ab05e92014-06-13 17:34:05 +053010840 pAdapter = pAdapterNode->pAdapter;
10841 if (NULL != pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -070010842 {
Mahesh A Saptasagar305e2632015-03-04 12:57:33 +053010843 /* Disable TX on the interface, after this hard_start_xmit() will
10844 * not be called on that interface
10845 */
10846 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
10847 netif_tx_disable(pAdapter->dev);
10848
10849 /* Mark the interface status as "down" for outside world */
10850 netif_carrier_off(pAdapter->dev);
10851
Agarwal Ashish9ffa5b92014-11-18 21:07:02 +053010852 /* DeInit the adapter. This ensures that all data packets
10853 * are freed.
10854 */
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +053010855#ifdef FEATURE_WLAN_TDLS
10856 mutex_lock(&pHddCtx->tdls_lock);
10857#endif
c_hpothu002231a2015-02-05 14:58:51 +053010858 hdd_deinit_adapter(pHddCtx, pAdapter, FALSE);
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +053010859#ifdef FEATURE_WLAN_TDLS
10860 mutex_unlock(&pHddCtx->tdls_lock);
10861#endif
Masti, Narayanraddi26378462016-01-05 18:20:28 +053010862 vos_flush_delayed_work(&pHddCtx->scan_ctxt.scan_work);
10863
10864 wlan_hdd_init_deinit_defer_scan_context(&pHddCtx->scan_ctxt);
Agarwal Ashish9ffa5b92014-11-18 21:07:02 +053010865
c_hpothu5ab05e92014-06-13 17:34:05 +053010866 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode ||
10867 WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)
10868 {
10869 wlan_hdd_cfg80211_deregister_frames(pAdapter);
10870 hdd_UnregisterWext(pAdapter->dev);
10871 }
Kaushik, Sushant4975a572014-10-21 16:07:48 +053010872
Jeff Johnson295189b2012-06-20 16:38:30 -070010873 }
c_hpothu5ab05e92014-06-13 17:34:05 +053010874 vosStatus = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10875 pAdapterNode = pNext;
Jeff Johnson295189b2012-06-20 16:38:30 -070010876 }
mukul sharmabab477d2015-06-11 17:14:55 +053010877
Kaushik, Sushant4975a572014-10-21 16:07:48 +053010878 // Cancel any outstanding scan requests. We are about to close all
10879 // of our adapters, but an adapter structure is what SME passes back
10880 // to our callback function. Hence if there are any outstanding scan
10881 // requests then there is a race condition between when the adapter
10882 // is closed and when the callback is invoked.We try to resolve that
10883 // race condition here by canceling any outstanding scans before we
10884 // close the adapters.
10885 // Note that the scans may be cancelled in an asynchronous manner,
10886 // so ideally there needs to be some kind of synchronization. Rather
10887 // than introduce a new synchronization here, we will utilize the
10888 // fact that we are about to Request Full Power, and since that is
10889 // synchronized, the expectation is that by the time Request Full
10890 // Power has completed all scans will be cancelled.
10891 if (pHddCtx->scan_info.mScanPending)
10892 {
Hema Aparna Medicharlaf05f6cd2015-01-21 14:44:19 +053010893 if(NULL != pAdapter)
10894 {
10895 hddLog(VOS_TRACE_LEVEL_INFO,
10896 FL("abort scan mode: %d sessionId: %d"),
10897 pAdapter->device_mode,
10898 pAdapter->sessionId);
10899 }
10900 hdd_abort_mac_scan(pHddCtx,
10901 pHddCtx->scan_info.sessionId,
10902 eCSR_SCAN_ABORT_DEFAULT);
Kaushik, Sushant4975a572014-10-21 16:07:48 +053010903 }
Jeff Johnson295189b2012-06-20 16:38:30 -070010904 }
c_hpothu5ab05e92014-06-13 17:34:05 +053010905 else
Jeff Johnson88ba7742013-02-27 14:36:02 -080010906 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +053010907 hddLog(VOS_TRACE_LEVEL_INFO,"%s: FTM MODE",__func__);
Hanumantha Reddy Pothula45af96b2015-02-12 16:07:58 +053010908 if (pHddCtx->ftm.ftm_state == WLAN_FTM_STARTING)
10909 {
10910 INIT_COMPLETION(pHddCtx->ftm.startCmpVar);
10911 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
10912 "%s: in middle of FTM START", __func__);
10913 lrc = wait_for_completion_timeout(&pHddCtx->ftm.startCmpVar,
10914 msecs_to_jiffies(20000));
10915 if(!lrc)
10916 {
10917 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
10918 "%s: timedout on ftmStartCmpVar fatal error", __func__);
10919 }
10920 }
Jeff Johnson88ba7742013-02-27 14:36:02 -080010921 wlan_hdd_ftm_close(pHddCtx);
10922 goto free_hdd_ctx;
10923 }
c_hpothu6ff1c3c2013-10-01 19:01:57 +053010924
Jeff Johnson295189b2012-06-20 16:38:30 -070010925 /* DeRegister with platform driver as client for Suspend/Resume */
10926 vosStatus = hddDeregisterPmOps(pHddCtx);
10927 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
10928 {
10929 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
10930 VOS_ASSERT(0);
10931 }
10932
10933 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
10934 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
10935 {
10936 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
10937 }
Jeff Johnson295189b2012-06-20 16:38:30 -070010938
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -070010939 //Stop the traffic monitor timer
Mahesh A Saptasagard461e432016-07-20 15:01:40 +053010940 if ((pHddCtx->cfg_ini->dynSplitscan) && (VOS_TIMER_STATE_RUNNING ==
10941 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr)))
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -070010942 {
10943 vos_timer_stop(&pHddCtx->tx_rx_trafficTmr);
10944 }
10945
10946 // Destroy the traffic monitor timer
Mahesh A Saptasagard461e432016-07-20 15:01:40 +053010947 if ((pHddCtx->cfg_ini->dynSplitscan) &&
10948 (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
10949 &pHddCtx->tx_rx_trafficTmr))))
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -070010950 {
10951 hddLog(VOS_TRACE_LEVEL_ERROR,
10952 "%s: Cannot deallocate Traffic monitor timer", __func__);
10953 }
10954
Bhargav Shahd0715912015-10-01 18:17:37 +053010955 if (VOS_TIMER_STATE_RUNNING ==
10956 vos_timer_getCurrentState(&pHddCtx->delack_timer)) {
10957 vos_timer_stop(&pHddCtx->delack_timer);
10958 }
10959
10960 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
10961 &pHddCtx->delack_timer))) {
10962 hddLog(VOS_TRACE_LEVEL_ERROR,
10963 "%s: Cannot deallocate Bus bandwidth timer", __func__);
10964 }
10965
Masti, Narayanraddi44b0db02015-12-22 11:54:35 +053010966 if (VOS_TIMER_STATE_RUNNING ==
10967 vos_timer_getCurrentState(&pHddCtx->tdls_source_timer)) {
10968 vos_timer_stop(&pHddCtx->tdls_source_timer);
10969 }
10970
Abhishek Singh8a3e4dc2017-01-02 10:39:18 +053010971 vos_set_snoc_high_freq_voting(false);
10972
Masti, Narayanraddi44b0db02015-12-22 11:54:35 +053010973 vos_timer_destroy(&pHddCtx->tdls_source_timer);
10974
Jeff Johnson295189b2012-06-20 16:38:30 -070010975 //Disable IMPS/BMPS as we do not want the device to enter any power
10976 //save mode during shutdown
10977 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
10978 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
10979 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
10980
10981 //Ensure that device is in full power as we will touch H/W during vos_Stop
10982 init_completion(&powerContext.completion);
10983 powerContext.magic = POWER_CONTEXT_MAGIC;
10984
10985 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
10986 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
10987
10988 if (eHAL_STATUS_SUCCESS != halStatus)
10989 {
10990 if (eHAL_STATUS_PMC_PENDING == halStatus)
10991 {
10992 /* request was sent -- wait for the response */
10993 lrc = wait_for_completion_interruptible_timeout(
10994 &powerContext.completion,
10995 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
Jeff Johnson295189b2012-06-20 16:38:30 -070010996 if (lrc <= 0)
10997 {
10998 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070010999 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -070011000 }
11001 }
11002 else
11003 {
11004 hddLog(VOS_TRACE_LEVEL_ERROR,
11005 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070011006 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -070011007 /* continue -- need to clean up as much as possible */
11008 }
11009 }
Hanumantha Reddy Pothula81b42b22015-05-12 13:52:00 +053011010 if ((eHAL_STATUS_SUCCESS == halStatus) ||
11011 (eHAL_STATUS_PMC_PENDING == halStatus && lrc > 0))
11012 {
11013 /* This will issue a dump command which will clean up
11014 BTQM queues and unblock MC thread */
11015 vos_fwDumpReq(274, 0, 0, 0, 0, 1);
11016 }
Jeff Johnson295189b2012-06-20 16:38:30 -070011017
Jeff Johnson72a40512013-12-19 10:14:15 -080011018 /* either we never sent a request, we sent a request and received a
11019 response or we sent a request and timed out. if we never sent a
11020 request or if we sent a request and got a response, we want to
11021 clear the magic out of paranoia. if we timed out there is a
11022 race condition such that the callback function could be
11023 executing at the same time we are. of primary concern is if the
11024 callback function had already verified the "magic" but had not
11025 yet set the completion variable when a timeout occurred. we
11026 serialize these activities by invalidating the magic while
11027 holding a shared spinlock which will cause us to block if the
11028 callback is currently executing */
11029 spin_lock(&hdd_context_lock);
11030 powerContext.magic = 0;
11031 spin_unlock(&hdd_context_lock);
11032
Hema Aparna Medicharlaa6cf65e2015-06-01 16:23:28 +053011033 /* If Device is shutdown, no point for SME to wait for responses
11034 from device. Pre Close SME */
11035 if(wcnss_device_is_shutdown())
11036 {
11037 sme_PreClose(pHddCtx->hHal);
11038 }
Yue Ma0d4891e2013-08-06 17:01:45 -070011039 hdd_debugfs_exit(pHddCtx);
11040
Ratheesh S P35ed8b12015-04-27 14:01:07 +053011041#ifdef WLAN_NS_OFFLOAD
Ratheesh S P36dbc932015-08-07 14:28:57 +053011042 hddLog(LOG1, FL("Unregister IPv6 notifier"));
Ratheesh S P35ed8b12015-04-27 14:01:07 +053011043 unregister_inet6addr_notifier(&pHddCtx->ipv6_notifier);
11044#endif
Ratheesh S P36dbc932015-08-07 14:28:57 +053011045 hddLog(LOG1, FL("Unregister IPv4 notifier"));
Ratheesh S P35ed8b12015-04-27 14:01:07 +053011046 unregister_inetaddr_notifier(&pHddCtx->ipv4_notifier);
11047
Jeff Johnson295189b2012-06-20 16:38:30 -070011048 // Unregister the Net Device Notifier
11049 unregister_netdevice_notifier(&hdd_netdev_notifier);
11050
Jeff Johnson295189b2012-06-20 16:38:30 -070011051 hdd_stop_all_adapters( pHddCtx );
11052
Jeff Johnson295189b2012-06-20 16:38:30 -070011053#ifdef WLAN_BTAMP_FEATURE
11054 vosStatus = WLANBAP_Stop(pVosContext);
11055 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
11056 {
11057 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
11058 "%s: Failed to stop BAP",__func__);
11059 }
11060#endif //WLAN_BTAMP_FEATURE
11061
11062 //Stop all the modules
11063 vosStatus = vos_stop( pVosContext );
11064 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
11065 {
11066 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
11067 "%s: Failed to stop VOSS",__func__);
11068 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
Hanumantha Reddy Pothulabd9601a2016-02-12 13:22:27 +053011069 if (isSsrPanicOnFailure())
11070 VOS_BUG(0);
Jeff Johnson295189b2012-06-20 16:38:30 -070011071 }
11072
Jeff Johnson295189b2012-06-20 16:38:30 -070011073 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -070011074 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -070011075
11076 //Close the scheduler before calling vos_close to make sure no thread is
11077 // scheduled after the each module close is called i.e after all the data
11078 // structures are freed.
11079 vosStatus = vos_sched_close( pVosContext );
11080 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
11081 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
11082 "%s: Failed to close VOSS Scheduler",__func__);
11083 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
11084 }
Jeff Johnsone7245742012-09-05 17:12:55 -070011085#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
11086 /* Destroy the wake lock */
Sushant Kaushik83392fa2015-05-05 17:44:40 +053011087 vos_wake_lock_destroy(&pHddCtx->rx_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -070011088#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -080011089 /* Destroy the wake lock */
Sushant Kaushik83392fa2015-05-05 17:44:40 +053011090 vos_wake_lock_destroy(&pHddCtx->sap_wake_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070011091
Mihir Shete7a24b5f2013-12-21 12:18:31 +053011092#ifdef CONFIG_ENABLE_LINUX_REG
11093 vosStatus = vos_nv_close();
11094 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
11095 {
11096 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
11097 "%s: Failed to close NV", __func__);
11098 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
11099 }
11100#endif
11101
Jeff Johnson295189b2012-06-20 16:38:30 -070011102 //Close VOSS
11103 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
11104 vos_close(pVosContext);
11105
Jeff Johnson295189b2012-06-20 16:38:30 -070011106 //Close Watchdog
11107 if(pHddCtx->cfg_ini->fIsLogpEnabled)
11108 vos_watchdog_close(pVosContext);
11109
Gopichand Nakkalaa0358482013-06-12 17:05:47 +053011110 //Clean up HDD Nlink Service
11111 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Gopichand Nakkalaa0358482013-06-12 17:05:47 +053011112
Manjeet Singh47ee8472016-04-11 11:57:18 +053011113 hdd_close_tx_queues(pHddCtx);
c_manjeecfd1efb2015-09-25 19:32:34 +053011114 wlan_free_fwr_mem_dump_buffer();
11115 memdump_deinit();
11116
Vinay Krishna Erannad938c422014-03-10 17:14:21 +053011117#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +053011118 if (pHddCtx->cfg_ini->wlanLoggingEnable)
Vinay Krishna Erannad938c422014-03-10 17:14:21 +053011119 {
11120 wlan_logging_sock_deactivate_svc();
11121 }
11122#endif
11123
Vinay Krishna Erannaef30b522014-08-26 17:48:16 +053011124#ifdef WLAN_KD_READY_NOTIFIER
11125 nl_srv_exit(pHddCtx->ptt_pid);
11126#else
11127 nl_srv_exit();
11128#endif /* WLAN_KD_READY_NOTIFIER */
11129
Abhishek Singh00b71972016-01-07 10:51:04 +053011130#ifdef WLAN_FEATURE_RMC
11131 hdd_close_cesium_nl_sock();
11132#endif /* WLAN_FEATURE_RMC */
Vinay Krishna Erannaef30b522014-08-26 17:48:16 +053011133
Jeff Johnson295189b2012-06-20 16:38:30 -070011134 hdd_close_all_adapters( pHddCtx );
11135
Padma, Santhosh Kumar9cd38332015-11-17 12:18:10 +053011136 vos_flush_delayed_work(&pHddCtx->spoof_mac_addr_work);
Kapil Gupta137ef892016-12-13 19:38:00 +053011137 vos_flush_work(&pHddCtx->sap_start_work);
Padma, Santhosh Kumar9cd38332015-11-17 12:18:10 +053011138
Hanumantha Reddy Pothula97f9bc92015-08-10 17:21:20 +053011139free_hdd_ctx:
Jeff Johnson295189b2012-06-20 16:38:30 -070011140 /* free the power on lock from platform driver */
11141 if (free_riva_power_on_lock("wlan"))
11142 {
11143 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
11144 __func__);
11145 }
11146
c_hpothu78c7b602014-05-17 17:35:49 +053011147 //Free up dynamically allocated members inside HDD Adapter
11148 if (pHddCtx->cfg_ini)
11149 {
11150 kfree(pHddCtx->cfg_ini);
11151 pHddCtx->cfg_ini= NULL;
11152 }
11153
Hanumantha Reddy Pothula6fe221c2016-01-28 15:01:09 +053011154 /* FTM/MONITOR mode, WIPHY did not registered
Leo Changf04ddad2013-09-18 13:46:38 -070011155 If un-register here, system crash will happen */
Hanumantha Reddy Pothula6fe221c2016-01-28 15:01:09 +053011156 if (!(VOS_FTM_MODE == hdd_get_conparam() ||
11157 VOS_MONITOR_MODE == hdd_get_conparam()))
Leo Changf04ddad2013-09-18 13:46:38 -070011158 {
11159 wiphy_unregister(wiphy) ;
Agrawal Ashish33ec71e2015-11-26 20:20:58 +053011160 hdd_wlan_free_wiphy_channels(wiphy);
Leo Changf04ddad2013-09-18 13:46:38 -070011161 }
Jeff Johnson295189b2012-06-20 16:38:30 -070011162 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -070011163 if (hdd_is_ssr_required())
11164 {
11165 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -070011166 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -070011167 msleep(5000);
11168 }
11169 hdd_set_ssr_required (VOS_FALSE);
11170}
11171
11172
11173/**---------------------------------------------------------------------------
11174
11175 \brief hdd_update_config_from_nv() - Function to update the contents of
11176 the running configuration with parameters taken from NV storage
11177
11178 \param - pHddCtx - Pointer to the HDD global context
11179
11180 \return - VOS_STATUS_SUCCESS if successful
11181
11182 --------------------------------------------------------------------------*/
11183static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
11184{
Jeff Johnson295189b2012-06-20 16:38:30 -070011185 v_BOOL_t itemIsValid = VOS_FALSE;
11186 VOS_STATUS status;
11187 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
11188 v_U8_t macLoop;
11189
11190 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
11191 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
11192 if(status != VOS_STATUS_SUCCESS)
11193 {
Arif Hussain6d2a3322013-11-17 19:50:10 -080011194 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed");
Jeff Johnson295189b2012-06-20 16:38:30 -070011195 return VOS_STATUS_E_FAILURE;
11196 }
11197
11198 if (itemIsValid == VOS_TRUE)
11199 {
Arif Hussain6d2a3322013-11-17 19:50:10 -080011200 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV");
Jeff Johnson295189b2012-06-20 16:38:30 -070011201 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
11202 VOS_MAX_CONCURRENCY_PERSONA);
11203 if(status != VOS_STATUS_SUCCESS)
11204 {
11205 /* Get MAC from NV fail, not update CFG info
11206 * INI MAC value will be used for MAC setting */
Arif Hussain6d2a3322013-11-17 19:50:10 -080011207 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed");
Jeff Johnson295189b2012-06-20 16:38:30 -070011208 return VOS_STATUS_E_FAILURE;
11209 }
11210
11211 /* If first MAC is not valid, treat all others are not valid
11212 * Then all MACs will be got from ini file */
11213 if(vos_is_macaddr_zero(&macFromNV[0]))
11214 {
11215 /* MAC address in NV file is not configured yet */
11216 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
11217 return VOS_STATUS_E_INVAL;
11218 }
11219
11220 /* Get MAC address from NV, update CFG info */
11221 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
11222 {
11223 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
11224 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +053011225 hddLog(VOS_TRACE_LEVEL_ERROR,"not valid MAC from NV for %d", macLoop);
Jeff Johnson295189b2012-06-20 16:38:30 -070011226 /* This MAC is not valid, skip it
11227 * This MAC will be got from ini file */
11228 }
11229 else
11230 {
11231 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
11232 (v_U8_t *)&macFromNV[macLoop].bytes[0],
11233 VOS_MAC_ADDR_SIZE);
11234 }
11235 }
11236 }
11237 else
11238 {
11239 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
11240 return VOS_STATUS_E_FAILURE;
11241 }
Jeff Johnson295189b2012-06-20 16:38:30 -070011242
Jeff Johnson295189b2012-06-20 16:38:30 -070011243
11244 return VOS_STATUS_SUCCESS;
11245}
11246
11247/**---------------------------------------------------------------------------
11248
11249 \brief hdd_post_voss_start_config() - HDD post voss start config helper
11250
11251 \param - pAdapter - Pointer to the HDD
11252
11253 \return - None
11254
11255 --------------------------------------------------------------------------*/
11256VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
11257{
11258 eHalStatus halStatus;
11259 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +053011260 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -070011261
Jeff Johnson295189b2012-06-20 16:38:30 -070011262
11263 // Send ready indication to the HDD. This will kick off the MAC
11264 // into a 'running' state and should kick off an initial scan.
11265 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
11266 if ( !HAL_STATUS_SUCCESS( halStatus ) )
11267 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +053011268 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -070011269 "code %08d [x%08x]",__func__, halStatus, halStatus );
11270 return VOS_STATUS_E_FAILURE;
11271 }
11272
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +053011273 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -070011274 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
11275 // And RIVA will crash
11276 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
11277 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +053011278 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
11279 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
11280
11281
Jeff Johnson295189b2012-06-20 16:38:30 -070011282 return VOS_STATUS_SUCCESS;
11283}
11284
Jeff Johnson295189b2012-06-20 16:38:30 -070011285/* wake lock APIs for HDD */
Sushant Kaushik83392fa2015-05-05 17:44:40 +053011286void hdd_prevent_suspend(uint32_t reason)
Jeff Johnson295189b2012-06-20 16:38:30 -070011287{
Sushant Kaushik83392fa2015-05-05 17:44:40 +053011288
11289 vos_wake_lock_acquire(&wlan_wake_lock, reason);
11290
Jeff Johnson295189b2012-06-20 16:38:30 -070011291}
11292
Sushant Kaushik83392fa2015-05-05 17:44:40 +053011293void hdd_allow_suspend(uint32_t reason)
Jeff Johnson295189b2012-06-20 16:38:30 -070011294{
Sushant Kaushik83392fa2015-05-05 17:44:40 +053011295
11296 vos_wake_lock_release(&wlan_wake_lock, reason);
11297
Jeff Johnson295189b2012-06-20 16:38:30 -070011298}
11299
Sushant Kaushik83392fa2015-05-05 17:44:40 +053011300void hdd_prevent_suspend_timeout(v_U32_t timeout, uint32_t reason)
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -070011301{
Sushant Kaushik83392fa2015-05-05 17:44:40 +053011302
11303 vos_wake_lock_timeout_release(&wlan_wake_lock, timeout,
11304 reason);
11305
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -070011306}
11307
Jeff Johnson295189b2012-06-20 16:38:30 -070011308/**---------------------------------------------------------------------------
11309
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070011310 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
11311 information between Host and Riva
11312
11313 This function gets reported version of FW
11314 It also finds the version of Riva headers used to compile the host
11315 It compares the above two and prints a warning if they are different
11316 It gets the SW and HW version string
11317 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
11318 indicating the features they support through a bitmap
11319
11320 \param - pHddCtx - Pointer to HDD context
11321
11322 \return - void
11323
11324 --------------------------------------------------------------------------*/
11325
11326void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
11327{
11328
11329 tSirVersionType versionCompiled;
11330 tSirVersionType versionReported;
11331 tSirVersionString versionString;
11332 tANI_U8 fwFeatCapsMsgSupported = 0;
11333 VOS_STATUS vstatus;
11334
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -080011335 memset(&versionCompiled, 0, sizeof(versionCompiled));
11336 memset(&versionReported, 0, sizeof(versionReported));
11337
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070011338 /* retrieve and display WCNSS version information */
11339 do {
11340
11341 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
11342 &versionCompiled);
11343 if (!VOS_IS_STATUS_SUCCESS(vstatus))
11344 {
11345 hddLog(VOS_TRACE_LEVEL_FATAL,
11346 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070011347 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070011348 break;
11349 }
11350
11351 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
11352 &versionReported);
11353 if (!VOS_IS_STATUS_SUCCESS(vstatus))
11354 {
11355 hddLog(VOS_TRACE_LEVEL_FATAL,
11356 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070011357 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070011358 break;
11359 }
11360
11361 if ((versionCompiled.major != versionReported.major) ||
11362 (versionCompiled.minor != versionReported.minor) ||
11363 (versionCompiled.version != versionReported.version) ||
11364 (versionCompiled.revision != versionReported.revision))
11365 {
11366 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
11367 "Host expected %u.%u.%u.%u\n",
11368 WLAN_MODULE_NAME,
11369 (int)versionReported.major,
11370 (int)versionReported.minor,
11371 (int)versionReported.version,
11372 (int)versionReported.revision,
11373 (int)versionCompiled.major,
11374 (int)versionCompiled.minor,
11375 (int)versionCompiled.version,
11376 (int)versionCompiled.revision);
11377 }
11378 else
11379 {
11380 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
11381 WLAN_MODULE_NAME,
11382 (int)versionReported.major,
11383 (int)versionReported.minor,
11384 (int)versionReported.version,
11385 (int)versionReported.revision);
11386 }
11387
11388 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
11389 versionString,
11390 sizeof(versionString));
11391 if (!VOS_IS_STATUS_SUCCESS(vstatus))
11392 {
11393 hddLog(VOS_TRACE_LEVEL_FATAL,
11394 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070011395 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070011396 break;
11397 }
11398
11399 pr_info("%s: WCNSS software version %s\n",
11400 WLAN_MODULE_NAME, versionString);
Sushant Kaushik084f6592015-09-10 13:11:56 +053011401 vos_mem_copy(pHddCtx->fw_Version, versionString, sizeof(versionString));
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070011402
11403 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
11404 versionString,
11405 sizeof(versionString));
11406 if (!VOS_IS_STATUS_SUCCESS(vstatus))
11407 {
11408 hddLog(VOS_TRACE_LEVEL_FATAL,
11409 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070011410 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070011411 break;
11412 }
11413
11414 pr_info("%s: WCNSS hardware version %s\n",
11415 WLAN_MODULE_NAME, versionString);
11416
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -070011417 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
11418 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070011419 send the message only if it the riva is 1.1
11420 minor numbers for different riva branches:
11421 0 -> (1.0)Mainline Build
11422 1 -> (1.1)Mainline Build
11423 2->(1.04) Stability Build
11424 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -070011425 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070011426 ((versionReported.minor>=1) && (versionReported.version>=1)))
11427 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
11428 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -070011429
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070011430 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -080011431 {
11432#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
11433 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
11434 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
11435#endif
Ravi Joshid2ca7c42013-07-23 08:37:49 -070011436 /* Indicate if IBSS heartbeat monitoring needs to be offloaded */
11437 if (!pHddCtx->cfg_ini->enableIbssHeartBeatOffload)
11438 {
11439 sme_disableFeatureCapablity(IBSS_HEARTBEAT_OFFLOAD);
11440 }
11441
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070011442 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -080011443 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070011444
11445 } while (0);
11446
11447}
Neelansh Mittaledafed22014-09-04 18:54:39 +053011448void wlan_hdd_send_svc_nlink_msg(int type, void *data, int len)
11449{
11450 struct sk_buff *skb;
11451 struct nlmsghdr *nlh;
11452 tAniMsgHdr *ani_hdr;
Hanumantha Reddy Pothulacf2c7ea2015-04-27 14:50:47 +053011453 int flags = GFP_KERNEL;
Bhargav shah23c94942015-10-13 12:48:35 +053011454 void *nl_data = NULL;
Neelansh Mittaledafed22014-09-04 18:54:39 +053011455
Hanumantha Reddy Pothulacf2c7ea2015-04-27 14:50:47 +053011456 if (in_interrupt() || irqs_disabled() || in_atomic())
11457 flags = GFP_ATOMIC;
11458
11459 skb = alloc_skb(NLMSG_SPACE(WLAN_NL_MAX_PAYLOAD), flags);
Neelansh Mittaledafed22014-09-04 18:54:39 +053011460
11461 if(skb == NULL) {
11462 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
11463 "%s: alloc_skb failed", __func__);
11464 return;
11465 }
11466
11467 nlh = (struct nlmsghdr *)skb->data;
11468 nlh->nlmsg_pid = 0; /* from kernel */
11469 nlh->nlmsg_flags = 0;
11470 nlh->nlmsg_seq = 0;
11471 nlh->nlmsg_type = WLAN_NL_MSG_SVC;
11472
11473 ani_hdr = NLMSG_DATA(nlh);
11474 ani_hdr->type = type;
11475
11476 switch(type) {
11477 case WLAN_SVC_SAP_RESTART_IND:
11478 ani_hdr->length = 0;
11479 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr)));
11480 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr)));
11481 break;
Bhargav Shahd0715912015-10-01 18:17:37 +053011482 case WLAN_SVC_WLAN_TP_IND:
11483 ani_hdr->length = len;
11484 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr)
11485 + len));
11486 nl_data = (char *)ani_hdr + sizeof(tAniMsgHdr);
11487 memcpy(nl_data, data, len);
11488 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + len));
11489 break;
Bhargav shah23c94942015-10-13 12:48:35 +053011490 case WLAN_MSG_RPS_ENABLE_IND:
11491 ani_hdr->length = len;
11492 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + len));
11493 nl_data = (char *)ani_hdr + sizeof(tAniMsgHdr);
11494 memcpy(nl_data, data, len);
11495 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + len));
11496 break;
Neelansh Mittaledafed22014-09-04 18:54:39 +053011497 default:
11498 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
11499 "Attempt to send unknown nlink message %d", type);
11500 kfree_skb(skb);
11501 return;
11502 }
11503
11504 nl_srv_bcast(skb);
11505
11506 return;
11507}
11508
Bhargav Shahd0715912015-10-01 18:17:37 +053011509/**
11510 * hdd_request_tcp_delack() - Find the Delack value based on RX packet
11511 * @pHddCtx: Valid Global HDD context pointer
11512 * @rx_packets: Number of RX packet in perticular time
11513 *
11514 * Based on the RX packet this function calculate next value of tcp delack.
11515 * This function compare rx packet value to high and low threshold limit.
11516 *
11517 * Return: void
11518 */
11519void hdd_request_tcp_delack(hdd_context_t *pHddCtx, uint64_t rx_packets)
11520{
11521 /* average of rx_packets and prev_rx is taken so that
11522 bus width doesnot fluctuate much */
11523 uint64_t temp_rx = (rx_packets + pHddCtx->prev_rx)/2;
11524 TP_IND_TYPE next_rx_level = pHddCtx->cur_rx_level;
Neelansh Mittaledafed22014-09-04 18:54:39 +053011525
Bhargav Shahd0715912015-10-01 18:17:37 +053011526 pHddCtx->prev_rx = rx_packets;
11527 if (temp_rx > pHddCtx->cfg_ini->tcpDelAckThresholdHigh)
11528 next_rx_level = TP_IND_HIGH;
11529 else if (temp_rx <= pHddCtx->cfg_ini->tcpDelAckThresholdLow)
11530 next_rx_level = TP_IND_LOW;
11531
11532 hdd_set_delack_value(pHddCtx, next_rx_level);
11533}
11534
11535#define HDD_BW_GET_DIFF(x, y) ((x) >= (y) ? (x) - (y) : (ULONG_MAX - (y) + (x)))
11536
11537/**
11538 * hdd_tcp_delack_compute_function() - get link status
11539 * @priv: Valid Global HDD context pointer
11540 *
11541 * This function find number of RX packet during timer life span.
11542 * It request tcp delack with number of RX packet and re-configure delack timer
11543 * for tcpDelAckComputeInterval timer interval.
11544 *
11545 * Return: void
11546 */
11547void hdd_tcp_delack_compute_function(void *priv)
11548{
11549 hdd_context_t *pHddCtx = (hdd_context_t *)priv;
11550 hdd_adapter_t *pAdapter = NULL;
11551 v_U32_t rx_packets = 0;
11552 hdd_adapter_list_node_t *pAdapterNode = NULL;
11553 VOS_STATUS status = 0;
11554
11555 for (status = hdd_get_front_adapter(pHddCtx, &pAdapterNode);
11556 NULL != pAdapterNode && VOS_STATUS_SUCCESS == status;
11557 status = hdd_get_next_adapter(pHddCtx, pAdapterNode, &pAdapterNode)) {
11558 if ((pAdapter = pAdapterNode->pAdapter) == NULL)
11559 continue;
11560
11561 rx_packets += HDD_BW_GET_DIFF(pAdapter->stats.rx_packets,
11562 pAdapter->prev_rx_packets);
11563 pAdapter->prev_rx_packets = pAdapter->stats.rx_packets;
11564 }
11565
11566 hdd_request_tcp_delack(pHddCtx, rx_packets);
11567
11568 vos_timer_start(&pHddCtx->delack_timer,
11569 pHddCtx->cfg_ini->tcpDelAckComputeInterval);
11570}
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070011571
11572/**---------------------------------------------------------------------------
11573
Gopichand Nakkalafce506f2013-07-03 23:55:16 +053011574 \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
11575
11576 \param - pHddCtx - Pointer to the hdd context
11577
11578 \return - true if hardware supports 5GHz
11579
11580 --------------------------------------------------------------------------*/
Vinay Krishna Erannafacf5e22014-02-24 13:16:25 +053011581boolean hdd_is_5g_supported(hdd_context_t * pHddCtx)
Gopichand Nakkalafce506f2013-07-03 23:55:16 +053011582{
11583 /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
11584 * then hardware support 5Ghz.
11585 */
11586 if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode())
11587 {
Ratheesh S P36dbc932015-08-07 14:28:57 +053011588 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware supports 5Ghz", __func__);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +053011589 return true;
11590 }
11591 else
11592 {
Ratheesh S P36dbc932015-08-07 14:28:57 +053011593 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware doesn't supports 5Ghz",
Gopichand Nakkalafce506f2013-07-03 23:55:16 +053011594 __func__);
11595 return false;
11596 }
11597}
11598
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053011599/**---------------------------------------------------------------------------
11600
11601 \brief hdd_generate_iface_mac_addr_auto() - HDD Mac Interface Auto
11602 generate function
11603
11604 This is generate the random mac address for WLAN interface
11605
11606 \param - pHddCtx - Pointer to HDD context
11607 idx - Start interface index to get auto
11608 generated mac addr.
11609 mac_addr - Mac address
11610
11611 \return - 0 for success, < 0 for failure
11612
11613 --------------------------------------------------------------------------*/
11614
11615static int hdd_generate_iface_mac_addr_auto(hdd_context_t *pHddCtx,
11616 int idx, v_MACADDR_t mac_addr)
11617{
11618 int i;
11619 unsigned int serialno;
11620 serialno = wcnss_get_serial_number();
11621
11622 if (0 != serialno)
11623 {
11624 /* MAC address has 3 bytes of OUI so we have a maximum of 3
11625 bytes of the serial number that can be used to generate
11626 the other 3 bytes of the MAC address. Mask off all but
11627 the lower 3 bytes (this will also make sure we don't
11628 overflow in the next step) */
11629 serialno &= 0x00FFFFFF;
11630
11631 /* we need a unique address for each session */
11632 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
11633
11634 /* autogen other Mac addresses */
11635 for (i = idx; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
11636 {
11637 /* start with the entire default address */
11638 pHddCtx->cfg_ini->intfMacAddr[i] = mac_addr;
11639 /* then replace the lower 3 bytes */
11640 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
11641 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
11642 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
11643
11644 serialno++;
11645 hddLog(VOS_TRACE_LEVEL_ERROR,
11646 "%s: Derived Mac Addr: "
11647 MAC_ADDRESS_STR, __func__,
11648 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[i].bytes));
11649 }
11650
11651 }
11652 else
11653 {
11654 hddLog(LOGE, FL("Failed to Get Serial NO"));
11655 return -1;
11656 }
11657 return 0;
11658}
Gopichand Nakkalafce506f2013-07-03 23:55:16 +053011659
Katya Nigame7b69a82015-04-28 15:24:06 +053011660int wlan_hdd_mon_open(hdd_context_t *pHddCtx)
11661{
11662 VOS_STATUS status;
11663 v_CONTEXT_t pVosContext= NULL;
11664 hdd_adapter_t *pAdapter= NULL;
11665
11666 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
11667
11668 if (NULL == pVosContext)
11669 {
11670 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
11671 "%s: Trying to open VOSS without a PreOpen", __func__);
11672 VOS_ASSERT(0);
11673 return VOS_STATUS_E_FAILURE;
11674 }
11675
11676 status = vos_nv_open();
11677 if (!VOS_IS_STATUS_SUCCESS(status))
11678 {
11679 /* NV module cannot be initialized */
11680 hddLog( VOS_TRACE_LEVEL_FATAL,
11681 "%s: vos_nv_open failed", __func__);
11682 return VOS_STATUS_E_FAILURE;
11683 }
11684
11685 status = vos_init_wiphy_from_nv_bin();
11686 if (!VOS_IS_STATUS_SUCCESS(status))
11687 {
11688 /* NV module cannot be initialized */
11689 hddLog( VOS_TRACE_LEVEL_FATAL,
11690 "%s: vos_init_wiphy failed", __func__);
11691 goto err_vos_nv_close;
11692 }
11693
11694 status = vos_open( &pVosContext, pHddCtx->parent_dev);
11695 if ( !VOS_IS_STATUS_SUCCESS( status ))
11696 {
11697 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
11698 goto err_vos_nv_close;
11699 }
11700
11701 status = vos_mon_start( pVosContext );
11702 if ( !VOS_IS_STATUS_SUCCESS( status ) )
11703 {
11704 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
11705 goto err_vosclose;
11706 }
11707
11708 WLANTL_SetMonRxCbk( pVosContext, hdd_rx_packet_monitor_cbk );
11709 WDA_featureCapsExchange(pVosContext);
11710 wcnss_wlan_set_drvdata(pHddCtx->parent_dev, pHddCtx);
11711
11712 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_MONITOR, "wlan%d",
11713 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
11714 if( pAdapter == NULL )
11715 {
11716 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
11717 goto err_close_adapter;
11718 }
11719
11720 //Initialize the nlink service
11721 if(nl_srv_init() != 0)
11722 {
11723 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
11724 goto err_close_adapter;
11725 }
11726 return VOS_STATUS_SUCCESS;
11727
11728err_close_adapter:
11729 hdd_close_all_adapters( pHddCtx );
11730 vos_mon_stop( pVosContext );
11731err_vosclose:
11732 status = vos_sched_close( pVosContext );
11733 if (!VOS_IS_STATUS_SUCCESS(status)) {
11734 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
11735 "%s: Failed to close VOSS Scheduler", __func__);
11736 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
11737 }
11738 vos_close(pVosContext );
11739
11740err_vos_nv_close:
11741 vos_nv_close();
11742
11743return status;
11744}
Gopichand Nakkalafce506f2013-07-03 23:55:16 +053011745/**---------------------------------------------------------------------------
11746
Mihir Shetefc7ff5b2014-01-27 11:30:05 +053011747 \brief hdd_11d_scan_done - callback to be executed when 11d scan is
11748 completed to flush out the scan results
11749
11750 11d scan is done during driver load and is a passive scan on all
11751 channels supported by the device, 11d scans may find some APs on
11752 frequencies which are forbidden to be used in the regulatory domain
11753 the device is operating in. If these APs are notified to the supplicant
11754 it may try to connect to these APs, thus flush out all the scan results
11755 which are present in SME after 11d scan is done.
11756
11757 \return - eHalStatus
11758
11759 --------------------------------------------------------------------------*/
11760static eHalStatus hdd_11d_scan_done(tHalHandle halHandle, void *pContext,
11761 tANI_U32 scanId, eCsrScanStatus status)
11762{
11763 ENTER();
11764
11765 sme_ScanFlushResult(halHandle, 0);
11766
11767 EXIT();
11768
11769 return eHAL_STATUS_SUCCESS;
11770}
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011771/**---------------------------------------------------------------------------
11772
11773 \brief hdd_init_frame_logging_done - callback to be executed when mgmt frame
11774 logging is completed successfully.
11775
11776 \return - None
11777
11778 --------------------------------------------------------------------------*/
c_manjeecfd1efb2015-09-25 19:32:34 +053011779void hdd_init_frame_logging_done(void *fwlogInitCbContext, tAniLoggingInitRsp *pRsp)
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011780{
Siddharth Bhald1be97f2015-05-27 22:39:59 +053011781 hdd_context_t* pHddCtx = (hdd_context_t*)fwlogInitCbContext;
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011782
11783 if (NULL == pHddCtx)
11784 {
11785 hddLog(VOS_TRACE_LEVEL_ERROR,
11786 "%s: HDD context is NULL",__func__);
11787 return;
11788 }
11789
c_manjeecfd1efb2015-09-25 19:32:34 +053011790 if ((pRsp->status == VOS_STATUS_SUCCESS) &&
Mahesh A Saptasagarfabb1a02015-06-29 12:17:04 +053011791 (TRUE == pHddCtx->cfg_ini->enableMgmtLogging))
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011792 {
11793 hddLog(VOS_TRACE_LEVEL_INFO, FL("Mgmt Frame Logging init successful"));
11794 pHddCtx->mgmt_frame_logging = TRUE;
11795 }
11796 else
11797 {
11798 hddLog(VOS_TRACE_LEVEL_INFO, FL("Mgmt Frame Logging init not success"));
11799 pHddCtx->mgmt_frame_logging = FALSE;
c_manjeecfd1efb2015-09-25 19:32:34 +053011800 return;
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011801 }
11802
c_manjeecfd1efb2015-09-25 19:32:34 +053011803 /*Check feature supported by FW*/
11804 if(TRUE == sme_IsFeatureSupportedByFW(MEMORY_DUMP_SUPPORTED))
11805 {
11806 //Store fwr mem dump size given by firmware.
11807 wlan_store_fwr_mem_dump_size(pRsp->fw_mem_dump_max_size);
11808 }
11809 else
11810 {
11811 wlan_store_fwr_mem_dump_size(0);
11812 }
11813
11814
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011815}
11816/**---------------------------------------------------------------------------
11817
11818 \brief hdd_init_frame_logging - function to initialize frame logging.
11819 Currently only Mgmt Frames are logged in both TX
11820 and Rx direction and are sent to userspace
11821 application using logger thread when queried.
11822
11823 \return - None
11824
11825 --------------------------------------------------------------------------*/
Siddharth Bhald1be97f2015-05-27 22:39:59 +053011826void hdd_init_frame_logging(hdd_context_t* pHddCtx)
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011827{
11828 eHalStatus halStatus = eHAL_STATUS_FAILURE;
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053011829 tSirFWLoggingInitParam wlanFWLoggingInitParam = {0};
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011830
Siddharth Bhald1be97f2015-05-27 22:39:59 +053011831 if (TRUE != sme_IsFeatureSupportedByFW(MGMT_FRAME_LOGGING) &&
11832 TRUE != sme_IsFeatureSupportedByFW(LOGGING_ENHANCEMENT))
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011833 {
11834 hddLog(VOS_TRACE_LEVEL_INFO, FL("MGMT_FRAME_LOGGING not supp by FW"));
11835 return;
11836 }
11837
c_manjeecfd1efb2015-09-25 19:32:34 +053011838 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Configuring %s %s %s %s Logging",__func__,
Siddharth Bhald1be97f2015-05-27 22:39:59 +053011839 pHddCtx->cfg_ini->enableFWLogging?"FW Log,":"",
11840 pHddCtx->cfg_ini->enableContFWLogging ? "Cont FW log,":"",
c_manjeecfd1efb2015-09-25 19:32:34 +053011841 pHddCtx->cfg_ini->enableMgmtLogging ? "Mgmt Pkt Log":"",
11842 pHddCtx->cfg_ini->enableFwrMemDump ? "Fw Mem dump":"");
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011843
Siddharth Bhald1be97f2015-05-27 22:39:59 +053011844 if (pHddCtx->cfg_ini->enableFWLogging ||
11845 pHddCtx->cfg_ini->enableContFWLogging)
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011846 {
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053011847 wlanFWLoggingInitParam.enableFlag |= WLAN_QXDM_LOG_EN;
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011848 }
11849
Sushant Kaushik46804902015-07-08 14:46:03 +053011850 if (pHddCtx->cfg_ini->enableMgmtLogging)
11851 {
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053011852 wlanFWLoggingInitParam.enableFlag |= WLAN_FRAME_LOG_EN;
Sushant Kaushik46804902015-07-08 14:46:03 +053011853 }
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011854 if (pHddCtx->cfg_ini->enableBMUHWtracing)
11855 {
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053011856 wlanFWLoggingInitParam.enableFlag |= WLAN_BMUHW_TRACE_LOG_EN;
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011857 }
c_manjeecfd1efb2015-09-25 19:32:34 +053011858 if(pHddCtx->cfg_ini->enableFwrMemDump &&
11859 (TRUE == sme_IsFeatureSupportedByFW(MEMORY_DUMP_SUPPORTED)))
11860 {
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053011861 wlanFWLoggingInitParam.enableFlag |= WLAN_FW_MEM_DUMP_EN;
c_manjeecfd1efb2015-09-25 19:32:34 +053011862 }
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053011863 if( wlanFWLoggingInitParam.enableFlag == 0 )
c_manjeecfd1efb2015-09-25 19:32:34 +053011864 {
11865 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Logging not enabled", __func__);
11866 return;
11867 }
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053011868 wlanFWLoggingInitParam.frameType = WLAN_FRAME_LOGGING_FRAMETYPE_MGMT;
11869 wlanFWLoggingInitParam.frameSize = WLAN_MGMT_LOGGING_FRAMESIZE_128BYTES;
11870 wlanFWLoggingInitParam.bufferMode = WLAN_FRAME_LOGGING_BUFFERMODE_CIRCULAR;
11871 wlanFWLoggingInitParam.continuousFrameLogging =
Siddharth Bhald1be97f2015-05-27 22:39:59 +053011872 pHddCtx->cfg_ini->enableContFWLogging;
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011873
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053011874 wlanFWLoggingInitParam.enableFlag &= ~WLAN_DPU_TXP_LOG_EN;
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011875
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053011876 wlanFWLoggingInitParam.minLogBufferSize =
Siddharth Bhald1be97f2015-05-27 22:39:59 +053011877 pHddCtx->cfg_ini->minLoggingBufferSize;
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053011878 wlanFWLoggingInitParam.maxLogBufferSize =
Siddharth Bhald1be97f2015-05-27 22:39:59 +053011879 pHddCtx->cfg_ini->maxLoggingBufferSize;
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053011880 wlanFWLoggingInitParam.fwlogInitCallback = hdd_init_frame_logging_done;
11881 wlanFWLoggingInitParam.fwlogInitCbContext= pHddCtx;
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011882
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053011883 halStatus = sme_InitMgmtFrameLogging(pHddCtx->hHal, &wlanFWLoggingInitParam);
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011884
11885 if (eHAL_STATUS_SUCCESS != halStatus)
11886 {
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053011887 hddLog(LOGE, FL("sme_InitMgmtFrameLogging failed, returned %d"),
11888 halStatus);
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011889 }
11890
11891 return;
11892}
Mihir Shetefc7ff5b2014-01-27 11:30:05 +053011893
Bhargav shah23c94942015-10-13 12:48:35 +053011894static void hdd_dp_util_send_rps_ind(hdd_context_t *hdd_ctxt)
11895{
11896 hdd_adapter_t *adapter;
11897 hdd_adapter_list_node_t *adapter_node, *next;
11898 VOS_STATUS status = VOS_STATUS_SUCCESS;
11899 struct wlan_rps_data rps_data;
11900 int count;
11901
11902 if(!hdd_ctxt->cfg_ini->rps_mask)
11903 {
11904 return;
11905 }
11906
11907 for (count=0; count < WLAN_SVC_IFACE_NUM_QUEUES; count++)
11908 {
11909 rps_data.cpu_map[count] = hdd_ctxt->cfg_ini->rps_mask;
11910 }
11911
11912 rps_data.num_queues = WLAN_SVC_IFACE_NUM_QUEUES;
11913
11914 hddLog(LOG1, FL("0x%x 0x%x 0x%x 0x%x 0x%x 0x%x"),
11915 rps_data.cpu_map[0], rps_data.cpu_map[1],rps_data.cpu_map[2],
11916 rps_data.cpu_map[3], rps_data.cpu_map[4], rps_data.cpu_map[5]);
11917
11918 status = hdd_get_front_adapter (hdd_ctxt, &adapter_node);
11919
11920 while (NULL != adapter_node && VOS_STATUS_SUCCESS == status)
11921 {
11922 adapter = adapter_node->pAdapter;
11923 if (NULL != adapter) {
11924 strlcpy(rps_data.ifname, adapter->dev->name,
11925 sizeof(rps_data.ifname));
11926 wlan_hdd_send_svc_nlink_msg(WLAN_MSG_RPS_ENABLE_IND,
11927 (void *)&rps_data,sizeof(rps_data));
11928 }
11929 status = hdd_get_next_adapter (hdd_ctxt, adapter_node, &next);
11930 adapter_node = next;
11931 }
11932}
11933
Masti, Narayanraddi26378462016-01-05 18:20:28 +053011934void wlan_hdd_schedule_defer_scan(struct work_struct *work)
11935{
11936 scan_context_t *scan_ctx =
11937 container_of(work, scan_context_t, scan_work.work);
11938
11939 if (NULL == scan_ctx)
11940 {
11941 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
11942 FL("scan_ctx is NULL"));
11943 return;
11944 }
11945
11946 if (unlikely(TDLS_CTX_MAGIC != scan_ctx->magic))
11947 return;
11948
11949 scan_ctx->attempt++;
11950
11951 wlan_hdd_cfg80211_scan(scan_ctx->wiphy,
11952#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
11953 scan_ctx->dev,
11954#endif
11955 scan_ctx->scan_request);
11956}
11957
11958int wlan_hdd_copy_defer_scan_context(hdd_context_t *pHddCtx,
11959 struct wiphy *wiphy,
11960#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
11961 struct net_device *dev,
11962#endif
11963 struct cfg80211_scan_request *request)
11964{
11965 scan_context_t *scan_ctx;
11966
11967 ENTER();
11968 if (0 != (wlan_hdd_validate_context(pHddCtx)))
11969 {
11970 return -1;
11971 }
11972
11973 scan_ctx = &pHddCtx->scan_ctxt;
11974
11975 scan_ctx->wiphy = wiphy;
11976#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
11977 scan_ctx->dev = dev;
11978#endif
11979
11980 scan_ctx->scan_request = request;
11981
11982 EXIT();
11983 return 0;
11984}
11985
11986void wlan_hdd_defer_scan_init_work(hdd_context_t *pHddCtx,
11987 struct wiphy *wiphy,
11988#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
11989 struct net_device *dev,
11990#endif
11991 struct cfg80211_scan_request *request,
11992 unsigned long delay)
11993{
11994 if (TDLS_CTX_MAGIC != pHddCtx->scan_ctxt.magic)
11995 {
11996#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
11997 wlan_hdd_copy_defer_scan_context(pHddCtx, wiphy, dev, request);
11998#else
11999 wlan_hdd_copy_defer_scan_context(pHddCtx, wiphy, request);
12000#endif
12001 pHddCtx->scan_ctxt.attempt = 0;
12002 pHddCtx->scan_ctxt.magic = TDLS_CTX_MAGIC;
12003 }
12004 schedule_delayed_work(&pHddCtx->scan_ctxt.scan_work, delay);
12005}
12006
12007void wlan_hdd_init_deinit_defer_scan_context(scan_context_t *scan_ctx)
12008{
12009 scan_ctx->magic = 0;
12010 scan_ctx->attempt = 0;
12011 scan_ctx->reject = 0;
12012 scan_ctx->scan_request = NULL;
12013
12014 return;
12015}
12016
Mihir Shetefc7ff5b2014-01-27 11:30:05 +053012017/**---------------------------------------------------------------------------
12018
Jeff Johnson295189b2012-06-20 16:38:30 -070012019 \brief hdd_wlan_startup() - HDD init function
12020
12021 This is the driver startup code executed once a WLAN device has been detected
12022
12023 \param - dev - Pointer to the underlying device
12024
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -080012025 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -070012026
12027 --------------------------------------------------------------------------*/
12028
12029int hdd_wlan_startup(struct device *dev )
12030{
12031 VOS_STATUS status;
12032 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -070012033 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -070012034 hdd_context_t *pHddCtx = NULL;
12035 v_CONTEXT_t pVosContext= NULL;
12036#ifdef WLAN_BTAMP_FEATURE
12037 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
12038 WLANBAP_ConfigType btAmpConfig;
12039 hdd_config_t *pConfig;
12040#endif
12041 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -070012042 struct wiphy *wiphy;
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053012043 v_MACADDR_t mac_addr;
Jeff Johnson295189b2012-06-20 16:38:30 -070012044
12045 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -070012046 /*
12047 * cfg80211: wiphy allocation
12048 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +053012049 wiphy = wlan_hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t)) ;
Jeff Johnson295189b2012-06-20 16:38:30 -070012050
12051 if(wiphy == NULL)
12052 {
12053 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -080012054 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -070012055 }
Jeff Johnson295189b2012-06-20 16:38:30 -070012056 pHddCtx = wiphy_priv(wiphy);
12057
Jeff Johnson295189b2012-06-20 16:38:30 -070012058 //Initialize the adapter context to zeros.
12059 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
12060
Jeff Johnson295189b2012-06-20 16:38:30 -070012061 pHddCtx->wiphy = wiphy;
Sushant Kaushik83392fa2015-05-05 17:44:40 +053012062 hdd_prevent_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_INIT);
Mihir Shete18156292014-03-11 15:38:30 +053012063 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_LOAD_IN_PROGRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -070012064
12065 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
12066
Siddharth Bhalcd92b782015-06-29 12:25:40 +053012067 /* register for riva power on lock to platform driver
12068 * Locking power early to ensure FW doesn't reset by kernel while
12069 * host driver is busy initializing itself */
12070 if (req_riva_power_on_lock("wlan"))
12071 {
12072 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
12073 __func__);
12074 goto err_free_hdd_context;
12075 }
12076
Jeff Johnson295189b2012-06-20 16:38:30 -070012077 /*Get vos context here bcoz vos_open requires it*/
12078 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
12079
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -080012080 if(pVosContext == NULL)
12081 {
12082 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
12083 goto err_free_hdd_context;
12084 }
12085
Jeff Johnson295189b2012-06-20 16:38:30 -070012086 //Save the Global VOSS context in adapter context for future.
12087 pHddCtx->pvosContext = pVosContext;
12088
12089 //Save the adapter context in global context for future.
12090 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
12091
Jeff Johnson295189b2012-06-20 16:38:30 -070012092 pHddCtx->parent_dev = dev;
Sreelakshmi Konamkif0646d52016-12-09 12:35:31 +053012093 pHddCtx->last_scan_reject_session_id = 0xFF;
12094 pHddCtx->last_scan_reject_reason = 0;
Sreelakshmi Konamki20ebed92016-10-27 12:13:30 +053012095 pHddCtx->last_scan_reject_timestamp = 0;
Abhishek Singhe4b12562017-06-20 16:53:39 +053012096 pHddCtx->scan_reject_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -070012097
12098 init_completion(&pHddCtx->full_pwr_comp_var);
12099 init_completion(&pHddCtx->standby_comp_var);
12100 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -070012101 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -080012102 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Kiet Lam46b8e4e2013-11-06 21:49:53 +053012103 init_completion(&pHddCtx->wiphy_channel_update_event);
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +053012104 init_completion(&pHddCtx->ssr_comp_var);
Mahesh A Saptasagar67ab9222015-10-21 15:38:41 +053012105 init_completion(&pHddCtx->mc_sus_event_var);
12106 init_completion(&pHddCtx->tx_sus_event_var);
12107 init_completion(&pHddCtx->rx_sus_event_var);
12108
Amar Singhala49cbc52013-10-08 18:37:44 -070012109
mukul sharma4bd8d2e2015-08-13 20:33:25 +053012110 hdd_init_ll_stats_ctx(pHddCtx);
Anurag Chouhan6ee81542017-02-09 18:09:27 +053012111 hdd_init_nud_stats_ctx(pHddCtx);
mukul sharma4bd8d2e2015-08-13 20:33:25 +053012112
Amar Singhala49cbc52013-10-08 18:37:44 -070012113#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhalfddc28c2013-09-05 13:03:40 -070012114 init_completion(&pHddCtx->linux_reg_req);
Amar Singhala49cbc52013-10-08 18:37:44 -070012115#else
12116 init_completion(&pHddCtx->driver_crda_req);
12117#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070012118
Padma, Santhosh Kumara1aa4a32015-06-19 19:00:46 +053012119#ifdef WLAN_FEATURE_EXTSCAN
12120 init_completion(&pHddCtx->ext_scan_context.response_event);
12121#endif /* WLAN_FEATURE_EXTSCAN */
12122
Kamath Vinayak4000c9a2013-08-23 14:24:27 +053012123 spin_lock_init(&pHddCtx->schedScan_lock);
Kapil Gupta137ef892016-12-13 19:38:00 +053012124 vos_spin_lock_init(&pHddCtx->sap_update_info_lock);
Kamath Vinayak4000c9a2013-08-23 14:24:27 +053012125
Jeff Johnson295189b2012-06-20 16:38:30 -070012126 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
12127
Padma, Santhosh Kumar9cd38332015-11-17 12:18:10 +053012128 vos_init_delayed_work(&pHddCtx->spoof_mac_addr_work,
12129 hdd_processSpoofMacAddrRequest);
Kapil Gupta137ef892016-12-13 19:38:00 +053012130 vos_init_work(&pHddCtx->sap_start_work, hdd_sap_restart_handle);
Padma, Santhosh Kumar9cd38332015-11-17 12:18:10 +053012131
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +053012132#ifdef FEATURE_WLAN_TDLS
12133 /* tdls_lock is initialized before an hdd_open_adapter ( which is
12134 * invoked by other instances also) to protect the concurrent
12135 * access for the Adapters by TDLS module.
12136 */
12137 mutex_init(&pHddCtx->tdls_lock);
12138#endif
Siddharth Bhal76972212014-10-15 16:22:51 +053012139 mutex_init(&pHddCtx->spoofMacAddr.macSpoofingLock);
Mukul Sharma1fd6efd2015-02-14 00:29:14 +053012140 mutex_init(&pHddCtx->wmmLock);
12141
Srinivas Girigowda8bf64cb2015-09-30 19:50:09 +053012142 hdd_init_offloaded_packets_ctx(pHddCtx);
Agarwal Ashish1f422872014-07-22 00:11:55 +053012143 /* By default Strict Regulatory For FCC should be false */
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +053012144
Agarwal Ashish1f422872014-07-22 00:11:55 +053012145 pHddCtx->nEnableStrictRegulatoryForFCC = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -070012146 // Load all config first as TL config is needed during vos_open
12147 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
12148 if(pHddCtx->cfg_ini == NULL)
12149 {
12150 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
12151 goto err_free_hdd_context;
12152 }
12153
12154 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
12155
12156 // Read and parse the qcom_cfg.ini file
12157 status = hdd_parse_config_ini( pHddCtx );
12158 if ( VOS_STATUS_SUCCESS != status )
12159 {
12160 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
12161 __func__, WLAN_INI_FILE);
12162 goto err_config;
12163 }
Arif Hussaind5218912013-12-05 01:10:55 -080012164#ifdef MEMORY_DEBUG
12165 if (pHddCtx->cfg_ini->IsMemoryDebugSupportEnabled)
12166 vos_mem_init();
12167
12168 hddLog(VOS_TRACE_LEVEL_INFO, "%s: gEnableMemoryDebug=%d",
12169 __func__, pHddCtx->cfg_ini->IsMemoryDebugSupportEnabled);
12170#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070012171
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +053012172 /* INI has been read, initialise the configuredMcastBcastFilter with
12173 * INI value as this will serve as the default value
12174 */
12175 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
12176 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
12177 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +053012178
12179 if (false == hdd_is_5g_supported(pHddCtx))
12180 {
12181 //5Ghz is not supported.
12182 if (1 != pHddCtx->cfg_ini->nBandCapability)
12183 {
12184 hddLog(VOS_TRACE_LEVEL_INFO,
12185 "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__);
12186 pHddCtx->cfg_ini->nBandCapability = 1;
12187 }
12188 }
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +053012189
12190 /* If SNR Monitoring is enabled, FW has to parse all beacons
12191 * for calcaluting and storing the average SNR, so set Nth beacon
12192 * filter to 1 to enable FW to parse all the beaocons
12193 */
12194 if (1 == pHddCtx->cfg_ini->fEnableSNRMonitoring)
12195 {
12196 /* The log level is deliberately set to WARN as overriding
12197 * nthBeaconFilter to 1 will increase power cosumption and this
12198 * might just prove helpful to detect the power issue.
12199 */
12200 hddLog(VOS_TRACE_LEVEL_WARN,
12201 "%s: Setting pHddCtx->cfg_ini->nthBeaconFilter = 1", __func__);
12202 pHddCtx->cfg_ini->nthBeaconFilter = 1;
12203 }
Jeff Johnson295189b2012-06-20 16:38:30 -070012204 /*
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +053012205 * cfg80211: Initialization ...
Jeff Johnson295189b2012-06-20 16:38:30 -070012206 */
Manjeet Singh61016fa2016-12-02 11:10:19 +053012207 if (0 < wlan_hdd_cfg80211_init(dev, wiphy, pHddCtx->cfg_ini))
Jeff Johnson295189b2012-06-20 16:38:30 -070012208 {
Manjeet Singh61016fa2016-12-02 11:10:19 +053012209 hddLog(VOS_TRACE_LEVEL_FATAL,
12210 "%s: wlan_hdd_cfg80211_init return failure", __func__);
12211 goto err_config;
Jeff Johnson295189b2012-06-20 16:38:30 -070012212 }
Jeff Johnson295189b2012-06-20 16:38:30 -070012213
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -080012214 // Update VOS trace levels based upon the cfg.ini
12215 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
12216 pHddCtx->cfg_ini->vosTraceEnableBAP);
12217 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
12218 pHddCtx->cfg_ini->vosTraceEnableTL);
12219 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
12220 pHddCtx->cfg_ini->vosTraceEnableWDI);
12221 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
12222 pHddCtx->cfg_ini->vosTraceEnableHDD);
12223 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
12224 pHddCtx->cfg_ini->vosTraceEnableSME);
12225 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
12226 pHddCtx->cfg_ini->vosTraceEnablePE);
Katya Nigam70d68332013-09-16 16:49:45 +053012227 hdd_vos_trace_enable(VOS_MODULE_ID_PMC,
12228 pHddCtx->cfg_ini->vosTraceEnablePMC);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -080012229 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
12230 pHddCtx->cfg_ini->vosTraceEnableWDA);
12231 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
12232 pHddCtx->cfg_ini->vosTraceEnableSYS);
12233 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
12234 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -080012235 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
12236 pHddCtx->cfg_ini->vosTraceEnableSAP);
12237 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
12238 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -080012239
Jeff Johnson295189b2012-06-20 16:38:30 -070012240 // Update WDI trace levels based upon the cfg.ini
12241 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
12242 pHddCtx->cfg_ini->wdiTraceEnableDAL);
12243 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
12244 pHddCtx->cfg_ini->wdiTraceEnableCTL);
12245 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
12246 pHddCtx->cfg_ini->wdiTraceEnableDAT);
12247 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
12248 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -070012249
Jeff Johnson88ba7742013-02-27 14:36:02 -080012250 if (VOS_FTM_MODE == hdd_get_conparam())
12251 {
Jeff Johnson295189b2012-06-20 16:38:30 -070012252 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
12253 {
12254 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
12255 goto err_free_hdd_context;
12256 }
12257 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
Sachin Ahuja38ef5e02015-03-13 17:31:16 +053012258 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_NO_LOAD_UNLOAD_IN_PROGRESS;
c_hpothu2de0ef62014-04-15 16:16:15 +053012259 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -070012260 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -080012261 }
Jeff Johnson295189b2012-06-20 16:38:30 -070012262
Katya Nigame7b69a82015-04-28 15:24:06 +053012263 if( VOS_MONITOR_MODE == hdd_get_conparam())
12264 {
12265 if ( VOS_STATUS_SUCCESS != wlan_hdd_mon_open(pHddCtx))
12266 {
12267 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_mon_open Failed",__func__);
12268 goto err_free_hdd_context;
12269 }
12270 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Driver loaded in Monitor Mode",__func__);
12271 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_NO_LOAD_UNLOAD_IN_PROGRESS;
12272 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
12273 return VOS_STATUS_SUCCESS;
12274 }
12275
Jeff Johnson88ba7742013-02-27 14:36:02 -080012276 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -070012277 if(pHddCtx->cfg_ini->fIsLogpEnabled)
12278 {
12279 status = vos_watchdog_open(pVosContext,
12280 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
12281
12282 if(!VOS_IS_STATUS_SUCCESS( status ))
12283 {
12284 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Ashish Kumar Dhanotiya532bdef2017-05-09 17:31:59 +053012285 goto err_config;
Jeff Johnson295189b2012-06-20 16:38:30 -070012286 }
12287 }
12288
12289 pHddCtx->isLogpInProgress = FALSE;
12290 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
12291
Amar Singhala49cbc52013-10-08 18:37:44 -070012292#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -070012293 /* initialize the NV module. This is required so that
12294 we can initialize the channel information in wiphy
12295 from the NV.bin data. The channel information in
12296 wiphy needs to be initialized before wiphy registration */
12297
12298 status = vos_nv_open();
12299 if (!VOS_IS_STATUS_SUCCESS(status))
12300 {
12301 /* NV module cannot be initialized */
12302 hddLog( VOS_TRACE_LEVEL_FATAL,
12303 "%s: vos_nv_open failed", __func__);
Vinay Krishna Eranna2025d892014-09-18 16:51:42 +053012304 goto err_wdclose;
Amar Singhal0a402232013-10-11 20:57:16 -070012305 }
12306
12307 status = vos_init_wiphy_from_nv_bin();
12308 if (!VOS_IS_STATUS_SUCCESS(status))
12309 {
12310 /* NV module cannot be initialized */
12311 hddLog( VOS_TRACE_LEVEL_FATAL,
12312 "%s: vos_init_wiphy failed", __func__);
12313 goto err_vos_nv_close;
12314 }
12315
Amar Singhala49cbc52013-10-08 18:37:44 -070012316#endif
Mahesh A Saptasagarc3ed0122016-01-19 16:45:11 +053012317 //Initialize the nlink service
12318 if(nl_srv_init() != 0)
12319 {
12320 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
12321 goto err_vos_nv_close;
12322 }
12323
12324#ifdef WLAN_KD_READY_NOTIFIER
12325 pHddCtx->kd_nl_init = 1;
12326#endif /* WLAN_KD_READY_NOTIFIER */
12327
Girish Gowlibf0e1ab2015-01-19 16:05:16 +053012328 vos_set_roam_delay_stats_enabled(pHddCtx->cfg_ini->gEnableRoamDelayStats);
Arun Kumar Khandavalliebb19482014-03-25 13:56:53 +053012329 status = vos_open( &pVosContext, pHddCtx->parent_dev);
Jeff Johnson295189b2012-06-20 16:38:30 -070012330 if ( !VOS_IS_STATUS_SUCCESS( status ))
12331 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -080012332 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
Mahesh A Saptasagarc3ed0122016-01-19 16:45:11 +053012333 goto err_nl_srv;
Jeff Johnson295189b2012-06-20 16:38:30 -070012334 }
12335
Jeff Johnson295189b2012-06-20 16:38:30 -070012336 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
12337
12338 if ( NULL == pHddCtx->hHal )
12339 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -080012340 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -070012341 goto err_vosclose;
12342 }
12343
Jeff Johnsonbc676b42013-02-14 16:04:08 -080012344 status = vos_preStart( pHddCtx->pvosContext );
12345 if ( !VOS_IS_STATUS_SUCCESS( status ) )
12346 {
12347 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053012348 goto err_vosclose;
Jeff Johnsonbc676b42013-02-14 16:04:08 -080012349 }
Jeff Johnsone7245742012-09-05 17:12:55 -070012350
Arif Hussaineaf68602013-12-30 23:10:44 -080012351 if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan)
12352 {
12353 pHddCtx->cfg_ini->enableDFSChnlScan = enable_dfs_chan_scan;
12354 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_dfs_chan_scan set to %d",
12355 __func__, enable_dfs_chan_scan);
12356 }
12357 if (0 == enable_11d || 1 == enable_11d)
12358 {
12359 pHddCtx->cfg_ini->Is11dSupportEnabled = enable_11d;
12360 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_11d set to %d",
12361 __func__, enable_11d);
12362 }
12363
Jeff Johnsonbc676b42013-02-14 16:04:08 -080012364 /* Note that the vos_preStart() sequence triggers the cfg download.
12365 The cfg download must occur before we update the SME config
12366 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -070012367 status = hdd_set_sme_config( pHddCtx );
12368
12369 if ( VOS_STATUS_SUCCESS != status )
12370 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -080012371 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053012372 goto err_vosclose;
Jeff Johnsonbc676b42013-02-14 16:04:08 -080012373 }
Jeff Johnson295189b2012-06-20 16:38:30 -070012374
Jeff Johnson295189b2012-06-20 16:38:30 -070012375 /* In the integrated architecture we update the configuration from
12376 the INI file and from NV before vOSS has been started so that
12377 the final contents are available to send down to the cCPU */
12378
12379 // Apply the cfg.ini to cfg.dat
12380 if (FALSE == hdd_update_config_dat(pHddCtx))
12381 {
12382 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053012383 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -070012384 }
12385
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053012386 // Get mac addr from platform driver
12387 ret = wcnss_get_wlan_mac_address((char*)&mac_addr.bytes);
12388
12389 if ((0 == ret) && (!vos_is_macaddr_zero(&mac_addr)))
Jeff Johnson295189b2012-06-20 16:38:30 -070012390 {
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053012391 /* Store the mac addr for first interface */
12392 pHddCtx->cfg_ini->intfMacAddr[0] = mac_addr;
12393
12394 hddLog(VOS_TRACE_LEVEL_ERROR,
12395 "%s: WLAN Mac Addr: "
12396 MAC_ADDRESS_STR, __func__,
12397 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
12398
12399 /* Here, passing Arg2 as 1 because we do not want to change the
12400 last 3 bytes (means non OUI bytes) of first interface mac
12401 addr.
12402 */
12403 if (0 != hdd_generate_iface_mac_addr_auto(pHddCtx, 1, mac_addr))
12404 {
12405 hddLog(VOS_TRACE_LEVEL_ERROR,
12406 "%s: Failed to generate wlan interface mac addr "
12407 "using MAC from ini file ", __func__);
12408 }
12409 }
12410 else if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
12411 {
12412 // Apply the NV to cfg.dat
12413 /* Prima Update MAC address only at here */
Jeff Johnson295189b2012-06-20 16:38:30 -070012414#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
12415 /* There was not a valid set of MAC Addresses in NV. See if the
12416 default addresses were modified by the cfg.ini settings. If so,
12417 we'll use them, but if not, we'll autogenerate a set of MAC
12418 addresses based upon the device serial number */
12419
12420 static const v_MACADDR_t default_address =
12421 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
Jeff Johnson295189b2012-06-20 16:38:30 -070012422
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053012423 if (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
12424 sizeof(default_address)))
Jeff Johnson295189b2012-06-20 16:38:30 -070012425 {
12426 /* cfg.ini has the default address, invoke autogen logic */
12427
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053012428 /* Here, passing Arg2 as 0 because we want to change the
12429 last 3 bytes (means non OUI bytes) of all the interfaces
12430 mac addr.
12431 */
12432 if (0 != hdd_generate_iface_mac_addr_auto(pHddCtx, 0,
12433 default_address))
Jeff Johnson295189b2012-06-20 16:38:30 -070012434 {
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053012435 hddLog(VOS_TRACE_LEVEL_ERROR,
12436 "%s: Failed to generate wlan interface mac addr "
12437 "using MAC from ini file " MAC_ADDRESS_STR, __func__,
12438 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
Jeff Johnson295189b2012-06-20 16:38:30 -070012439 }
Jeff Johnson295189b2012-06-20 16:38:30 -070012440 }
12441 else
12442#endif //WLAN_AUTOGEN_MACADDR_FEATURE
12443 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -080012444 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -070012445 "%s: Invalid MAC address in NV, using MAC from ini file "
12446 MAC_ADDRESS_STR, __func__,
12447 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
12448 }
12449 }
12450 {
12451 eHalStatus halStatus;
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053012452
12453 /* Set the MAC Address Currently this is used by HAL to
12454 * add self sta. Remove this once self sta is added as
12455 * part of session open.
12456 */
Jeff Johnson295189b2012-06-20 16:38:30 -070012457 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
12458 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
12459 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053012460
Jeff Johnson295189b2012-06-20 16:38:30 -070012461 if (!HAL_STATUS_SUCCESS( halStatus ))
12462 {
12463 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
12464 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053012465 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -070012466 }
12467 }
Jeff Johnson295189b2012-06-20 16:38:30 -070012468
12469 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
12470 Note: Firmware image will be read and downloaded inside vos_start API */
12471 status = vos_start( pHddCtx->pvosContext );
12472 if ( !VOS_IS_STATUS_SUCCESS( status ) )
12473 {
12474 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
Hanumantha Reddy Pothulabd9601a2016-02-12 13:22:27 +053012475 if (isSsrPanicOnFailure())
12476 VOS_BUG(0);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053012477 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -070012478 }
12479
Leo Chang6cec3e22014-01-21 15:33:49 -080012480#ifdef FEATURE_WLAN_CH_AVOID
12481 /* Plug in avoid channel notification callback
12482 * This should happen before ADD_SELF_STA
12483 * FW will send first IND with ADD_SELF_STA REQ from host */
Pradeep Reddy POTTETI5c2e16d2014-06-27 16:47:38 +053012484
12485 /* check the Channel Avoidance is enabled */
12486 if (TRUE == pHddCtx->cfg_ini->fenableCHAvoidance)
12487 {
12488 sme_AddChAvoidCallback(pHddCtx->hHal,
12489 hdd_hostapd_ch_avoid_cb);
12490 }
Leo Chang6cec3e22014-01-21 15:33:49 -080012491#endif /* FEATURE_WLAN_CH_AVOID */
12492
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070012493 /* Exchange capability info between Host and FW and also get versioning info from FW */
12494 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -070012495
Agarwal Ashishad9281b2014-06-10 14:57:30 +053012496#ifdef CONFIG_ENABLE_LINUX_REG
12497 status = wlan_hdd_init_channels(pHddCtx);
12498 if ( !VOS_IS_STATUS_SUCCESS( status ) )
12499 {
12500 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: wlan_hdd_init_channels failed",
12501 __func__);
12502 goto err_vosstop;
12503 }
12504#endif
12505
Jeff Johnson295189b2012-06-20 16:38:30 -070012506 status = hdd_post_voss_start_config( pHddCtx );
12507 if ( !VOS_IS_STATUS_SUCCESS( status ) )
12508 {
12509 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
12510 __func__);
12511 goto err_vosstop;
12512 }
Amar Singhala49cbc52013-10-08 18:37:44 -070012513
12514#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +053012515 wlan_hdd_cfg80211_update_reg_info( wiphy );
12516
12517 /* registration of wiphy dev with cfg80211 */
12518 if (0 > wlan_hdd_cfg80211_register(wiphy))
12519 {
12520 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
12521 goto err_vosstop;
12522 }
Amar Singhala49cbc52013-10-08 18:37:44 -070012523#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070012524
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053012525#ifdef CONFIG_ENABLE_LINUX_REG
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053012526 /* registration of wiphy dev with cfg80211 */
12527 if (0 > wlan_hdd_cfg80211_register(wiphy))
12528 {
12529 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
12530 goto err_vosstop;
12531 }
12532
Agarwal Ashish6db9d532014-09-30 18:19:10 +053012533 status = wlan_hdd_init_channels_for_cc(pHddCtx, INIT);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053012534 if ( !VOS_IS_STATUS_SUCCESS( status ) )
12535 {
12536 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: wlan_hdd_init_channels_for_cc failed",
12537 __func__);
12538 goto err_unregister_wiphy;
12539 }
12540#endif
12541
c_hpothu4a298be2014-12-22 21:12:51 +053012542 wcnss_wlan_set_drvdata(pHddCtx->parent_dev, pHddCtx);
12543
Jeff Johnson295189b2012-06-20 16:38:30 -070012544 if (VOS_STA_SAP_MODE == hdd_get_conparam())
12545 {
12546 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
12547 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
12548 }
12549 else
12550 {
Jeff Johnson295189b2012-06-20 16:38:30 -070012551 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
12552 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
12553 if (pAdapter != NULL)
12554 {
Katya Nigama7d81d72014-11-12 12:44:34 +053012555 if (pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated && !(pHddCtx->cfg_ini->intfMacAddr[0].bytes[0] & 0x02))
Jeff Johnson295189b2012-06-20 16:38:30 -070012556 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +053012557 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
12558 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
12559 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -070012560
Gopichand Nakkala49f96f62013-02-06 14:38:17 +053012561 /* Generate the P2P Device Address. This consists of the device's
12562 * primary MAC address with the locally administered bit set.
12563 */
12564 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -070012565 }
12566 else
12567 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +053012568 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
12569 if (p2p_dev_addr != NULL)
12570 {
12571 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
12572 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
12573 }
12574 else
12575 {
12576 hddLog(VOS_TRACE_LEVEL_FATAL,
12577 "%s: Failed to allocate mac_address for p2p_device",
12578 __func__);
12579 goto err_close_adapter;
12580 }
Jeff Johnson295189b2012-06-20 16:38:30 -070012581 }
Jeff Johnsone7245742012-09-05 17:12:55 -070012582
12583 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
12584 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
12585 if ( NULL == pP2pAdapter )
12586 {
12587 hddLog(VOS_TRACE_LEVEL_FATAL,
12588 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070012589 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -070012590 goto err_close_adapter;
12591 }
Jeff Johnsone7245742012-09-05 17:12:55 -070012592 }
Jeff Johnson295189b2012-06-20 16:38:30 -070012593 }
Jeff Johnson295189b2012-06-20 16:38:30 -070012594
12595 if( pAdapter == NULL )
12596 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -080012597 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
12598 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -070012599 }
Jeff Johnsone7245742012-09-05 17:12:55 -070012600
Arif Hussain66559122013-11-21 10:11:40 -080012601 if (country_code)
12602 {
12603 eHalStatus ret;
Arif Hussaincb607082013-12-20 11:57:42 -080012604 INIT_COMPLETION(pAdapter->change_country_code);
Arif Hussain66559122013-11-21 10:11:40 -080012605 hdd_checkandupdate_dfssetting(pAdapter, country_code);
12606#ifndef CONFIG_ENABLE_LINUX_REG
12607 hdd_checkandupdate_phymode(pAdapter, country_code);
12608#endif
Arif Hussaineaf68602013-12-30 23:10:44 -080012609 ret = sme_ChangeCountryCode(pHddCtx->hHal,
12610 (void *)(tSmeChangeCountryCallback)
12611 wlan_hdd_change_country_code_callback,
Arif Hussain66559122013-11-21 10:11:40 -080012612 country_code,
12613 pAdapter, pHddCtx->pvosContext,
Abhishek Singha306a442013-11-07 18:39:01 +053012614 eSIR_TRUE, eSIR_TRUE);
Arif Hussain66559122013-11-21 10:11:40 -080012615 if (eHAL_STATUS_SUCCESS == ret)
12616 {
Arif Hussaincb607082013-12-20 11:57:42 -080012617 ret = wait_for_completion_interruptible_timeout(
12618 &pAdapter->change_country_code,
12619 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
12620
12621 if (0 >= ret)
12622 {
12623 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
12624 "%s: SME while setting country code timed out", __func__);
12625 }
Arif Hussain66559122013-11-21 10:11:40 -080012626 }
12627 else
12628 {
Arif Hussaincb607082013-12-20 11:57:42 -080012629 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
12630 "%s: SME Change Country code from module param fail ret=%d",
12631 __func__, ret);
Arif Hussain66559122013-11-21 10:11:40 -080012632 }
12633 }
12634
Jeff Johnson295189b2012-06-20 16:38:30 -070012635#ifdef WLAN_BTAMP_FEATURE
12636 vStatus = WLANBAP_Open(pVosContext);
12637 if(!VOS_IS_STATUS_SUCCESS(vStatus))
12638 {
12639 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
12640 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -070012641 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -070012642 }
12643
12644 vStatus = BSL_Init(pVosContext);
12645 if(!VOS_IS_STATUS_SUCCESS(vStatus))
12646 {
12647 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
12648 "%s: Failed to Init BSL",__func__);
12649 goto err_bap_close;
12650 }
12651 vStatus = WLANBAP_Start(pVosContext);
12652 if (!VOS_IS_STATUS_SUCCESS(vStatus))
12653 {
12654 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
12655 "%s: Failed to start TL",__func__);
12656 goto err_bap_close;
12657 }
12658
12659 pConfig = pHddCtx->cfg_ini;
12660 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
12661 status = WLANBAP_SetConfig(&btAmpConfig);
12662
12663#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -070012664
Mihir Shete9c238772014-10-15 14:35:16 +053012665 /*
12666 * UapsdMask is 0xf if U-APSD is enbaled for all AC's...
12667 * The value of CFG_QOS_WMM_UAPSD_MASK_DEFAULT is 0xaa(Magic Value)
12668 * which is greater than 0xf. So the below check is safe to make
12669 * sure that there is no entry for UapsdMask in the ini
12670 */
12671 if (CFG_QOS_WMM_UAPSD_MASK_DEFAULT == pHddCtx->cfg_ini->UapsdMask)
12672 {
12673 if(IS_DYNAMIC_WMM_PS_ENABLED)
12674 {
12675 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: Enable UAPSD for VI & VO",
12676 __func__);
12677 pHddCtx->cfg_ini->UapsdMask =
12678 CFG_QOS_WMM_UAPSD_MASK_DYMANIC_WMM_PS_DEFAULT;
12679 }
12680 else
12681 {
12682 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: Do not enable UAPSD",
12683 __func__);
12684 pHddCtx->cfg_ini->UapsdMask =
12685 CFG_QOS_WMM_UAPSD_MASK_LEGACY_WMM_PS_DEFAULT;
12686 }
12687 }
12688
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -070012689#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
12690 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
12691 {
12692 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
12693 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
12694 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
12695 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
12696 }
12697#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070012698
Agarwal Ashish4b87f922014-06-18 03:03:21 +053012699 wlan_hdd_tdls_init(pHddCtx);
12700
Masti, Narayanraddi26378462016-01-05 18:20:28 +053012701 wlan_hdd_init_deinit_defer_scan_context(&pHddCtx->scan_ctxt);
12702
12703 vos_init_delayed_work(&pHddCtx->scan_ctxt.scan_work,
12704 wlan_hdd_schedule_defer_scan);
12705
Mihir Shetefc7ff5b2014-01-27 11:30:05 +053012706 sme_Register11dScanDoneCallback(pHddCtx->hHal, hdd_11d_scan_done);
12707
Jeff Johnson295189b2012-06-20 16:38:30 -070012708 /* Register with platform driver as client for Suspend/Resume */
12709 status = hddRegisterPmOps(pHddCtx);
12710 if ( !VOS_IS_STATUS_SUCCESS( status ) )
12711 {
12712 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
12713#ifdef WLAN_BTAMP_FEATURE
12714 goto err_bap_stop;
12715#else
Jeff Johnsone7245742012-09-05 17:12:55 -070012716 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -070012717#endif //WLAN_BTAMP_FEATURE
12718 }
12719
Yue Ma0d4891e2013-08-06 17:01:45 -070012720 /* Open debugfs interface */
12721 if (VOS_STATUS_SUCCESS != hdd_debugfs_init(pAdapter))
12722 {
12723 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
12724 "%s: hdd_debugfs_init failed!", __func__);
Yue Ma0d4891e2013-08-06 17:01:45 -070012725 }
12726
Jeff Johnson295189b2012-06-20 16:38:30 -070012727 /* Register TM level change handler function to the platform */
12728 status = hddDevTmRegisterNotifyCallback(pHddCtx);
12729 if ( !VOS_IS_STATUS_SUCCESS( status ) )
12730 {
12731 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
12732 goto err_unregister_pmops;
12733 }
Jeff Johnson295189b2012-06-20 16:38:30 -070012734
Jeff Johnson295189b2012-06-20 16:38:30 -070012735 // register net device notifier for device change notification
12736 ret = register_netdevice_notifier(&hdd_netdev_notifier);
12737
12738 if(ret < 0)
12739 {
12740 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
Siddharth Bhalcd92b782015-06-29 12:25:40 +053012741 goto err_unregister_pmops;
Jeff Johnson295189b2012-06-20 16:38:30 -070012742 }
12743
Jeff Johnson295189b2012-06-20 16:38:30 -070012744 //Initialize the BTC service
12745 if(btc_activate_service(pHddCtx) != 0)
12746 {
12747 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
Mahesh A Saptasagarc3ed0122016-01-19 16:45:11 +053012748 goto err_reg_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -070012749 }
12750
Padma, Santhosh Kumar2762e9d2015-10-20 15:02:57 +053012751#ifdef FEATURE_OEM_DATA_SUPPORT
12752 //Initialize the OEM service
12753 if (oem_activate_service(pHddCtx) != 0)
12754 {
12755 hddLog(VOS_TRACE_LEVEL_FATAL,
12756 "%s: oem_activate_service failed", __func__);
Hanumanth Reddy Pothula13789c42017-09-12 15:18:13 +053012757 goto err_btc_activate_service;
Padma, Santhosh Kumar2762e9d2015-10-20 15:02:57 +053012758 }
12759#endif
12760
Jeff Johnson295189b2012-06-20 16:38:30 -070012761#ifdef PTT_SOCK_SVC_ENABLE
12762 //Initialize the PTT service
12763 if(ptt_sock_activate_svc(pHddCtx) != 0)
12764 {
12765 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
Hanumanth Reddy Pothula13789c42017-09-12 15:18:13 +053012766 goto err_oem_activate_service;
Jeff Johnson295189b2012-06-20 16:38:30 -070012767 }
12768#endif
12769
Abhishek Singh00b71972016-01-07 10:51:04 +053012770#ifdef WLAN_FEATURE_RMC
12771 if (hdd_open_cesium_nl_sock() < 0)
12772 {
12773 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_open_cesium_nl_sock failed", __func__);
Hanumanth Reddy Pothula13789c42017-09-12 15:18:13 +053012774 goto err_ptt_sock_activate_svc;
Abhishek Singh00b71972016-01-07 10:51:04 +053012775 }
12776#endif
12777
Vinay Krishna Erannad938c422014-03-10 17:14:21 +053012778#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
12779 if(pHddCtx->cfg_ini && pHddCtx->cfg_ini->wlanLoggingEnable)
12780 {
Deepthi Gowri78083a32014-11-04 12:55:51 +053012781 if(wlan_logging_sock_activate_svc(
12782 pHddCtx->cfg_ini->wlanLoggingFEToConsole,
Sushant Kaushik33200572015-08-05 16:46:20 +053012783 pHddCtx->cfg_ini->wlanLoggingNumBuf,
12784 pHddCtx->cfg_ini->wlanPerPktStatsLogEnable,
12785 pHddCtx->cfg_ini->wlanPerPktStatsNumBuf))
Deepthi Gowri78083a32014-11-04 12:55:51 +053012786 {
12787 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wlan_logging_sock_activate_svc"
12788 " failed", __func__);
Hanumanth Reddy Pothula13789c42017-09-12 15:18:13 +053012789 goto err_open_cesium_nl_sock;
Deepthi Gowri78083a32014-11-04 12:55:51 +053012790 }
12791 //TODO: To Remove enableDhcpDebug and use gEnableDebugLog for
12792 //EAPOL and DHCP
Sachin Ahuja8c65f382014-12-12 15:34:21 +053012793 if (!pHddCtx->cfg_ini->gEnableDebugLog)
12794 pHddCtx->cfg_ini->gEnableDebugLog =
Sushant Kaushik6e4e2bc2015-10-05 17:23:07 +053012795 VOS_PKT_PROTO_TYPE_EAPOL | VOS_PKT_PROTO_TYPE_DHCP |
12796 VOS_PKT_PROTO_TYPE_ARP;
Vinay Krishna Erannad938c422014-03-10 17:14:21 +053012797 }
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012798
Siddharth Bhald1be97f2015-05-27 22:39:59 +053012799 if (pHddCtx->cfg_ini->wlanLoggingEnable &&
12800 (pHddCtx->cfg_ini->enableFWLogging ||
Siddharth Bhaldb963232015-06-25 19:34:35 +053012801 pHddCtx->cfg_ini->enableMgmtLogging ||
c_manjeecfd1efb2015-09-25 19:32:34 +053012802 pHddCtx->cfg_ini->enableContFWLogging ||
12803 pHddCtx->cfg_ini->enableFwrMemDump )
12804 )
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012805 {
Siddharth Bhald1be97f2015-05-27 22:39:59 +053012806 hdd_init_frame_logging(pHddCtx);
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012807 }
12808 else
12809 {
Siddharth Bhald1be97f2015-05-27 22:39:59 +053012810 hddLog(VOS_TRACE_LEVEL_INFO, FL("Logging disabled in ini"));
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012811 }
12812
Vinay Krishna Erannad938c422014-03-10 17:14:21 +053012813#endif
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012814
Agrawal Ashish17ef5082016-10-17 18:33:21 +053012815#ifdef SAP_AUTH_OFFLOAD
12816 if (!sme_IsFeatureSupportedByFW(SAP_OFFLOADS))
12817 {
12818 hddLog(VOS_TRACE_LEVEL_INFO, FL(" SAP AUTH OFFLOAD not supp by FW"));
12819 pHddCtx->cfg_ini->enable_sap_auth_offload = 0;
12820 }
12821#endif
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012822
Sushant Kaushik215778f2015-05-21 14:05:36 +053012823 if (vos_is_multicast_logging())
12824 wlan_logging_set_log_level();
12825
Jeff Johnson295189b2012-06-20 16:38:30 -070012826 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -070012827 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -070012828 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -070012829 /* Action frame registered in one adapter which will
12830 * applicable to all interfaces
12831 */
Agarwal Ashish8fa0e9a2014-05-23 00:40:12 +053012832 wlan_hdd_cfg80211_register_frames(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -070012833 }
Jeff Johnson295189b2012-06-20 16:38:30 -070012834
12835 mutex_init(&pHddCtx->sap_lock);
Mahesh A Saptasagar60627942014-10-13 13:55:14 +053012836 mutex_init(&pHddCtx->roc_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070012837
Jeff Johnsone7245742012-09-05 17:12:55 -070012838#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
12839 /* Initialize the wake lcok */
Sushant Kaushik83392fa2015-05-05 17:44:40 +053012840 vos_wake_lock_init(&pHddCtx->rx_wake_lock,
Jeff Johnsone7245742012-09-05 17:12:55 -070012841 "qcom_rx_wakelock");
Sushant Kaushik83392fa2015-05-05 17:44:40 +053012842
Jeff Johnsone7245742012-09-05 17:12:55 -070012843#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -080012844 /* Initialize the wake lcok */
Sushant Kaushik83392fa2015-05-05 17:44:40 +053012845 vos_wake_lock_init(&pHddCtx->sap_wake_lock,
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -080012846 "qcom_sap_wakelock");
Sushant Kaushik83392fa2015-05-05 17:44:40 +053012847
Jeff Johnsone7245742012-09-05 17:12:55 -070012848
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -070012849 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
12850 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -070012851
Katya Nigam5c306ea2014-06-19 15:39:54 +053012852 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_NO_LOAD_UNLOAD_IN_PROGRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -070012853 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
Sushant Kaushik83392fa2015-05-05 17:44:40 +053012854 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_INIT);
Katya Nigam5c306ea2014-06-19 15:39:54 +053012855
12856#ifdef FEATURE_WLAN_SCAN_PNO
12857 /*SME must send channel update configuration to RIVA*/
12858 sme_UpdateChannelConfig(pHddCtx->hHal);
12859#endif
Abhishek Singhf644b272014-08-21 02:59:39 +053012860 /* Send the update default channel list to the FW*/
12861 sme_UpdateChannelList(pHddCtx->hHal);
Mukul Sharma45063942015-04-01 20:07:59 +053012862
12863 /* Fwr capabilities received, Set the Dot11 mode */
Abhishek Singh41ebce12016-02-03 10:43:21 +053012864 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter),
12865 hdd_cfg_xlate_to_csr_phy_mode(pHddCtx->cfg_ini->dot11Mode));
Mukul Sharma45063942015-04-01 20:07:59 +053012866 sme_SetDefDot11Mode(pHddCtx->hHal);
12867
Abhishek Singha306a442013-11-07 18:39:01 +053012868#ifndef CONFIG_ENABLE_LINUX_REG
12869 /*updating wiphy so that regulatory user hints can be processed*/
12870 if (wiphy)
12871 {
12872 regulatory_hint(wiphy, "00");
12873 }
12874#endif
Jeff Johnsone7245742012-09-05 17:12:55 -070012875 // Initialize the restart logic
12876 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +053012877
Hanumanth Reddy Pothula146bca42016-11-08 12:01:07 +053012878 if (pHddCtx->cfg_ini->fIsLogpEnabled) {
12879 vos_wdthread_init_timer_work(vos_process_wd_timer);
12880 /* Initialize the timer to detect thread stuck issues */
12881 vos_thread_stuck_timer_init(
12882 &((VosContextType*)pVosContext)->vosWatchdog);
12883 }
12884
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -070012885 //Register the traffic monitor timer now
12886 if ( pHddCtx->cfg_ini->dynSplitscan)
12887 {
12888 vos_timer_init(&pHddCtx->tx_rx_trafficTmr,
12889 VOS_TIMER_TYPE_SW,
12890 hdd_tx_rx_pkt_cnt_stat_timer_handler,
12891 (void *)pHddCtx);
12892 }
Srinivas Dasari030bad32015-02-18 23:23:54 +053012893 wlan_hdd_cfg80211_nan_init(pHddCtx);
12894
Bhargav Shahd0715912015-10-01 18:17:37 +053012895 mutex_init(&pHddCtx->cur_rx_level_lock);
12896 vos_timer_init(&pHddCtx->delack_timer, VOS_TIMER_TYPE_SW,
12897 hdd_tcp_delack_compute_function,(void *)pHddCtx);
Masti, Narayanraddi44b0db02015-12-22 11:54:35 +053012898 vos_timer_init(&pHddCtx->tdls_source_timer, VOS_TIMER_TYPE_SW,
12899 wlan_hdd_change_tdls_mode, (void *)pHddCtx);
Bhargav Shahd0715912015-10-01 18:17:37 +053012900
Dino Mycle6fb96c12014-06-10 11:52:40 +053012901#ifdef WLAN_FEATURE_EXTSCAN
12902 sme_EXTScanRegisterCallback(pHddCtx->hHal,
12903 wlan_hdd_cfg80211_extscan_callback,
12904 pHddCtx);
12905#endif /* WLAN_FEATURE_EXTSCAN */
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053012906
Padma, Santhosh Kumar2ccac212015-10-20 17:27:27 +053012907#ifdef FEATURE_OEM_DATA_SUPPORT
12908 sme_OemDataRegisterCallback(pHddCtx->hHal,
12909 wlan_hdd_cfg80211_oemdata_callback,
12910 pHddCtx);
12911#endif /* FEATURE_OEM_DATA_SUPPORT */
12912
Gupta, Kapil7c34b322015-09-30 13:12:35 +053012913 sme_set_rssi_threshold_breached_cb(pHddCtx->hHal, hdd_rssi_threshold_breached_cb);
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053012914#ifdef WLAN_NS_OFFLOAD
12915 // Register IPv6 notifier to notify if any change in IP
12916 // So that we can reconfigure the offload parameters
12917 pHddCtx->ipv6_notifier.notifier_call = wlan_hdd_ipv6_changed;
12918 ret = register_inet6addr_notifier(&pHddCtx->ipv6_notifier);
12919 if (ret)
12920 {
Ratheesh S P36dbc932015-08-07 14:28:57 +053012921 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Failed to register IPv6 notifier"));
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053012922 }
12923 else
12924 {
Ratheesh S P36dbc932015-08-07 14:28:57 +053012925 hddLog(VOS_TRACE_LEVEL_INFO, FL("Registered IPv6 notifier"));
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053012926 }
12927#endif
12928
Sravan Kumar Kairamb0edc612016-10-26 13:55:24 +053012929 vos_mem_set((uint8_t *)&pHddCtx->bad_sta, HDD_MAX_STA_COUNT, 0);
12930
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053012931 // Register IPv4 notifier to notify if any change in IP
12932 // So that we can reconfigure the offload parameters
12933 pHddCtx->ipv4_notifier.notifier_call = wlan_hdd_ipv4_changed;
12934 ret = register_inetaddr_notifier(&pHddCtx->ipv4_notifier);
12935 if (ret)
12936 {
Ratheesh S P36dbc932015-08-07 14:28:57 +053012937 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Failed to register IPv4 notifier"));
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053012938 }
12939 else
12940 {
Ratheesh S P36dbc932015-08-07 14:28:57 +053012941 hddLog(VOS_TRACE_LEVEL_INFO, FL("Registered IPv4 notifier"));
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053012942 }
c_manjeecfd1efb2015-09-25 19:32:34 +053012943 /*Fw mem dump procfs initialization*/
12944 memdump_init();
Bhargav shah23c94942015-10-13 12:48:35 +053012945 hdd_dp_util_send_rps_ind(pHddCtx);
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053012946
Nishank Aggarwalc11826c2016-12-15 18:54:10 +053012947 pHddCtx->is_ap_mode_wow_supported =
12948 sme_IsFeatureSupportedByFW(SAP_MODE_WOW);
Sravan Kumar Kairam091e5b62017-01-23 14:14:20 +053012949
Hanumanth Reddy Pothulae92bcc12017-05-19 13:56:35 +053012950 pHddCtx->is_fatal_event_log_sup =
12951 sme_IsFeatureSupportedByFW(FATAL_EVENT_LOGGING);
12952 hddLog(VOS_TRACE_LEVEL_INFO, FL("FATAL_EVENT_LOGGING: %d"),
12953 pHddCtx->is_fatal_event_log_sup);
12954
Sravan Kumar Kairam091e5b62017-01-23 14:14:20 +053012955 hdd_assoc_registerFwdEapolCB(pVosContext);
12956
Jeff Johnson295189b2012-06-20 16:38:30 -070012957 goto success;
12958
Hanumanth Reddy Pothula13789c42017-09-12 15:18:13 +053012959err_open_cesium_nl_sock:
12960#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
12961 hdd_close_cesium_nl_sock();
12962#endif
12963
12964err_ptt_sock_activate_svc:
12965#ifdef PTT_SOCK_SVC_ENABLE
12966 ptt_sock_deactivate_svc(pHddCtx);
12967#endif
12968
12969err_oem_activate_service:
12970#ifdef FEATURE_OEM_DATA_SUPPORT
12971 oem_deactivate_service();
12972#endif
12973
12974err_btc_activate_service:
12975 btc_deactivate_service();
12976
Jeff Johnson295189b2012-06-20 16:38:30 -070012977err_reg_netdev:
12978 unregister_netdevice_notifier(&hdd_netdev_notifier);
12979
Jeff Johnson295189b2012-06-20 16:38:30 -070012980err_unregister_pmops:
12981 hddDevTmUnregisterNotifyCallback(pHddCtx);
12982 hddDeregisterPmOps(pHddCtx);
12983
Yue Ma0d4891e2013-08-06 17:01:45 -070012984 hdd_debugfs_exit(pHddCtx);
12985
Jeff Johnson295189b2012-06-20 16:38:30 -070012986#ifdef WLAN_BTAMP_FEATURE
12987err_bap_stop:
12988 WLANBAP_Stop(pVosContext);
12989#endif
12990
12991#ifdef WLAN_BTAMP_FEATURE
12992err_bap_close:
12993 WLANBAP_Close(pVosContext);
12994#endif
12995
Jeff Johnson295189b2012-06-20 16:38:30 -070012996err_close_adapter:
12997 hdd_close_all_adapters( pHddCtx );
Mahesh A Saptasagar9ecefe42014-07-15 18:43:49 +053012998#ifdef CONFIG_ENABLE_LINUX_REG
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053012999err_unregister_wiphy:
Mahesh A Saptasagar9ecefe42014-07-15 18:43:49 +053013000#endif
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +053013001 wiphy_unregister(wiphy) ;
Agrawal Ashish33ec71e2015-11-26 20:20:58 +053013002 hdd_wlan_free_wiphy_channels(wiphy);
13003
Jeff Johnson295189b2012-06-20 16:38:30 -070013004err_vosstop:
13005 vos_stop(pVosContext);
13006
Amar Singhala49cbc52013-10-08 18:37:44 -070013007err_vosclose:
Jeff Johnson295189b2012-06-20 16:38:30 -070013008 status = vos_sched_close( pVosContext );
13009 if (!VOS_IS_STATUS_SUCCESS(status)) {
13010 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
13011 "%s: Failed to close VOSS Scheduler", __func__);
13012 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
13013 }
Amar Singhala49cbc52013-10-08 18:37:44 -070013014 vos_close(pVosContext );
13015
Mahesh A Saptasagarc3ed0122016-01-19 16:45:11 +053013016err_nl_srv:
13017#ifdef WLAN_KD_READY_NOTIFIER
13018 nl_srv_exit(pHddCtx->ptt_pid);
13019#else
13020 nl_srv_exit();
13021#endif /* WLAN_KD_READY_NOTIFIER */
Amar Singhal0a402232013-10-11 20:57:16 -070013022err_vos_nv_close:
13023
c_hpothue6a36282014-03-19 12:27:38 +053013024#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -070013025 vos_nv_close();
13026
c_hpothu70f8d812014-03-22 22:59:23 +053013027#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070013028
13029err_wdclose:
13030 if(pHddCtx->cfg_ini->fIsLogpEnabled)
13031 vos_watchdog_close(pVosContext);
13032
Jeff Johnson295189b2012-06-20 16:38:30 -070013033err_config:
13034 kfree(pHddCtx->cfg_ini);
13035 pHddCtx->cfg_ini= NULL;
13036
13037err_free_hdd_context:
Sushant Kaushik83392fa2015-05-05 17:44:40 +053013038 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_INIT);
Siddharth Bhalcd92b782015-06-29 12:25:40 +053013039 free_riva_power_on_lock("wlan");
Jeff Johnson295189b2012-06-20 16:38:30 -070013040 wiphy_free(wiphy) ;
13041 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -070013042 VOS_BUG(1);
13043
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -080013044 if (hdd_is_ssr_required())
13045 {
13046 /* WDI timeout had happened during load, so SSR is needed here */
13047 subsystem_restart("wcnss");
13048 msleep(5000);
13049 }
13050 hdd_set_ssr_required (VOS_FALSE);
13051
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -080013052 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -070013053
13054success:
13055 EXIT();
13056 return 0;
13057}
13058
13059/**---------------------------------------------------------------------------
13060
Jeff Johnson32d95a32012-09-10 13:15:23 -070013061 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -070013062
Jeff Johnson32d95a32012-09-10 13:15:23 -070013063 This is the driver entry point - called in different timeline depending
13064 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -070013065
13066 \param - None
13067
13068 \return - 0 for success, non zero for failure
13069
13070 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -070013071static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -070013072{
13073 VOS_STATUS status;
13074 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -070013075 struct device *dev = NULL;
13076 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -070013077#ifdef HAVE_WCNSS_CAL_DOWNLOAD
13078 int max_retries = 0;
13079#endif
Siddharth Bhalc7e79b62014-10-10 22:37:38 +053013080#ifdef HAVE_CBC_DONE
13081 int max_cbc_retries = 0;
13082#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070013083
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +053013084#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
13085 wlan_logging_sock_init_svc();
13086#endif
13087
Jeff Johnson295189b2012-06-20 16:38:30 -070013088 ENTER();
13089
Sushant Kaushik83392fa2015-05-05 17:44:40 +053013090 vos_wake_lock_init(&wlan_wake_lock, "wlan");
Jeff Johnson295189b2012-06-20 16:38:30 -070013091
13092 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
13093 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
13094
Jeff Johnson295189b2012-06-20 16:38:30 -070013095#ifdef ANI_BUS_TYPE_PCI
13096
13097 dev = wcnss_wlan_get_device();
13098
13099#endif // ANI_BUS_TYPE_PCI
13100
13101#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -070013102
13103#ifdef HAVE_WCNSS_CAL_DOWNLOAD
13104 /* wait until WCNSS driver downloads NV */
Ravi Kumar Bokka7a139e62016-11-17 21:32:55 +053013105 while (!wcnss_device_ready() && 10 >= ++max_retries) {
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -070013106 msleep(1000);
13107 }
Siddharth Bhalc7e79b62014-10-10 22:37:38 +053013108
Ravi Kumar Bokka7a139e62016-11-17 21:32:55 +053013109 if (max_retries >= 10) {
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -070013110 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
Sushant Kaushik83392fa2015-05-05 17:44:40 +053013111 vos_wake_lock_destroy(&wlan_wake_lock);
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +053013112#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
13113 wlan_logging_sock_deinit_svc();
13114#endif
13115
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -070013116 return -ENODEV;
13117 }
13118#endif
13119
Siddharth Bhalc7e79b62014-10-10 22:37:38 +053013120#ifdef HAVE_CBC_DONE
13121 while (!wcnss_cbc_complete() && 10 >= ++max_cbc_retries) {
13122 msleep(1000);
13123 }
13124 if (max_cbc_retries >= 10) {
13125 hddLog(VOS_TRACE_LEVEL_FATAL, "%s:CBC not completed", __func__);
13126 }
13127#endif
13128
Jeff Johnson295189b2012-06-20 16:38:30 -070013129 dev = wcnss_wlan_get_device();
13130#endif // ANI_BUS_TYPE_PLATFORM
13131
13132
13133 do {
13134 if (NULL == dev) {
13135 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
13136 ret_status = -1;
13137 break;
13138 }
13139
Jeff Johnson295189b2012-06-20 16:38:30 -070013140#ifdef TIMER_MANAGER
13141 vos_timer_manager_init();
13142#endif
13143
13144 /* Preopen VOSS so that it is ready to start at least SAL */
13145 status = vos_preOpen(&pVosContext);
13146
13147 if (!VOS_IS_STATUS_SUCCESS(status))
13148 {
13149 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
13150 ret_status = -1;
13151 break;
13152 }
13153
Sushant Kaushik02beb352015-06-04 15:15:01 +053013154 hddTraceInit();
Padma, Santhosh Kumar9093b202015-07-21 15:37:38 +053013155 hdd_register_debug_callback();
13156
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070013157#ifndef MODULE
13158 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
13159 */
13160 hdd_set_conparam((v_UINT_t)con_mode);
13161#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070013162
13163 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -080013164 if (hdd_wlan_startup(dev))
13165 {
Jeff Johnson295189b2012-06-20 16:38:30 -070013166 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -080013167 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -070013168 vos_preClose( &pVosContext );
13169 ret_status = -1;
13170 break;
13171 }
13172
Jeff Johnson295189b2012-06-20 16:38:30 -070013173 } while (0);
13174
13175 if (0 != ret_status)
13176 {
Jeff Johnson295189b2012-06-20 16:38:30 -070013177#ifdef TIMER_MANAGER
13178 vos_timer_exit();
13179#endif
13180#ifdef MEMORY_DEBUG
13181 vos_mem_exit();
13182#endif
Sushant Kaushik83392fa2015-05-05 17:44:40 +053013183 vos_wake_lock_destroy(&wlan_wake_lock);
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +053013184#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
13185 wlan_logging_sock_deinit_svc();
13186#endif
13187
Jeff Johnson295189b2012-06-20 16:38:30 -070013188 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
13189 }
13190 else
13191 {
13192 //Send WLAN UP indication to Nlink Service
13193 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
13194
13195 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Jeff Johnson295189b2012-06-20 16:38:30 -070013196 }
13197
13198 EXIT();
13199
13200 return ret_status;
13201}
13202
Jeff Johnson32d95a32012-09-10 13:15:23 -070013203/**---------------------------------------------------------------------------
13204
13205 \brief hdd_module_init() - Init Function
13206
13207 This is the driver entry point (invoked when module is loaded using insmod)
13208
13209 \param - None
13210
13211 \return - 0 for success, non zero for failure
13212
13213 --------------------------------------------------------------------------*/
13214#ifdef MODULE
13215static int __init hdd_module_init ( void)
13216{
13217 return hdd_driver_init();
13218}
Jeff Johnson32d95a32012-09-10 13:15:23 -070013219#else /* #ifdef MODULE */
13220static int __init hdd_module_init ( void)
13221{
13222 /* Driver initialization is delayed to fwpath_changed_handler */
13223 return 0;
13224}
Jeff Johnson32d95a32012-09-10 13:15:23 -070013225#endif /* #ifdef MODULE */
13226
Jeff Johnson295189b2012-06-20 16:38:30 -070013227
13228/**---------------------------------------------------------------------------
13229
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070013230 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -070013231
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070013232 This is the driver exit point (invoked when module is unloaded using rmmod
13233 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -070013234
13235 \param - None
13236
13237 \return - None
13238
13239 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070013240static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -070013241{
13242 hdd_context_t *pHddCtx = NULL;
13243 v_CONTEXT_t pVosContext = NULL;
Agarwal Ashish5e414792014-06-08 15:25:23 +053013244 v_REGDOMAIN_t regId;
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +053013245 unsigned long rc = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -070013246
13247 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
13248
13249 //Get the global vos context
13250 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
13251
13252 if(!pVosContext)
13253 {
13254 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
13255 goto done;
13256 }
13257
13258 //Get the HDD context.
13259 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
13260
13261 if(!pHddCtx)
13262 {
13263 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
13264 }
Katya Nigame7b69a82015-04-28 15:24:06 +053013265 else if (VOS_MONITOR_MODE == hdd_get_conparam())
13266 {
13267 hddLog(VOS_TRACE_LEVEL_INFO,"%s: MONITOR MODE",__func__);
13268 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_UNLOAD_IN_PROGRESS;
13269 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
13270 hdd_wlan_exit(pHddCtx);
13271 vos_preClose( &pVosContext );
13272 goto done;
13273 }
Jeff Johnson295189b2012-06-20 16:38:30 -070013274 else
13275 {
Siddharth Bhal2e5871b2015-03-24 16:20:51 +053013276 /* We wait for active entry threads to exit from driver
13277 * by waiting until rtnl_lock is available.
13278 */
13279 rtnl_lock();
13280 rtnl_unlock();
13281
Siddharth Bhal3c29dca2015-02-19 00:41:40 +053013282 INIT_COMPLETION(pHddCtx->ssr_comp_var);
13283 if ((pHddCtx->isLogpInProgress) && (FALSE ==
13284 vos_is_wlan_in_badState(VOS_MODULE_ID_HDD, NULL)))
13285 {
Siddharth Bhala204f572015-01-17 02:03:36 +053013286 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Siddharth Bhal3c29dca2015-02-19 00:41:40 +053013287 "%s:SSR in Progress; block rmmod !!!", __func__);
Siddharth Bhala204f572015-01-17 02:03:36 +053013288 rc = wait_for_completion_timeout(&pHddCtx->ssr_comp_var,
13289 msecs_to_jiffies(30000));
13290 if(!rc)
13291 {
13292 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
13293 "%s:SSR timedout, fatal error", __func__);
13294 VOS_BUG(0);
13295 }
13296 }
13297
Siddharth Bhal3c29dca2015-02-19 00:41:40 +053013298 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_UNLOAD_IN_PROGRESS;
13299 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
Jeff Johnson295189b2012-06-20 16:38:30 -070013300
c_hpothu8adb97b2014-12-08 19:38:20 +053013301 /* Driver Need to send country code 00 in below condition
13302 * 1) If gCountryCodePriority is set to 1; and last country
13303 * code set is through 11d. This needs to be done in case
13304 * when NV country code is 00.
13305 * This Needs to be done as when kernel store last country
13306 * code and if stored country code is not through 11d,
13307 * in sme_HandleChangeCountryCodeByUser we will disable 11d
13308 * in next load/unload as soon as we get any country through
13309 * 11d. In sme_HandleChangeCountryCodeByUser
13310 * pMsg->countryCode will be last countryCode and
13311 * pMac->scan.countryCode11d will be country through 11d so
13312 * due to mismatch driver will disable 11d.
13313 *
13314 */
Agarwal Ashish8db39882014-07-30 21:56:07 +053013315
c_hpothu8adb97b2014-12-08 19:38:20 +053013316 if ((eANI_BOOLEAN_TRUE == sme_Is11dCountrycode(pHddCtx->hHal) &&
Agarwal Ashish8dcd2862014-07-25 11:58:52 +053013317 pHddCtx->cfg_ini->fSupplicantCountryCodeHasPriority &&
Abhishek Singh2a705962014-10-30 14:47:28 +053013318 sme_Is11dSupported(pHddCtx->hHal)))
c_hpothu8adb97b2014-12-08 19:38:20 +053013319 {
13320 hddLog(VOS_TRACE_LEVEL_INFO,
Agarwal Ashish8dcd2862014-07-25 11:58:52 +053013321 FL("CountryCode 00 is being set while unloading driver"));
c_hpothu8adb97b2014-12-08 19:38:20 +053013322 vos_nv_getRegDomainFromCountryCode(&regId , "00", COUNTRY_USER);
13323 }
Agarwal Ashish5e414792014-06-08 15:25:23 +053013324
c_hpothu8adb97b2014-12-08 19:38:20 +053013325 //Do all the cleanup before deregistering the driver
13326 hdd_wlan_exit(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -070013327 }
13328
Jeff Johnson295189b2012-06-20 16:38:30 -070013329 vos_preClose( &pVosContext );
13330
13331#ifdef TIMER_MANAGER
13332 vos_timer_exit();
13333#endif
13334#ifdef MEMORY_DEBUG
13335 vos_mem_exit();
13336#endif
13337
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +053013338#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
13339 wlan_logging_sock_deinit_svc();
13340#endif
13341
Jeff Johnson295189b2012-06-20 16:38:30 -070013342done:
Sushant Kaushik83392fa2015-05-05 17:44:40 +053013343 vos_wake_lock_destroy(&wlan_wake_lock);
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +053013344
Jeff Johnson295189b2012-06-20 16:38:30 -070013345 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
13346}
13347
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070013348/**---------------------------------------------------------------------------
13349
13350 \brief hdd_module_exit() - Exit function
13351
13352 This is the driver exit point (invoked when module is unloaded using rmmod)
13353
13354 \param - None
13355
13356 \return - None
13357
13358 --------------------------------------------------------------------------*/
13359static void __exit hdd_module_exit(void)
13360{
13361 hdd_driver_exit();
13362}
13363
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070013364#ifdef MODULE
13365static int fwpath_changed_handler(const char *kmessage,
13366 struct kernel_param *kp)
13367{
Jeff Johnson76052702013-04-16 13:55:05 -070013368 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070013369}
13370
13371static int con_mode_handler(const char *kmessage,
13372 struct kernel_param *kp)
13373{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -070013374 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070013375}
13376#else /* #ifdef MODULE */
13377/**---------------------------------------------------------------------------
13378
Jeff Johnson76052702013-04-16 13:55:05 -070013379 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070013380
Jeff Johnson76052702013-04-16 13:55:05 -070013381 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070013382 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -070013383 - invoked when module parameter fwpath is modified from userspace to signal
13384 initializing the WLAN driver or when con_mode is modified from userspace
13385 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070013386
13387 \return - 0 for success, non zero for failure
13388
13389 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -070013390static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070013391{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -070013392 int ret_status;
13393
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070013394 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -070013395 ret_status = hdd_driver_init();
13396 wlan_hdd_inited = ret_status ? 0 : 1;
13397 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070013398 }
13399
13400 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -070013401
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070013402 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -070013403
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -070013404 ret_status = hdd_driver_init();
13405 wlan_hdd_inited = ret_status ? 0 : 1;
13406 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070013407}
13408
Jeff Johnson295189b2012-06-20 16:38:30 -070013409/**---------------------------------------------------------------------------
13410
Jeff Johnson76052702013-04-16 13:55:05 -070013411 \brief fwpath_changed_handler() - Handler Function
13412
13413 Handle changes to the fwpath parameter
13414
13415 \return - 0 for success, non zero for failure
13416
13417 --------------------------------------------------------------------------*/
13418static int fwpath_changed_handler(const char *kmessage,
13419 struct kernel_param *kp)
13420{
13421 int ret;
13422
13423 ret = param_set_copystring(kmessage, kp);
13424 if (0 == ret)
13425 ret = kickstart_driver();
13426 return ret;
13427}
13428
13429/**---------------------------------------------------------------------------
13430
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070013431 \brief con_mode_handler() -
13432
13433 Handler function for module param con_mode when it is changed by userspace
13434 Dynamically linked - do nothing
13435 Statically linked - exit and init driver, as in rmmod and insmod
13436
Jeff Johnson76052702013-04-16 13:55:05 -070013437 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070013438
Jeff Johnson76052702013-04-16 13:55:05 -070013439 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070013440
13441 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -070013442static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070013443{
Jeff Johnson76052702013-04-16 13:55:05 -070013444 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070013445
Jeff Johnson76052702013-04-16 13:55:05 -070013446 ret = param_set_int(kmessage, kp);
13447 if (0 == ret)
13448 ret = kickstart_driver();
13449 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070013450}
13451#endif /* #ifdef MODULE */
13452
13453/**---------------------------------------------------------------------------
13454
Jeff Johnson295189b2012-06-20 16:38:30 -070013455 \brief hdd_get_conparam() -
13456
13457 This is the driver exit point (invoked when module is unloaded using rmmod)
13458
13459 \param - None
13460
13461 \return - tVOS_CON_MODE
13462
13463 --------------------------------------------------------------------------*/
13464tVOS_CON_MODE hdd_get_conparam ( void )
13465{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070013466#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -070013467 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070013468#else
13469 return (tVOS_CON_MODE)curr_con_mode;
13470#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070013471}
13472void hdd_set_conparam ( v_UINT_t newParam )
13473{
13474 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070013475#ifndef MODULE
13476 curr_con_mode = con_mode;
13477#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070013478}
13479/**---------------------------------------------------------------------------
13480
13481 \brief hdd_softap_sta_deauth() - function
13482
13483 This to take counter measure to handle deauth req from HDD
13484
13485 \param - pAdapter - Pointer to the HDD
13486
13487 \param - enable - boolean value
13488
13489 \return - None
13490
13491 --------------------------------------------------------------------------*/
13492
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +053013493VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter,
13494 struct tagCsrDelStaParams *pDelStaParams)
Jeff Johnson295189b2012-06-20 16:38:30 -070013495{
Jeff Johnson295189b2012-06-20 16:38:30 -070013496 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -080013497 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -070013498
13499 ENTER();
13500
Rajesh Chauhan18488fc2013-08-22 10:15:03 -070013501 hddLog(LOG1, "hdd_softap_sta_deauth:(%p, false)",
13502 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -070013503
13504 //Ignore request to deauth bcmc station
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +053013505 if (pDelStaParams->peerMacAddr[0] & 0x1)
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -080013506 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -070013507
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +053013508 vosStatus = WLANSAP_DeauthSta(pVosContext, pDelStaParams);
Jeff Johnson295189b2012-06-20 16:38:30 -070013509
13510 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -080013511 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -070013512}
13513
13514/**---------------------------------------------------------------------------
13515
Rashmi Ramanna1f0948d2014-08-28 15:33:48 +053013516 \brief hdd_del_all_sta() - function
13517
13518 This function removes all the stations associated on stopping AP/P2P GO.
13519
13520 \param - pAdapter - Pointer to the HDD
13521
13522 \return - None
13523
13524 --------------------------------------------------------------------------*/
13525
13526int hdd_del_all_sta(hdd_adapter_t *pAdapter)
13527{
13528 v_U16_t i;
13529 VOS_STATUS vos_status;
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +053013530 v_CONTEXT_t pVosContext = ( WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
13531 ptSapContext pSapCtx = NULL;
13532 pSapCtx = VOS_GET_SAP_CB(pVosContext);
13533 if(pSapCtx == NULL){
13534 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
13535 FL("psapCtx is NULL"));
13536 return 1;
13537 }
Rashmi Ramanna1f0948d2014-08-28 15:33:48 +053013538 ENTER();
13539
13540 hddLog(VOS_TRACE_LEVEL_INFO,
13541 "%s: Delete all STAs associated.",__func__);
13542 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
13543 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
13544 )
13545 {
13546 for(i = 0; i < WLAN_MAX_STA_COUNT; i++)
13547 {
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +053013548 if ((pSapCtx->aStaInfo[i].isUsed) &&
13549 (!pSapCtx->aStaInfo[i].isDeauthInProgress))
Rashmi Ramanna1f0948d2014-08-28 15:33:48 +053013550 {
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +053013551 struct tagCsrDelStaParams delStaParams;
13552
13553 WLANSAP_PopulateDelStaParams(
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +053013554 pSapCtx->aStaInfo[i].macAddrSTA.bytes,
Sushant Kaushik4cd28f62014-12-26 14:23:50 +053013555 eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
13556 SIR_MAC_MGMT_DEAUTH >> 4,
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +053013557 &delStaParams);
13558 vos_status = hdd_softap_sta_deauth(pAdapter, &delStaParams);
Rashmi Ramanna1f0948d2014-08-28 15:33:48 +053013559 if (VOS_IS_STATUS_SUCCESS(vos_status))
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +053013560 pSapCtx->aStaInfo[i].isDeauthInProgress = TRUE;
Rashmi Ramanna1f0948d2014-08-28 15:33:48 +053013561 }
13562 }
13563 }
13564
13565 EXIT();
13566 return 0;
13567}
13568
13569/**---------------------------------------------------------------------------
13570
Jeff Johnson295189b2012-06-20 16:38:30 -070013571 \brief hdd_softap_sta_disassoc() - function
13572
13573 This to take counter measure to handle deauth req from HDD
13574
13575 \param - pAdapter - Pointer to the HDD
13576
13577 \param - enable - boolean value
13578
13579 \return - None
13580
13581 --------------------------------------------------------------------------*/
13582
13583void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
13584{
13585 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
13586
13587 ENTER();
13588
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +053013589 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -070013590
13591 //Ignore request to disassoc bcmc station
13592 if( pDestMacAddress[0] & 0x1 )
13593 return;
13594
13595 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
13596}
13597
13598void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
13599{
13600 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
13601
13602 ENTER();
13603
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +053013604 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -070013605
13606 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
13607}
13608
Jeff Johnson295189b2012-06-20 16:38:30 -070013609/**---------------------------------------------------------------------------
13610 *
13611 * \brief hdd_get__concurrency_mode() -
13612 *
13613 *
13614 * \param - None
13615 *
13616 * \return - CONCURRENCY MODE
13617 *
13618 * --------------------------------------------------------------------------*/
13619tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
13620{
13621 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
13622 hdd_context_t *pHddCtx;
13623
13624 if (NULL != pVosContext)
13625 {
13626 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
13627 if (NULL != pHddCtx)
13628 {
13629 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
13630 }
13631 }
13632
13633 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070013634 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -070013635 return VOS_STA;
13636}
Sushant Kaushikabb7ee62014-07-18 16:20:12 +053013637v_BOOL_t
13638wlan_hdd_is_GO_power_collapse_allowed (hdd_context_t* pHddCtx)
13639{
13640 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -070013641
Sushant Kaushikabb7ee62014-07-18 16:20:12 +053013642 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_GO);
13643 if (pAdapter == NULL)
13644 {
13645 hddLog(VOS_TRACE_LEVEL_INFO,
13646 FL("GO doesn't exist"));
13647 return TRUE;
13648 }
13649 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
13650 {
13651 hddLog(VOS_TRACE_LEVEL_INFO,
13652 FL("GO started"));
13653 return TRUE;
13654 }
13655 else
13656 /* wait till GO changes its interface to p2p device */
13657 hddLog(VOS_TRACE_LEVEL_INFO,
13658 FL("Del_bss called, avoid apps suspend"));
13659 return FALSE;
13660
13661}
Jeff Johnson295189b2012-06-20 16:38:30 -070013662/* Decide whether to allow/not the apps power collapse.
13663 * Allow apps power collapse if we are in connected state.
13664 * if not, allow only if we are in IMPS */
13665v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
13666{
13667 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -080013668 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -080013669 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -070013670 hdd_config_t *pConfig = pHddCtx->cfg_ini;
13671 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
13672 hdd_adapter_t *pAdapter = NULL;
13673 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -080013674 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -070013675
Jeff Johnson295189b2012-06-20 16:38:30 -070013676 if (VOS_STA_SAP_MODE == hdd_get_conparam())
13677 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -070013678
Yathish9f22e662012-12-10 14:21:35 -080013679 concurrent_state = hdd_get_concurrency_mode();
13680
Sushant Kaushikabb7ee62014-07-18 16:20:12 +053013681 if ((concurrent_state == (VOS_STA | VOS_P2P_GO)) &&
13682 !(wlan_hdd_is_GO_power_collapse_allowed(pHddCtx)))
13683 return FALSE;
Yathish9f22e662012-12-10 14:21:35 -080013684#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
Sushant Kaushikabb7ee62014-07-18 16:20:12 +053013685
Yathish9f22e662012-12-10 14:21:35 -080013686 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
Sushant Kaushikabb7ee62014-07-18 16:20:12 +053013687 (concurrent_state == (VOS_STA | VOS_P2P_GO)))&&
Yathish9f22e662012-12-10 14:21:35 -080013688 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
13689 return TRUE;
13690#endif
13691
Jeff Johnson295189b2012-06-20 16:38:30 -070013692 /*loop through all adapters. TBD fix for Concurrency */
13693 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
13694 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
13695 {
13696 pAdapter = pAdapterNode->pAdapter;
13697 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
13698 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
13699 {
Srikant Kuppafef66a72013-01-30 17:32:44 -080013700 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
c_hpothu4e8faac2014-05-16 17:38:44 +053013701 && (pmcState != IMPS && pmcState != BMPS && pmcState != UAPSD
c_hpothu1c6957d2015-01-06 18:19:47 +053013702 && pmcState != STOPPED && pmcState != STANDBY &&
13703 pmcState != WOWL)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -080013704 (eANI_BOOLEAN_TRUE == scanRspPending) ||
13705 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -070013706 {
Mukul Sharma4be88422015-03-09 20:29:07 +053013707 if(pmcState == FULL_POWER &&
13708 sme_IsCoexScoIndicationSet(pHddCtx->hHal))
13709 {
13710 /*
13711 * When SCO indication comes from Coex module , host will
13712 * enter in to full power mode, but this should not prevent
13713 * apps processor power collapse.
13714 */
13715 hddLog(LOG1,
13716 FL("Allow apps power collapse"
13717 "even when sco indication is set"));
13718 return TRUE;
13719 }
Srikant Kuppafef66a72013-01-30 17:32:44 -080013720 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Deepthi Gowri03a979f2016-11-03 15:20:19 +053013721 "pmcState = %d scanRspPending = %d "
13722 "inMiddleOfRoaming = %d connected = %d",
13723 __func__, pmcState, scanRspPending,
13724 inMiddleOfRoaming, hdd_connIsConnected(
13725 WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )));
13726 wlan_hdd_get_tdls_stats(pAdapter);
13727 return FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -070013728 }
13729 }
13730 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
13731 pAdapterNode = pNext;
13732 }
13733 return TRUE;
13734}
13735
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -080013736/* Decides whether to send suspend notification to Riva
13737 * if any adapter is in BMPS; then it is required */
13738v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
13739{
13740 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
13741 hdd_config_t *pConfig = pHddCtx->cfg_ini;
13742
13743 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
13744 {
13745 return TRUE;
13746 }
13747 return FALSE;
13748}
13749
Jeff Johnson295189b2012-06-20 16:38:30 -070013750void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
13751{
13752 switch(mode)
13753 {
Chilam Ngc4244af2013-04-01 15:37:32 -070013754 case VOS_STA_MODE:
13755 case VOS_P2P_CLIENT_MODE:
13756 case VOS_P2P_GO_MODE:
13757 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -070013758 pHddCtx->concurrency_mode |= (1 << mode);
Agarwal Ashish51325b52014-06-16 16:50:49 +053013759 pHddCtx->no_of_open_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -070013760 break;
13761 default:
13762 break;
Jeff Johnson295189b2012-06-20 16:38:30 -070013763 }
Agarwal Ashish51325b52014-06-16 16:50:49 +053013764 hddLog(VOS_TRACE_LEVEL_INFO, FL("concurrency_mode = 0x%x "
13765 "Number of open sessions for mode %d = %d"),
13766 pHddCtx->concurrency_mode, mode,
13767 pHddCtx->no_of_open_sessions[mode]);
Jeff Johnson295189b2012-06-20 16:38:30 -070013768}
13769
13770
13771void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
13772{
13773 switch(mode)
13774 {
Chilam Ngc4244af2013-04-01 15:37:32 -070013775 case VOS_STA_MODE:
13776 case VOS_P2P_CLIENT_MODE:
13777 case VOS_P2P_GO_MODE:
13778 case VOS_STA_SAP_MODE:
Agarwal Ashish51325b52014-06-16 16:50:49 +053013779 pHddCtx->no_of_open_sessions[mode]--;
13780 if (!(pHddCtx->no_of_open_sessions[mode]))
13781 pHddCtx->concurrency_mode &= (~(1 << mode));
Jeff Johnson295189b2012-06-20 16:38:30 -070013782 break;
13783 default:
13784 break;
13785 }
Agarwal Ashish51325b52014-06-16 16:50:49 +053013786 hddLog(VOS_TRACE_LEVEL_INFO, FL("concurrency_mode = 0x%x "
13787 "Number of open sessions for mode %d = %d"),
13788 pHddCtx->concurrency_mode, mode, pHddCtx->no_of_open_sessions[mode]);
13789
13790}
13791/**---------------------------------------------------------------------------
13792 *
13793 * \brief wlan_hdd_incr_active_session()
13794 *
13795 * This function increments the number of active sessions
13796 * maintained per device mode
13797 * Incase of STA/P2P CLI/IBSS upon connection indication it is incremented
13798 * Incase of SAP/P2P GO upon bss start it is incremented
13799 *
13800 * \param pHddCtx - HDD Context
13801 * \param mode - device mode
13802 *
13803 * \return - None
13804 *
13805 * --------------------------------------------------------------------------*/
13806void wlan_hdd_incr_active_session(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
13807{
13808 switch (mode) {
13809 case VOS_STA_MODE:
13810 case VOS_P2P_CLIENT_MODE:
13811 case VOS_P2P_GO_MODE:
13812 case VOS_STA_SAP_MODE:
13813 pHddCtx->no_of_active_sessions[mode]++;
13814 break;
13815 default:
13816 hddLog(VOS_TRACE_LEVEL_INFO, FL("Not Expected Mode %d"), mode);
13817 break;
13818 }
13819 hddLog(VOS_TRACE_LEVEL_INFO, FL("No.# of active sessions for mode %d = %d"),
13820 mode,
13821 pHddCtx->no_of_active_sessions[mode]);
13822}
13823
13824/**---------------------------------------------------------------------------
13825 *
13826 * \brief wlan_hdd_decr_active_session()
13827 *
13828 * This function decrements the number of active sessions
13829 * maintained per device mode
13830 * Incase of STA/P2P CLI/IBSS upon disconnection it is decremented
13831 * Incase of SAP/P2P GO upon bss stop it is decremented
13832 *
13833 * \param pHddCtx - HDD Context
13834 * \param mode - device mode
13835 *
13836 * \return - None
13837 *
13838 * --------------------------------------------------------------------------*/
13839void wlan_hdd_decr_active_session(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
13840{
Bhargav Shahd0715912015-10-01 18:17:37 +053013841
Agarwal Ashish51325b52014-06-16 16:50:49 +053013842 switch (mode) {
13843 case VOS_STA_MODE:
13844 case VOS_P2P_CLIENT_MODE:
13845 case VOS_P2P_GO_MODE:
13846 case VOS_STA_SAP_MODE:
Agarwal Ashish5325f522014-08-06 00:58:44 +053013847 if (pHddCtx->no_of_active_sessions[mode] > 0)
13848 pHddCtx->no_of_active_sessions[mode]--;
13849 else
13850 hddLog(VOS_TRACE_LEVEL_INFO, FL(" No.# of Active sessions"
13851 "is already Zero"));
Agarwal Ashish51325b52014-06-16 16:50:49 +053013852 break;
13853 default:
13854 hddLog(VOS_TRACE_LEVEL_INFO, FL("Not Expected Mode %d"), mode);
13855 break;
13856 }
13857 hddLog(VOS_TRACE_LEVEL_INFO, FL("No.# of active sessions for mode %d = %d"),
13858 mode,
13859 pHddCtx->no_of_active_sessions[mode]);
Jeff Johnson295189b2012-06-20 16:38:30 -070013860}
13861
Jeff Johnsone7245742012-09-05 17:12:55 -070013862/**---------------------------------------------------------------------------
13863 *
13864 * \brief wlan_hdd_restart_init
13865 *
13866 * This function initalizes restart timer/flag. An internal function.
13867 *
13868 * \param - pHddCtx
13869 *
13870 * \return - None
13871 *
13872 * --------------------------------------------------------------------------*/
13873
13874static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
13875{
13876 /* Initialize */
13877 pHddCtx->hdd_restart_retries = 0;
13878 atomic_set(&pHddCtx->isRestartInProgress, 0);
13879 vos_timer_init(&pHddCtx->hdd_restart_timer,
13880 VOS_TIMER_TYPE_SW,
13881 wlan_hdd_restart_timer_cb,
13882 pHddCtx);
13883}
13884/**---------------------------------------------------------------------------
13885 *
13886 * \brief wlan_hdd_restart_deinit
13887 *
13888 * This function cleans up the resources used. An internal function.
13889 *
13890 * \param - pHddCtx
13891 *
13892 * \return - None
13893 *
13894 * --------------------------------------------------------------------------*/
13895
13896static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
13897{
13898
13899 VOS_STATUS vos_status;
13900 /* Block any further calls */
13901 atomic_set(&pHddCtx->isRestartInProgress, 1);
13902 /* Cleanup */
13903 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
13904 if (!VOS_IS_STATUS_SUCCESS(vos_status))
c_hpothu6ff1c3c2013-10-01 19:01:57 +053013905 hddLog(LOGE, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -070013906 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
13907 if (!VOS_IS_STATUS_SUCCESS(vos_status))
c_hpothu6ff1c3c2013-10-01 19:01:57 +053013908 hddLog(LOGE, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -070013909
13910}
13911
13912/**---------------------------------------------------------------------------
13913 *
13914 * \brief wlan_hdd_framework_restart
13915 *
13916 * This function uses a cfg80211 API to start a framework initiated WLAN
13917 * driver module unload/load.
13918 *
13919 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
13920 *
13921 *
13922 * \param - pHddCtx
13923 *
13924 * \return - VOS_STATUS_SUCCESS: Success
13925 * VOS_STATUS_E_EMPTY: Adapter is Empty
13926 * VOS_STATUS_E_NOMEM: No memory
13927
13928 * --------------------------------------------------------------------------*/
13929
13930static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
13931{
13932 VOS_STATUS status = VOS_STATUS_SUCCESS;
13933 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -070013934 int len = (sizeof (struct ieee80211_mgmt));
13935 struct ieee80211_mgmt *mgmt = NULL;
13936
13937 /* Prepare the DEAUTH managment frame with reason code */
13938 mgmt = kzalloc(len, GFP_KERNEL);
13939 if(mgmt == NULL)
13940 {
13941 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
13942 "%s: memory allocation failed (%d bytes)", __func__, len);
13943 return VOS_STATUS_E_NOMEM;
13944 }
13945 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -070013946
13947 /* Iterate over all adapters/devices */
13948 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Hanumantha Reddy Pothulada0fe362015-02-27 18:37:03 +053013949 if ((NULL == pAdapterNode) || (VOS_STATUS_SUCCESS != status))
13950 {
13951 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
13952 FL("fail to get adapter: %p %d"), pAdapterNode, status);
13953 goto end;
13954 }
13955
Jeff Johnsone7245742012-09-05 17:12:55 -070013956 do
13957 {
Hanumantha Reddy Pothulada0fe362015-02-27 18:37:03 +053013958 if(pAdapterNode->pAdapter &&
13959 WLAN_HDD_ADAPTER_MAGIC == pAdapterNode->pAdapter->magic)
Jeff Johnsone7245742012-09-05 17:12:55 -070013960 {
13961 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
13962 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
13963 pAdapterNode->pAdapter->dev->name,
13964 pAdapterNode->pAdapter->device_mode,
13965 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -070013966 /*
13967 * CFG80211 event to restart the driver
13968 *
13969 * 'cfg80211_send_unprot_deauth' sends a
13970 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
13971 * of SME(Linux Kernel) state machine.
13972 *
13973 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
13974 * the driver.
13975 *
13976 */
Abhishek Singh00b71972016-01-07 10:51:04 +053013977
Anand N Sunkade9adb1b2015-07-29 09:56:45 +053013978#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
13979 cfg80211_rx_unprot_mlme_mgmt(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len);
13980#else
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -070013981 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Anand N Sunkade9adb1b2015-07-29 09:56:45 +053013982#endif
Jeff Johnsone7245742012-09-05 17:12:55 -070013983 }
13984 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
13985 pAdapterNode = pNext;
13986 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
13987
Hanumantha Reddy Pothulada0fe362015-02-27 18:37:03 +053013988 end:
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -070013989 /* Free the allocated management frame */
13990 kfree(mgmt);
13991
Jeff Johnsone7245742012-09-05 17:12:55 -070013992 /* Retry until we unload or reach max count */
13993 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
13994 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
13995
13996 return status;
13997
13998}
13999/**---------------------------------------------------------------------------
14000 *
14001 * \brief wlan_hdd_restart_timer_cb
14002 *
14003 * Restart timer callback. An internal function.
14004 *
14005 * \param - User data:
14006 *
14007 * \return - None
14008 *
14009 * --------------------------------------------------------------------------*/
14010
14011void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
14012{
14013 hdd_context_t *pHddCtx = usrDataForCallback;
14014 wlan_hdd_framework_restart(pHddCtx);
14015 return;
14016
14017}
14018
14019
14020/**---------------------------------------------------------------------------
14021 *
14022 * \brief wlan_hdd_restart_driver
14023 *
14024 * This function sends an event to supplicant to restart the WLAN driver.
14025 *
14026 * This function is called from vos_wlanRestart.
14027 *
14028 * \param - pHddCtx
14029 *
14030 * \return - VOS_STATUS_SUCCESS: Success
14031 * VOS_STATUS_E_EMPTY: Adapter is Empty
14032 * VOS_STATUS_E_ALREADY: Request already in progress
14033
14034 * --------------------------------------------------------------------------*/
14035VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
14036{
14037 VOS_STATUS status = VOS_STATUS_SUCCESS;
14038
14039 /* A tight check to make sure reentrancy */
14040 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
14041 {
Mihir Shetefd528652014-06-23 19:07:50 +053014042 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnsone7245742012-09-05 17:12:55 -070014043 "%s: WLAN restart is already in progress", __func__);
14044
14045 return VOS_STATUS_E_ALREADY;
14046 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -070014047 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -080014048#ifdef HAVE_WCNSS_RESET_INTR
Siddharth Bhal864e7e82015-04-07 20:07:24 +053014049 wcnss_reset_fiq(TRUE);
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -070014050#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -070014051
Jeff Johnsone7245742012-09-05 17:12:55 -070014052 return status;
14053}
14054
Bhargav Shahd0715912015-10-01 18:17:37 +053014055/**
14056 * hdd_get_total_sessions() - provide total number of active sessions
14057 * @pHddCtx: Valid Global HDD context pointer
14058 *
14059 * This function iterates through pAdaptors and find the number of all active
14060 * sessions. This active sessions includes connected sta, p2p client and number
14061 * of client connected to sap/p2p go.
14062 *
14063 * Return: Total number of active sessions.
14064 */
14065v_U8_t hdd_get_total_sessions(hdd_context_t *pHddCtx)
14066{
14067 v_U8_t active_session = 0;
14068 hdd_station_ctx_t *pHddStaCtx;
14069 hdd_adapter_list_node_t *pAdapterNode, *pNext;
14070 hdd_adapter_t *pAdapter;
14071 VOS_STATUS status;
14072
14073 status = hdd_get_front_adapter(pHddCtx, &pAdapterNode);
14074 while (NULL != pAdapterNode && VOS_STATUS_SUCCESS == status) {
14075 pAdapter = pAdapterNode->pAdapter;
14076 switch (pAdapter->device_mode) {
14077 case VOS_STA_MODE:
14078 case VOS_P2P_CLIENT_MODE:
14079 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14080 if(eConnectionState_Associated == pHddStaCtx->conn_info.connState)
14081 active_session += 1;
14082 break;
14083 case VOS_STA_SAP_MODE:
14084 case VOS_P2P_GO_MODE:
14085 active_session += hdd_softap_get_connected_sta(pAdapter);
14086 break;
14087 default:
14088 break;
14089 }
14090
14091 status = hdd_get_next_adapter(pHddCtx, pAdapterNode, &pNext);
14092 pAdapterNode = pNext;
14093 }
14094
14095 return active_session;
14096}
14097
14098/**
14099 * hdd_set_delack_value() - Set delack value
14100 * @pHddCtx: Valid Global HDD context pointer
14101 * @next_rx_level: Value to set for delack
14102 *
14103 * This function compare present value and next value of delack. If the both
14104 * are diffrent then it sets next value .
14105 *
14106 * Return: void.
14107 */
14108void hdd_set_delack_value(hdd_context_t *pHddCtx, v_U32_t next_rx_level)
14109{
14110 if (pHddCtx->cur_rx_level != next_rx_level) {
14111 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_DEBUG,
14112 "%s: TCP DELACK trigger level %d",
14113 __func__, next_rx_level);
14114 mutex_lock(&pHddCtx->cur_rx_level_lock);
14115 pHddCtx->cur_rx_level = next_rx_level;
14116 mutex_unlock(&pHddCtx->cur_rx_level_lock);
14117 wlan_hdd_send_svc_nlink_msg(WLAN_SVC_WLAN_TP_IND, &next_rx_level,
14118 sizeof(next_rx_level));
14119 }
14120}
14121
14122/**
14123 * hdd_set_default_stop_delack_timer() - Start delack timer
14124 * @pHddCtx: Valid Global HDD context pointer
14125 *
14126 * This function stop delack timer and set delack value to default..
14127 *
14128 * Return: void.
14129 */
14130
14131void hdd_set_default_stop_delack_timer(hdd_context_t *pHddCtx)
14132{
14133 if (VOS_TIMER_STATE_RUNNING !=
14134 vos_timer_getCurrentState(&pHddCtx->delack_timer)) {
14135 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_DEBUG,
14136 "%s: Can not stop timer", __func__);
14137 return;
14138 }
14139
14140 vos_timer_stop(&pHddCtx->delack_timer);
14141 hdd_set_delack_value(pHddCtx, TP_IND_LOW);
14142}
14143
14144/**
14145 * hdd_start_delack_timer() - Start delack timer
14146 * @pHddCtx: Valid Global HDD context pointer
14147 *
14148 * This function starts the delack timer for tcpDelAckComputeInterval time
14149 * interval.The default timer value is 2 second.
14150 *
14151 * Return: void.
14152 */
14153void hdd_start_delack_timer(hdd_context_t *pHddCtx)
14154{
14155 if (VOS_TIMER_STATE_RUNNING ==
14156 vos_timer_getCurrentState(&pHddCtx->delack_timer)) {
14157 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_DEBUG,
14158 "%s: Timer is already running", __func__);
14159 return;
14160 }
14161
14162 vos_timer_start(&pHddCtx->delack_timer,
14163 pHddCtx->cfg_ini->tcpDelAckComputeInterval);
14164}
14165
14166/**
14167 * hdd_update_prev_rx_packet_count() - Update previous rx packet count
14168 * @pHddCtx: Valid Global HDD context pointer
14169 *
14170 * This function updates the prev_rx_packets count from the corresponding
14171 * pAdapter states. This prev_rx_packets will diffed with the packet count
14172 * at the end of delack timer. That can give number of RX packet is spacific
14173 * time.
14174 *
14175 * Return: void.
14176 */
14177void hdd_update_prev_rx_packet_count(hdd_context_t *pHddCtx)
14178{
14179 hdd_adapter_list_node_t *pAdapterNode, *pNext;
14180 hdd_adapter_t *pAdapter;
14181 VOS_STATUS status;
14182
14183 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
14184 while (NULL != pAdapterNode && VOS_STATUS_SUCCESS == status) {
14185 pAdapter = pAdapterNode->pAdapter;
14186 pAdapter->prev_rx_packets = pAdapter->stats.rx_packets;
14187 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
14188 pAdapterNode = pNext;
14189 }
14190}
14191
14192/**
14193 * hdd_manage_delack_timer() - start\stop delack timer
14194 * @pHddCtx: Valid Global HDD context pointer
14195 *
14196 * This function check the number of concerent session present, it starts the
14197 * delack timer if only one session is present.
14198 * In the case of BT_COEX and TDLS mode it blindly stop delack functionality.
14199 *
14200 * Return: void.
14201 */
14202void hdd_manage_delack_timer(hdd_context_t *pHddCtx)
14203{
14204 uint8_t sessions;
14205
14206 if (!pHddCtx->cfg_ini->enable_delack) {
14207 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_DEBUG,
14208 "%s: TCP DELACK is not enabled", __func__);
14209 return;
14210 }
14211
14212 /* Blindly stop timer of BTCOEX and TDLS Session is up */
14213 if (pHddCtx->mode != 0) {
14214 hdd_set_default_stop_delack_timer(pHddCtx);
14215 return;
14216 }
14217
14218 sessions = hdd_get_total_sessions(pHddCtx);
14219 if (sessions == 1) {
14220 hdd_update_prev_rx_packet_count(pHddCtx);
14221 hdd_start_delack_timer(pHddCtx);
14222 } else {
14223 hdd_set_default_stop_delack_timer(pHddCtx);
14224 }
14225}
14226
Mihir Shetee1093ba2014-01-21 20:13:32 +053014227/**---------------------------------------------------------------------------
14228 *
14229 * \brief wlan_hdd_init_channels
14230 *
14231 * This function is used to initialize the channel list in CSR
14232 *
14233 * This function is called from hdd_wlan_startup
14234 *
14235 * \param - pHddCtx: HDD context
14236 *
14237 * \return - VOS_STATUS_SUCCESS: Success
14238 * VOS_STATUS_E_FAULT: Failure reported by SME
14239
14240 * --------------------------------------------------------------------------*/
14241static VOS_STATUS wlan_hdd_init_channels(hdd_context_t *pHddCtx)
14242{
14243 eHalStatus status;
14244
14245 status = sme_InitChannels(pHddCtx->hHal);
14246 if (HAL_STATUS_SUCCESS(status))
14247 {
14248 return VOS_STATUS_SUCCESS;
14249 }
14250 else
14251 {
14252 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Channel initialization failed(%d)",
14253 __func__, status);
14254 return VOS_STATUS_E_FAULT;
14255 }
14256}
14257
Mihir Shete04206452014-11-20 17:50:58 +053014258#ifdef CONFIG_ENABLE_LINUX_REG
Agarwal Ashish6db9d532014-09-30 18:19:10 +053014259VOS_STATUS wlan_hdd_init_channels_for_cc(hdd_context_t *pHddCtx, driver_load_type init )
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053014260{
14261 eHalStatus status;
14262
Agarwal Ashish6db9d532014-09-30 18:19:10 +053014263 status = sme_InitChannelsForCC(pHddCtx->hHal, init);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053014264 if (HAL_STATUS_SUCCESS(status))
14265 {
14266 return VOS_STATUS_SUCCESS;
14267 }
14268 else
14269 {
14270 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Issue reg hint failed(%d)",
14271 __func__, status);
14272 return VOS_STATUS_E_FAULT;
14273 }
14274}
Mihir Shete04206452014-11-20 17:50:58 +053014275#endif
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -070014276/*
14277 * API to find if there is any STA or P2P-Client is connected
14278 */
14279VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
14280{
14281 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
14282}
Jeff Johnsone7245742012-09-05 17:12:55 -070014283
Mihir Shetee2ae82a2015-03-16 14:08:49 +053014284
14285/*
14286 * API to find if the firmware will send logs using DXE channel
14287 */
14288v_U8_t hdd_is_fw_logging_enabled(void)
14289{
14290 hdd_context_t *pHddCtx;
14291
14292 pHddCtx = vos_get_context(VOS_MODULE_ID_HDD,
14293 vos_get_global_context(VOS_MODULE_ID_HDD, NULL));
14294
Sachin Ahuja084313e2015-05-21 17:57:10 +053014295 return (pHddCtx && pHddCtx->cfg_ini->enableMgmtLogging);
Mihir Shetee2ae82a2015-03-16 14:08:49 +053014296}
14297
Agarwal Ashish57e84372014-12-05 18:26:53 +053014298/*
Mihir Shetebe94ebb2015-05-26 12:07:14 +053014299 * API to find if the firmware will send trace logs using DXE channel
14300 */
14301v_U8_t hdd_is_fw_ev_logging_enabled(void)
14302{
14303 hdd_context_t *pHddCtx;
14304
14305 pHddCtx = vos_get_context(VOS_MODULE_ID_HDD,
14306 vos_get_global_context(VOS_MODULE_ID_HDD, NULL));
14307
14308 return (pHddCtx && pHddCtx->cfg_ini->enableFWLogging);
14309}
14310/*
Agarwal Ashish57e84372014-12-05 18:26:53 +053014311 * API to find if there is any session connected
14312 */
14313VOS_STATUS hdd_is_any_session_connected(hdd_context_t *pHddCtx)
14314{
14315 return sme_is_any_session_connected(pHddCtx->hHal);
14316}
14317
14318
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053014319int wlan_hdd_scan_abort(hdd_adapter_t *pAdapter)
14320{
14321 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14322 hdd_scaninfo_t *pScanInfo = NULL;
Girish Gowli4bf7a632014-06-12 13:42:11 +053014323 long status = 0;
c_hpothua3d45d52015-01-05 14:11:17 +053014324 tSirAbortScanStatus abortScanStatus;
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053014325
14326 pScanInfo = &pHddCtx->scan_info;
Ratnam Rachuric7681132015-06-30 10:35:13 +053014327 INIT_COMPLETION(pScanInfo->abortscan_event_var);
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053014328 if (pScanInfo->mScanPending)
14329 {
c_hpothua3d45d52015-01-05 14:11:17 +053014330 abortScanStatus = hdd_abort_mac_scan(pHddCtx, pScanInfo->sessionId,
14331 eCSR_SCAN_ABORT_DEFAULT);
14332 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
14333 FL("abortScanStatus: %d"), abortScanStatus);
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053014334
c_hpothua3d45d52015-01-05 14:11:17 +053014335 /* If there is active scan command lets wait for the completion else
14336 * there is no need to wait as scan command might be in the SME pending
14337 * command list.
14338 */
14339 if (abortScanStatus == eSIR_ABORT_ACTIVE_SCAN_LIST_NOT_EMPTY)
14340 {
Mukul Sharmab392b642017-08-17 17:45:29 +053014341 status = wait_for_completion_timeout(
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053014342 &pScanInfo->abortscan_event_var,
14343 msecs_to_jiffies(5000));
c_hpothua3d45d52015-01-05 14:11:17 +053014344 if (0 >= status)
14345 {
14346 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Girish Gowli4bf7a632014-06-12 13:42:11 +053014347 "%s: Timeout or Interrupt occurred while waiting for abort"
14348 "scan, status- %ld", __func__, status);
c_hpothua3d45d52015-01-05 14:11:17 +053014349 return -ETIMEDOUT;
14350 }
14351 }
14352 else if (abortScanStatus == eSIR_ABORT_SCAN_FAILURE)
14353 {
14354 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
14355 FL("hdd_abort_mac_scan failed"));
14356 return -VOS_STATUS_E_FAILURE;
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053014357 }
14358 }
Girish Gowli4bf7a632014-06-12 13:42:11 +053014359 return 0;
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053014360}
14361
Abhishek Singh7d624e12015-11-30 14:29:27 +053014362/**
14363 * hdd_indicate_mgmt_frame() - Wrapper to indicate management frame to
14364 * user space
14365 * @frame_ind: Management frame data to be informed.
14366 *
14367 * This function is used to indicate management frame to
14368 * user space
14369 *
14370 * Return: None
14371 *
14372 */
14373void hdd_indicate_mgmt_frame(tSirSmeMgmtFrameInd *frame_ind)
14374{
14375 hdd_context_t *hdd_ctx = NULL;
14376 hdd_adapter_t *adapter = NULL;
14377 v_CONTEXT_t vos_context = NULL;
14378
14379 /* Get the global VOSS context.*/
14380 vos_context = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
14381 if (!vos_context) {
14382 hddLog(LOGE, FL("Global VOS context is Null"));
14383 return;
14384 }
14385 /* Get the HDD context.*/
14386 hdd_ctx =
14387 (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, vos_context );
14388
14389 if (0 != wlan_hdd_validate_context(hdd_ctx))
14390 {
14391 return;
14392 }
14393 adapter = hdd_get_adapter_by_sme_session_id(hdd_ctx,
14394 frame_ind->sessionId);
14395
14396 if ((NULL != adapter) &&
14397 (WLAN_HDD_ADAPTER_MAGIC == adapter->magic))
14398 __hdd_indicate_mgmt_frame(adapter,
14399 frame_ind->frameLen,
14400 frame_ind->frameBuf,
14401 frame_ind->frameType,
14402 frame_ind->rxChan,
14403 frame_ind->rxRssi);
14404 return;
14405
14406}
14407
c_hpothu225aa7c2014-10-22 17:45:13 +053014408VOS_STATUS wlan_hdd_cancel_remain_on_channel(hdd_context_t *pHddCtx)
14409{
14410 hdd_adapter_t *pAdapter;
14411 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
14412 VOS_STATUS vosStatus;
14413
14414 vosStatus = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
14415 while (NULL != pAdapterNode && VOS_STATUS_E_EMPTY != vosStatus)
14416 {
14417 pAdapter = pAdapterNode->pAdapter;
14418 if (NULL != pAdapter)
14419 {
14420 if (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode ||
14421 WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ||
14422 WLAN_HDD_P2P_GO == pAdapter->device_mode)
14423 {
14424 hddLog(LOG1, FL("abort ROC deviceMode: %d"),
14425 pAdapter->device_mode);
14426 if (VOS_STATUS_SUCCESS !=
14427 wlan_hdd_cancel_existing_remain_on_channel(pAdapter))
14428 {
14429 hddLog(LOGE, FL("failed to abort ROC"));
14430 return VOS_STATUS_E_FAILURE;
14431 }
14432 }
14433 }
14434 vosStatus = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
14435 pAdapterNode = pNext;
14436 }
14437 return VOS_STATUS_SUCCESS;
14438}
Mahesh A Saptasagard477b092015-02-06 15:12:16 +053014439
Mihir Shete0be28772015-02-17 18:42:14 +053014440hdd_remain_on_chan_ctx_t *hdd_get_remain_on_channel_ctx(hdd_context_t *pHddCtx)
14441{
14442 hdd_adapter_t *pAdapter;
14443 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
14444 hdd_cfg80211_state_t *cfgState;
14445 hdd_remain_on_chan_ctx_t *pRemainChanCtx = NULL;
14446 VOS_STATUS vosStatus;
14447
14448 vosStatus = hdd_get_front_adapter (pHddCtx, &pAdapterNode);
14449 while (NULL != pAdapterNode && VOS_STATUS_E_EMPTY != vosStatus)
14450 {
14451 pAdapter = pAdapterNode->pAdapter;
14452 if (NULL != pAdapter)
14453 {
14454 cfgState = WLAN_HDD_GET_CFG_STATE_PTR(pAdapter);
14455 pRemainChanCtx = cfgState->remain_on_chan_ctx;
14456 if (pRemainChanCtx)
14457 break;
14458 }
14459 vosStatus = hdd_get_next_adapter (pHddCtx, pAdapterNode, &pNext);
14460 pAdapterNode = pNext;
14461 }
14462 return pRemainChanCtx;
14463}
14464
Padma, Santhosh Kumar778d8382015-03-04 17:41:22 +053014465/**
14466 * wlan_hdd_handle_dfs_chan_scan () - handles disable/enable DFS channels
14467 *
14468 * @pHddCtx: HDD context within host driver
14469 * @dfsScanMode: dfsScanMode passed from ioctl
14470 *
14471 */
14472
14473VOS_STATUS wlan_hdd_handle_dfs_chan_scan(hdd_context_t *pHddCtx,
14474 tANI_U8 dfsScanMode)
14475{
14476 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
14477 hdd_adapter_t *pAdapter;
14478 VOS_STATUS vosStatus;
14479 hdd_station_ctx_t *pHddStaCtx;
14480 eHalStatus status = eHAL_STATUS_SUCCESS;
14481
14482 if(!pHddCtx)
14483 {
14484 hddLog(LOGE, FL("HDD context is Null"));
14485 return eHAL_STATUS_FAILURE;
14486 }
14487
14488 if (pHddCtx->scan_info.mScanPending)
14489 {
14490 hddLog(LOG1, FL("Aborting scan for sessionId: %d"),
14491 pHddCtx->scan_info.sessionId);
14492 hdd_abort_mac_scan(pHddCtx,
14493 pHddCtx->scan_info.sessionId,
14494 eCSR_SCAN_ABORT_DEFAULT);
14495 }
14496
14497 if (!dfsScanMode)
14498 {
14499 vosStatus = hdd_get_front_adapter( pHddCtx, &pAdapterNode);
14500 while ((NULL != pAdapterNode) &&
14501 (VOS_STATUS_SUCCESS == vosStatus))
14502 {
14503 pAdapter = pAdapterNode->pAdapter;
14504
14505 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
14506 {
14507 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14508
14509 if(!pHddStaCtx)
14510 {
14511 hddLog(LOGE, FL("HDD STA context is Null"));
14512 return eHAL_STATUS_FAILURE;
14513 }
14514
14515 /* if STA is already connected on DFS channel,
14516 disconnect immediately*/
14517 if (hdd_connIsConnected(pHddStaCtx) &&
14518 (NV_CHANNEL_DFS ==
14519 vos_nv_getChannelEnabledState(
14520 pHddStaCtx->conn_info.operationChannel)))
14521 {
14522 status = sme_RoamDisconnect(pHddCtx->hHal,
14523 pAdapter->sessionId,
14524 eCSR_DISCONNECT_REASON_UNSPECIFIED);
14525 hddLog(LOG1, FL("Client connected on DFS channel %d,"
14526 "sme_RoamDisconnect returned with status: %d"
14527 "for sessionid: %d"), pHddStaCtx->conn_info.
14528 operationChannel, status, pAdapter->sessionId);
14529 }
14530 }
14531
14532 vosStatus = hdd_get_next_adapter(pHddCtx, pAdapterNode,
14533 &pNext);
14534 pAdapterNode = pNext;
14535 }
14536 }
14537
14538 sme_UpdateDFSScanMode(pHddCtx->hHal, dfsScanMode);
14539 sme_UpdateDFSRoamMode(pHddCtx->hHal,
14540 (dfsScanMode != DFS_CHNL_SCAN_DISABLED));
14541
14542 status = sme_HandleDFSChanScan(pHddCtx->hHal);
14543 if (!HAL_STATUS_SUCCESS(status))
14544 {
14545 hddLog(LOGE,
14546 FL("Failed in sme_HandleDFSChanScan (err=%d)"), status);
14547 return status;
14548 }
14549
14550 return status;
14551}
14552
Nirav Shah7e3c8132015-06-22 23:51:42 +053014553static int hdd_log2_ceil(unsigned value)
14554{
14555 /* need to switch to unsigned math so that negative values
14556 * will right-shift towards 0 instead of -1
14557 */
14558 unsigned tmp = value;
14559 int log2 = -1;
14560
14561 if (value == 0)
14562 return 0;
14563
14564 while (tmp) {
14565 log2++;
14566 tmp >>= 1;
14567 }
14568 if (1U << log2 != value)
14569 log2++;
14570
14571 return log2;
14572}
14573
14574/**
14575 * hdd_sta_id_hash_attach() - initialize sta id to macaddr hash
14576 * @pAdapter: adapter handle
14577 *
14578 * Return: vos status
14579 */
14580VOS_STATUS hdd_sta_id_hash_attach(hdd_adapter_t *pAdapter)
14581{
14582 int hash_elem, log2, i;
14583
14584 spin_lock_bh( &pAdapter->sta_hash_lock);
14585 if (pAdapter->is_sta_id_hash_initialized == VOS_TRUE) {
14586 spin_unlock_bh( &pAdapter->sta_hash_lock);
14587 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
14588 "%s: hash already attached for session id %d",
14589 __func__, pAdapter->sessionId);
14590 return VOS_STATUS_SUCCESS;
14591 }
14592 spin_unlock_bh( &pAdapter->sta_hash_lock);
14593
14594 hash_elem = WLAN_MAX_STA_COUNT;
14595 hash_elem *= HDD_STA_ID_HASH_MULTIPLIER;
14596 log2 = hdd_log2_ceil(hash_elem);
14597 hash_elem = 1 << log2;
14598
14599 pAdapter->sta_id_hash.mask = hash_elem - 1;
14600 pAdapter->sta_id_hash.idx_bits = log2;
14601 pAdapter->sta_id_hash.bins =
14602 vos_mem_malloc(hash_elem *sizeof(hdd_list_t));
14603 if (!pAdapter->sta_id_hash.bins) {
14604 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
14605 "%s: malloc failed for session %d",
14606 __func__, pAdapter->sessionId);
14607 return VOS_STATUS_E_NOMEM;
14608 }
14609
14610 for (i = 0; i < hash_elem; i++)
14611 hdd_list_init(&pAdapter->sta_id_hash.bins[i], WLAN_MAX_STA_COUNT);
14612
14613 spin_lock_bh( &pAdapter->sta_hash_lock);
14614 pAdapter->is_sta_id_hash_initialized = VOS_TRUE;
14615 spin_unlock_bh( &pAdapter->sta_hash_lock);
14616 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
14617 "%s: Station ID Hash attached for session id %d",
14618 __func__, pAdapter->sessionId);
14619
14620 return VOS_STATUS_SUCCESS;
14621}
14622
14623/**
14624 * hdd_sta_id_hash_detach() - deinit sta_id to macaddr hash
14625 * @pAdapter: adapter handle
14626 *
14627 * Return: vos status
14628 */
14629VOS_STATUS hdd_sta_id_hash_detach(hdd_adapter_t *pAdapter)
14630{
14631 int hash_elem, i;
14632 v_SIZE_t size;
14633
14634 spin_lock_bh( &pAdapter->sta_hash_lock);
14635 if (pAdapter->is_sta_id_hash_initialized != VOS_TRUE) {
14636 spin_unlock_bh( &pAdapter->sta_hash_lock);
14637 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
14638 "%s: hash not initialized for session id %d",
14639 __func__, pAdapter->sessionId);
14640 return VOS_STATUS_SUCCESS;
14641 }
14642
14643 pAdapter->is_sta_id_hash_initialized = VOS_FALSE;
14644 spin_unlock_bh( &pAdapter->sta_hash_lock);
14645
14646 hash_elem = 1 << pAdapter->sta_id_hash.idx_bits;
14647
14648 /* free all station info*/
14649 for (i = 0; i < hash_elem; i++) {
14650 hdd_list_size(&pAdapter->sta_id_hash.bins[i], &size);
14651 if (size != 0) {
14652 VOS_STATUS status;
14653 hdd_staid_hash_node_t *sta_info_node = NULL;
14654 hdd_staid_hash_node_t *next_node = NULL;
14655 status = hdd_list_peek_front ( &pAdapter->sta_id_hash.bins[i],
14656 (hdd_list_node_t**) &sta_info_node );
14657
14658 while ( NULL != sta_info_node && VOS_STATUS_SUCCESS == status )
14659 {
14660 status = hdd_list_remove_node( &pAdapter->sta_id_hash.bins[i],
14661 &sta_info_node->node);
14662 vos_mem_free(sta_info_node);
14663
14664 status = hdd_list_peek_next (&pAdapter->sta_id_hash.bins[i],
14665 (hdd_list_node_t*)sta_info_node,
14666 (hdd_list_node_t**)&next_node);
14667 sta_info_node = next_node;
14668 }
14669 }
14670 }
14671
14672 vos_mem_free(pAdapter->sta_id_hash.bins);
14673 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
14674 "%s: Station ID Hash detached for session id %d",
14675 __func__, pAdapter->sessionId);
14676 return VOS_STATUS_SUCCESS;
14677}
14678
14679/**
14680 * hdd_sta_id_hash_calculate_index() - derive index from macaddr
14681 * @pAdapter: adapter handle
14682 * @mac_addr_in: input mac address
14683 *
14684 * Return: index derived from mac address
14685 */
14686int hdd_sta_id_hash_calculate_index(hdd_adapter_t *pAdapter,
14687 v_MACADDR_t *mac_addr_in)
14688{
14689 uint16 index;
14690 struct hdd_align_mac_addr_t * mac_addr =
14691 (struct hdd_align_mac_addr_t *)mac_addr_in;
14692
14693 index = mac_addr->bytes_ab ^
14694 mac_addr->bytes_cd ^ mac_addr->bytes_ef;
14695 index ^= index >> pAdapter->sta_id_hash.idx_bits;
14696 index &= pAdapter->sta_id_hash.mask;
14697 return index;
14698}
14699
14700/**
14701 * hdd_sta_id_hash_add_entry() - add entry in hash
14702 * @pAdapter: adapter handle
14703 * @sta_id: station id
14704 * @mac_addr: mac address
14705 *
14706 * Return: vos status
14707 */
14708VOS_STATUS hdd_sta_id_hash_add_entry(hdd_adapter_t *pAdapter,
14709 v_U8_t sta_id, v_MACADDR_t *mac_addr)
14710{
14711 uint16 index;
14712 hdd_staid_hash_node_t *sta_info_node = NULL;
14713
Nirav Shah7e3c8132015-06-22 23:51:42 +053014714 index = hdd_sta_id_hash_calculate_index(pAdapter, mac_addr);
14715 sta_info_node = vos_mem_malloc(sizeof(hdd_staid_hash_node_t));
14716 if (!sta_info_node) {
Nirav Shah7e3c8132015-06-22 23:51:42 +053014717 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
14718 "%s: malloc failed", __func__);
14719 return VOS_STATUS_E_NOMEM;
14720 }
14721
14722 sta_info_node->sta_id = sta_id;
14723 vos_mem_copy(&sta_info_node->mac_addr, mac_addr, sizeof(v_MACADDR_t));
14724
Nirav Shah303ed5c2015-08-24 10:29:25 +053014725 spin_lock_bh( &pAdapter->sta_hash_lock);
14726 if (pAdapter->is_sta_id_hash_initialized != VOS_TRUE) {
14727 spin_unlock_bh( &pAdapter->sta_hash_lock);
14728 vos_mem_free(sta_info_node);
14729 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
14730 "%s: hash is not initialized for session id %d",
14731 __func__, pAdapter->sessionId);
14732 return VOS_STATUS_E_FAILURE;
14733 }
14734
Nirav Shah7e3c8132015-06-22 23:51:42 +053014735 hdd_list_insert_back ( &pAdapter->sta_id_hash.bins[index],
14736 (hdd_list_node_t*) sta_info_node );
14737 spin_unlock_bh( &pAdapter->sta_hash_lock);
14738 return VOS_STATUS_SUCCESS;
14739}
14740
14741/**
14742 * hdd_sta_id_hash_remove_entry() - remove entry from hash
14743 * @pAdapter: adapter handle
14744 * @sta_id: station id
14745 * @mac_addr: mac address
14746 *
14747 * Return: vos status
14748 */
14749VOS_STATUS hdd_sta_id_hash_remove_entry(hdd_adapter_t *pAdapter,
14750 v_U8_t sta_id, v_MACADDR_t *mac_addr)
14751{
14752 uint16 index;
14753 VOS_STATUS status;
14754 hdd_staid_hash_node_t *sta_info_node = NULL;
14755 hdd_staid_hash_node_t *next_node = NULL;
14756
14757 spin_lock_bh( &pAdapter->sta_hash_lock);
14758 if (pAdapter->is_sta_id_hash_initialized != VOS_TRUE) {
14759 spin_unlock_bh( &pAdapter->sta_hash_lock);
14760 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
14761 "%s: hash is not initialized for session id %d",
14762 __func__, pAdapter->sessionId);
14763 return VOS_STATUS_E_FAILURE;
14764 }
14765
14766 index = hdd_sta_id_hash_calculate_index(pAdapter, mac_addr);
14767 status = hdd_list_peek_front ( &pAdapter->sta_id_hash.bins[index],
14768 (hdd_list_node_t**) &sta_info_node );
14769
14770 while ( NULL != sta_info_node && VOS_STATUS_SUCCESS == status )
14771 {
14772 if (sta_info_node->sta_id == sta_id) {
14773 status = hdd_list_remove_node( &pAdapter->sta_id_hash.bins[index],
14774 &sta_info_node->node);
14775 vos_mem_free(sta_info_node);
14776 break;
14777 }
14778 status = hdd_list_peek_next (&pAdapter->sta_id_hash.bins[index],
14779 (hdd_list_node_t*)sta_info_node, (hdd_list_node_t**)&next_node);
14780 sta_info_node = next_node;
14781 }
14782 spin_unlock_bh( &pAdapter->sta_hash_lock);
14783 return status;
14784}
14785
14786/**
14787 * hdd_sta_id_find_from_mac_addr() - find sta id from mac address
14788 * @pAdapter: adapter handle
14789 * @mac_addr_in: mac address
14790 *
14791 * Return: station id
14792 */
14793int hdd_sta_id_find_from_mac_addr(hdd_adapter_t *pAdapter,
14794 v_MACADDR_t *mac_addr_in)
14795{
14796 uint8 is_found = 0;
14797 uint8 sta_id = HDD_WLAN_INVALID_STA_ID;
14798 uint16 index;
14799 VOS_STATUS status;
14800 hdd_staid_hash_node_t *sta_info_node = NULL;
14801 hdd_staid_hash_node_t *next_node = NULL;
14802
14803 spin_lock_bh( &pAdapter->sta_hash_lock);
14804 if (pAdapter->is_sta_id_hash_initialized != VOS_TRUE) {
14805 spin_unlock_bh( &pAdapter->sta_hash_lock);
Bhargav Shahce3b32c2015-08-10 12:29:24 +053014806 hddLog(VOS_TRACE_LEVEL_INFO,
Nirav Shah7e3c8132015-06-22 23:51:42 +053014807 FL("hash is not initialized for session id %d"),
14808 pAdapter->sessionId);
14809 return HDD_WLAN_INVALID_STA_ID;
14810 }
14811
14812 index = hdd_sta_id_hash_calculate_index(pAdapter, mac_addr_in);
14813 status = hdd_list_peek_front ( &pAdapter->sta_id_hash.bins[index],
14814 (hdd_list_node_t**) &sta_info_node );
14815
14816 while ( NULL != sta_info_node && VOS_STATUS_SUCCESS == status )
14817 {
14818 if (vos_mem_compare(&sta_info_node->mac_addr,
14819 mac_addr_in, sizeof(v_MACADDR_t))) {
14820 is_found = 1;
14821 sta_id = sta_info_node->sta_id;
14822 break;
14823 }
14824 status = hdd_list_peek_next (&pAdapter->sta_id_hash.bins[index],
14825 (hdd_list_node_t*)sta_info_node,
14826 (hdd_list_node_t**)&next_node);
14827 sta_info_node = next_node;
14828 }
14829 spin_unlock_bh( &pAdapter->sta_hash_lock);
14830 return sta_id;
14831}
14832
c_manjeecfd1efb2015-09-25 19:32:34 +053014833/*FW memory dump feature*/
14834/**
14835 * This structure hold information about the /proc file
14836 *
14837 */
14838static struct proc_dir_entry *proc_file, *proc_dir;
14839
14840/**
14841 * memdump_read() - perform read operation in memory dump proc file
14842 *
14843 * @file - handle for the proc file.
14844 * @buf - pointer to user space buffer.
14845 * @count - number of bytes to be read.
14846 * @pos - offset in the from buffer.
14847 *
14848 * This function performs read operation for the memory dump proc file.
14849 *
14850 * Return: number of bytes read on success, error code otherwise.
14851 */
14852static ssize_t memdump_read(struct file *file, char __user *buf,
14853 size_t count, loff_t *pos)
14854{
14855 int status;
14856 hdd_context_t *hdd_ctx = (hdd_context_t *)PDE_DATA(file_inode(file));
14857 size_t ret_count;
c_manjeef1495642015-10-13 18:35:01 +053014858 loff_t bytes_left;
c_manjeecfd1efb2015-09-25 19:32:34 +053014859 ENTER();
14860
14861 hddLog(LOG1, FL("Read req for size:%zu pos:%llu"), count, *pos);
14862 status = wlan_hdd_validate_context(hdd_ctx);
14863 if (0 != status) {
14864 return -EINVAL;
14865 }
14866
14867 if (!wlan_fwr_mem_dump_test_and_set_read_allowed_bit()) {
14868 hddLog(LOGE, FL("Current mem dump request timed out/failed"));
14869 return -EINVAL;
14870 }
14871
14872 /* run fs_read_handler in an atomic context*/
14873 vos_ssr_protect(__func__);
c_manjeef1495642015-10-13 18:35:01 +053014874 ret_count = wlan_fwr_mem_dump_fsread_handler( buf, count, pos, &bytes_left);
14875 if(bytes_left == 0)
c_manjeecfd1efb2015-09-25 19:32:34 +053014876 {
14877 /*Free the fwr mem dump buffer */
14878 wlan_free_fwr_mem_dump_buffer();
14879 wlan_set_fwr_mem_dump_state(FW_MEM_DUMP_IDLE);
c_manjeef1495642015-10-13 18:35:01 +053014880 ret_count=0;
c_manjeecfd1efb2015-09-25 19:32:34 +053014881 }
14882 /*if SSR/unload code is waiting for memdump_read to finish,signal it*/
14883 vos_ssr_unprotect(__func__);
14884 EXIT();
14885 return ret_count;
14886}
14887
14888/**
14889 * struct memdump_fops - file operations for memory dump feature
14890 * @read - read function for memory dump operation.
14891 *
14892 * This structure initialize the file operation handle for memory
14893 * dump feature
14894 */
14895static const struct file_operations memdump_fops = {
14896 read: memdump_read
14897};
14898
14899/*
14900* wlan_hdd_fw_mem_dump_cb : callback for Fw mem dump request
14901* To be passed by HDD to WDA and called upon receiving of response
14902* from firmware
14903* @fwMemDumpReqContext : memory dump request context
14904* @dump_rsp : dump response from HAL
14905* Returns none
14906*/
14907void wlan_hdd_fw_mem_dump_cb(void *fwMemDumpReqContext,
14908 tAniFwrDumpRsp *dump_rsp)
14909{
c_manjeef1495642015-10-13 18:35:01 +053014910 struct hdd_fw_mem_dump_req_ctx *pHddFwMemDumpCtx = (struct hdd_fw_mem_dump_req_ctx *)fwMemDumpReqContext;
c_manjeecfd1efb2015-09-25 19:32:34 +053014911
c_manjeef1495642015-10-13 18:35:01 +053014912 ENTER();
14913 spin_lock(&hdd_context_lock);
14914 if(!pHddFwMemDumpCtx || (FW_MEM_DUMP_MAGIC != pHddFwMemDumpCtx->magic)) {
14915 spin_unlock(&hdd_context_lock);
14916 return;
14917 }
14918 /* report the status to requesting function and free mem.*/
c_manjeecfd1efb2015-09-25 19:32:34 +053014919 if (dump_rsp->dump_status != eHAL_STATUS_SUCCESS) {
c_manjeef1495642015-10-13 18:35:01 +053014920 hddLog(LOGE, FL("fw dump request declined by fwr"));
14921 //set the request completion variable
14922 complete(&(pHddFwMemDumpCtx->req_completion));
c_manjeecfd1efb2015-09-25 19:32:34 +053014923 //Free the allocated fwr dump
14924 wlan_free_fwr_mem_dump_buffer();
14925 wlan_set_fwr_mem_dump_state(FW_MEM_DUMP_IDLE);
c_manjeecfd1efb2015-09-25 19:32:34 +053014926 }
c_manjeef1495642015-10-13 18:35:01 +053014927 else {
14928 hddLog(LOG1, FL("fw dump request accepted by fwr"));
14929 /* register the HDD callback which will be called by SVC */
14930 wlan_set_svc_fw_mem_dump_req_cb((void*)wlan_hdd_fw_mem_dump_req_cb,(void*)pHddFwMemDumpCtx);
14931 }
14932 spin_unlock(&hdd_context_lock);
c_manjeecfd1efb2015-09-25 19:32:34 +053014933 EXIT();
14934
14935}
14936
14937/**
14938 * memdump_procfs_remove() - Remove file/dir under procfs for memory dump
14939 *
14940 * This function removes file/dir under proc file system that was
14941 * processing firmware memory dump
14942 *
14943 * Return: None
14944 */
14945static void memdump_procfs_remove(void)
14946{
14947 remove_proc_entry(PROCFS_MEMDUMP_NAME, proc_dir);
14948 hddLog(LOG1 , FL("/proc/%s/%s removed\n"),
14949 PROCFS_MEMDUMP_DIR, PROCFS_MEMDUMP_NAME);
14950 remove_proc_entry(PROCFS_MEMDUMP_DIR, NULL);
14951 hddLog(LOG1 , FL("/proc/%s removed\n"), PROCFS_MEMDUMP_DIR);
14952}
14953
14954/**
14955 * memdump_procfs_init() - Initialize procfs for memory dump
14956 *
14957 * @vos_ctx - Global vos context.
14958 *
14959 * This function create file under proc file system to be used later for
14960 * processing firmware memory dump
14961 *
14962 * Return: 0 on success, error code otherwise.
14963 */
14964static int memdump_procfs_init(void *vos_ctx)
14965{
14966 hdd_context_t *hdd_ctx;
14967
14968 hdd_ctx = vos_get_context(VOS_MODULE_ID_HDD, vos_ctx);
14969 if (!hdd_ctx) {
14970 hddLog(LOGE , FL("Invalid HDD context"));
14971 return -EINVAL;
14972 }
14973
14974 proc_dir = proc_mkdir(PROCFS_MEMDUMP_DIR, NULL);
14975 if (proc_dir == NULL) {
14976 remove_proc_entry(PROCFS_MEMDUMP_DIR, NULL);
14977 hddLog(LOGE , FL("Error: Could not initialize /proc/%s"),
14978 PROCFS_MEMDUMP_DIR);
14979 return -ENOMEM;
14980 }
14981
14982 proc_file = proc_create_data(PROCFS_MEMDUMP_NAME,
14983 S_IRUSR | S_IWUSR, proc_dir,
14984 &memdump_fops, hdd_ctx);
14985 if (proc_file == NULL) {
14986 remove_proc_entry(PROCFS_MEMDUMP_NAME, proc_dir);
14987 hddLog(LOGE , FL("Error: Could not initialize /proc/%s"),
14988 PROCFS_MEMDUMP_NAME);
14989 return -ENOMEM;
14990 }
14991
14992 hddLog(LOG1 , FL("/proc/%s/%s created"),
14993 PROCFS_MEMDUMP_DIR, PROCFS_MEMDUMP_NAME);
14994
14995 return 0;
14996}
14997
14998/**
14999 * memdump_init() - Initialization function for memory dump feature
15000 *
15001 * This function creates proc file for memdump feature and registers
15002 * HDD callback function with SME.
15003 *
15004 * Return - 0 on success, error otherwise
15005 */
15006int memdump_init(void)
15007{
15008 hdd_context_t *hdd_ctx;
15009 void *vos_ctx;
15010 int status = 0;
15011
15012 vos_ctx = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
15013 if (!vos_ctx) {
15014 hddLog(LOGE, FL("Invalid VOS context"));
15015 return -EINVAL;
15016 }
15017
15018 hdd_ctx = vos_get_context(VOS_MODULE_ID_HDD, vos_ctx);
15019 if (!hdd_ctx) {
15020 hddLog(LOGE , FL("Invalid HDD context"));
15021 return -EINVAL;
15022 }
15023
15024 status = memdump_procfs_init(vos_ctx);
15025 if (status) {
15026 hddLog(LOGE , FL("Failed to create proc file"));
15027 return status;
15028 }
15029
15030 return 0;
15031}
15032
15033/**
15034 * memdump_deinit() - De initialize memdump feature
15035 *
15036 * This function removes proc file created for memdump feature.
15037 *
15038 * Return: None
15039 */
15040int memdump_deinit(void)
15041{
15042 hdd_context_t *hdd_ctx;
15043 void *vos_ctx;
15044
15045 vos_ctx = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
15046 if (!vos_ctx) {
15047 hddLog(LOGE, FL("Invalid VOS context"));
15048 return -EINVAL;
15049 }
15050
15051 hdd_ctx = vos_get_context(VOS_MODULE_ID_HDD, vos_ctx);
15052 if(!hdd_ctx) {
15053 hddLog(LOGE , FL("Invalid HDD context"));
15054 return -EINVAL;
15055 }
15056
15057 memdump_procfs_remove();
15058 return 0;
15059}
15060
15061/**
15062 * wlan_hdd_fw_mem_dump_req(pHddCtx) - common API(cfg80211/ioctl) for requesting fw mem dump to SME
15063 * Return: HAL status
15064 */
15065
15066int wlan_hdd_fw_mem_dump_req(hdd_context_t * pHddCtx)
15067{
15068 tAniFwrDumpReq fw_mem_dump_req={0};
c_manjeef1495642015-10-13 18:35:01 +053015069 struct hdd_fw_mem_dump_req_ctx fw_mem_dump_ctx;
c_manjeecfd1efb2015-09-25 19:32:34 +053015070 eHalStatus status = eHAL_STATUS_FAILURE;
Abhishek Singh4eca9822015-12-09 18:07:34 +053015071 int ret=0, result;
c_manjeecfd1efb2015-09-25 19:32:34 +053015072 ENTER();
c_manjeef1495642015-10-13 18:35:01 +053015073
c_manjeecfd1efb2015-09-25 19:32:34 +053015074 /*Check whether a dump request is already going on
15075 *Caution this function will free previously held memory if new dump request is allowed*/
15076 if (!wlan_fwr_mem_dump_test_and_set_write_allowed_bit()) {
15077 hddLog(LOGE, FL("Fw memdump already in progress"));
15078 return -EBUSY;
15079 }
15080 //Allocate memory for fw mem dump buffer
15081 ret = wlan_fwr_mem_dump_buffer_allocation();
15082 if(ret == -EFAULT)
15083 {
15084 hddLog(LOGE, FL("Fwr mem dump not supported by FW"));
15085 return ret;
15086 }
15087 if (0 != ret) {
15088 hddLog(LOGE, FL("Fwr mem Allocation failed"));
15089 return -ENOMEM;
15090 }
c_manjeef1495642015-10-13 18:35:01 +053015091 init_completion(&fw_mem_dump_ctx.req_completion);
15092 fw_mem_dump_ctx.magic = FW_MEM_DUMP_MAGIC;
15093 fw_mem_dump_ctx.status = false;
15094
c_manjeecfd1efb2015-09-25 19:32:34 +053015095 fw_mem_dump_req.fwMemDumpReqCallback = wlan_hdd_fw_mem_dump_cb;
c_manjeef1495642015-10-13 18:35:01 +053015096 fw_mem_dump_req.fwMemDumpReqContext = &fw_mem_dump_ctx;
c_manjeecfd1efb2015-09-25 19:32:34 +053015097 status = sme_FwMemDumpReq(pHddCtx->hHal, &fw_mem_dump_req);
15098 if(eHAL_STATUS_SUCCESS != status)
15099 {
15100 hddLog(VOS_TRACE_LEVEL_ERROR,
15101 "%s: fw_mem_dump_req failed ", __func__);
15102 wlan_free_fwr_mem_dump_buffer();
c_manjeef1495642015-10-13 18:35:01 +053015103 ret = -EFAULT;
15104 goto cleanup;
c_manjeecfd1efb2015-09-25 19:32:34 +053015105 }
c_manjeef1495642015-10-13 18:35:01 +053015106 /*wait for fw mem dump completion to send event to userspace*/
Abhishek Singh4eca9822015-12-09 18:07:34 +053015107 result =
15108 wait_for_completion_timeout(&fw_mem_dump_ctx.req_completion,
15109 msecs_to_jiffies(FW_MEM_DUMP_TIMEOUT_MS));
15110 if (0 >= result )
c_manjeef1495642015-10-13 18:35:01 +053015111 {
15112 hddLog(VOS_TRACE_LEVEL_ERROR,
Abhishek Singh4eca9822015-12-09 18:07:34 +053015113 "%s: fw_mem_dump_req timeout %d ", __func__,result);
15114 ret = -ETIMEDOUT;
c_manjeef1495642015-10-13 18:35:01 +053015115 }
15116cleanup:
15117 spin_lock(&hdd_context_lock);
15118 fw_mem_dump_ctx.magic = 0;
Abhishek Singh4eca9822015-12-09 18:07:34 +053015119 if(!ret && !fw_mem_dump_ctx.status)
15120 ret = -EFAULT;
c_manjeef1495642015-10-13 18:35:01 +053015121 spin_unlock(&hdd_context_lock);
c_manjeecfd1efb2015-09-25 19:32:34 +053015122
c_manjeef1495642015-10-13 18:35:01 +053015123 EXIT();
Abhishek Singh4eca9822015-12-09 18:07:34 +053015124 return ret;
c_manjeef1495642015-10-13 18:35:01 +053015125}
15126
15127/**
15128 * HDD callback which will be called by SVC to indicate mem dump completion.
15129 */
15130void wlan_hdd_fw_mem_dump_req_cb(struct hdd_fw_mem_dump_req_ctx* pHddFwMemDumpCtx)
15131{
15132 if (!pHddFwMemDumpCtx) {
15133 hddLog(VOS_TRACE_LEVEL_ERROR,
15134 "%s: HDD context not valid ", __func__);
15135 return;
15136 }
15137 spin_lock(&hdd_context_lock);
15138 /* check the req magic and set status */
15139 if (pHddFwMemDumpCtx->magic == FW_MEM_DUMP_MAGIC)
15140 {
15141 pHddFwMemDumpCtx->status = true;
15142 //signal the completion
15143 complete(&(pHddFwMemDumpCtx->req_completion));
15144 }
15145 else
15146 {
15147 hddLog(VOS_TRACE_LEVEL_ERROR,
15148 "%s: fw mem dump request possible timeout ", __func__);
15149 }
15150 spin_unlock(&hdd_context_lock);
c_manjeecfd1efb2015-09-25 19:32:34 +053015151}
15152
Mahesh A Saptasagar67ab9222015-10-21 15:38:41 +053015153void hdd_initialize_adapter_common(hdd_adapter_t *pAdapter)
15154{
15155 if (NULL == pAdapter)
15156 {
15157 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: pAdapter is NULL ", __func__);
15158 return;
15159 }
15160 init_completion(&pAdapter->session_open_comp_var);
15161 init_completion(&pAdapter->session_close_comp_var);
15162 init_completion(&pAdapter->disconnect_comp_var);
15163 init_completion(&pAdapter->linkup_event_var);
15164 init_completion(&pAdapter->cancel_rem_on_chan_var);
15165 init_completion(&pAdapter->rem_on_chan_ready_event);
15166 init_completion(&pAdapter->pno_comp_var);
15167#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
15168 init_completion(&pAdapter->offchannel_tx_event);
15169#endif
15170 init_completion(&pAdapter->tx_action_cnf_event);
15171#ifdef FEATURE_WLAN_TDLS
15172 init_completion(&pAdapter->tdls_add_station_comp);
15173 init_completion(&pAdapter->tdls_del_station_comp);
15174 init_completion(&pAdapter->tdls_mgmt_comp);
15175 init_completion(&pAdapter->tdls_link_establish_req_comp);
15176#endif
15177
15178#ifdef WLAN_FEATURE_RMC
15179 init_completion(&pAdapter->ibss_peer_info_comp);
15180#endif /* WLAN_FEATURE_RMC */
15181 init_completion(&pAdapter->ula_complete);
15182 init_completion(&pAdapter->change_country_code);
15183
15184#ifdef FEATURE_WLAN_BATCH_SCAN
15185 init_completion(&pAdapter->hdd_set_batch_scan_req_var);
15186 init_completion(&pAdapter->hdd_get_batch_scan_req_var);
15187#endif
Kapil Gupta2b44acb2016-12-30 16:49:51 +053015188 init_completion(&pAdapter->wlan_suspend_comp_var);
Mahesh A Saptasagar67ab9222015-10-21 15:38:41 +053015189
15190 return;
15191}
c_manjeecfd1efb2015-09-25 19:32:34 +053015192
Anurag Chouhan0b29de02016-12-16 13:18:40 +053015193#ifdef MDNS_OFFLOAD
15194
15195/**
15196 * hdd_mdns_enable_offload_done() - mdns enable offload response api
15197 * @padapter: holds adapter
15198 * @status: response status
15199 *
15200 * Return - None
15201 */
15202void hdd_mdns_enable_offload_done(void *padapter, VOS_STATUS status)
15203{
15204 hdd_adapter_t* adapter = (hdd_adapter_t*) padapter;
15205
15206 ENTER();
15207
15208 if (NULL == adapter)
15209 {
15210 hddLog(VOS_TRACE_LEVEL_ERROR,
15211 "%s: adapter is NULL",__func__);
15212 return;
15213 }
15214
15215 adapter->mdns_status.mdns_enable_status = status;
15216 vos_event_set(&adapter->mdns_status.vos_event);
15217 return;
15218}
15219
15220/**
15221 * hdd_mdns_fqdn_offload_done() - mdns fqdn offload response api
15222 * @padapter: holds adapter
15223 * @status: responce status
15224 *
15225 * Return - None
15226 */
15227void hdd_mdns_fqdn_offload_done(void *padapter, VOS_STATUS status)
15228{
15229 hdd_adapter_t* adapter = (hdd_adapter_t*) padapter;
15230
15231 ENTER();
15232
15233 if (NULL == adapter)
15234 {
15235 hddLog(VOS_TRACE_LEVEL_ERROR,
15236 "%s: adapter is NULL",__func__);
15237 return;
15238 }
15239
15240 adapter->mdns_status.mdns_fqdn_status = status;
15241 return;
15242}
15243
15244/**
15245 * hdd_mdns_resp_offload_done() - mdns resp offload response api
15246 * @padapter: holds adapter
15247 * @status: responce status
15248 *
15249 * Return - None
15250 */
15251void hdd_mdns_resp_offload_done(void *padapter, VOS_STATUS status)
15252{
15253 hdd_adapter_t* adapter = (hdd_adapter_t*) padapter;
15254
15255 ENTER();
15256
15257 if (NULL == adapter)
15258 {
15259 hddLog(VOS_TRACE_LEVEL_ERROR,
15260 "%s: adapter is NULL",__func__);
15261 return;
15262 }
15263
15264 adapter->mdns_status.mdns_resp_status = status;
15265 return;
15266}
15267
15268/**
15269 * wlan_hdd_mdns_process_response_dname() - Process mDNS domain name
15270 * @response: Pointer to a struct hdd_mdns_resp_info
15271 * @resp_info: Pointer to a struct tSirMDNSResponseInfo
15272 *
15273 * This function will pack the whole domain name without compression. It will
15274 * add the leading len for each field and add zero length octet to terminate
15275 * the domain name.
15276 *
15277 * Return: Return boolean. TRUE for success, FALSE for fail.
15278 */
15279static bool
15280wlan_hdd_mdns_process_response_dname(struct hdd_mdns_resp_info *response,
15281 sir_mdns_resp_info resp_info)
15282{
15283 uint8_t num;
15284 uint16_t idx;
15285 uint8_t len = 0;
15286
15287 if ((response == NULL) || (response->data == NULL) ||
15288 (response->offset == NULL)) {
15289 hddLog(LOGE, FL("Either data or offset in response is NULL!"));
15290 return FALSE;
15291 }
15292
15293 if ((resp_info == NULL) ||
15294 (resp_info->resp_len >= MAX_MDNS_RESP_LEN)) {
15295 hddLog(LOGE, FL("resp_len exceeds %d!"), MAX_MDNS_RESP_LEN);
15296 return FALSE;
15297 }
15298
15299 for (num = 0; num < response->num_entries; num++) {
15300 response->offset[num] =
15301 resp_info->resp_len + MDNS_HEADER_LEN;
15302 idx = num * MAX_LEN_DOMAINNAME_FIELD;
15303 len = strlen((char *)&response->data[idx]);
15304 if ((resp_info->resp_len + len + 1) >= MAX_MDNS_RESP_LEN) {
15305 hddLog(LOGE, FL("resp_len exceeds %d!"),
15306 MAX_MDNS_RESP_LEN);
15307 return FALSE;
15308 }
15309 resp_info->resp_data[resp_info->resp_len] = len;
15310 resp_info->resp_len++;
15311 vos_mem_copy(&resp_info->resp_data[resp_info->resp_len],
15312 &response->data[idx], len);
15313 resp_info->resp_len += len;
15314 }
15315
15316 /* The domain name terminates with the zero length octet */
15317 if (num == response->num_entries) {
15318 if (resp_info->resp_len >= MAX_MDNS_RESP_LEN) {
15319 hddLog(LOGE, FL("resp_len exceeds %d!"),
15320 MAX_MDNS_RESP_LEN);
15321 return FALSE;
15322 }
15323 resp_info->resp_data[resp_info->resp_len] = 0;
15324 resp_info->resp_len++;
15325 }
15326
15327 return TRUE;
15328}
15329
15330/**
15331 * wlan_hdd_mdns_format_response_u16() - Form uint16_t response data
15332 * @value: The uint16_t value is formed to the struct tSirMDNSResponseInfo
15333 * @resp_info: Pointer to a struct tSirMDNSResponseInfo
15334 *
15335 * Return: None
15336 */
15337static void wlan_hdd_mdns_format_response_u16(uint16_t value,
15338 sir_mdns_resp_info resp_info)
15339{
15340 uint8_t val_u8;
15341
15342 if ((resp_info == NULL) || (resp_info->resp_data == NULL))
15343 return;
15344 val_u8 = (value & 0xff00) >> 8;
15345 resp_info->resp_data[resp_info->resp_len++] = val_u8;
15346 val_u8 = value & 0xff;
15347 resp_info->resp_data[resp_info->resp_len++] = val_u8;
15348}
15349
15350/**
15351 * wlan_hdd_mdns_format_response_u32() - Form uint32_t response data
15352 * @value: The uint32_t value is formed to the struct tSirMDNSResponseInfo
15353 * @resp_info: Pointer to a struct tSirMDNSResponseInfo
15354 *
15355 * Return: None
15356 */
15357static void wlan_hdd_mdns_format_response_u32(uint32_t value,
15358 sir_mdns_resp_info resp_info)
15359{
15360 uint8_t val_u8;
15361
15362 if ((resp_info == NULL) || (resp_info->resp_data == NULL))
15363 return;
15364 val_u8 = (value & 0xff000000) >> 24;
15365 resp_info->resp_data[resp_info->resp_len++] = val_u8;
15366 val_u8 = (value & 0xff0000) >> 16;
15367 resp_info->resp_data[resp_info->resp_len++] = val_u8;
15368 val_u8 = (value & 0xff00) >> 8;
15369 resp_info->resp_data[resp_info->resp_len++] = val_u8;
15370 val_u8 = value & 0xff;
15371 resp_info->resp_data[resp_info->resp_len++] = val_u8;
15372}
15373
15374/**
15375 * wlan_hdd_mdns_process_response_misc() - Process misc info in mDNS response
15376 * @resp_type: Response type for mDNS
15377 * @resp_info: Pointer to a struct tSirMDNSResponseInfo
15378 *
15379 * This function will pack the response type, class and TTL (Time To Live).
15380 *
15381 * Return: Return boolean. TRUE for success, FALSE for fail.
15382 */
15383static bool wlan_hdd_mdns_process_response_misc(uint16_t resp_type,
15384 sir_mdns_resp_info resp_info)
15385{
15386 uint16_t len;
15387
15388 if (resp_info == NULL) {
15389 hddLog(LOGE, FL("resp_info is NULL!"));
15390 return FALSE;
15391 }
15392
15393 len = resp_info->resp_len + (2 * sizeof(uint16_t) + sizeof(uint32_t));
15394 if (len >= MAX_MDNS_RESP_LEN) {
15395 hddLog(LOGE, FL("resp_len exceeds %d!"), MAX_MDNS_RESP_LEN);
15396 return FALSE;
15397 }
15398
15399 /* Fill Type, Class, TTL */
15400 wlan_hdd_mdns_format_response_u16(resp_type, resp_info);
15401 wlan_hdd_mdns_format_response_u16(MDNS_CLASS, resp_info);
15402 wlan_hdd_mdns_format_response_u32(MDNS_TTL, resp_info);
15403
15404 return TRUE;
15405}
15406
15407/**
15408 * wlan_hdd_mdns_compress_data() - Compress the domain name in mDNS response
15409 * @resp_info: Pointer to a struct tSirMDNSResponseInfo
15410 * @response_dst: The response which domain name is compressed.
15411 * @response_src: The response which domain name is matched with response_dst.
15412 * Its offset is used for data compression.
15413 * @num_matched: The number of matched entries between response_dst and
15414 * response_src
15415 *
15416 * This function will form the different fields of domain name in response_dst
15417 * if any. Then use the offset of the matched domain name in response_src to
15418 * compress the matched domain name.
15419 *
15420 * Return: Return boolean. TRUE for success, FALSE for fail.
15421 */
15422static bool
15423wlan_hdd_mdns_compress_data(sir_mdns_resp_info resp_info,
15424 struct hdd_mdns_resp_info *response_dst,
15425 struct hdd_mdns_resp_info *response_src,
15426 uint8_t num_matched)
15427{
15428 uint8_t num, num_diff;
15429 uint16_t value, idx;
15430 uint8_t len = 0;
15431
15432 if ((response_src == NULL) || (response_dst == NULL) ||
15433 (resp_info == NULL)) {
15434 hddLog(LOGE, FL("response info is NULL!"));
15435 return FALSE;
15436 }
15437
15438 if (response_dst->num_entries < num_matched) {
15439 hddLog(LOGE, FL("num_entries is less than num_matched!"));
15440 return FALSE;
15441 }
15442
15443 if (resp_info->resp_len >= MAX_MDNS_RESP_LEN) {
15444 hddLog(LOGE, FL("resp_len exceeds %d!"), MAX_MDNS_RESP_LEN);
15445 return FALSE;
15446 }
15447
15448 num_diff = response_dst->num_entries - num_matched;
15449 if ((num_diff > 0) && (response_dst->data == NULL)) {
15450 hddLog(LOGE, FL("response_dst->data is NULL!"));
15451 return FALSE;
15452 }
15453
15454 /*
15455 * Handle the unmatched string at the beginning
15456 * Store the length of octets and the octets
15457 */
15458 for (num = 0; num < num_diff; num++) {
15459 response_dst->offset[num] =
15460 resp_info->resp_len + MDNS_HEADER_LEN;
15461 idx = num * MAX_LEN_DOMAINNAME_FIELD;
15462 len = strlen((char *)&response_dst->data[idx]);
15463 if ((resp_info->resp_len + len + 1) >= MAX_MDNS_RESP_LEN) {
15464 hddLog(LOGE, FL("resp_len exceeds %d!"),
15465 MAX_MDNS_RESP_LEN);
15466 return FALSE;
15467 }
15468 resp_info->resp_data[resp_info->resp_len] = len;
15469 resp_info->resp_len++;
15470 vos_mem_copy(&resp_info->resp_data[resp_info->resp_len],
15471 &response_dst->data[idx], len);
15472 resp_info->resp_len += len;
15473 }
15474 /*
15475 * Handle the matched string from the end
15476 * Just keep the offset and mask the leading two bit
15477 */
15478 if (response_src->num_entries >= num_matched) {
15479 num_diff = response_src->num_entries - num_matched;
15480 value = response_src->offset[num_diff];
15481 if (value > 0) {
15482 value |= 0xc000;
15483 if ((resp_info->resp_len + sizeof(uint16_t)) >=
15484 MAX_MDNS_RESP_LEN) {
15485 hddLog(LOGE, FL("resp_len exceeds %d!"),
15486 MAX_MDNS_RESP_LEN);
15487 return FALSE;
15488 }
15489 wlan_hdd_mdns_format_response_u16(value, resp_info);
15490 return TRUE;
15491 }
15492 }
15493 return FALSE;
15494}
15495
15496/**
15497 * wlan_hdd_mdns_reset_response() - Reset the response info
15498 * @response: The response which info is reset.
15499 *
15500 * Return: None
15501 */
15502static void wlan_hdd_mdns_reset_response(struct hdd_mdns_resp_info *response)
15503{
15504 if (response == NULL)
15505 return;
15506 response->num_entries = 0;
15507 response->data = NULL;
15508 response->offset = NULL;
15509}
15510
15511/**
15512 * wlan_hdd_mdns_init_response() - Initialize the response info
15513 * @response: The response which info is initiatized.
15514 * @resp_dname: The domain name string which might be tokenized.
15515 *
15516 * This function will allocate the memory for both response->data and
15517 * response->offset. Besides, it will also tokenize the domain name to some
15518 * entries and fill response->num_entries with the num of entries.
15519 *
15520 * Return: Return boolean. TRUE for success, FALSE for fail.
15521 */
15522static bool wlan_hdd_mdns_init_response(struct hdd_mdns_resp_info *response,
15523 uint8_t *resp_dname, char separator)
15524{
15525 uint16_t size;
15526
15527 if ((resp_dname == NULL) || (response == NULL)) {
15528 hddLog(LOGE, FL("resp_dname or response is NULL!"));
15529 return FALSE;
15530 }
15531
15532 size = MAX_NUM_FIELD_DOMAINNAME * MAX_LEN_DOMAINNAME_FIELD;
15533 response->data = vos_mem_malloc(size);
15534 if (response->data) {
15535 vos_mem_zero(response->data, size);
15536 if (VOS_STATUS_SUCCESS !=
15537 hdd_string_to_string_array((char *)resp_dname,
15538 response->data,
15539 separator,
15540 &response->num_entries,
15541 MAX_NUM_FIELD_DOMAINNAME,
15542 MAX_LEN_DOMAINNAME_FIELD)) {
15543 hddLog(LOGE, FL("hdd_string_to_string_array fail!"));
15544 goto err_init_resp;
15545 }
15546
15547 if ((response->num_entries > 0) &&
15548 (strlen((char *)&response->data[0]) > 0)) {
15549 size = sizeof(uint16_t) * response->num_entries;
15550 response->offset = vos_mem_malloc(size);
15551 if (response->offset) {
15552 vos_mem_zero(response->offset, size);
15553 return TRUE;
15554 }
15555 }
15556 }
15557
15558err_init_resp:
15559 if (response->data)
15560 vos_mem_free(response->data);
15561 wlan_hdd_mdns_reset_response(response);
15562 return FALSE;
15563}
15564
15565/**
15566 * wlan_hdd_mdns_find_entries_from_end() - Find the matched entries
15567 * @response1: The response info is used to be compared.
15568 * @response2: The response info is used to be compared.
15569 *
15570 * This function will find the matched entries from the end.
15571 *
15572 * Return: Return the number of the matched entries.
15573 */
15574static uint8_t
15575wlan_hdd_mdns_find_entries_from_end(struct hdd_mdns_resp_info *response1,
15576 struct hdd_mdns_resp_info *response2)
15577{
15578 uint8_t min, len1, i;
15579 uint16_t num1, num2;
15580 uint8_t num_matched = 0;
15581
15582 min = VOS_MIN(response1->num_entries, response2->num_entries);
15583
15584 for (i = 1; i <= min; i++) {
15585 num1 = (response1->num_entries - i);
15586 num1 *= MAX_LEN_DOMAINNAME_FIELD;
15587 num2 = (response2->num_entries - i);
15588 num2 *= MAX_LEN_DOMAINNAME_FIELD;
15589 len1 = strlen((char *)&response1->data[num1]);
15590
15591 if ((len1 == 0) ||
15592 (len1 != strlen((char *)&response2->data[num2])))
15593 break;
15594 if (memcmp(&response1->data[num1],
15595 &response2->data[num2], len1))
15596 break;
15597 else
15598 num_matched++;
15599 }
15600
15601 return num_matched;
15602}
15603
15604/**
15605 * wlan_hdd_mdns_find_max() - Find the maximum number of the matched entries
15606 * @matchedlist: Pointer to the array of struct hdd_mdns_resp_matched
15607 * @numlist: The number of the elements in the array matchedlist.
15608 *
15609 * Find the max number of the matched entries among the array matchedlist.
15610 *
15611 * Return: None
15612 */
15613static void wlan_hdd_mdns_find_max(struct hdd_mdns_resp_matched *matchedlist,
15614 uint8_t numlist)
15615{
15616 int j;
15617 struct hdd_mdns_resp_matched tmp;
15618
15619 /* At least two values are used for sorting */
15620 if ((numlist < 2) || (matchedlist == NULL)) {
15621 hddLog(LOGE, FL("At least two values are used for sorting!"));
15622 return;
15623 }
15624
15625 for (j = 0; j < numlist-1; j++) {
15626 if (matchedlist[j].num_matched >
15627 matchedlist[j+1].num_matched) {
15628 vos_mem_copy(&tmp, &matchedlist[j],
15629 sizeof(struct hdd_mdns_resp_matched));
15630 vos_mem_copy(&matchedlist[j], &matchedlist[j+1],
15631 sizeof(struct hdd_mdns_resp_matched));
15632 vos_mem_copy(&matchedlist[j+1], &tmp,
15633 sizeof(struct hdd_mdns_resp_matched));
15634 }
15635 }
15636}
15637
15638/**
15639 * wlan_hdd_mdns_pack_response_type_a() - Pack Type A response
15640 * @ini_config: Pointer to the struct hdd_config_t
15641 * @resp_info: Pointer to the struct tSirMDNSResponseInfo
15642 * @resptype_a: Pointer to the struct hdd_mdns_resp_info of Type A
15643 *
15644 * Type A response include QName, response type, class, TTL and Ipv4.
15645 *
15646 * Return: Return boolean. TRUE for success, FALSE for fail.
15647 */
15648static bool
15649wlan_hdd_mdns_pack_response_type_a(hdd_config_t *ini_config,
15650 sir_mdns_resp_info resp_info,
15651 struct hdd_mdns_resp_info *resptype_a)
15652{
15653 uint16_t value;
15654 uint32_t len;
15655
15656 ENTER();
15657 if ((ini_config == NULL) || (resp_info == NULL) ||
15658 (resptype_a == NULL)) {
15659 hddLog(LOGE, FL("ini_config or response info is NULL!"));
15660 return FALSE;
15661 }
15662
15663 /* No Type A response */
15664 if (strlen((char *)ini_config->mdns_resp_type_a) <= 0)
15665 return TRUE;
15666
15667 /* Wrong response is assigned, just ignore this response */
15668 if (!wlan_hdd_mdns_init_response(resptype_a,
15669 ini_config->mdns_resp_type_a, '.'))
15670 return TRUE;
15671
15672 /* Process response domain name */
15673 if (!wlan_hdd_mdns_process_response_dname(resptype_a, resp_info)) {
15674 hddLog(LOGE, FL("Fail to process mDNS response (%d)!"),
15675 MDNS_TYPE_A);
15676 return FALSE;
15677 }
15678
15679 /* Process response Type, Class, TTL */
15680 if (!wlan_hdd_mdns_process_response_misc(MDNS_TYPE_A, resp_info)) {
15681 hddLog(LOGE, FL("Fail to process mDNS misc response (%d)!"),
15682 MDNS_TYPE_A);
15683 return FALSE;
15684 }
15685
15686 /* Process response RDLength, RData */
15687 len = sizeof(uint16_t) + sizeof(uint32_t);
15688 len += resp_info->resp_len;
15689 if (len >= MAX_MDNS_RESP_LEN) {
15690 hddLog(LOGE, FL("resp_len exceeds %d!"), MAX_MDNS_RESP_LEN);
15691 return FALSE;
15692 }
15693 value = sizeof(uint32_t);
15694 wlan_hdd_mdns_format_response_u16(value, resp_info);
15695 wlan_hdd_mdns_format_response_u32(ini_config->mdns_resp_type_a_ipv4,
15696 resp_info);
15697
15698 EXIT();
15699 return TRUE;
15700}
15701
15702/**
15703 * wlan_hdd_mdns_pack_response_type_txt() - Pack Type Txt response
15704 * @ini_config: Pointer to the struct hdd_config_t
15705 * @resp_info: Pointer to the struct tSirMDNSResponseInfo
15706 * @resptype_txt: Pointer to the struct hdd_mdns_resp_info of Type txt
15707 * @resptype_a: Pointer to the struct hdd_mdns_resp_info of Type A
15708 *
15709 * Type Txt response include QName, response type, class, TTL and text content.
15710 * Also, it will find the matched QName from resptype_A and compress the data.
15711 *
15712 * Return: Return boolean. TRUE for success, FALSE for fail.
15713 */
15714static bool
15715wlan_hdd_mdns_pack_response_type_txt(hdd_config_t *ini_config,
15716 sir_mdns_resp_info resp_info,
15717 struct hdd_mdns_resp_info *resptype_txt,
15718 struct hdd_mdns_resp_info *resptype_a)
15719{
15720 uint8_t num_matched;
15721 uint8_t num;
15722 uint16_t idx;
15723 uint16_t value = 0;
15724 uint32_t len;
15725 uint32_t total_len;
15726 bool status;
15727 struct hdd_mdns_resp_info resptype_content;
15728
15729 ENTER();
15730
15731 if ((ini_config == NULL) || (resp_info == NULL) ||
15732 (resptype_txt == NULL)) {
15733 hddLog(LOGE, FL("ini_config or response info is NULL!"));
15734 return FALSE;
15735 }
15736
15737 /* No Type Txt response */
15738 if (strlen((char *)ini_config->mdns_resp_type_txt) <= 0)
15739 return TRUE;
15740
15741 /* Wrong response is assigned, just ignore this response */
15742 if (!wlan_hdd_mdns_init_response(resptype_txt,
15743 ini_config->mdns_resp_type_txt, '.'))
15744 return TRUE;
15745
15746 /*
15747 * For data compression
15748 * Check if any strings are matched with Type A response
15749 */
15750 if (resptype_a && (resptype_a->num_entries > 0)) {
15751 num_matched = wlan_hdd_mdns_find_entries_from_end(resptype_txt,
15752 resptype_a);
15753 if (num_matched > 0) {
15754 if (!wlan_hdd_mdns_compress_data(resp_info,
15755 resptype_txt, resptype_a, num_matched)) {
15756 hddLog(LOGE, FL("Fail to compress mDNS "
15757 "response (%d)!"), MDNS_TYPE_TXT);
15758 return FALSE;
15759 }
15760 } else {
15761 /*
15762 * num_matched is zero. Error!
15763 * At least ".local" is needed.
15764 */
15765 hddLog(LOGE, FL("No matched string! Fail to pack mDNS "
15766 "response (%d)!"), MDNS_TYPE_TXT);
15767 return FALSE;
15768 }
15769 } else {
15770 /* no TypeA response, so show the whole data */
15771 if (!wlan_hdd_mdns_process_response_dname(resptype_txt,
15772 resp_info)) {
15773 hddLog(LOGE, FL("Fail to process mDNS response (%d)!"),
15774 MDNS_TYPE_TXT);
15775 return FALSE;
15776 }
15777 }
15778
15779 /* Process response Type, Class, TTL */
15780 if (!wlan_hdd_mdns_process_response_misc(MDNS_TYPE_TXT, resp_info)) {
15781 hddLog(LOGE, FL("Fail to process mDNS misc response (%d)!"),
15782 MDNS_TYPE_TXT);
15783 return FALSE;
15784 }
15785
15786 /*
15787 * Process response RDLength, RData.
15788 * TypeTxt RData include len.
15789 */
15790 status = wlan_hdd_mdns_init_response(&resptype_content,
15791 ini_config->mdns_resp_type_txt_content,
15792 '/');
15793 if (status == FALSE) {
15794 hddLog(LOGE, FL("wlan_hdd_mdns_init_response FAIL"));
15795 return FALSE;
15796 }
15797
15798 for (num = 0; num < resptype_content.num_entries; num++) {
15799 idx = num * MAX_LEN_DOMAINNAME_FIELD;
15800 value += strlen((char *)&resptype_content.data[idx]);
15801 }
15802
15803 /* content len is uint16_t */
15804 total_len = sizeof(uint16_t);
15805 total_len += resp_info->resp_len + value +
15806 resptype_content.num_entries;
15807
15808 if (total_len >= MAX_MDNS_RESP_LEN) {
15809 hddLog(LOGE, FL("resp_len exceeds %d!"), MAX_MDNS_RESP_LEN);
15810 return FALSE;
15811 }
15812 wlan_hdd_mdns_format_response_u16(value + resptype_content.num_entries,
15813 resp_info);
15814
15815 for (num = 0; num < resptype_content.num_entries; num++) {
15816 idx = num * MAX_LEN_DOMAINNAME_FIELD;
15817 len = strlen((char *)&resptype_content.data[idx]);
15818 resp_info->resp_data[resp_info->resp_len] = len;
15819 resp_info->resp_len++;
15820
15821 vos_mem_copy(&resp_info->resp_data[resp_info->resp_len],
15822 &resptype_content.data[idx], len);
15823
15824 resp_info->resp_len += len;
15825 hddLog(LOG1, FL("index = %d, len = %d, str = %s"),
15826 num, len, &resptype_content.data[idx]);
15827 }
15828
15829 EXIT();
15830 return TRUE;
15831}
15832
15833/**
15834 * wlan_hdd_mdns_pack_response_type_ptr_dname() - Pack Type PTR domain name
15835 * @ini_config: Pointer to the struct hdd_config_t
15836 * @resp_info: Pointer to the struct tSirMDNSResponseInfo
15837 * @resptype_ptr_dn: Pointer to the struct hdd_mdns_resp_info of Type Ptr
15838 * domain name
15839 * @resptype_ptr: Pointer to the struct hdd_mdns_resp_info of Type Ptr
15840 * @resptype_txt: Pointer to the struct hdd_mdns_resp_info of Type Txt
15841 * @resptype_a: Pointer to the struct hdd_mdns_resp_info of Type A
15842 *
15843 * The Type Ptr response include Type PTR domain name in its data field.
15844 * Also, it will find the matched QName from the existing resptype_ptr,
15845 * resptype_txt, resptype_a and then compress the data.
15846 *
15847 * Return: Return boolean. TRUE for success, FALSE for fail.
15848 */
15849static bool
15850wlan_hdd_mdns_pack_response_type_ptr_dname(hdd_config_t *ini_config,
15851 sir_mdns_resp_info resp_info,
15852 struct hdd_mdns_resp_info *resptype_ptr_dn,
15853 struct hdd_mdns_resp_info *resptype_ptr,
15854 struct hdd_mdns_resp_info *resptype_txt,
15855 struct hdd_mdns_resp_info *resptype_a)
15856{
15857 uint8_t num_matched, numlist, size;
15858 struct hdd_mdns_resp_matched matchedlist[MAX_MDNS_RESP_TYPE-1];
15859 struct hdd_mdns_resp_info *resp;
15860
15861 if ((ini_config == NULL) || (resp_info == NULL) ||
15862 (resptype_ptr == NULL) || (resptype_ptr_dn == NULL)) {
15863 hddLog(LOGE, FL("ini_config or response info is NULL!"));
15864 return FALSE;
15865 }
15866
15867 /* No Type Ptr domain name response */
15868 if (strlen((char *)ini_config->mdns_resp_type_ptr_dname) <= 0)
15869 return TRUE;
15870
15871 /* Wrong response is assigned, just ignore this response */
15872 if (!wlan_hdd_mdns_init_response(resptype_ptr_dn,
15873 ini_config->mdns_resp_type_ptr_dname, '.'))
15874 return TRUE;
15875
15876 /*
15877 * For data compression
15878 * Check if any strings are matched with previous
15879 * response.
15880 */
15881 numlist = 0;
15882 size = (MAX_MDNS_RESP_TYPE-1);
15883 size *= sizeof(struct hdd_mdns_resp_matched);
15884 vos_mem_zero(matchedlist, size);
15885 num_matched = wlan_hdd_mdns_find_entries_from_end(resptype_ptr_dn,
15886 resptype_ptr);
15887 if (num_matched > 0) {
15888 matchedlist[numlist].num_matched = num_matched;
15889 matchedlist[numlist].type = MDNS_TYPE_PTR;
15890 numlist++;
15891 }
15892 if (resptype_txt && (resptype_txt->num_entries > 0)) {
15893 num_matched = wlan_hdd_mdns_find_entries_from_end(
15894 resptype_ptr_dn, resptype_txt);
15895 if (num_matched > 0) {
15896 matchedlist[numlist].num_matched = num_matched;
15897 matchedlist[numlist].type = MDNS_TYPE_TXT;
15898 numlist++;
15899 }
15900 }
15901 if (resptype_a && (resptype_a->num_entries > 0)) {
15902 num_matched = wlan_hdd_mdns_find_entries_from_end(
15903 resptype_ptr_dn,resptype_a);
15904 if (num_matched > 0) {
15905 matchedlist[numlist].num_matched = num_matched;
15906 matchedlist[numlist].type = MDNS_TYPE_A;
15907 numlist++;
15908 }
15909 }
15910 if (numlist > 0) {
15911 if (numlist > 1)
15912 wlan_hdd_mdns_find_max(matchedlist, numlist);
15913 resp = NULL;
15914 switch (matchedlist[numlist-1].type) {
15915 case MDNS_TYPE_A:
15916 resp = resptype_a;
15917 break;
15918 case MDNS_TYPE_TXT:
15919 resp = resptype_txt;
15920 break;
15921 case MDNS_TYPE_PTR:
15922 resp = resptype_ptr;
15923 break;
15924 default:
15925 hddLog(LOGE, FL("Fail to compress mDNS response "
15926 "(%d)!"), MDNS_TYPE_PTR_DNAME);
15927 return FALSE;
15928 }
15929 num_matched = matchedlist[numlist-1].num_matched;
15930 if (!wlan_hdd_mdns_compress_data(resp_info, resptype_ptr_dn,
15931 resp, num_matched)) {
15932 hddLog(LOGE, FL("Fail to compress mDNS response "
15933 "(%d)!"), MDNS_TYPE_PTR_DNAME);
15934 return FALSE;
15935 }
15936 } else {
15937 /* num = 0 -> no matched string */
15938 if (!wlan_hdd_mdns_process_response_dname(resptype_ptr_dn,
15939 resp_info)) {
15940 hddLog(LOGE, FL("Fail to process mDNS response (%d)!"),
15941 MDNS_TYPE_PTR_DNAME);
15942 return FALSE;
15943 }
15944 }
15945
15946 return TRUE;
15947}
15948
15949/**
15950 * wlan_hdd_mdns_pack_response_type_ptr() - Pack Type PTR response
15951 * @ini_config: Pointer to the struct hdd_config_t
15952 * @resp_info: Pointer to the struct tSirMDNSResponseInfo
15953 * @resptype_ptr: Pointer to the struct hdd_mdns_resp_info of Type Ptr
15954 * @resptype_ptr_dn: Pointer to the struct hdd_mdns_resp_info of Type Ptr
15955 * domain name
15956 * @resptype_txt: Pointer to the struct hdd_mdns_resp_info of Type Txt
15957 * @resptype_a: Pointer to the struct hdd_mdns_resp_info of Type A
15958 *
15959 * The Type Ptr response include QName, response type, class, TTL and
15960 * Type PTR domain name. Also, it will find the matched QName from the
15961 * existing resptype_txt, resptype_a and then compress the data.
15962 *
15963 * Return: Return boolean. TRUE for success, FALSE for fail.
15964 */
15965static bool
15966wlan_hdd_mdns_pack_response_type_ptr(hdd_config_t *ini_config,
15967 sir_mdns_resp_info resp_info,
15968 struct hdd_mdns_resp_info *resptype_ptr,
15969 struct hdd_mdns_resp_info *resptype_ptr_dn,
15970 struct hdd_mdns_resp_info *resptype_txt,
15971 struct hdd_mdns_resp_info *resptype_a)
15972{
15973 uint8_t num_matched, num_matched1;
15974 uint16_t value;
15975 uint8_t val_u8;
15976 uint32_t offset_data_len, len;
15977
15978 ENTER();
15979 if ((ini_config == NULL) || (resp_info == NULL) ||
15980 (resptype_ptr == NULL) || (resptype_ptr_dn == NULL)) {
15981 hddLog(LOGE, FL("ini_config or response info is NULL!"));
15982 return FALSE;
15983 }
15984
15985 /* No Type Ptr response */
15986 if (strlen((char *)ini_config->mdns_resp_type_ptr) <= 0)
15987 return TRUE;
15988
15989 /* Wrong response is assigned, just ignore this response */
15990 if (!wlan_hdd_mdns_init_response(resptype_ptr,
15991 ini_config->mdns_resp_type_ptr, '.'))
15992 return TRUE;
15993
15994 /*
15995 * For data compression
15996 * Check if any strings are matched with Type A response
15997 */
15998 num_matched = 0;
15999 num_matched1 = 0;
16000 if (resptype_a && (resptype_a->num_entries > 0)) {
16001 num_matched = wlan_hdd_mdns_find_entries_from_end(resptype_ptr,
16002 resptype_a);
16003 }
16004 if (resptype_txt && (resptype_txt->num_entries > 0)) {
16005 num_matched1 = wlan_hdd_mdns_find_entries_from_end(
16006 resptype_ptr, resptype_txt);
16007 }
16008 if ((num_matched != num_matched1) ||
16009 ((num_matched > 0) && (num_matched1 > 0))) {
16010 if (num_matched >= num_matched1) {
16011 if (!wlan_hdd_mdns_compress_data(resp_info,
16012 resptype_ptr, resptype_a, num_matched)) {
16013 hddLog(LOGE, FL("Fail to compress mDNS "
16014 "response (%d)!"), MDNS_TYPE_PTR);
16015 return FALSE;
16016 }
16017 } else {
16018 /* num_matched is less than num_matched1 */
16019 if (!wlan_hdd_mdns_compress_data(resp_info,
16020 resptype_ptr, resptype_txt, num_matched1)) {
16021 hddLog(LOGE, FL("Fail to compress mDNS "
16022 "response (%d)!"), MDNS_TYPE_PTR);
16023 return FALSE;
16024 }
16025 }
16026 } else {
16027 /*
16028 * Both num_matched and num_matched1 are zero.
16029 * no TypeA & TypeTxt
16030 */
16031 if (!wlan_hdd_mdns_process_response_dname(resptype_ptr,
16032 resp_info)) {
16033 hddLog(LOGE, FL("Fail to process mDNS response (%d)!"),
16034 MDNS_TYPE_PTR);
16035 return FALSE;
16036 }
16037 }
16038
16039 /* Process response Type, Class, TTL */
16040 if (!wlan_hdd_mdns_process_response_misc(MDNS_TYPE_PTR, resp_info)) {
16041 hddLog(LOGE, FL("Fail to process mDNS misc response (%d)!"),
16042 MDNS_TYPE_PTR);
16043 return FALSE;
16044 }
16045
16046 /*
16047 * Process response RDLength, RData (Ptr domain name)
16048 * Save the offset of RData length
16049 */
16050 offset_data_len = resp_info->resp_len;
16051 resp_info->resp_len += sizeof(uint16_t);
16052
16053 if (!wlan_hdd_mdns_pack_response_type_ptr_dname(ini_config, resp_info,
16054 resptype_ptr_dn, resptype_ptr,
16055 resptype_txt, resptype_a)) {
16056 return FALSE;
16057 }
16058 /* Set the RData length */
16059 len = offset_data_len + sizeof(uint16_t);
16060 if ((resptype_ptr_dn->num_entries > 0) &&
16061 (resp_info->resp_len > len)) {
16062 value = resp_info->resp_len - len;
16063 val_u8 = (value & 0xff00) >> 8;
16064 resp_info->resp_data[offset_data_len] = val_u8;
16065 val_u8 = value & 0xff;
16066 resp_info->resp_data[offset_data_len+1] = val_u8;
16067 } else {
16068 hddLog(LOGE, FL("Fail to process mDNS response (%d)!"),
16069 MDNS_TYPE_PTR);
16070 return FALSE;
16071 }
16072
16073 EXIT();
16074 return TRUE;
16075}
16076
16077/**
16078 * wlan_hdd_mdns_pack_response_type_srv_target()- Pack Type Service Target
16079 * @ini_config: Pointer to the struct hdd_config_t
16080 * @resp_info: Pointer to the struct tSirMDNSResponseInfo
16081 * @resptype_srv_tgt: Pointer to the struct hdd_mdns_resp_info of Type Srv
16082 * target
16083 * @resptype_srv: Pointer to the struct hdd_mdns_resp_info of Type Srv
16084 * @resptype_ptr: Pointer to the struct hdd_mdns_resp_info of Type Ptr
16085 * @resptype_ptr_dn: Pointer to the struct hdd_mdns_resp_info of Type Ptr
16086 * domain name
16087 * @resptype_txt: Pointer to the struct hdd_mdns_resp_info of Type Txt
16088 * @resptype_a: Pointer to the struct hdd_mdns_resp_info of Type A
16089 *
16090 * The Type service target is one of the data field in the Type SRV response.
16091 * Also, it will find the matched QName from the existing resptype_srv,
16092 * resptype_ptr, resptype_ptr_dn, resptype_txt, resptype_a and then compress
16093 * the data.
16094 *
16095 * Return: Return boolean. TRUE for success, FALSE for fail.
16096 */
16097static bool
16098wlan_hdd_mdns_pack_response_type_srv_target(hdd_config_t *ini_config,
16099 sir_mdns_resp_info resp_info,
16100 struct hdd_mdns_resp_info *resptype_srv_tgt,
16101 struct hdd_mdns_resp_info *resptype_srv,
16102 struct hdd_mdns_resp_info *resptype_ptr,
16103 struct hdd_mdns_resp_info *resptype_ptr_dn,
16104 struct hdd_mdns_resp_info *resptype_txt,
16105 struct hdd_mdns_resp_info *resptype_a)
16106{
16107 uint8_t num_matched, num, size;
16108 struct hdd_mdns_resp_matched matchedlist[MAX_MDNS_RESP_TYPE-1];
16109 struct hdd_mdns_resp_info *resp;
16110
16111 if ((ini_config == NULL) || (resp_info == NULL) ||
16112 (resptype_srv == NULL) || (resptype_srv_tgt == NULL)) {
16113 hddLog(LOGE, FL("ini_config or response info is NULL!"));
16114 return FALSE;
16115 }
16116
16117 /* No Type Srv Target response */
16118 if (strlen((char *)ini_config->mdns_resp_type_srv_target) <= 0)
16119 return TRUE;
16120
16121 /* Wrong response is assigned, just ignore this response */
16122 if (!wlan_hdd_mdns_init_response(resptype_srv_tgt,
16123 ini_config->mdns_resp_type_srv_target, '.'))
16124 return TRUE;
16125
16126 /*
16127 * For data compression
16128 * Check if any strings are matched with previous response.
16129 */
16130 num = 0;
16131 size = (MAX_MDNS_RESP_TYPE-1);
16132 size *= sizeof(struct hdd_mdns_resp_matched);
16133 vos_mem_zero(matchedlist, size);
16134 num_matched = wlan_hdd_mdns_find_entries_from_end(resptype_srv_tgt,
16135 resptype_srv);
16136 if (num_matched > 0) {
16137 matchedlist[num].num_matched = num_matched;
16138 matchedlist[num].type = MDNS_TYPE_SRV;
16139 num++;
16140 }
16141 if (resptype_ptr && (resptype_ptr->num_entries > 0)) {
16142 if (resptype_ptr_dn && (resptype_ptr_dn->num_entries > 0)) {
16143 num_matched = wlan_hdd_mdns_find_entries_from_end(
16144 resptype_srv_tgt, resptype_ptr_dn);
16145 if (num_matched > 0) {
16146 matchedlist[num].num_matched = num_matched;
16147 matchedlist[num].type = MDNS_TYPE_PTR_DNAME;
16148 num++;
16149 }
16150 }
16151 num_matched = wlan_hdd_mdns_find_entries_from_end(
16152 resptype_srv_tgt, resptype_ptr);
16153 if (num_matched > 0) {
16154 matchedlist[num].num_matched = num_matched;
16155 matchedlist[num].type = MDNS_TYPE_PTR;
16156 num++;
16157 }
16158 }
16159 if (resptype_txt && (resptype_txt->num_entries > 0)) {
16160 num_matched = wlan_hdd_mdns_find_entries_from_end(
16161 resptype_srv_tgt, resptype_txt);
16162 if (num_matched > 0) {
16163 matchedlist[num].num_matched = num_matched;
16164 matchedlist[num].type = MDNS_TYPE_TXT;
16165 num++;
16166 }
16167 }
16168 if (resptype_a && (resptype_a->num_entries > 0)) {
16169 num_matched = wlan_hdd_mdns_find_entries_from_end(
16170 resptype_srv_tgt, resptype_a);
16171 if (num_matched > 0) {
16172 matchedlist[num].num_matched = num_matched;
16173 matchedlist[num].type = MDNS_TYPE_A;
16174 num++;
16175 }
16176 }
16177 if (num > 0) {
16178 if (num > 1)
16179 wlan_hdd_mdns_find_max(matchedlist, num);
16180 resp = NULL;
16181 switch (matchedlist[num-1].type) {
16182 case MDNS_TYPE_A:
16183 resp = resptype_a;
16184 break;
16185 case MDNS_TYPE_TXT:
16186 resp = resptype_txt;
16187 break;
16188 case MDNS_TYPE_PTR:
16189 resp = resptype_ptr;
16190 break;
16191 case MDNS_TYPE_PTR_DNAME:
16192 resp = resptype_ptr_dn;
16193 break;
16194 case MDNS_TYPE_SRV:
16195 resp = resptype_srv;
16196 break;
16197 default:
16198 hddLog(LOGE, FL("Fail to compress mDNS response "
16199 "(%d)!"), MDNS_TYPE_SRV_TARGET);
16200 return FALSE;
16201 }
16202 num_matched = matchedlist[num-1].num_matched;
16203 if (!wlan_hdd_mdns_compress_data(resp_info, resptype_srv_tgt,
16204 resp, num_matched)) {
16205 hddLog(LOGE, FL("Fail to compress mDNS response "
16206 "(%d)!"), MDNS_TYPE_SRV_TARGET);
16207 return FALSE;
16208 }
16209 } else {
16210 /* num = 0 -> no matched string */
16211 if (!wlan_hdd_mdns_process_response_dname(resptype_srv_tgt,
16212 resp_info)) {
16213 hddLog(LOGE, FL("Fail to process mDNS response (%d)!"),
16214 MDNS_TYPE_SRV_TARGET);
16215 return FALSE;
16216 }
16217 }
16218
16219 return TRUE;
16220}
16221
16222/**
16223 * wlan_hdd_mdns_pack_response_type_srv()- Pack Type Service response
16224 * @ini_config: Pointer to the struct hdd_config_t
16225 * @resp_info: Pointer to the struct tSirMDNSResponseInfo
16226 * @resptype_srv: Pointer to the struct hdd_mdns_resp_info of Type Srv
16227 * @resptype_srv_tgt: Pointer to the struct hdd_mdns_resp_info of Type Srv
16228 * target
16229 * @resptype_ptr: Pointer to the struct hdd_mdns_resp_info of Type Ptr
16230 * @resptype_ptr_dn: Pointer to the struct hdd_mdns_resp_info of Type Ptr
16231 * domain name
16232 * @resptype_txt: Pointer to the struct hdd_mdns_resp_info of Type Txt
16233 * @resptype_a: Pointer to the struct hdd_mdns_resp_info of Type A
16234 *
16235 * The Type SRV (Service) response include QName, response type, class, TTL
16236 * and four kinds of data fields. Also, it will find the matched QName from
16237 * the existing resptype_ptr, resptype_ptr_dn, resptype_txt, resptype_a and
16238 * then compress the data.
16239 *
16240 * Return: Return boolean. TRUE for success, FALSE for fail.
16241 */
16242static bool
16243wlan_hdd_mdns_pack_response_type_srv(hdd_config_t *ini_config,
16244 sir_mdns_resp_info resp_info,
16245 struct hdd_mdns_resp_info *resptype_srv,
16246 struct hdd_mdns_resp_info *resptype_srv_tgt,
16247 struct hdd_mdns_resp_info *resptype_ptr,
16248 struct hdd_mdns_resp_info *resptype_ptr_dn,
16249 struct hdd_mdns_resp_info *resptype_txt,
16250 struct hdd_mdns_resp_info *resptype_a)
16251{
16252 uint8_t num_matched, num, size;
16253 uint16_t value;
16254 uint8_t val_u8;
16255 uint32_t offset_data_len, len;
16256 struct hdd_mdns_resp_info *resp;
16257 struct hdd_mdns_resp_matched matchedlist[MAX_MDNS_RESP_TYPE-1];
16258
16259 ENTER();
16260
16261 if ((ini_config == NULL) || (resp_info == NULL) ||
16262 (resptype_srv == NULL) || (resptype_srv_tgt == NULL)) {
16263 hddLog(LOGE, FL("ini_config or response info is NULL!"));
16264 return FALSE;
16265 }
16266
16267 /* No Type Srv response */
16268 if (strlen((char *)ini_config->mdns_resp_type_srv) <= 0)
16269 return TRUE;
16270
16271 /* Wrong response is assigned, just ignore this response */
16272 if (!wlan_hdd_mdns_init_response(resptype_srv,
16273 ini_config->mdns_resp_type_srv, '.'))
16274 return TRUE;
16275
16276 /*
16277 * For data compression
16278 * Check if any strings are matched with Type A response
16279 */
16280 num = 0;
16281 size = (MAX_MDNS_RESP_TYPE-1);
16282 size *= sizeof(struct hdd_mdns_resp_matched);
16283 vos_mem_zero(matchedlist, size);
16284 if (resptype_ptr && (resptype_ptr->num_entries > 0)) {
16285 if (resptype_ptr_dn && (resptype_ptr_dn->num_entries > 0)) {
16286 num_matched = wlan_hdd_mdns_find_entries_from_end(
16287 resptype_srv,
16288 resptype_ptr_dn);
16289 if (num_matched > 0) {
16290 matchedlist[num].num_matched = num_matched;
16291 matchedlist[num].type = MDNS_TYPE_PTR_DNAME;
16292 num++;
16293 }
16294 }
16295 num_matched = wlan_hdd_mdns_find_entries_from_end(resptype_srv,
16296 resptype_ptr);
16297 if (num_matched > 0) {
16298 matchedlist[num].num_matched = num_matched;
16299 matchedlist[num].type = MDNS_TYPE_PTR;
16300 num++;
16301 }
16302 }
16303 if (resptype_txt && (resptype_txt->num_entries > 0)) {
16304 num_matched = wlan_hdd_mdns_find_entries_from_end(resptype_srv,
16305 resptype_txt);
16306 if (num_matched > 0) {
16307 matchedlist[num].num_matched =num_matched;
16308 matchedlist[num].type = MDNS_TYPE_TXT;
16309 num++;
16310 }
16311 }
16312 if (resptype_a && (resptype_a->num_entries > 0)) {
16313 num_matched = wlan_hdd_mdns_find_entries_from_end(resptype_srv,
16314 resptype_a);
16315 if (num_matched > 0) {
16316 matchedlist[num].num_matched = num_matched;
16317 matchedlist[num].type = MDNS_TYPE_A;
16318 num++;
16319 }
16320 }
16321 if (num > 0) {
16322 if (num > 1)
16323 wlan_hdd_mdns_find_max(matchedlist, num);
16324 resp = NULL;
16325 switch (matchedlist[num-1].type) {
16326 case MDNS_TYPE_A:
16327 resp = resptype_a;
16328 break;
16329 case MDNS_TYPE_TXT:
16330 resp = resptype_txt;
16331 break;
16332 case MDNS_TYPE_PTR:
16333 resp = resptype_ptr;
16334 break;
16335 case MDNS_TYPE_PTR_DNAME:
16336 resp = resptype_ptr_dn;
16337 break;
16338 default:
16339 hddLog(LOGE, FL("Fail to compress mDNS response "
16340 "(%d)!"), MDNS_TYPE_SRV);
16341 return FALSE;
16342 }
16343 num_matched = matchedlist[num-1].num_matched;
16344 if (!wlan_hdd_mdns_compress_data(resp_info, resptype_srv,
16345 resp, num_matched)) {
16346 hddLog(LOGE, FL("Fail to compress mDNS response "
16347 "(%d)!"), MDNS_TYPE_SRV);
16348 return FALSE;
16349 }
16350 } else {
16351 /* num = 0 -> no matched string */
16352 if (!wlan_hdd_mdns_process_response_dname(resptype_srv,
16353 resp_info)) {
16354 hddLog(LOGE, FL("Fail to process mDNS response (%d)!"),
16355 MDNS_TYPE_SRV);
16356 return FALSE;
16357 }
16358 }
16359
16360 /* Process response Type, Class, TTL */
16361 if (!wlan_hdd_mdns_process_response_misc(MDNS_TYPE_SRV, resp_info)) {
16362 hddLog(LOGE, FL("Fail to process mDNS misc response (%d)!"),
16363 MDNS_TYPE_SRV);
16364 return FALSE;
16365 }
16366
16367 /*
16368 * Process response RDLength, RData (Srv target name)
16369 * Save the offset of RData length
16370 */
16371 offset_data_len = resp_info->resp_len;
16372 resp_info->resp_len += sizeof(uint16_t);
16373
16374 len = resp_info->resp_len + (3 * sizeof(uint16_t));
16375 if (len >= MAX_MDNS_RESP_LEN) {
16376 hddLog(LOGE, FL("resp_len exceeds %d!"), MAX_MDNS_RESP_LEN);
16377 return FALSE;
16378 }
16379
16380 /* set Srv Priority */
16381 value = ini_config->mdns_resp_type_srv_priority;
16382 wlan_hdd_mdns_format_response_u16(value, resp_info);
16383 /* set Srv Weight */
16384 value = ini_config->mdns_resp_type_srv_weight;
16385 wlan_hdd_mdns_format_response_u16(value, resp_info);
16386 /* set Srv Port */
16387 value = ini_config->mdns_resp_type_srv_port;
16388 wlan_hdd_mdns_format_response_u16(value, resp_info);
16389
16390 if (!wlan_hdd_mdns_pack_response_type_srv_target(ini_config, resp_info,
16391 resptype_srv_tgt, resptype_srv,
16392 resptype_ptr, resptype_ptr_dn,
16393 resptype_txt, resptype_a)) {
16394 return FALSE;
16395 }
16396 /* Set the RData length */
16397 len = offset_data_len + sizeof(uint16_t);
16398 if ((resptype_srv_tgt->num_entries > 0) &&
16399 (resp_info->resp_len > len)) {
16400 value = resp_info->resp_len - len;
16401 val_u8 = (value & 0xff00) >> 8;
16402 resp_info->resp_data[offset_data_len] = val_u8;
16403 val_u8 = value & 0xff;
16404 resp_info->resp_data[offset_data_len+1] = val_u8;
16405 } else {
16406 hddLog(LOGE, FL("Fail to process mDNS response (%d)!"),
16407 MDNS_TYPE_SRV);
16408 return FALSE;
16409 }
16410
16411 EXIT();
16412 return TRUE;
16413}
16414
16415/**
16416 * wlan_hdd_mdns_free_mem() - Free the allocated memory
16417 * @response: Pointer to the struct hdd_mdns_resp_info
16418 *
16419 * Return: None
16420 */
16421static void wlan_hdd_mdns_free_mem(struct hdd_mdns_resp_info *response)
16422{
16423 if (response && response->data)
16424 vos_mem_free(response->data);
16425 if (response && response->offset)
16426 vos_mem_free(response->offset);
16427}
16428
16429/**
16430 * wlan_hdd_mdns_pack_response() - Pack mDNS response
16431 * @ini_config: Pointer to the struct hdd_config_t
16432 * @resp_info: Pointer to the struct tSirMDNSResponseInfo
16433 *
16434 * This function will pack four types of responses (Type A, Type Txt, Type Ptr
16435 * and Type Service). Each response contains QName, response type, class, TTL
16436 * and data fields.
16437 *
16438 * Return: Return boolean. TRUE for success, FALSE for fail.
16439 */
16440static bool wlan_hdd_mdns_pack_response(hdd_config_t *ini_config,
16441 sir_mdns_resp_info resp_info)
16442{
16443 struct hdd_mdns_resp_info resptype_a, resptype_txt;
16444 struct hdd_mdns_resp_info resptype_ptr, resptype_ptr_dn;
16445 struct hdd_mdns_resp_info resptype_srv, resptype_srv_tgt;
16446 uint32_t num_res_records = 0;
16447 bool status = FALSE;
16448
16449 ENTER();
16450
16451 wlan_hdd_mdns_reset_response(&resptype_a);
16452 wlan_hdd_mdns_reset_response(&resptype_txt);
16453 wlan_hdd_mdns_reset_response(&resptype_ptr);
16454 wlan_hdd_mdns_reset_response(&resptype_ptr_dn);
16455 wlan_hdd_mdns_reset_response(&resptype_srv);
16456 wlan_hdd_mdns_reset_response(&resptype_srv_tgt);
16457
16458 resp_info->resp_len = 0;
16459
16460 /* Process Type A response */
16461 if (!wlan_hdd_mdns_pack_response_type_a(ini_config, resp_info,
16462 &resptype_a))
16463 goto err_resptype_a;
16464
16465 if ((resptype_a.num_entries > 0) &&
16466 (strlen((char *)&resptype_a.data[0]) > 0))
16467 num_res_records++;
16468
16469 /* Process Type TXT response */
16470 if (!wlan_hdd_mdns_pack_response_type_txt(ini_config, resp_info,
16471 &resptype_txt, &resptype_a))
16472 goto err_resptype_txt;
16473
16474 if ((resptype_txt.num_entries > 0) &&
16475 (strlen((char *)&resptype_txt.data[0]) > 0))
16476 num_res_records++;
16477
16478 /* Process Type PTR response */
16479 if (!wlan_hdd_mdns_pack_response_type_ptr(ini_config, resp_info,
16480 &resptype_ptr, &resptype_ptr_dn,
16481 &resptype_txt, &resptype_a))
16482 goto err_resptype_ptr;
16483
16484 if ((resptype_ptr.num_entries > 0) &&
16485 (strlen((char *)&resptype_ptr.data[0]) > 0))
16486 num_res_records++;
16487
16488 /* Process Type SRV response */
16489 if (!wlan_hdd_mdns_pack_response_type_srv(ini_config, resp_info,
16490 &resptype_srv, &resptype_srv_tgt,
16491 &resptype_ptr, &resptype_ptr_dn,
16492 &resptype_txt, &resptype_a))
16493 goto err_resptype_srv;
16494
16495 if ((resptype_srv.num_entries > 0) &&
16496 (strlen((char *)&resptype_srv.data[0]) > 0))
16497 num_res_records++;
16498
16499 resp_info->resourceRecord_count = num_res_records;
16500 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
16501 "%s: Pack mDNS response data successfully!", __func__);
16502 status = TRUE;
16503
16504err_resptype_srv:
16505 wlan_hdd_mdns_free_mem(&resptype_srv);
16506 wlan_hdd_mdns_free_mem(&resptype_srv_tgt);
16507
16508err_resptype_ptr:
16509 wlan_hdd_mdns_free_mem(&resptype_ptr);
16510 wlan_hdd_mdns_free_mem(&resptype_ptr_dn);
16511
16512err_resptype_txt:
16513 wlan_hdd_mdns_free_mem(&resptype_txt);
16514
16515err_resptype_a:
16516 wlan_hdd_mdns_free_mem(&resptype_a);
16517
16518 EXIT();
16519 return status;
16520}
16521
16522/**
16523 * wlan_hdd_set_mdns_offload() - Enable mDNS offload
16524 * @hostapd_adapter: Pointer to the struct hdd_adapter_t
16525 *
16526 * This function will set FQDN/unique FQDN (full qualified domain name)
16527 * and the mDNS response. Then send them to SME.
16528 *
16529 * Return: Return boolean. TRUE for success, FALSE for fail.
16530 */
16531bool wlan_hdd_set_mdns_offload(hdd_adapter_t *hostapd_adapter)
16532{
16533 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(hostapd_adapter);
16534 sir_mdns_offload_info mdns_offload_info;
16535 sir_mdns_fqdn_info mdns_fqdn_info;
16536 sir_mdns_resp_info mdns_resp_info;
16537 uint32_t fqdn_len, ufqdn_len;
16538
16539 ENTER();
16540
16541 /* 1. Prepare the MDNS fqdn request to send to SME */
16542 fqdn_len = strlen(hdd_ctx->cfg_ini->mdns_fqdn);
16543 ufqdn_len = strlen(hdd_ctx->cfg_ini->mdns_uniquefqdn);
16544 if ((fqdn_len == 0) && (ufqdn_len == 0)) {
16545 hddLog(LOGE, FL("No mDNS FQDN or UFQDN is assigned fqdn_len %d,"
16546 "ufqdn_len %d!"), fqdn_len, ufqdn_len);
16547 return FALSE;
16548 }
16549
16550 mdns_fqdn_info = vos_mem_malloc(sizeof(*mdns_fqdn_info));
16551 if (NULL == mdns_fqdn_info) {
16552 hddLog(LOGE, FL("could not allocate tSirMDNSFqdnInfo!"));
16553 return FALSE;
16554 }
16555 /* MDNS fqdn request */
16556 if (fqdn_len > 0) {
16557 vos_mem_zero(mdns_fqdn_info, sizeof(*mdns_fqdn_info));
16558 mdns_fqdn_info->bss_idx = hostapd_adapter->sessionId;
16559 mdns_fqdn_info->fqdn_type = MDNS_FQDN_TYPE_GENERAL;
16560 mdns_fqdn_info->fqdn_len = fqdn_len;
16561 mdns_fqdn_info->mdns_fqdn_callback = hdd_mdns_fqdn_offload_done;
16562 mdns_fqdn_info->mdns_fqdn_cb_context = hostapd_adapter;
16563 vos_mem_copy(mdns_fqdn_info->fqdn_data,
16564 hdd_ctx->cfg_ini->mdns_fqdn,
16565 mdns_fqdn_info->fqdn_len);
16566
16567 if (eHAL_STATUS_SUCCESS !=
16568 sme_set_mdns_fqdn(hdd_ctx->hHal, mdns_fqdn_info)) {
16569 hddLog(LOGE, FL("sme_set_mdns_fqdn fail!"));
16570 vos_mem_free(mdns_fqdn_info);
16571 return FALSE;
16572 }
16573 }
16574 /* MDNS unique fqdn request */
16575 if (ufqdn_len > 0) {
16576 vos_mem_zero(mdns_fqdn_info, sizeof(*mdns_fqdn_info));
16577 mdns_fqdn_info->bss_idx = hostapd_adapter->sessionId;
16578 mdns_fqdn_info->fqdn_type = MDNS_FQDN_TYPE_UNIQUE;
16579 mdns_fqdn_info->fqdn_len = ufqdn_len;
16580 mdns_fqdn_info->mdns_fqdn_callback = hdd_mdns_fqdn_offload_done;
16581 mdns_fqdn_info->mdns_fqdn_cb_context = hostapd_adapter;
16582 vos_mem_copy(mdns_fqdn_info->fqdn_data,
16583 hdd_ctx->cfg_ini->mdns_uniquefqdn,
16584 mdns_fqdn_info->fqdn_len);
16585 if (eHAL_STATUS_SUCCESS !=
16586 sme_set_mdns_fqdn(hdd_ctx->hHal, mdns_fqdn_info)) {
16587 hddLog(LOGE, FL("sme_set_mdns_fqdn fail!"));
16588 vos_mem_free(mdns_fqdn_info);
16589 return FALSE;
16590 }
16591 }
16592 vos_mem_free(mdns_fqdn_info);
16593
16594 /* 2. Prepare the MDNS response request to send to SME */
16595 mdns_resp_info = vos_mem_malloc(sizeof(*mdns_resp_info));
16596 if (NULL == mdns_resp_info) {
16597 hddLog(LOGE, FL("could not allocate tSirMDNSResponseInfo!"));
16598 return FALSE;
16599 }
16600
16601 vos_mem_zero(mdns_resp_info, sizeof(*mdns_resp_info));
16602 mdns_resp_info->bss_idx = hostapd_adapter->sessionId;
16603 mdns_resp_info->mdns_resp_callback = hdd_mdns_resp_offload_done;
16604 mdns_resp_info->mdns_resp_cb_context = hostapd_adapter;
16605 if (!wlan_hdd_mdns_pack_response(hdd_ctx->cfg_ini, mdns_resp_info)) {
16606 hddLog(LOGE, FL("wlan_hdd_pack_mdns_response fail!"));
16607 vos_mem_free(mdns_resp_info);
16608 return FALSE;
16609 }
16610 if (eHAL_STATUS_SUCCESS !=
16611 sme_set_mdns_resp(hdd_ctx->hHal, mdns_resp_info)) {
16612 hddLog(LOGE, FL("sme_set_mdns_resp fail!"));
16613 vos_mem_free(mdns_resp_info);
16614 return FALSE;
16615 }
16616 vos_mem_free(mdns_resp_info);
16617
16618 /* 3. Prepare the MDNS Enable request to send to SME */
16619 mdns_offload_info = vos_mem_malloc(sizeof(*mdns_offload_info));
16620 if (NULL == mdns_offload_info) {
16621 hddLog(LOGE, FL("could not allocate tSirMDNSOffloadInfo!"));
16622 return FALSE;
16623 }
16624
16625 vos_mem_zero(mdns_offload_info, sizeof(*mdns_offload_info));
16626
16627 mdns_offload_info->bss_idx = hostapd_adapter->sessionId;
16628 mdns_offload_info->enable = hdd_ctx->cfg_ini->enable_mdns_offload;
16629 mdns_offload_info->mdns_enable_callback = hdd_mdns_enable_offload_done;
16630 mdns_offload_info->mdns_enable_cb_context = hostapd_adapter;
16631 if (eHAL_STATUS_SUCCESS !=
16632 sme_set_mdns_offload(hdd_ctx->hHal, mdns_offload_info)) {
16633 hddLog(LOGE, FL("sme_set_mdns_offload fail!"));
16634 vos_mem_free(mdns_offload_info);
16635 return FALSE;
16636 }
16637
16638 vos_mem_free(mdns_offload_info);
16639 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
16640 "%s: enable mDNS offload successfully!", __func__);
16641 return TRUE;
16642}
Manjeet Singh3ed79242017-01-11 19:04:32 +053016643
16644
Anurag Chouhan0b29de02016-12-16 13:18:40 +053016645#endif /* MDNS_OFFLOAD */
c_manjeecfd1efb2015-09-25 19:32:34 +053016646
Hanumanth Reddy Pothulad864f312017-01-18 16:16:08 +053016647/**
16648 * wlan_hdd_start_sap() - This function starts bss of SAP.
16649 * @ap_adapter: SAP adapter
16650 *
16651 * This function will process the starting of sap adapter.
16652 *
16653 * Return: void.
16654 */
16655void wlan_hdd_start_sap(hdd_adapter_t *ap_adapter)
16656{
16657 hdd_ap_ctx_t *hdd_ap_ctx;
16658 hdd_hostapd_state_t *hostapd_state;
16659 VOS_STATUS vos_status;
16660 hdd_context_t *hdd_ctx;
16661 tsap_Config_t *pConfig;
16662
16663 if (NULL == ap_adapter) {
16664 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
16665 FL("ap_adapter is NULL here"));
16666 return;
16667 }
16668
16669 hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter);
16670 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
16671 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
16672 pConfig = &ap_adapter->sessionCtx.ap.sapConfig;
16673
16674 mutex_lock(&hdd_ctx->sap_lock);
16675 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags))
16676 goto end;
16677
16678 if (0 != wlan_hdd_cfg80211_update_apies(ap_adapter)) {
16679 hddLog(LOGE, FL("SAP Not able to set AP IEs"));
16680 goto end;
16681 }
16682
16683 vos_event_reset(&hostapd_state->vosEvent);
16684 if (WLANSAP_StartBss(hdd_ctx->pvosContext, hdd_hostapd_SAPEventCB,
16685 &hdd_ap_ctx->sapConfig, (v_PVOID_t)ap_adapter->dev)
16686 != VOS_STATUS_SUCCESS) {
16687 goto end;
16688 }
16689
16690 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
16691 FL("Waiting for SAP to start"));
16692 vos_status = vos_wait_single_event(&hostapd_state->vosEvent, 10000);
16693 if (!VOS_IS_STATUS_SUCCESS(vos_status)) {
16694 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
16695 FL("SAP Start failed"));
16696 goto end;
16697 }
16698 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
16699 FL("SAP Start Success"));
16700 set_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
16701
16702 wlan_hdd_incr_active_session(hdd_ctx, ap_adapter->device_mode);
16703 hostapd_state->bCommit = TRUE;
16704
16705end:
16706 mutex_unlock(&hdd_ctx->sap_lock);
16707 return;
16708}
16709
Manjeet Singh3ed79242017-01-11 19:04:32 +053016710#ifdef WLAN_FEATURE_TSF
16711
16712/**
16713 * hdd_tsf_cb() - handle tsf request callback
16714 *
16715 * @pcb_cxt: pointer to the hdd_contex
16716 * @ptsf: pointer to struct stsf
16717 *
16718 * Based on the request sent .
16719 *
16720 * Return: Describe the execute result of this routine
16721 */
16722static int hdd_tsf_cb(void *pcb_ctx, struct stsf *ptsf)
16723{
16724 hdd_context_t *hddctx;
16725 int status;
16726 hdd_adapter_t* adapter = (hdd_adapter_t*)pcb_ctx;
16727
16728 if (pcb_ctx == NULL || ptsf == NULL) {
16729 hddLog(VOS_TRACE_LEVEL_ERROR,
16730 FL("HDD context is not valid"));
16731 return -EINVAL;
16732 }
16733
16734 hddctx = (hdd_context_t *)pcb_ctx;
16735 status = wlan_hdd_validate_context(hddctx);
16736 if (0 != status)
16737 return -EINVAL;
16738
16739 if (NULL == adapter) {
16740 hddLog(VOS_TRACE_LEVEL_ERROR,
16741 FL("failed to find adapter"));
16742 return -EINVAL;
16743 }
16744
16745 hddLog(VOS_TRACE_LEVEL_INFO,
16746 FL("tsf cb handle event, device_mode is %d"),
16747 adapter->device_mode);
16748
16749 /* copy the return value to hdd_tsf_ctx in adapter*/
16750 if (ptsf->tsf_req_status) {
16751
16752 vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
16753 adapter->tsf_cap_ctx.tsf_get_state = TSF_NOT_RETURNED_BY_FW;
16754 adapter->tsf_cap_ctx.tsf_capture_state = TSF_IDLE;
16755 vos_event_set (&adapter->tsf_cap_ctx.tsf_capture_done_event);
16756 vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
16757
16758 hddLog(VOS_TRACE_LEVEL_ERROR, FL("tsf req failure :%d"),
16759 ptsf->tsf_req_status);
16760 return ptsf->tsf_req_status;
16761 }
16762 /* If this is a get request.Store the tsf values in adapter. */
16763 if (!ptsf->set_tsf_req) {
16764 vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
16765 adapter->tsf_cap_ctx.tsf_low = ptsf->tsf_low;
16766 adapter->tsf_cap_ctx.tsf_high = ptsf->tsf_high;
16767 adapter->tsf_cap_ctx.tsf_get_state = TSF_RETURN;
16768 adapter->tsf_cap_ctx.tsf_capture_state = TSF_IDLE;
16769 vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
16770
16771 hddLog(VOS_TRACE_LEVEL_INFO,
16772 FL("hdd_get_tsf_cb sta=%u, tsf_low=%u, tsf_high=%u"),
16773 adapter->sessionId, ptsf->tsf_low, ptsf->tsf_high);
16774 }
16775 else {
16776 vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
16777 adapter->tsf_cap_ctx.tsf_capture_state = TSF_CAP_STATE;
16778 adapter->tsf_cap_ctx.tsf_get_state = TSF_CURRENT_IN_CAP_STATE;
16779 vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
16780 }
16781 vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
16782 vos_event_set (&adapter->tsf_cap_ctx.tsf_capture_done_event);
16783 vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
16784
16785 /* free allocated mem */
16786 vos_mem_free(ptsf);
16787
16788 return 0;
16789}
16790
16791/**
16792 * hdd_capture_tsf() - capture tsf
16793 *
16794 * @adapter: pointer to adapter
16795 * @buf: pointer to upper layer buf
16796 * @len : the length of buf
16797 *
16798 * This function returns tsf value to uplayer.
16799 *
16800 * Return: Describe the execute result of this routine
16801 */
16802int hdd_capture_tsf(hdd_adapter_t *adapter, uint32_t *buf, int len)
16803{
16804 int ret = 0;
16805 hdd_station_ctx_t *hdd_sta_ctx;
16806 hdd_context_t *hdd_ctx;
16807 tSirCapTsfParams cap_tsf_params;
16808 VOS_STATUS status;
16809
16810 if (adapter == NULL || buf == NULL) {
16811 hddLog(VOS_TRACE_LEVEL_ERROR,
16812 FL("invalid pointer"));
16813 return -EINVAL;
16814 }
16815 if (len != 1)
16816 return -EINVAL;
16817
16818 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
16819
16820 if (wlan_hdd_validate_context(hdd_ctx)) {
16821 hddLog(VOS_TRACE_LEVEL_ERROR,
16822 FL("invalid hdd ctx"));
16823 return -EINVAL;
16824 }
16825 if (adapter->device_mode == WLAN_HDD_INFRA_STATION ||
16826 adapter->device_mode == WLAN_HDD_P2P_CLIENT) {
16827 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
16828 if (hdd_sta_ctx->conn_info.connState !=
16829 eConnectionState_Associated) {
16830
16831 hddLog(VOS_TRACE_LEVEL_INFO,
16832 FL("failed to cap tsf, not connect with ap"));
16833 buf[0] = TSF_STA_NOT_CONNECTED_NO_TSF;
16834 return ret;
16835 }
16836 }
16837 if ((adapter->device_mode == WLAN_HDD_SOFTAP ||
16838 adapter->device_mode == WLAN_HDD_P2P_GO) &&
16839 !(test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags))) {
16840 hddLog(VOS_TRACE_LEVEL_INFO,
16841 FL("Soft AP / P2p GO not beaconing"));
16842 buf[0] = TSF_SAP_NOT_STARTED_NO_TSF;
16843 return ret;
16844 }
16845 if (adapter->tsf_cap_ctx.tsf_capture_state == TSF_CAP_STATE) {
16846 hddLog(VOS_TRACE_LEVEL_INFO,
16847 FL("current in capture state, pls reset"));
16848 buf[0] = TSF_CURRENT_IN_CAP_STATE;
16849 } else {
16850 hddLog(VOS_TRACE_LEVEL_INFO, FL("ioctl issue cap tsf cmd"));
16851 buf[0] = TSF_RETURN;
16852 cap_tsf_params.session_id = adapter->sessionId;
16853 cap_tsf_params.tsf_rsp_cb_func = hdd_tsf_cb;
16854 cap_tsf_params.tsf_rsp_cb_ctx = adapter;
16855
16856 vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
16857 adapter->tsf_cap_ctx.tsf_capture_state = TSF_CAP_STATE;
16858 adapter->tsf_cap_ctx.tsf_get_state = TSF_CURRENT_IN_CAP_STATE;
16859 vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
16860
16861 ret = sme_capture_tsf_req(hdd_ctx->hHal, cap_tsf_params);
16862
16863 if (ret != VOS_STATUS_SUCCESS) {
16864 hddLog(VOS_TRACE_LEVEL_ERROR, FL("capture fail"));
16865 buf[0] = TSF_CAPTURE_FAIL;
16866 vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
16867 adapter->tsf_cap_ctx.tsf_capture_state = TSF_IDLE;
16868 vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
16869 return -EINVAL;
16870 }
16871 /* wait till we get a response from fw */
16872 status = vos_wait_single_event(&adapter->tsf_cap_ctx.
16873 tsf_capture_done_event,
16874 HDD_TSF_CAP_REQ_TIMEOUT);
16875
16876 if (!VOS_IS_STATUS_SUCCESS(status)) {
16877 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
16878 ("capture tsf vos wait for single_event failed!! %d"),
16879 adapter->tsf_cap_ctx.tsf_get_state);
16880
16881 vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
16882 adapter->tsf_cap_ctx.tsf_capture_state = TSF_IDLE;
16883 vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
16884
16885 return -EINVAL;
16886 }
16887 }
16888 buf[0] = TSF_RETURN;
16889 hddLog(VOS_TRACE_LEVEL_INFO,
16890 FL("ioctl return cap tsf cmd, ret = %d"), ret);
16891 return ret;
16892}
16893
16894/**
16895 * hdd_indicate_tsf() - return tsf to uplayer
16896 *
16897 * @adapter: pointer to adapter
16898 * @buf: pointer to uplayer buf
16899 * @len : the length of buf
16900 *
16901 * This function returns tsf value to uplayer.
16902 *
16903 * Return: Describe the execute result of this routine
16904 */
16905int hdd_indicate_tsf(hdd_adapter_t *adapter, uint32_t *buf, int len)
16906{
16907 int ret = 0;
16908 hdd_station_ctx_t *hdd_sta_ctx;
16909 hdd_context_t *hdd_ctx;
16910 tSirCapTsfParams cap_tsf_params;
16911 VOS_STATUS status;
16912
16913 if (adapter == NULL || buf == NULL) {
16914 hddLog(VOS_TRACE_LEVEL_ERROR,
16915 FL("invalid pointer"));
16916 return -EINVAL;
16917 }
16918 if (len != 3)
16919 return -EINVAL;
16920
16921 buf [1] = 0;
16922 buf [2] = 0;
16923 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
16924
16925 if (wlan_hdd_validate_context(hdd_ctx)) {
16926 hddLog(VOS_TRACE_LEVEL_ERROR,
16927 FL("invalid hdd ctx"));
16928 return -EINVAL;
16929 }
16930 if (adapter->device_mode == WLAN_HDD_INFRA_STATION ||
16931 adapter->device_mode == WLAN_HDD_P2P_CLIENT) {
16932 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
16933 if (hdd_sta_ctx->conn_info.connState !=
16934 eConnectionState_Associated) {
16935
16936 hddLog(VOS_TRACE_LEVEL_INFO,
16937 FL("failed to cap tsf, not connect with ap"));
16938 buf[0] = TSF_STA_NOT_CONNECTED_NO_TSF;
16939 return ret;
16940 }
16941 }
16942 if ((adapter->device_mode == WLAN_HDD_SOFTAP ||
16943 adapter->device_mode == WLAN_HDD_P2P_GO) &&
16944 !(test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags))) {
16945 hddLog(VOS_TRACE_LEVEL_INFO,
16946 FL("Soft AP / P2p GO not beaconing"));
16947 buf[0] = TSF_SAP_NOT_STARTED_NO_TSF;
16948 return ret;
16949 }
16950
16951 if (adapter->tsf_cap_ctx.tsf_capture_state != TSF_CAP_STATE ||
16952 adapter->tsf_cap_ctx.tsf_get_state != TSF_CURRENT_IN_CAP_STATE ) {
16953 hddLog(VOS_TRACE_LEVEL_INFO,
16954 FL("Not in capture state,Enter capture state first"));
16955 buf[0] = TSF_GET_FAIL;
16956 } else {
16957 hddLog(VOS_TRACE_LEVEL_INFO, FL("ioctl issue cap tsf cmd"));
16958 cap_tsf_params.session_id = adapter->sessionId;
16959 cap_tsf_params.tsf_rsp_cb_func = hdd_tsf_cb;
16960 cap_tsf_params.tsf_rsp_cb_ctx = adapter;
16961
16962 ret = sme_get_tsf_req(hdd_ctx->hHal, cap_tsf_params);
16963
16964 if (ret != VOS_STATUS_SUCCESS) {
16965 hddLog(VOS_TRACE_LEVEL_ERROR, FL("capture fail"));
16966 buf[0] = TSF_CAPTURE_FAIL;
16967 vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
16968 adapter->tsf_cap_ctx.tsf_capture_state = TSF_IDLE;
16969 vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
16970 return -EINVAL;
16971 }
16972 /* wait till we get a response from fw */
16973 status = vos_wait_single_event(&adapter->tsf_cap_ctx.
16974 tsf_capture_done_event,
16975 HDD_TSF_GET_REQ_TIMEOUT);
16976
16977 if (!VOS_IS_STATUS_SUCCESS(status)) {
16978 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
16979 ("capture tsf vos wait for single_event failed!! %d"),
16980 status);
16981
16982 vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
16983 adapter->tsf_cap_ctx.tsf_capture_state = TSF_IDLE;
16984 vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
16985 return status;
16986 }
16987 buf[1] = adapter->tsf_cap_ctx.tsf_low;
16988 buf[2] = adapter->tsf_cap_ctx.tsf_high;
16989
16990 hddLog(VOS_TRACE_LEVEL_INFO,
16991 FL("get tsf cmd,status=%u, tsf_low=%u, tsf_high=%u"),
16992 buf[0], buf[1], buf[2]);
16993 }
16994 hddLog(VOS_TRACE_LEVEL_INFO,
16995 FL("ioctl return cap tsf cmd, ret = %d"), ret);
16996 return ret;
16997}
16998
16999void wlan_hdd_tsf_init(hdd_adapter_t *adapter)
17000{
17001
17002 if (adapter == NULL) {
17003 hddLog(VOS_TRACE_LEVEL_ERROR,
17004 FL("TSF init on a null adapter!"));
17005 return;
17006 }
17007
17008 adapter->tsf_cap_ctx.tsf_get_state = TSF_RETURN;
17009 adapter->tsf_cap_ctx.tsf_capture_state = TSF_IDLE;
17010 vos_event_init(&adapter->tsf_cap_ctx.tsf_capture_done_event);
17011 vos_spin_lock_init(&adapter->tsf_cap_ctx.tsf_lock);
17012 adapter->tsf_cap_ctx.tsf_high = 0;
17013 adapter->tsf_cap_ctx.tsf_low = 0;
17014}
17015
17016#endif
17017
Jeff Johnson295189b2012-06-20 16:38:30 -070017018//Register the module init/exit functions
17019module_init(hdd_module_init);
17020module_exit(hdd_module_exit);
17021
17022MODULE_LICENSE("Dual BSD/GPL");
17023MODULE_AUTHOR("Qualcomm Atheros, Inc.");
17024MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
17025
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070017026module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
17027 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -070017028
Jeff Johnson76052702013-04-16 13:55:05 -070017029module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -070017030 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Arif Hussain66559122013-11-21 10:11:40 -080017031
17032module_param(enable_dfs_chan_scan, int,
17033 S_IRUSR | S_IRGRP | S_IROTH);
17034
17035module_param(enable_11d, int,
17036 S_IRUSR | S_IRGRP | S_IROTH);
17037
17038module_param(country_code, charp,
17039 S_IRUSR | S_IRGRP | S_IROTH);