blob: ce3af45b690ee2b93e35fb0e4a356943957b2e9c [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 */
904 sscanf(inPtr, "%32s ", buf);
905 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
2591 *
2592 * Return: 0 for success non-zero for failure
2593 */
2594static int
2595hdd_parse_reassoc_v2(hdd_adapter_t *pAdapter, const char *command)
2596{
2597 struct android_wifi_reassoc_params params;
2598 tSirMacAddr bssid;
2599 int ret;
2600
2601 /* The params are located after "REASSOC " */
2602 memcpy(&params, command + 8, sizeof(params));
2603
2604 if (!mac_pton(params.bssid, (u8 *)&bssid)) {
2605 hddLog(LOGE, FL("MAC address parsing failed"));
2606 ret = -EINVAL;
2607 } else {
Selvaraj, Sridhar4fa15232016-06-18 12:27:25 +05302608 ret = hdd_reassoc(pAdapter, bssid, params.channel, REASSOC);
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05302609 }
2610 return ret;
2611}
2612
2613/**
2614 * hdd_parse_reassoc() - parse the REASSOC command
2615 * There are two different versions of the REASSOC command.Version 1
2616 * of the command contains a parameter list that is ASCII characters
2617 * whereas version 2 contains a combination of ASCII and binary
2618 * payload. Determine if a version 1 or a version 2 command is being
2619 * parsed by examining the parameters, and then dispatch the parser
2620 * that is appropriate for the command.
2621 *
2622 * @pAdapter: Adapter upon which the command was received
2623 * @command: command that was received
2624 *
2625 * Return: 0 for success non-zero for failure
2626 */
2627static int
2628hdd_parse_reassoc(hdd_adapter_t *pAdapter, const char *command)
2629{
2630 int ret;
2631
2632 /*
2633 * both versions start with "REASSOC"
2634 * v1 has a bssid and channel # as an ASCII string
2635 * REASSOC xx:xx:xx:xx:xx:xx CH
2636 * v2 has a C struct
2637 * REASSOC <binary c struct>
2638 *
2639 * The first field in the v2 struct is also the bssid in ASCII.
2640 * But in the case of a v2 message the BSSID is NUL-terminated.
2641 * Hence we can peek at that offset to see if this is V1 or V2
2642 * REASSOC xx:xx:xx:xx:xx:xx*
2643 * 1111111111222222
2644 * 01234567890123456789012345
2645 */
2646 if (command[25])
2647 ret = hdd_parse_reassoc_v1(pAdapter, command);
2648 else
2649 ret = hdd_parse_reassoc_v2(pAdapter, command);
2650
2651 return ret;
2652}
2653#endif /* WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_ESE FEATURE_WLAN_LFR */
2654
c_hpothu92367912014-05-01 15:18:17 +05302655static void getBcnMissRateCB(VOS_STATUS status, int bcnMissRate, void *data)
2656{
c_hpothu39eb1e32014-06-26 16:31:50 +05302657 bcnMissRateContext_t *pCBCtx;
2658
2659 if (NULL == data)
2660 {
2661 hddLog(VOS_TRACE_LEVEL_ERROR, FL("argument data is NULL"));
2662 return;
2663 }
c_hpothu92367912014-05-01 15:18:17 +05302664
2665 /* there is a race condition that exists between this callback
2666 function and the caller since the caller could time out either
2667 before or while this code is executing. we use a spinlock to
2668 serialize these actions */
2669 spin_lock(&hdd_context_lock);
2670
c_hpothu39eb1e32014-06-26 16:31:50 +05302671 pCBCtx = (bcnMissRateContext_t *)data;
c_hpothu92367912014-05-01 15:18:17 +05302672 gbcnMissRate = -1;
2673
c_hpothu39eb1e32014-06-26 16:31:50 +05302674 if (pCBCtx->magic != BCN_MISS_RATE_CONTEXT_MAGIC)
c_hpothu92367912014-05-01 15:18:17 +05302675 {
2676 hddLog(VOS_TRACE_LEVEL_ERROR,
c_hpothu39eb1e32014-06-26 16:31:50 +05302677 FL("invalid context magic: %08x"), pCBCtx->magic);
c_hpothu92367912014-05-01 15:18:17 +05302678 spin_unlock(&hdd_context_lock);
2679 return ;
2680 }
2681
2682 if (VOS_STATUS_SUCCESS == status)
2683 {
c_hpothu39eb1e32014-06-26 16:31:50 +05302684 gbcnMissRate = bcnMissRate;
c_hpothu92367912014-05-01 15:18:17 +05302685 }
c_hpothu39eb1e32014-06-26 16:31:50 +05302686 else
2687 {
2688 hddLog(VOS_TRACE_LEVEL_ERROR, FL("failed to get bcnMissRate"));
2689 }
2690
c_hpothu92367912014-05-01 15:18:17 +05302691 complete(&(pCBCtx->completion));
2692 spin_unlock(&hdd_context_lock);
2693
2694 return;
2695}
2696
Abhishek Singh08aa7762014-12-16 13:59:03 +05302697void hdd_FWStatisCB( VOS_STATUS status,
2698 tSirFwStatsResult *fwStatsResult, void *pContext )
Satyanarayana Dash72806012014-12-02 14:30:08 +05302699{
2700 fwStatsContext_t *fwStatsCtx;
Satyanarayana Dash72806012014-12-02 14:30:08 +05302701 hdd_adapter_t *pAdapter;
2702
2703 hddLog(VOS_TRACE_LEVEL_INFO, FL(" with status = %d"),status);
2704
Abhishek Singh08aa7762014-12-16 13:59:03 +05302705 if (NULL == pContext)
Satyanarayana Dash72806012014-12-02 14:30:08 +05302706 {
2707 hddLog(VOS_TRACE_LEVEL_ERROR, FL("argument data is NULL"));
2708 return;
2709 }
2710 /* there is a race condition that exists between this callback
2711 function and the caller since the caller could time out either
2712 before or while this code is executing. we use a spinlock to
2713 serialize these actions */
2714 spin_lock(&hdd_context_lock);
Abhishek Singh08aa7762014-12-16 13:59:03 +05302715 fwStatsCtx = (fwStatsContext_t *) pContext;
Satyanarayana Dash72806012014-12-02 14:30:08 +05302716 if (fwStatsCtx->magic != FW_STATS_CONTEXT_MAGIC)
2717 {
2718 hddLog(VOS_TRACE_LEVEL_ERROR,
2719 FL("invalid context magic: %08x"), fwStatsCtx->magic);
2720 spin_unlock(&hdd_context_lock);
2721 return;
2722 }
2723 pAdapter = fwStatsCtx->pAdapter;
2724 if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
2725 {
2726 hddLog(VOS_TRACE_LEVEL_ERROR,
2727 FL("pAdapter returned is NULL or invalid"));
2728 spin_unlock(&hdd_context_lock);
2729 return;
2730 }
2731 pAdapter->fwStatsRsp.type = 0;
Abhishek Singh08aa7762014-12-16 13:59:03 +05302732 if ((VOS_STATUS_SUCCESS == status) && (NULL != fwStatsResult))
Satyanarayana Dash72806012014-12-02 14:30:08 +05302733 {
Satyanarayana Dash72806012014-12-02 14:30:08 +05302734 switch( fwStatsResult->type )
2735 {
2736 case FW_UBSP_STATS:
2737 {
Abhishek Singh08aa7762014-12-16 13:59:03 +05302738 memcpy(&pAdapter->fwStatsRsp,fwStatsResult,sizeof(tSirFwStatsResult));
Satyanarayana Dash72806012014-12-02 14:30:08 +05302739 hddLog(VOS_TRACE_LEVEL_INFO,
2740 FL("ubsp_enter_cnt = %d ubsp_jump_ddr_cnt = %d"),
Abhishek Singh08aa7762014-12-16 13:59:03 +05302741 pAdapter->fwStatsRsp.fwStatsData.ubspStats.ubsp_enter_cnt,
2742 pAdapter->fwStatsRsp.fwStatsData.ubspStats.ubsp_jump_ddr_cnt);
Satyanarayana Dash72806012014-12-02 14:30:08 +05302743 }
2744 break;
2745 default:
2746 {
2747 hddLog(VOS_TRACE_LEVEL_ERROR,
2748 FL(" No handling for stats type %d"),fwStatsResult->type);
2749 }
2750 }
2751 }
2752 complete(&(fwStatsCtx->completion));
2753 spin_unlock(&hdd_context_lock);
2754 return;
2755}
2756
jge35567202017-06-21 16:39:38 +08002757/*
2758 *hdd_parse_setmaxtxpower_command() - HDD Parse MAXTXPOWER command
2759 *@pValue Pointer to MAXTXPOWER command
2760 *@pTxPower Pointer to tx power
2761 *
2762 *This function parses the MAXTXPOWER command passed in the format
2763 * MAXTXPOWER<space>X(Tx power in dbm)
2764 * For example input commands:
2765 * 1) MAXTXPOWER -8 -> This is translated into set max TX power to -8 dbm
2766 * 2) MAXTXPOWER -23 -> This is translated into set max TX power to -23 dbm
2767 *
2768 *return - 0 for success non-zero for failure
2769 */
2770static int hdd_parse_setmaxtxpower_command(unsigned char *pValue, int *pTxPower)
2771{
2772 unsigned char *inPtr = pValue;
2773 int tempInt;
2774 int v = 0;
2775 *pTxPower = 0;
2776
2777 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
2778 /* no argument after the command */
2779 if (NULL == inPtr)
2780 return -EINVAL;
2781 /* no space after the command */
2782 else if (SPACE_ASCII_VALUE != *inPtr)
2783 return -EINVAL;
2784
2785 /* removing empty spaces */
2786 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
2787
2788 /* no argument followed by spaces */
2789 if ('\0' == *inPtr)
2790 return 0;
2791
2792 v = kstrtos32(inPtr, 10, &tempInt);
2793
2794 /* Range checking for passed parameter */
2795 if ((tempInt < HDD_MIN_TX_POWER) || (tempInt > HDD_MAX_TX_POWER))
2796 return -EINVAL;
2797
2798 *pTxPower = tempInt;
2799
2800 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2801 "SETMAXTXPOWER: %d", *pTxPower);
2802
2803 return 0;
2804}
2805
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302806static int hdd_get_dwell_time(hdd_config_t *pCfg, tANI_U8 *command, char *extra, tANI_U8 n, tANI_U8 *len)
2807{
2808 int ret = 0;
2809
2810 if (!pCfg || !command || !extra || !len)
2811 {
2812 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2813 "%s: argument passsed for GETDWELLTIME is incorrect", __func__);
2814 ret = -EINVAL;
2815 return ret;
2816 }
2817
2818 if (strncmp(command, "GETDWELLTIME ACTIVE MAX", 23) == 0)
2819 {
2820 *len = scnprintf(extra, n, "GETDWELLTIME ACTIVE MAX %u\n",
2821 (int)pCfg->nActiveMaxChnTime);
2822 return ret;
2823 }
2824 else if (strncmp(command, "GETDWELLTIME ACTIVE MIN", 23) == 0)
2825 {
2826 *len = scnprintf(extra, n, "GETDWELLTIME ACTIVE MIN %u\n",
2827 (int)pCfg->nActiveMinChnTime);
2828 return ret;
2829 }
2830 else if (strncmp(command, "GETDWELLTIME PASSIVE MAX", 24) == 0)
2831 {
2832 *len = scnprintf(extra, n, "GETDWELLTIME PASSIVE MAX %u\n",
2833 (int)pCfg->nPassiveMaxChnTime);
2834 return ret;
2835 }
2836 else if (strncmp(command, "GETDWELLTIME PASSIVE MIN", 24) == 0)
2837 {
2838 *len = scnprintf(extra, n, "GETDWELLTIME PASSIVE MIN %u\n",
2839 (int)pCfg->nPassiveMinChnTime);
2840 return ret;
2841 }
Rajesh Babu Prathipati0fd227e2014-07-05 12:50:00 +05302842 else if (strncmp(command, "GETDWELLTIME", 12) == 0)
2843 {
2844 *len = scnprintf(extra, n, "GETDWELLTIME %u \n",
2845 (int)pCfg->nActiveMaxChnTime);
2846 return ret;
2847 }
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302848 else
2849 {
2850 ret = -EINVAL;
2851 }
2852
2853 return ret;
2854}
2855
2856static int hdd_set_dwell_time(hdd_adapter_t *pAdapter, tANI_U8 *command)
2857{
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302858 tHalHandle hHal;
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302859 hdd_config_t *pCfg;
2860 tANI_U8 *value = command;
2861 int val = 0, ret = 0, temp = 0;
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302862 tSmeConfigParams smeConfig;
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302863
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302864 if (!pAdapter || !command || !(pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini)
2865 || !(hHal = (WLAN_HDD_GET_HAL_CTX(pAdapter))))
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302866 {
2867 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2868 "%s: argument passed for SETDWELLTIME is incorrect", __func__);
2869 ret = -EINVAL;
2870 return ret;
2871 }
2872
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302873 vos_mem_zero(&smeConfig, sizeof(smeConfig));
2874 sme_GetConfigParam(hHal, &smeConfig);
2875
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302876 if (strncmp(command, "SETDWELLTIME ACTIVE MAX", 23) == 0 )
2877 {
2878 value = value + 24;
2879 temp = kstrtou32(value, 10, &val);
2880 if (temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_MIN ||
2881 val > CFG_ACTIVE_MAX_CHANNEL_TIME_MAX )
2882 {
2883 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2884 "%s: argument passed for SETDWELLTIME ACTIVE MAX is incorrect", __func__);
2885 ret = -EFAULT;
2886 return ret;
2887 }
2888 pCfg->nActiveMaxChnTime = val;
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302889 smeConfig.csrConfig.nActiveMaxChnTime = val;
2890 sme_UpdateConfig(hHal, &smeConfig);
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302891 }
2892 else if (strncmp(command, "SETDWELLTIME ACTIVE MIN", 23) == 0)
2893 {
2894 value = value + 24;
2895 temp = kstrtou32(value, 10, &val);
2896 if (temp !=0 || val < CFG_ACTIVE_MIN_CHANNEL_TIME_MIN ||
2897 val > CFG_ACTIVE_MIN_CHANNEL_TIME_MAX )
2898 {
2899 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2900 "%s: argument passsed for SETDWELLTIME ACTIVE MIN is incorrect", __func__);
2901 ret = -EFAULT;
2902 return ret;
2903 }
2904 pCfg->nActiveMinChnTime = val;
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302905 smeConfig.csrConfig.nActiveMinChnTime = val;
2906 sme_UpdateConfig(hHal, &smeConfig);
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302907 }
2908 else if (strncmp(command, "SETDWELLTIME PASSIVE MAX", 24) == 0)
2909 {
2910 value = value + 25;
2911 temp = kstrtou32(value, 10, &val);
2912 if (temp != 0 || val < CFG_PASSIVE_MAX_CHANNEL_TIME_MIN ||
2913 val > CFG_PASSIVE_MAX_CHANNEL_TIME_MAX )
2914 {
2915 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2916 "%s: argument passed for SETDWELLTIME PASSIVE MAX is incorrect", __func__);
2917 ret = -EFAULT;
2918 return ret;
2919 }
2920 pCfg->nPassiveMaxChnTime = val;
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302921 smeConfig.csrConfig.nPassiveMaxChnTime = val;
2922 sme_UpdateConfig(hHal, &smeConfig);
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302923 }
2924 else if (strncmp(command, "SETDWELLTIME PASSIVE MIN", 24) == 0)
2925 {
2926 value = value + 25;
2927 temp = kstrtou32(value, 10, &val);
2928 if (temp != 0 || val < CFG_PASSIVE_MIN_CHANNEL_TIME_MIN ||
2929 val > CFG_PASSIVE_MIN_CHANNEL_TIME_MAX )
2930 {
2931 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2932 "%s: argument passed for SETDWELLTIME PASSIVE MIN is incorrect", __func__);
2933 ret = -EFAULT;
2934 return ret;
2935 }
2936 pCfg->nPassiveMinChnTime = val;
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302937 smeConfig.csrConfig.nPassiveMinChnTime = val;
2938 sme_UpdateConfig(hHal, &smeConfig);
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302939 }
Rajesh Babu Prathipati0fd227e2014-07-05 12:50:00 +05302940 else if (strncmp(command, "SETDWELLTIME", 12) == 0)
2941 {
2942 value = value + 13;
2943 temp = kstrtou32(value, 10, &val);
2944 if (temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_MIN ||
2945 val > CFG_ACTIVE_MAX_CHANNEL_TIME_MAX )
2946 {
2947 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2948 "%s: argument passed for SETDWELLTIME is incorrect", __func__);
2949 ret = -EFAULT;
2950 return ret;
2951 }
2952 pCfg->nActiveMaxChnTime = val;
2953 smeConfig.csrConfig.nActiveMaxChnTime = val;
2954 sme_UpdateConfig(hHal, &smeConfig);
2955 }
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302956 else
2957 {
2958 ret = -EINVAL;
2959 }
2960
2961 return ret;
2962}
Agarwal Ashish8bd53ae2015-06-12 18:03:45 +05302963static int hdd_cmd_setFccChannel(hdd_context_t *pHddCtx, tANI_U8 *cmd,
2964 tANI_U8 cmd_len)
2965{
2966 tANI_U8 *value;
2967 tANI_U8 fcc_constraint;
2968
2969 eHalStatus status;
2970 int ret = 0;
2971 value = cmd + cmd_len + 1;
2972
2973 ret = kstrtou8(value, 10, &fcc_constraint);
2974 if ((ret < 0) || (fcc_constraint > 1)) {
2975 /*
2976 * If the input value is greater than max value of datatype,
2977 * then also it is a failure
2978 */
2979 hddLog(VOS_TRACE_LEVEL_ERROR,
2980 "%s: value out of range", __func__);
2981 return -EINVAL;
2982 }
2983
Agrawal Ashish842eea82016-02-04 17:56:16 +05302984 status = sme_handleSetFccChannel(pHddCtx->hHal, fcc_constraint,
2985 pHddCtx->scan_info.mScanPending);
Agarwal Ashish8bd53ae2015-06-12 18:03:45 +05302986 if (status != eHAL_STATUS_SUCCESS)
2987 ret = -EPERM;
2988
2989 return ret;
2990}
2991
Mahesh A Saptasagarbeca12c2015-09-07 16:21:06 +05302992/**---------------------------------------------------------------------------
Agarwal Ashish8bd53ae2015-06-12 18:03:45 +05302993
Mahesh A Saptasagarbeca12c2015-09-07 16:21:06 +05302994 \brief hdd_enable_disable_ca_event() - When Host sends IOCTL (enabled),
2995 FW will send *ONE* CA ind to Host(even though it is duplicate).
2996 When Host send IOCTL (disable), FW doesn't perform any action.
2997 Whenever any change in CA *and* WLAN is in SAP/P2P-GO mode, FW
2998 sends CA ind to host. (regard less of IOCTL status)
2999 \param - pHddCtx - HDD context
3000 \param - command - command received from framework
3001 \param - cmd_len - len of the command
3002
3003 \return - 0 on success, appropriate error values on failure.
3004
3005 --------------------------------------------------------------------------*/
3006int hdd_enable_disable_ca_event(hdd_context_t *pHddCtx, tANI_U8* command, tANI_U8 cmd_len)
3007{
3008 tANI_U8 set_value;
3009 int ret = 0;
3010 eHalStatus status;
3011
3012 ret = wlan_hdd_validate_context(pHddCtx);
3013 if (0 != ret)
3014 {
3015 ret = -EINVAL;
3016 goto exit;
3017 }
3018
3019 if (pHddCtx->cfg_ini->gOptimizeCAevent == 0)
3020 {
3021 hddLog(VOS_TRACE_LEVEL_ERROR, "Enable gOptimizeCAevent"
3022 " ini param to control channel avooidance indication");
3023 ret = 0;
3024 goto exit;
3025 }
3026
3027 set_value = command[cmd_len + 1] - '0';
3028 status = sme_enableDisableChanAvoidIndEvent(pHddCtx->hHal, set_value);
3029 if (status != eHAL_STATUS_SUCCESS)
3030 {
3031 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to send"
3032 " enableDisableChanAoidance command to SME\n", __func__);
3033 ret = -EINVAL;
3034 }
3035
3036exit:
3037 return ret;
3038}
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05303039
Selvaraj, Sridhar3714c4d2016-06-22 15:19:12 +05303040/**
3041 * wlan_hdd_fastreassoc_handoff_request() - Post Handoff request to SME
3042 * @pHddCtx: Pointer to the HDD context
3043 * @channel: channel to reassociate
3044 * @targetApBssid: Target AP/BSSID to reassociate
3045 *
3046 * Return: None
3047 */
3048#if defined(WLAN_FEATURE_ROAM_SCAN_OFFLOAD) && !defined(QCA_WIFI_ISOC)
3049static void wlan_hdd_fastreassoc_handoff_request(hdd_context_t *pHddCtx,
3050 uint8_t channel, tSirMacAddr targetApBssid)
3051{
3052 tCsrHandoffRequest handoffInfo;
3053 handoffInfo.channel = channel;
3054 handoffInfo.src = FASTREASSOC;
3055 vos_mem_copy(handoffInfo.bssid, targetApBssid, sizeof(tSirMacAddr));
3056 sme_HandoffRequest(pHddCtx->hHal, &handoffInfo);
3057}
3058#else
3059static void wlan_hdd_fastreassoc_handoff_request(hdd_context_t *pHddCtx,
3060 uint8_t channel, tSirMacAddr targetApBssid)
3061{
3062}
3063#endif
3064
3065/**
3066 * csr_fastroam_neighbor_ap_event() - Function to trigger scan/roam
3067 * @pAdapter: Pointer to HDD adapter
3068 * @channel: Channel to scan/roam
3069 * @targetApBssid: BSSID to roam
3070 *
3071 * Return: None
3072 */
3073#ifdef QCA_WIFI_ISOC
3074static void csr_fastroam_neighbor_ap_event(hdd_adapter_t *pAdapter,
3075 uint8_t channel, tSirMacAddr targetApBssid)
3076{
3077 smeIssueFastRoamNeighborAPEvent(WLAN_HDD_GET_HAL_CTX(pAdapter),
3078 &targetApBssid[0], eSME_ROAM_TRIGGER_SCAN, channel);
3079}
3080#else
3081static void csr_fastroam_neighbor_ap_event(hdd_adapter_t *pAdapter,
3082 uint8_t channel, tSirMacAddr targetApBssid)
3083{
3084}
3085#endif
3086
3087/**
3088 * wlan_hdd_handle_fastreassoc() - Handle fastreassoc command
3089 * @pAdapter: pointer to hdd adapter
3090 * @command: pointer to the command received
3091 *
3092 * Return: VOS_STATUS enum
3093 */
3094static VOS_STATUS wlan_hdd_handle_fastreassoc(hdd_adapter_t *pAdapter,
3095 uint8_t *command)
3096{
3097 tANI_U8 *value = command;
3098 tANI_U8 channel = 0;
3099 tSirMacAddr targetApBssid;
Selvaraj, Sridhar3714c4d2016-06-22 15:19:12 +05303100 hdd_station_ctx_t *pHddStaCtx = NULL;
3101 hdd_context_t *pHddCtx = NULL;
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05303102 int ret;
Selvaraj, Sridhar349b8fe2017-01-18 13:11:25 +05303103 tCsrRoamModifyProfileFields mod_profile_fields;
3104 uint32_t roam_id = 0;
Selvaraj, Sridhar3714c4d2016-06-22 15:19:12 +05303105 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3106 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3107
3108 /* if not associated, no need to proceed with reassoc */
3109 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
3110 hddLog(LOG1, FL("Not associated!"));
3111 return eHAL_STATUS_FAILURE;
3112 }
3113
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05303114 ret = hdd_parse_reassoc_command_v1_data(value, targetApBssid, &channel);
3115 if (ret) {
Selvaraj, Sridhar3714c4d2016-06-22 15:19:12 +05303116 hddLog(LOGE, FL("Failed to parse reassoc command data"));
3117 return eHAL_STATUS_FAILURE;
3118 }
3119
3120 /* if the target bssid is same as currently associated AP,
3121 then no need to proceed with reassoc */
3122 if (vos_mem_compare(targetApBssid,
3123 pHddStaCtx->conn_info.bssId,
3124 sizeof(tSirMacAddr))) {
Selvaraj, Sridhar349b8fe2017-01-18 13:11:25 +05303125 sme_GetModifyProfileFields(pHddCtx->hHal, pAdapter->sessionId,
3126 &mod_profile_fields);
3127 sme_RoamReassoc(pHddCtx->hHal, pAdapter->sessionId, NULL,
3128 mod_profile_fields, &roam_id, 1);
Selvaraj, Sridhar3714c4d2016-06-22 15:19:12 +05303129 hddLog(LOG1, FL("Reassoc BSSID is same as currently associated AP bssid"));
Selvaraj, Sridhar349b8fe2017-01-18 13:11:25 +05303130 return eHAL_STATUS_SUCCESS;
Selvaraj, Sridhar3714c4d2016-06-22 15:19:12 +05303131 }
3132
3133 /* Check channel number is a valid channel number */
3134 if (VOS_STATUS_SUCCESS !=
3135 wlan_hdd_validate_operation_channel(pAdapter, channel)) {
3136 hddLog(LOGE, FL("Invalid Channel [%d]"), channel);
3137 return eHAL_STATUS_FAILURE;
3138 }
3139
3140 /* Proceed with reassoc */
3141 wlan_hdd_fastreassoc_handoff_request(pHddCtx, channel, targetApBssid);
3142
3143 /* Proceed with scan/roam */
3144 csr_fastroam_neighbor_ap_event(pAdapter, channel, targetApBssid);
3145
3146 return eHAL_STATUS_SUCCESS;
3147}
3148
3149/**
3150 * hdd_assign_reassoc_handoff - Set handoff source as REASSOC
3151 * @handoffInfo: Pointer to the csr Handoff Request.
3152 *
3153 * Return: None
3154 */
3155#ifndef QCA_WIFI_ISOC
3156static inline void hdd_assign_reassoc_handoff(tCsrHandoffRequest *handoffInfo)
3157{
3158 handoffInfo->src = REASSOC;
3159}
3160#else
3161static inline void hdd_assign_reassoc_handoff(tCsrHandoffRequest *handoffInfo)
3162{
3163}
3164#endif
3165
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003166static int hdd_driver_command(hdd_adapter_t *pAdapter,
3167 hdd_priv_data_t *ppriv_data)
Jeff Johnson295189b2012-06-20 16:38:30 -07003168{
Jeff Johnson295189b2012-06-20 16:38:30 -07003169 hdd_priv_data_t priv_data;
3170 tANI_U8 *command = NULL;
Kaushik, Sushant96122442014-10-21 16:40:18 +05303171 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3172 hdd_scaninfo_t *pScanInfo = NULL;
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003173 int ret = 0;
Kaushik, Sushant96122442014-10-21 16:40:18 +05303174 int status;
Anand N Sunkade9adb1b2015-07-29 09:56:45 +05303175#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0))
3176 struct cfg80211_mgmt_tx_params params;
3177#endif
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05303178
3179 ENTER();
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003180 /*
3181 * Note that valid pointers are provided by caller
3182 */
Jeff Johnson295189b2012-06-20 16:38:30 -07003183
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003184 /* copy to local struct to avoid numerous changes to legacy code */
3185 priv_data = *ppriv_data;
Jeff Johnson295189b2012-06-20 16:38:30 -07003186
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003187 if (priv_data.total_len <= 0 ||
3188 priv_data.total_len > WLAN_PRIV_DATA_MAX_LEN)
Sameer Thalappil8ef3a0e2013-04-05 14:36:04 -07003189 {
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003190 hddLog(VOS_TRACE_LEVEL_WARN,
3191 "%s:invalid priv_data.total_len(%d)!!!", __func__,
3192 priv_data.total_len);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003193 ret = -EINVAL;
3194 goto exit;
3195 }
Kaushik, Sushant96122442014-10-21 16:40:18 +05303196 status = wlan_hdd_validate_context(pHddCtx);
3197 if (0 != status)
3198 {
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05303199 ret = -EINVAL;
3200 goto exit;
Kaushik, Sushant96122442014-10-21 16:40:18 +05303201 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003202 /* Allocate +1 for '\0' */
3203 command = kmalloc(priv_data.total_len + 1, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07003204 if (!command)
3205 {
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003206 hddLog(VOS_TRACE_LEVEL_ERROR,
3207 "%s: failed to allocate memory", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003208 ret = -ENOMEM;
3209 goto exit;
3210 }
3211
3212 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
3213 {
3214 ret = -EFAULT;
3215 goto exit;
3216 }
3217
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003218 /* Make sure the command is NUL-terminated */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003219 command[priv_data.total_len] = '\0';
3220
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003221 /* at one time the following block of code was conditional. braces
3222 * have been retained to avoid re-indenting the legacy code
3223 */
Jeff Johnson295189b2012-06-20 16:38:30 -07003224 {
3225 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
3226
3227 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07003228 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -07003229
3230 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
3231 {
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303232 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3233 TRACE_CODE_HDD_P2P_DEV_ADDR_IOCTL,
3234 pAdapter->sessionId, (unsigned)
3235 (*(pHddCtx->p2pDeviceAddress.bytes+2)<<24 |
3236 *(pHddCtx->p2pDeviceAddress.bytes+3)<<16 |
3237 *(pHddCtx->p2pDeviceAddress.bytes+4)<<8 |
3238 *(pHddCtx->p2pDeviceAddress.bytes+5))));
Jeff Johnson295189b2012-06-20 16:38:30 -07003239 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
3240 sizeof(tSirMacAddr)))
3241 {
3242 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Arif Hussain6d2a3322013-11-17 19:50:10 -08003243 "%s: failed to copy data to user buffer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003244 ret = -EFAULT;
3245 }
3246 }
Amar Singhal0974e402013-02-12 14:27:46 -08003247 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07003248 {
Amar Singhal0974e402013-02-12 14:27:46 -08003249 tANI_U8 *ptr = command ;
Srinivas Girigowdade697412013-02-14 16:31:48 -08003250
Jeff Johnson295189b2012-06-20 16:38:30 -07003251 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -08003252
3253 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -07003254 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07003255 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -08003256 "%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 +05303257 if(VOS_FTM_MODE != hdd_get_conparam())
3258 {
3259 /* Change band request received */
3260 ret = hdd_setBand_helper(pAdapter->dev, ptr);
3261 if(ret < 0)
3262 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
3263 "%s: failed to set band ret=%d", __func__, ret);
3264 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08003265 }
Kiet Lamf040f472013-11-20 21:15:23 +05303266 else if(strncmp(command, "SETWMMPS", 8) == 0)
3267 {
3268 tANI_U8 *ptr = command;
3269 ret = hdd_wmmps_helper(pAdapter, ptr);
3270 }
Agarwal Ashishef54a182014-12-16 15:07:31 +05303271
3272 else if(strncmp(command, "TDLSSCAN", 8) == 0)
3273 {
3274 tANI_U8 *ptr = command;
3275 ret = hdd_set_tdls_scan_type(pAdapter, ptr);
3276 }
3277
Jeff Johnson32d95a32012-09-10 13:15:23 -07003278 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
3279 {
3280 char *country_code;
3281
3282 country_code = command + 8;
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07003283
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07003284 INIT_COMPLETION(pAdapter->change_country_code);
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07003285 hdd_checkandupdate_dfssetting(pAdapter, country_code);
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -07003286#ifndef CONFIG_ENABLE_LINUX_REG
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +05303287 hdd_checkandupdate_phymode(pAdapter, country_code);
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -07003288#endif
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07003289 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal,
3290 (void *)(tSmeChangeCountryCallback)
3291 wlan_hdd_change_country_code_callback,
Abhishek Singha306a442013-11-07 18:39:01 +05303292 country_code, pAdapter, pHddCtx->pvosContext, eSIR_TRUE, eSIR_TRUE);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07003293 if (eHAL_STATUS_SUCCESS == ret)
3294 {
3295 ret = wait_for_completion_interruptible_timeout(
3296 &pAdapter->change_country_code,
3297 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
3298 if (0 >= ret)
3299 {
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003300 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: SME while setting country code timed out %d",
c_hpothu6ff1c3c2013-10-01 19:01:57 +05303301 __func__, ret);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07003302 }
3303 }
3304 else
Jeff Johnson32d95a32012-09-10 13:15:23 -07003305 {
3306 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003307 "%s: SME Change Country code fail ret=%d", __func__, ret);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07003308 ret = -EINVAL;
Jeff Johnson32d95a32012-09-10 13:15:23 -07003309 }
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07003310
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07003311 }
3312 /*
3313 command should be a string having format
3314 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
3315 */
Amar Singhal0974e402013-02-12 14:27:46 -08003316 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07003317 {
Amar Singhal0974e402013-02-12 14:27:46 -08003318 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07003319
3320 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003321 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07003322
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -08003323 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -07003324 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -08003325 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
3326 {
3327 int suspend = 0;
3328 tANI_U8 *ptr = (tANI_U8*)command + 15;
3329
3330 suspend = *ptr - '0';
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303331 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3332 TRACE_CODE_HDD_SETSUSPENDMODE_IOCTL,
3333 pAdapter->sessionId, suspend));
Sameer Thalappil45931fb2013-02-01 11:18:05 -08003334 hdd_set_wlan_suspend_mode(suspend);
3335 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08003336#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
3337 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
3338 {
3339 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003340 tANI_S8 rssi = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08003341 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
3342 eHalStatus status = eHAL_STATUS_SUCCESS;
3343
3344 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
3345 value = value + 15;
3346
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003347 /* Convert the value from ascii to integer */
3348 ret = kstrtos8(value, 10, &rssi);
3349 if (ret < 0)
3350 {
3351 /* If the input value is greater than max value of datatype, then also
3352 kstrtou8 fails */
3353 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3354 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdafa7157d2013-10-31 10:14:22 -07003355 __func__,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003356 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
3357 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
3358 ret = -EINVAL;
3359 goto exit;
3360 }
3361
Srinivas Girigowdade697412013-02-14 16:31:48 -08003362 lookUpThreshold = abs(rssi);
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003363
Srinivas Girigowdade697412013-02-14 16:31:48 -08003364 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
3365 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
3366 {
3367 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3368 "Neighbor lookup threshold value %d is out of range"
3369 " (Min: %d Max: %d)", lookUpThreshold,
3370 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
3371 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
3372 ret = -EINVAL;
3373 goto exit;
3374 }
3375
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303376 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3377 TRACE_CODE_HDD_SETROAMTRIGGER_IOCTL,
3378 pAdapter->sessionId, lookUpThreshold));
Srinivas Girigowdade697412013-02-14 16:31:48 -08003379 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3380 "%s: Received Command to Set Roam trigger"
3381 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
3382
3383 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
3384 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
3385 if (eHAL_STATUS_SUCCESS != status)
3386 {
3387 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3388 "%s: Failed to set roam trigger, try again", __func__);
3389 ret = -EPERM;
3390 goto exit;
3391 }
3392
3393 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
mukul sharmad6e1fdd2014-06-23 19:19:09 +05303394 pHddCtx->cfg_ini->nNeighborReassocRssiThreshold = lookUpThreshold + 5;
Srinivas Girigowdade697412013-02-14 16:31:48 -08003395 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
3396 }
3397 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
3398 {
3399 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
3400 int rssi = (-1) * lookUpThreshold;
3401 char extra[32];
3402 tANI_U8 len = 0;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303403 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3404 TRACE_CODE_HDD_GETROAMTRIGGER_IOCTL,
3405 pAdapter->sessionId, lookUpThreshold));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003406 len = scnprintf(extra, sizeof(extra), "%s %d", command, rssi);
Srinivas Girigowda91719232015-07-13 15:10:10 +05303407 len = VOS_MIN(priv_data.total_len, len + 1);
3408 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdade697412013-02-14 16:31:48 -08003409 {
3410 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3411 "%s: failed to copy data to user buffer", __func__);
3412 ret = -EFAULT;
3413 goto exit;
3414 }
3415 }
3416 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
3417 {
3418 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003419 tANI_U8 roamScanPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003420 tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003421
Srinivas Girigowdade697412013-02-14 16:31:48 -08003422 /* input refresh period is in terms of seconds */
3423 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
3424 value = value + 18;
3425 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003426 ret = kstrtou8(value, 10, &roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08003427 if (ret < 0)
3428 {
3429 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003430 kstrtou8 fails */
Srinivas Girigowdade697412013-02-14 16:31:48 -08003431 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003432 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdade697412013-02-14 16:31:48 -08003433 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07003434 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
3435 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08003436 ret = -EINVAL;
3437 goto exit;
3438 }
3439
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003440 if ((roamScanPeriod < (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000)) ||
3441 (roamScanPeriod > (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000)))
Srinivas Girigowdade697412013-02-14 16:31:48 -08003442 {
3443 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003444 "Roam scan period value %d is out of range"
3445 " (Min: %d Max: %d)", roamScanPeriod,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07003446 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
3447 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08003448 ret = -EINVAL;
3449 goto exit;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303450 }
3451 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3452 TRACE_CODE_HDD_SETROAMSCANPERIOD_IOCTL,
3453 pAdapter->sessionId, roamScanPeriod));
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003454 neighborEmptyScanRefreshPeriod = roamScanPeriod * 1000;
Srinivas Girigowdade697412013-02-14 16:31:48 -08003455
3456 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3457 "%s: Received Command to Set roam scan period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003458 " (Empty Scan refresh period) = %d", __func__, roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08003459
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003460 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod;
3461 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08003462 }
3463 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
3464 {
3465 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
3466 char extra[32];
3467 tANI_U8 len = 0;
3468
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303469 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3470 TRACE_CODE_HDD_GETROAMSCANPERIOD_IOCTL,
3471 pAdapter->sessionId, nEmptyScanRefreshPeriod));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003472 len = scnprintf(extra, sizeof(extra), "%s %d",
3473 "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08003474 /* Returned value is in units of seconds */
Ratnam Rachuria72ba112015-07-17 13:27:03 +05303475 len = VOS_MIN(priv_data.total_len, len + 1);
3476 if (copy_to_user(priv_data.buf, &extra, len)) {
Srinivas Girigowdade697412013-02-14 16:31:48 -08003477 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3478 "%s: failed to copy data to user buffer", __func__);
3479 ret = -EFAULT;
3480 goto exit;
3481 }
3482 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003483 else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0)
3484 {
3485 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003486 tANI_U8 roamScanRefreshPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003487 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003488
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003489 /* input refresh period is in terms of seconds */
3490 /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */
3491 value = value + 25;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003492
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003493 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003494 ret = kstrtou8(value, 10, &roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003495 if (ret < 0)
3496 {
3497 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003498 kstrtou8 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003499 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003500 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003501 __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003502 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
3503 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
3504 ret = -EINVAL;
3505 goto exit;
3506 }
3507
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003508 if ((roamScanRefreshPeriod < (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000)) ||
3509 (roamScanRefreshPeriod > (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000)))
3510 {
3511 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3512 "Neighbor scan results refresh period value %d is out of range"
3513 " (Min: %d Max: %d)", roamScanRefreshPeriod,
3514 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
3515 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
3516 ret = -EINVAL;
3517 goto exit;
3518 }
3519 neighborScanRefreshPeriod = roamScanRefreshPeriod * 1000;
3520
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003521 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3522 "%s: Received Command to Set roam scan refresh period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003523 " (Scan refresh period) = %d", __func__, roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003524
3525 pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod;
3526 sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
3527 }
3528 else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0)
3529 {
3530 tANI_U16 value = sme_getNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
3531 char extra[32];
3532 tANI_U8 len = 0;
3533
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003534 len = scnprintf(extra, sizeof(extra), "%s %d",
3535 "GETROAMSCANREFRESHPERIOD", (value/1000));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003536 /* Returned value is in units of seconds */
Ratnam Rachuri2c9d6702015-07-17 13:25:16 +05303537 len = VOS_MIN(priv_data.total_len, len + 1);
3538 if (copy_to_user(priv_data.buf, &extra, len)) {
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003539 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3540 "%s: failed to copy data to user buffer", __func__);
3541 ret = -EFAULT;
3542 goto exit;
3543 }
3544 }
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07003545#ifdef FEATURE_WLAN_LFR
3546 /* SETROAMMODE */
3547 else if (strncmp(command, "SETROAMMODE", SIZE_OF_SETROAMMODE) == 0)
3548 {
3549 tANI_U8 *value = command;
3550 tANI_BOOLEAN roamMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
3551
3552 /* Move pointer to ahead of SETROAMMODE<delimiter> */
3553 value = value + SIZE_OF_SETROAMMODE + 1;
3554
3555 /* Convert the value from ascii to integer */
3556 ret = kstrtou8(value, SIZE_OF_SETROAMMODE, &roamMode);
3557 if (ret < 0)
3558 {
3559 /* If the input value is greater than max value of datatype, then also
3560 kstrtou8 fails */
3561 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3562 "%s: kstrtou8 failed range [%d - %d]", __func__,
3563 CFG_LFR_FEATURE_ENABLED_MIN,
3564 CFG_LFR_FEATURE_ENABLED_MAX);
3565 ret = -EINVAL;
3566 goto exit;
3567 }
3568 if ((roamMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
3569 (roamMode > CFG_LFR_FEATURE_ENABLED_MAX))
3570 {
3571 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3572 "Roam Mode value %d is out of range"
3573 " (Min: %d Max: %d)", roamMode,
3574 CFG_LFR_FEATURE_ENABLED_MIN,
3575 CFG_LFR_FEATURE_ENABLED_MAX);
3576 ret = -EINVAL;
3577 goto exit;
3578 }
3579
3580 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3581 "%s: Received Command to Set Roam Mode = %d", __func__, roamMode);
3582 /*
3583 * Note that
3584 * SETROAMMODE 0 is to enable LFR while
3585 * SETROAMMODE 1 is to disable LFR, but
3586 * NotifyIsFastRoamIniFeatureEnabled 0/1 is to enable/disable.
3587 * So, we have to invert the value to call sme_UpdateIsFastRoamIniFeatureEnabled.
3588 */
3589 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
3590 roamMode = CFG_LFR_FEATURE_ENABLED_MAX; /* Roam enable */
3591 else
3592 roamMode = CFG_LFR_FEATURE_ENABLED_MIN; /* Roam disable */
3593
3594 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = roamMode;
3595 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), roamMode);
3596 }
3597 /* GETROAMMODE */
Mahesh A Saptasagarec7d1092015-04-02 13:41:34 +05303598 else if (strncmp(command, "GETROAMMODE", SIZE_OF_GETROAMMODE) == 0)
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07003599 {
3600 tANI_BOOLEAN roamMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
3601 char extra[32];
3602 tANI_U8 len = 0;
3603
3604 /*
3605 * roamMode value shall be inverted because the sementics is different.
3606 */
3607 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
3608 roamMode = CFG_LFR_FEATURE_ENABLED_MAX;
3609 else
3610 roamMode = CFG_LFR_FEATURE_ENABLED_MIN;
3611
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003612 len = scnprintf(extra, sizeof(extra), "%s %d", command, roamMode);
Ratnam Rachuri28693eb2015-07-17 13:23:42 +05303613 len = VOS_MIN(priv_data.total_len, len + 1);
3614 if (copy_to_user(priv_data.buf, &extra, len)) {
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07003615 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3616 "%s: failed to copy data to user buffer", __func__);
3617 ret = -EFAULT;
3618 goto exit;
3619 }
3620 }
3621#endif
Srinivas Girigowdade697412013-02-14 16:31:48 -08003622#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003623#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -08003624 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
3625 {
3626 tANI_U8 *value = command;
3627 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
3628
3629 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
3630 value = value + 13;
3631 /* Convert the value from ascii to integer */
3632 ret = kstrtou8(value, 10, &roamRssiDiff);
3633 if (ret < 0)
3634 {
3635 /* If the input value is greater than max value of datatype, then also
3636 kstrtou8 fails */
3637 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3638 "%s: kstrtou8 failed range [%d - %d]", __func__,
3639 CFG_ROAM_RSSI_DIFF_MIN,
3640 CFG_ROAM_RSSI_DIFF_MAX);
3641 ret = -EINVAL;
3642 goto exit;
3643 }
3644
3645 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
3646 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
3647 {
3648 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3649 "Roam rssi diff value %d is out of range"
3650 " (Min: %d Max: %d)", roamRssiDiff,
3651 CFG_ROAM_RSSI_DIFF_MIN,
3652 CFG_ROAM_RSSI_DIFF_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 rssi diff = %d", __func__, roamRssiDiff);
3659
3660 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
3661 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
3662 }
Mahesh A Saptasagarec7d1092015-04-02 13:41:34 +05303663 else if (strncmp(command, "GETROAMDELTA", 12) == 0)
Srinivas Girigowdade697412013-02-14 16:31:48 -08003664 {
3665 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
3666 char extra[32];
3667 tANI_U8 len = 0;
3668
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303669 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3670 TRACE_CODE_HDD_GETROAMDELTA_IOCTL,
3671 pAdapter->sessionId, roamRssiDiff));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003672 len = scnprintf(extra, sizeof(extra), "%s %d",
3673 command, roamRssiDiff);
Ratnam Rachuri22a3b402015-07-17 13:21:49 +05303674 len = VOS_MIN(priv_data.total_len, len + 1);
3675 if (copy_to_user(priv_data.buf, &extra, len)) {
Srinivas Girigowdade697412013-02-14 16:31:48 -08003676 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3677 "%s: failed to copy data to user buffer", __func__);
3678 ret = -EFAULT;
3679 goto exit;
3680 }
3681 }
3682#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003683#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -08003684 else if (strncmp(command, "GETBAND", 7) == 0)
3685 {
3686 int band = -1;
3687 char extra[32];
3688 tANI_U8 len = 0;
3689 hdd_getBand_helper(pHddCtx, &band);
3690
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303691 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3692 TRACE_CODE_HDD_GETBAND_IOCTL,
3693 pAdapter->sessionId, band));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003694 len = scnprintf(extra, sizeof(extra), "%s %d", command, band);
Ratnam Rachuri52139592015-07-17 13:17:29 +05303695 len = VOS_MIN(priv_data.total_len, len + 1);
3696 if (copy_to_user(priv_data.buf, &extra, len)) {
Srinivas Girigowdade697412013-02-14 16:31:48 -08003697 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3698 "%s: failed to copy data to user buffer", __func__);
3699 ret = -EFAULT;
3700 goto exit;
3701 }
3702 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08003703 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
3704 {
3705 tANI_U8 *value = command;
3706 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
3707 tANI_U8 numChannels = 0;
3708 eHalStatus status = eHAL_STATUS_SUCCESS;
3709
3710 status = hdd_parse_channellist(value, ChannelList, &numChannels);
3711 if (eHAL_STATUS_SUCCESS != status)
3712 {
3713 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3714 "%s: Failed to parse channel list information", __func__);
3715 ret = -EINVAL;
3716 goto exit;
3717 }
3718
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303719 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3720 TRACE_CODE_HDD_SETROAMSCANCHANNELS_IOCTL,
3721 pAdapter->sessionId, numChannels));
Srinivas Girigowdade697412013-02-14 16:31:48 -08003722 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
3723 {
3724 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3725 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
3726 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
3727 ret = -EINVAL;
3728 goto exit;
3729 }
3730 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
3731 numChannels);
3732 if (eHAL_STATUS_SUCCESS != status)
3733 {
3734 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3735 "%s: Failed to update channel list information", __func__);
3736 ret = -EINVAL;
3737 goto exit;
3738 }
3739 }
3740 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
3741 {
3742 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
3743 tANI_U8 numChannels = 0;
Jeff Johnson51b67782013-04-05 12:35:41 -07003744 tANI_U8 j = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08003745 char extra[128] = {0};
Jeff Johnson51b67782013-04-05 12:35:41 -07003746 int len;
Srinivas Girigowdade697412013-02-14 16:31:48 -08003747
3748 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
3749 ChannelList, &numChannels ))
3750 {
3751 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3752 "%s: failed to get roam scan channel list", __func__);
3753 ret = -EFAULT;
3754 goto exit;
3755 }
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303756 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3757 TRACE_CODE_HDD_GETROAMSCANCHANNELS_IOCTL,
3758 pAdapter->sessionId, numChannels));
Srinivas Girigowdade697412013-02-14 16:31:48 -08003759 /* output channel list is of the format
3760 [Number of roam scan channels][Channel1][Channel2]... */
3761 /* copy the number of channels in the 0th index */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003762 len = scnprintf(extra, sizeof(extra), "%s %d", command, numChannels);
Sushant Kaushika08ca192015-09-16 15:52:04 +05303763 for (j = 0; (j < numChannels) && len <= sizeof(extra); j++)
Srinivas Girigowdade697412013-02-14 16:31:48 -08003764 {
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003765 len += scnprintf(extra + len, sizeof(extra) - len, " %d",
3766 ChannelList[j]);
Srinivas Girigowdade697412013-02-14 16:31:48 -08003767 }
3768
Sushant Kaushikc9b8be52015-07-15 16:41:27 +05303769 len = VOS_MIN(priv_data.total_len, len + 1);
3770 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdade697412013-02-14 16:31:48 -08003771 {
3772 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3773 "%s: failed to copy data to user buffer", __func__);
3774 ret = -EFAULT;
3775 goto exit;
3776 }
3777 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003778 else if (strncmp(command, "GETCCXMODE", 10) == 0)
3779 {
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003780 tANI_BOOLEAN eseMode = sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003781 char extra[32];
3782 tANI_U8 len = 0;
3783
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003784 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003785 then this operation is not permitted (return FAILURE) */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003786 if (eseMode &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003787 hdd_is_okc_mode_enabled(pHddCtx) &&
3788 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
3789 {
3790 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003791 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003792 " hence this operation is not permitted!", __func__);
3793 ret = -EPERM;
3794 goto exit;
3795 }
3796
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003797 len = scnprintf(extra, sizeof(extra), "%s %d",
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003798 "GETCCXMODE", eseMode);
Sushant Kaushikf8abd352015-07-15 16:37:49 +05303799 len = VOS_MIN(priv_data.total_len, len + 1);
3800 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003801 {
3802 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3803 "%s: failed to copy data to user buffer", __func__);
3804 ret = -EFAULT;
3805 goto exit;
3806 }
3807 }
3808 else if (strncmp(command, "GETOKCMODE", 10) == 0)
3809 {
3810 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
3811 char extra[32];
3812 tANI_U8 len = 0;
3813
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003814 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003815 then this operation is not permitted (return FAILURE) */
3816 if (okcMode &&
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003817 sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003818 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
3819 {
3820 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003821 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003822 " hence this operation is not permitted!", __func__);
3823 ret = -EPERM;
3824 goto exit;
3825 }
3826
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003827 len = scnprintf(extra, sizeof(extra), "%s %d",
3828 "GETOKCMODE", okcMode);
Sushant Kaushikbc2fb5c2015-07-15 16:43:16 +05303829 len = VOS_MIN(priv_data.total_len, len + 1);
3830 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003831 {
3832 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3833 "%s: failed to copy data to user buffer", __func__);
3834 ret = -EFAULT;
3835 goto exit;
3836 }
3837 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003838 else if (strncmp(command, "GETFASTROAM", 11) == 0)
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003839 {
3840 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
3841 char extra[32];
3842 tANI_U8 len = 0;
3843
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003844 len = scnprintf(extra, sizeof(extra), "%s %d",
3845 "GETFASTROAM", lfrMode);
Sushant Kaushik4da7ec92015-07-15 16:39:32 +05303846 len = VOS_MIN(priv_data.total_len, len + 1);
3847 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003848 {
3849 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3850 "%s: failed to copy data to user buffer", __func__);
3851 ret = -EFAULT;
3852 goto exit;
3853 }
3854 }
3855 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
3856 {
3857 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
3858 char extra[32];
3859 tANI_U8 len = 0;
3860
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003861 len = scnprintf(extra, sizeof(extra), "%s %d",
3862 "GETFASTTRANSITION", ft);
Sushant Kaushik231a4452015-07-15 16:23:56 +05303863 len = VOS_MIN(priv_data.total_len, len + 1);
3864 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003865 {
3866 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3867 "%s: failed to copy data to user buffer", __func__);
3868 ret = -EFAULT;
3869 goto exit;
3870 }
3871 }
3872 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
3873 {
3874 tANI_U8 *value = command;
3875 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
3876
3877 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
3878 value = value + 26;
3879 /* Convert the value from ascii to integer */
3880 ret = kstrtou8(value, 10, &minTime);
3881 if (ret < 0)
3882 {
3883 /* If the input value is greater than max value of datatype, then also
3884 kstrtou8 fails */
3885 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3886 "%s: kstrtou8 failed range [%d - %d]", __func__,
3887 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
3888 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
3889 ret = -EINVAL;
3890 goto exit;
3891 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003892 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
3893 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
3894 {
3895 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3896 "scan min channel time value %d is out of range"
3897 " (Min: %d Max: %d)", minTime,
3898 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
3899 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
3900 ret = -EINVAL;
3901 goto exit;
3902 }
3903
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303904 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3905 TRACE_CODE_HDD_SETROAMSCANCHANNELMINTIME_IOCTL,
3906 pAdapter->sessionId, minTime));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003907 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3908 "%s: Received Command to change channel min time = %d", __func__, minTime);
3909
3910 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
3911 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
3912 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003913 else if (strncmp(command, "SENDACTIONFRAME", 15) == 0)
3914 {
3915 tANI_U8 *value = command;
3916 tANI_U8 channel = 0;
3917 tANI_U8 dwellTime = 0;
3918 tANI_U8 bufLen = 0;
3919 tANI_U8 *buf = NULL;
3920 tSirMacAddr targetApBssid;
3921 eHalStatus status = eHAL_STATUS_SUCCESS;
3922 struct ieee80211_channel chan;
3923 tANI_U8 finalLen = 0;
3924 tANI_U8 *finalBuf = NULL;
3925 tANI_U8 temp = 0;
3926 u64 cookie;
3927 hdd_station_ctx_t *pHddStaCtx = NULL;
3928 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3929
3930 /* if not associated, no need to send action frame */
3931 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3932 {
3933 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
3934 ret = -EINVAL;
3935 goto exit;
3936 }
3937
3938 status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel,
3939 &dwellTime, &buf, &bufLen);
3940 if (eHAL_STATUS_SUCCESS != status)
3941 {
3942 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3943 "%s: Failed to parse send action frame data", __func__);
3944 ret = -EINVAL;
3945 goto exit;
3946 }
3947
3948 /* if the target bssid is different from currently associated AP,
3949 then no need to send action frame */
3950 if (VOS_TRUE != vos_mem_compare(targetApBssid,
3951 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
3952 {
3953 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__);
3954 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07003955 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08003956 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003957 goto exit;
3958 }
3959
3960 /* if the channel number is different from operating channel then
3961 no need to send action frame */
3962 if (channel != pHddStaCtx->conn_info.operationChannel)
3963 {
3964 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3965 "%s: channel(%d) is different from operating channel(%d)",
3966 __func__, channel, pHddStaCtx->conn_info.operationChannel);
3967 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07003968 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08003969 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003970 goto exit;
3971 }
3972 chan.center_freq = sme_ChnToFreq(channel);
3973
3974 finalLen = bufLen + 24;
3975 finalBuf = vos_mem_malloc(finalLen);
3976 if (NULL == finalBuf)
3977 {
3978 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__);
3979 ret = -ENOMEM;
Jeff Johnson11c33152013-04-16 17:52:40 -07003980 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08003981 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003982 goto exit;
3983 }
3984 vos_mem_zero(finalBuf, finalLen);
3985
3986 /* Fill subtype */
3987 temp = SIR_MAC_MGMT_ACTION << 4;
3988 vos_mem_copy(finalBuf + 0, &temp, sizeof(temp));
3989
3990 /* Fill type */
3991 temp = SIR_MAC_MGMT_FRAME;
3992 vos_mem_copy(finalBuf + 2, &temp, sizeof(temp));
3993
3994 /* Fill destination address (bssid of the AP) */
3995 vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid));
3996
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07003997 /* Fill source address (STA mac address) */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003998 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
3999
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07004000 /* Fill BSSID (AP mac address) */
4001 vos_mem_copy(finalBuf + 16, targetApBssid, sizeof(targetApBssid));
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004002
4003 /* Fill received buffer from 24th address */
4004 vos_mem_copy(finalBuf + 24, buf, bufLen);
4005
Jeff Johnson11c33152013-04-16 17:52:40 -07004006 /* done with the parsed buffer */
4007 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08004008 buf = NULL;
Jeff Johnson11c33152013-04-16 17:52:40 -07004009
Anand N Sunkade9adb1b2015-07-29 09:56:45 +05304010#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0))
4011 params.chan = &chan;
4012 params.offchan = 0;
4013 params.wait = dwellTime;
4014 params.buf = finalBuf;
4015 params.len = finalLen;
4016 params.no_cck = 1;
4017 params.dont_wait_for_ack = 1;
4018 ret = wlan_hdd_mgmt_tx(NULL, &pAdapter->wdev, &params, &cookie);
4019#else
DARAM SUDHA39eede62014-02-12 11:16:40 +05304020 wlan_hdd_mgmt_tx( NULL,
Yue Maf49ba872013-08-19 12:04:25 -07004021#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
4022 &(pAdapter->wdev),
4023#else
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07004024 pAdapter->dev,
Yue Maf49ba872013-08-19 12:04:25 -07004025#endif
4026 &chan, 0,
4027#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
4028 NL80211_CHAN_HT20, 1,
4029#endif
4030 dwellTime, finalBuf, finalLen, 1,
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004031 1, &cookie );
Anand N Sunkade9adb1b2015-07-29 09:56:45 +05304032#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0)*/
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004033 vos_mem_free(finalBuf);
4034 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004035 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
4036 {
4037 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
4038 char extra[32];
4039 tANI_U8 len = 0;
4040
4041 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004042 len = scnprintf(extra, sizeof(extra), "%s %d",
4043 "GETROAMSCANCHANNELMINTIME", val);
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05304044 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
4045 TRACE_CODE_HDD_GETROAMSCANCHANNELMINTIME_IOCTL,
4046 pAdapter->sessionId, val));
Sushant Kaushikbb8c52c2015-07-15 16:36:23 +05304047 len = VOS_MIN(priv_data.total_len, len + 1);
4048 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004049 {
4050 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4051 "%s: failed to copy data to user buffer", __func__);
4052 ret = -EFAULT;
4053 goto exit;
4054 }
4055 }
4056 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
4057 {
4058 tANI_U8 *value = command;
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07004059 tANI_U16 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004060
4061 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
4062 value = value + 19;
4063 /* Convert the value from ascii to integer */
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07004064 ret = kstrtou16(value, 10, &maxTime);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004065 if (ret < 0)
4066 {
4067 /* If the input value is greater than max value of datatype, then also
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07004068 kstrtou16 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004069 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07004070 "%s: kstrtou16 failed range [%d - %d]", __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004071 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
4072 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
4073 ret = -EINVAL;
4074 goto exit;
4075 }
4076
4077 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
4078 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
4079 {
4080 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4081 "lfr mode value %d is out of range"
4082 " (Min: %d Max: %d)", maxTime,
4083 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
4084 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
4085 ret = -EINVAL;
4086 goto exit;
4087 }
4088
4089 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4090 "%s: Received Command to change channel max time = %d", __func__, maxTime);
4091
4092 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
4093 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
4094 }
4095 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
4096 {
4097 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
4098 char extra[32];
4099 tANI_U8 len = 0;
4100
4101 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004102 len = scnprintf(extra, sizeof(extra), "%s %d",
4103 "GETSCANCHANNELTIME", val);
Ratheesh S Pacbfa932015-07-16 15:27:18 +05304104 len = VOS_MIN(priv_data.total_len, len + 1);
4105 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004106 {
4107 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4108 "%s: failed to copy data to user buffer", __func__);
4109 ret = -EFAULT;
4110 goto exit;
4111 }
4112 }
4113 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
4114 {
4115 tANI_U8 *value = command;
4116 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
4117
4118 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
4119 value = value + 16;
4120 /* Convert the value from ascii to integer */
4121 ret = kstrtou16(value, 10, &val);
4122 if (ret < 0)
4123 {
4124 /* If the input value is greater than max value of datatype, then also
4125 kstrtou16 fails */
4126 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4127 "%s: kstrtou16 failed range [%d - %d]", __func__,
4128 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
4129 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
4130 ret = -EINVAL;
4131 goto exit;
4132 }
4133
4134 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
4135 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
4136 {
4137 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4138 "scan home time value %d is out of range"
4139 " (Min: %d Max: %d)", val,
4140 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
4141 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
4142 ret = -EINVAL;
4143 goto exit;
4144 }
4145
4146 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4147 "%s: Received Command to change scan home time = %d", __func__, val);
4148
4149 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
4150 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
4151 }
4152 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
4153 {
4154 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
4155 char extra[32];
4156 tANI_U8 len = 0;
4157
4158 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004159 len = scnprintf(extra, sizeof(extra), "%s %d",
4160 "GETSCANHOMETIME", val);
Ratheesh S P728d7c62015-07-16 15:38:58 +05304161 len = VOS_MIN(priv_data.total_len, len + 1);
4162 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004163 {
4164 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4165 "%s: failed to copy data to user buffer", __func__);
4166 ret = -EFAULT;
4167 goto exit;
4168 }
4169 }
4170 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
4171 {
4172 tANI_U8 *value = command;
4173 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
4174
4175 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
4176 value = value + 17;
4177 /* Convert the value from ascii to integer */
4178 ret = kstrtou8(value, 10, &val);
4179 if (ret < 0)
4180 {
4181 /* If the input value is greater than max value of datatype, then also
4182 kstrtou8 fails */
4183 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4184 "%s: kstrtou8 failed range [%d - %d]", __func__,
4185 CFG_ROAM_INTRA_BAND_MIN,
4186 CFG_ROAM_INTRA_BAND_MAX);
4187 ret = -EINVAL;
4188 goto exit;
4189 }
4190
4191 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
4192 (val > CFG_ROAM_INTRA_BAND_MAX))
4193 {
4194 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4195 "intra band mode value %d is out of range"
4196 " (Min: %d Max: %d)", val,
4197 CFG_ROAM_INTRA_BAND_MIN,
4198 CFG_ROAM_INTRA_BAND_MAX);
4199 ret = -EINVAL;
4200 goto exit;
4201 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004202 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4203 "%s: Received Command to change intra band = %d", __func__, val);
4204
4205 pHddCtx->cfg_ini->nRoamIntraBand = val;
4206 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
4207 }
4208 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
4209 {
4210 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
4211 char extra[32];
4212 tANI_U8 len = 0;
4213
4214 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004215 len = scnprintf(extra, sizeof(extra), "%s %d",
4216 "GETROAMINTRABAND", val);
Ratheesh S P2dd2a3e2015-07-16 15:34:23 +05304217 len = VOS_MIN(priv_data.total_len, len + 1);
4218 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004219 {
4220 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4221 "%s: failed to copy data to user buffer", __func__);
4222 ret = -EFAULT;
4223 goto exit;
4224 }
4225 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004226 else if (strncmp(command, "SETSCANNPROBES", 14) == 0)
4227 {
4228 tANI_U8 *value = command;
4229 tANI_U8 nProbes = CFG_ROAM_SCAN_N_PROBES_DEFAULT;
4230
4231 /* Move pointer to ahead of SETSCANNPROBES<delimiter> */
4232 value = value + 15;
4233 /* Convert the value from ascii to integer */
4234 ret = kstrtou8(value, 10, &nProbes);
4235 if (ret < 0)
4236 {
4237 /* If the input value is greater than max value of datatype, then also
4238 kstrtou8 fails */
4239 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4240 "%s: kstrtou8 failed range [%d - %d]", __func__,
4241 CFG_ROAM_SCAN_N_PROBES_MIN,
4242 CFG_ROAM_SCAN_N_PROBES_MAX);
4243 ret = -EINVAL;
4244 goto exit;
4245 }
4246
4247 if ((nProbes < CFG_ROAM_SCAN_N_PROBES_MIN) ||
4248 (nProbes > CFG_ROAM_SCAN_N_PROBES_MAX))
4249 {
4250 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4251 "NProbes value %d is out of range"
4252 " (Min: %d Max: %d)", nProbes,
4253 CFG_ROAM_SCAN_N_PROBES_MIN,
4254 CFG_ROAM_SCAN_N_PROBES_MAX);
4255 ret = -EINVAL;
4256 goto exit;
4257 }
4258
4259 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4260 "%s: Received Command to Set nProbes = %d", __func__, nProbes);
4261
4262 pHddCtx->cfg_ini->nProbes = nProbes;
4263 sme_UpdateRoamScanNProbes((tHalHandle)(pHddCtx->hHal), nProbes);
4264 }
Mahesh A Saptasagarec7d1092015-04-02 13:41:34 +05304265 else if (strncmp(command, "GETSCANNPROBES", 14) == 0)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004266 {
4267 tANI_U8 val = sme_getRoamScanNProbes((tHalHandle)(pHddCtx->hHal));
4268 char extra[32];
4269 tANI_U8 len = 0;
4270
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004271 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Ratnam Rachuri6da525d2015-08-07 13:55:54 +05304272 len = VOS_MIN(priv_data.total_len, len + 1);
4273 if (copy_to_user(priv_data.buf, &extra, len)) {
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004274 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4275 "%s: failed to copy data to user buffer", __func__);
4276 ret = -EFAULT;
4277 goto exit;
4278 }
4279 }
4280 else if (strncmp(command, "SETSCANHOMEAWAYTIME", 19) == 0)
4281 {
4282 tANI_U8 *value = command;
4283 tANI_U16 homeAwayTime = CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT;
4284
4285 /* Move pointer to ahead of SETSCANHOMEAWAYTIME<delimiter> */
4286 /* input value is in units of msec */
4287 value = value + 20;
4288 /* Convert the value from ascii to integer */
4289 ret = kstrtou16(value, 10, &homeAwayTime);
4290 if (ret < 0)
4291 {
4292 /* If the input value is greater than max value of datatype, then also
4293 kstrtou8 fails */
4294 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4295 "%s: kstrtou8 failed range [%d - %d]", __func__,
4296 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
4297 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
4298 ret = -EINVAL;
4299 goto exit;
4300 }
4301
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004302 if ((homeAwayTime < CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN) ||
4303 (homeAwayTime > CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX))
4304 {
4305 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4306 "homeAwayTime value %d is out of range"
4307 " (Min: %d Max: %d)", homeAwayTime,
4308 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
4309 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
4310 ret = -EINVAL;
4311 goto exit;
4312 }
4313
4314 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4315 "%s: Received Command to Set scan away time = %d", __func__, homeAwayTime);
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07004316 if (pHddCtx->cfg_ini->nRoamScanHomeAwayTime != homeAwayTime)
4317 {
4318 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
4319 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_TRUE);
4320 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004321 }
Mahesh A Saptasagarec7d1092015-04-02 13:41:34 +05304322 else if (strncmp(command, "GETSCANHOMEAWAYTIME", 19) == 0)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004323 {
4324 tANI_U16 val = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
4325 char extra[32];
4326 tANI_U8 len = 0;
4327
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004328 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Ratnam Rachuri51a5ad12015-08-07 14:06:37 +05304329 len = VOS_MIN(priv_data.total_len, len + 1);
4330 if (copy_to_user(priv_data.buf, &extra, len)) {
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004331 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4332 "%s: failed to copy data to user buffer", __func__);
4333 ret = -EFAULT;
4334 goto exit;
4335 }
4336 }
4337 else if (strncmp(command, "REASSOC", 7) == 0)
4338 {
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05304339 ret = hdd_parse_reassoc(pAdapter, command);
4340 if (!ret)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004341 goto exit;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004342 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07004343 else if (strncmp(command, "SETWESMODE", 10) == 0)
4344 {
4345 tANI_U8 *value = command;
4346 tANI_BOOLEAN wesMode = CFG_ENABLE_WES_MODE_NAME_DEFAULT;
4347
4348 /* Move pointer to ahead of SETWESMODE<delimiter> */
4349 value = value + 11;
4350 /* Convert the value from ascii to integer */
4351 ret = kstrtou8(value, 10, &wesMode);
4352 if (ret < 0)
4353 {
4354 /* If the input value is greater than max value of datatype, then also
4355 kstrtou8 fails */
4356 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4357 "%s: kstrtou8 failed range [%d - %d]", __func__,
4358 CFG_ENABLE_WES_MODE_NAME_MIN,
4359 CFG_ENABLE_WES_MODE_NAME_MAX);
4360 ret = -EINVAL;
4361 goto exit;
4362 }
4363
4364 if ((wesMode < CFG_ENABLE_WES_MODE_NAME_MIN) ||
4365 (wesMode > CFG_ENABLE_WES_MODE_NAME_MAX))
4366 {
4367 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4368 "WES Mode value %d is out of range"
4369 " (Min: %d Max: %d)", wesMode,
4370 CFG_ENABLE_WES_MODE_NAME_MIN,
4371 CFG_ENABLE_WES_MODE_NAME_MAX);
4372 ret = -EINVAL;
4373 goto exit;
4374 }
4375 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4376 "%s: Received Command to Set WES Mode rssi diff = %d", __func__, wesMode);
4377
4378 pHddCtx->cfg_ini->isWESModeEnabled = wesMode;
4379 sme_UpdateWESMode((tHalHandle)(pHddCtx->hHal), wesMode);
4380 }
Mahesh A Saptasagarec7d1092015-04-02 13:41:34 +05304381 else if (strncmp(command, "GETWESMODE", 10) == 0)
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07004382 {
4383 tANI_BOOLEAN wesMode = sme_GetWESMode((tHalHandle)(pHddCtx->hHal));
4384 char extra[32];
4385 tANI_U8 len = 0;
4386
Arif Hussain826d9412013-11-12 16:44:54 -08004387 len = scnprintf(extra, sizeof(extra), "%s %d", command, wesMode);
Ratnam Rachuri8fe90c62015-08-07 14:03:26 +05304388 len = VOS_MIN(priv_data.total_len, len + 1);
4389 if (copy_to_user(priv_data.buf, &extra, len)) {
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07004390 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4391 "%s: failed to copy data to user buffer", __func__);
4392 ret = -EFAULT;
4393 goto exit;
4394 }
4395 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004396#endif /* WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_ESE || FEATURE_WLAN_LFR */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004397#ifdef FEATURE_WLAN_LFR
4398 else if (strncmp(command, "SETFASTROAM", 11) == 0)
4399 {
4400 tANI_U8 *value = command;
4401 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
4402
4403 /* Move pointer to ahead of SETFASTROAM<delimiter> */
4404 value = value + 12;
4405 /* Convert the value from ascii to integer */
4406 ret = kstrtou8(value, 10, &lfrMode);
4407 if (ret < 0)
4408 {
4409 /* If the input value is greater than max value of datatype, then also
4410 kstrtou8 fails */
4411 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4412 "%s: kstrtou8 failed range [%d - %d]", __func__,
4413 CFG_LFR_FEATURE_ENABLED_MIN,
4414 CFG_LFR_FEATURE_ENABLED_MAX);
4415 ret = -EINVAL;
4416 goto exit;
4417 }
4418
4419 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
4420 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
4421 {
4422 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4423 "lfr mode value %d is out of range"
4424 " (Min: %d Max: %d)", lfrMode,
4425 CFG_LFR_FEATURE_ENABLED_MIN,
4426 CFG_LFR_FEATURE_ENABLED_MAX);
4427 ret = -EINVAL;
4428 goto exit;
4429 }
4430
4431 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4432 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
4433
4434 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
4435 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
4436 }
4437#endif
4438#ifdef WLAN_FEATURE_VOWIFI_11R
4439 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
4440 {
4441 tANI_U8 *value = command;
4442 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
4443
4444 /* Move pointer to ahead of SETFASTROAM<delimiter> */
4445 value = value + 18;
4446 /* Convert the value from ascii to integer */
4447 ret = kstrtou8(value, 10, &ft);
4448 if (ret < 0)
4449 {
4450 /* If the input value is greater than max value of datatype, then also
4451 kstrtou8 fails */
4452 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4453 "%s: kstrtou8 failed range [%d - %d]", __func__,
4454 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
4455 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
4456 ret = -EINVAL;
4457 goto exit;
4458 }
4459
4460 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
4461 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
4462 {
4463 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4464 "ft mode value %d is out of range"
4465 " (Min: %d Max: %d)", ft,
4466 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
4467 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
4468 ret = -EINVAL;
4469 goto exit;
4470 }
4471
4472 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4473 "%s: Received Command to change ft mode = %d", __func__, ft);
4474
4475 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
4476 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
4477 }
Padma, Santhosh Kumar778d8382015-03-04 17:41:22 +05304478 else if (strncmp(command, "SETDFSSCANMODE", 14) == 0)
4479 {
4480 tANI_U8 *value = command;
4481 tANI_U8 dfsScanMode = DFS_CHNL_SCAN_ENABLED_NORMAL;
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05304482
Padma, Santhosh Kumar778d8382015-03-04 17:41:22 +05304483 /* Move pointer to ahead of SETDFSSCANMODE<delimiter> */
4484 value = value + 15;
4485 /* Convert the value from ascii to integer */
4486 ret = kstrtou8(value, 10, &dfsScanMode);
4487 if (ret < 0)
4488 {
4489 /* If the input value is greater than max value of
4490 datatype, then also kstrtou8 fails
4491 */
4492 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4493 "%s: kstrtou8 failed range [%d - %d]", __func__,
4494 CFG_ENABLE_DFS_CHNL_SCAN_MIN,
4495 CFG_ENABLE_DFS_CHNL_SCAN_MAX);
4496 ret = -EINVAL;
4497 goto exit;
4498 }
4499
4500 if ((dfsScanMode < CFG_ENABLE_DFS_CHNL_SCAN_MIN) ||
4501 (dfsScanMode > CFG_ENABLE_DFS_CHNL_SCAN_MAX))
4502 {
4503 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4504 "dfsScanMode value %d is out of range"
4505 " (Min: %d Max: %d)", dfsScanMode,
4506 CFG_ENABLE_DFS_CHNL_SCAN_MIN,
4507 CFG_ENABLE_DFS_CHNL_SCAN_MAX);
4508 ret = -EINVAL;
4509 goto exit;
4510 }
4511 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4512 "%s: Received Command to Set DFS Scan Mode = %d",
4513 __func__, dfsScanMode);
4514
4515 ret = wlan_hdd_handle_dfs_chan_scan(pHddCtx, dfsScanMode);
4516 }
4517 else if (strncmp(command, "GETDFSSCANMODE", 14) == 0)
4518 {
4519 tANI_U8 dfsScanMode = sme_GetDFSScanMode(pHddCtx->hHal);
4520 char extra[32];
4521 tANI_U8 len = 0;
4522
4523 len = scnprintf(extra, sizeof(extra), "%s %d", command, dfsScanMode);
Ratheesh S P767224e2015-07-16 15:35:51 +05304524 len = VOS_MIN(priv_data.total_len, len + 1);
4525 if (copy_to_user(priv_data.buf, &extra, len))
Padma, Santhosh Kumar778d8382015-03-04 17:41:22 +05304526 {
4527 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4528 "%s: failed to copy data to user buffer", __func__);
4529 ret = -EFAULT;
4530 goto exit;
4531 }
4532 }
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05304533 else if (strncmp(command, "FASTREASSOC", 11) == 0)
4534 {
Selvaraj, Sridhar3714c4d2016-06-22 15:19:12 +05304535 ret = wlan_hdd_handle_fastreassoc(pAdapter, command);
4536 if (!ret)
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05304537 goto exit;
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05304538 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004539#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004540#ifdef FEATURE_WLAN_ESE
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004541 else if (strncmp(command, "SETCCXMODE", 10) == 0)
4542 {
4543 tANI_U8 *value = command;
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004544 tANI_U8 eseMode = CFG_ESE_FEATURE_ENABLED_DEFAULT;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004545
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004546 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07004547 then this operation is not permitted (return FAILURE) */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004548 if (sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07004549 hdd_is_okc_mode_enabled(pHddCtx) &&
4550 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
4551 {
4552 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004553 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07004554 " hence this operation is not permitted!", __func__);
4555 ret = -EPERM;
4556 goto exit;
4557 }
4558
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004559 /* Move pointer to ahead of SETCCXMODE<delimiter> */
4560 value = value + 11;
4561 /* Convert the value from ascii to integer */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004562 ret = kstrtou8(value, 10, &eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004563 if (ret < 0)
4564 {
4565 /* If the input value is greater than max value of datatype, then also
4566 kstrtou8 fails */
4567 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4568 "%s: kstrtou8 failed range [%d - %d]", __func__,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004569 CFG_ESE_FEATURE_ENABLED_MIN,
4570 CFG_ESE_FEATURE_ENABLED_MAX);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004571 ret = -EINVAL;
4572 goto exit;
4573 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004574 if ((eseMode < CFG_ESE_FEATURE_ENABLED_MIN) ||
4575 (eseMode > CFG_ESE_FEATURE_ENABLED_MAX))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004576 {
4577 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004578 "Ese mode value %d is out of range"
4579 " (Min: %d Max: %d)", eseMode,
4580 CFG_ESE_FEATURE_ENABLED_MIN,
4581 CFG_ESE_FEATURE_ENABLED_MAX);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004582 ret = -EINVAL;
4583 goto exit;
4584 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004585 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004586 "%s: Received Command to change ese mode = %d", __func__, eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004587
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004588 pHddCtx->cfg_ini->isEseIniFeatureEnabled = eseMode;
4589 sme_UpdateIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal), eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004590 }
4591#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004592 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
4593 {
4594 tANI_U8 *value = command;
4595 tANI_BOOLEAN roamScanControl = 0;
4596
4597 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
4598 value = value + 19;
4599 /* Convert the value from ascii to integer */
4600 ret = kstrtou8(value, 10, &roamScanControl);
4601 if (ret < 0)
4602 {
4603 /* If the input value is greater than max value of datatype, then also
4604 kstrtou8 fails */
4605 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4606 "%s: kstrtou8 failed ", __func__);
4607 ret = -EINVAL;
4608 goto exit;
4609 }
4610
4611 if (0 != roamScanControl)
4612 {
4613 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4614 "roam scan control invalid value = %d",
4615 roamScanControl);
4616 ret = -EINVAL;
4617 goto exit;
4618 }
4619 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4620 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
4621
4622 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
4623 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004624#ifdef FEATURE_WLAN_OKC
4625 else if (strncmp(command, "SETOKCMODE", 10) == 0)
4626 {
4627 tANI_U8 *value = command;
4628 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
4629
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004630 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07004631 then this operation is not permitted (return FAILURE) */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004632 if (sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07004633 hdd_is_okc_mode_enabled(pHddCtx) &&
4634 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
4635 {
4636 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004637 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07004638 " hence this operation is not permitted!", __func__);
4639 ret = -EPERM;
4640 goto exit;
4641 }
4642
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004643 /* Move pointer to ahead of SETOKCMODE<delimiter> */
4644 value = value + 11;
4645 /* Convert the value from ascii to integer */
4646 ret = kstrtou8(value, 10, &okcMode);
4647 if (ret < 0)
4648 {
4649 /* If the input value is greater than max value of datatype, then also
4650 kstrtou8 fails */
4651 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4652 "%s: kstrtou8 failed range [%d - %d]", __func__,
4653 CFG_OKC_FEATURE_ENABLED_MIN,
4654 CFG_OKC_FEATURE_ENABLED_MAX);
4655 ret = -EINVAL;
4656 goto exit;
4657 }
4658
4659 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
4660 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
4661 {
4662 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4663 "Okc mode value %d is out of range"
4664 " (Min: %d Max: %d)", okcMode,
4665 CFG_OKC_FEATURE_ENABLED_MIN,
4666 CFG_OKC_FEATURE_ENABLED_MAX);
4667 ret = -EINVAL;
4668 goto exit;
4669 }
4670
4671 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4672 "%s: Received Command to change okc mode = %d", __func__, okcMode);
4673
4674 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
4675 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07004676#endif /* FEATURE_WLAN_OKC */
Mahesh A Saptasagarec7d1092015-04-02 13:41:34 +05304677 else if (strncmp(command, "GETROAMSCANCONTROL", 18) == 0)
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004678 {
4679 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
4680 char extra[32];
4681 tANI_U8 len = 0;
4682
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004683 len = scnprintf(extra, sizeof(extra), "%s %d",
4684 command, roamScanControl);
Ratnam Rachuri083ada82015-08-07 14:01:05 +05304685 len = VOS_MIN(priv_data.total_len, len + 1);
4686 if (copy_to_user(priv_data.buf, &extra, len)) {
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004687 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4688 "%s: failed to copy data to user buffer", __func__);
4689 ret = -EFAULT;
4690 goto exit;
4691 }
4692 }
Gopichand Nakkala227c7f32013-06-26 22:44:57 +05304693#ifdef WLAN_FEATURE_PACKET_FILTERING
4694 else if (strncmp(command, "ENABLE_PKTFILTER_IPV6", 21) == 0)
4695 {
4696 tANI_U8 filterType = 0;
4697 tANI_U8 *value = command;
4698
4699 /* Move pointer to ahead of ENABLE_PKTFILTER_IPV6<delimiter> */
4700 value = value + 22;
4701
4702 /* Convert the value from ascii to integer */
4703 ret = kstrtou8(value, 10, &filterType);
4704 if (ret < 0)
4705 {
4706 /* If the input value is greater than max value of datatype,
4707 * then also kstrtou8 fails
4708 */
4709 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4710 "%s: kstrtou8 failed range ", __func__);
4711 ret = -EINVAL;
4712 goto exit;
4713 }
4714
4715 if (filterType != 0 && filterType != 1)
4716 {
4717 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4718 "%s: Accepted Values are 0 and 1 ", __func__);
4719 ret = -EINVAL;
4720 goto exit;
4721 }
4722 wlan_hdd_setIPv6Filter(WLAN_HDD_GET_CTX(pAdapter), filterType,
4723 pAdapter->sessionId);
4724 }
4725#endif
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05304726 else if (strncmp(command, "BTCOEXMODE", 10) == 0 )
4727 {
Kiet Lamad161252014-07-22 11:23:32 -07004728 char *dhcpPhase;
Satyanarayana Dash1faea4f2014-09-22 16:21:04 +05304729 int ret;
4730
Kiet Lamad161252014-07-22 11:23:32 -07004731 dhcpPhase = command + 11;
4732 if ('1' == *dhcpPhase)
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05304733 {
Deepthi Gowribfd17132014-11-14 17:59:04 +05304734 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Kiet Lamad161252014-07-22 11:23:32 -07004735 FL("send DHCP START indication"));
c_hpothu9b781ba2013-12-30 20:57:45 +05304736
4737 pHddCtx->btCoexModeSet = TRUE;
Kiet Lamad161252014-07-22 11:23:32 -07004738
Satyanarayana Dash1faea4f2014-09-22 16:21:04 +05304739 ret = wlan_hdd_scan_abort(pAdapter);
4740 if (ret < 0)
4741 {
4742 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4743 FL("failed to abort existing scan %d"), ret);
4744 }
4745
Kiet Lamad161252014-07-22 11:23:32 -07004746 sme_DHCPStartInd(pHddCtx->hHal, pAdapter->device_mode,
4747 pAdapter->sessionId);
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05304748 }
Kiet Lamad161252014-07-22 11:23:32 -07004749 else if ('2' == *dhcpPhase)
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05304750 {
Deepthi Gowribfd17132014-11-14 17:59:04 +05304751 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Kiet Lamad161252014-07-22 11:23:32 -07004752 FL("send DHCP STOP indication"));
c_hpothu9b781ba2013-12-30 20:57:45 +05304753
4754 pHddCtx->btCoexModeSet = FALSE;
Kiet Lamad161252014-07-22 11:23:32 -07004755
4756 sme_DHCPStopInd(pHddCtx->hHal, pAdapter->device_mode,
4757 pAdapter->sessionId);
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05304758 }
4759 }
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07004760 else if (strncmp(command, "SCAN-ACTIVE", 11) == 0)
4761 {
Abhishek Singh58749d62016-02-03 15:27:20 +05304762 hddLog(LOG1,
4763 FL("making default scan to ACTIVE"));
c_hpothudbefd3e2014-04-28 15:59:47 +05304764 pHddCtx->scan_info.scan_mode = eSIR_ACTIVE_SCAN;
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07004765 }
4766 else if (strncmp(command, "SCAN-PASSIVE", 12) == 0)
4767 {
Abhishek Singh58749d62016-02-03 15:27:20 +05304768 hddLog(LOG1,
4769 FL("making default scan to PASSIVE"));
c_hpothudbefd3e2014-04-28 15:59:47 +05304770 pHddCtx->scan_info.scan_mode = eSIR_PASSIVE_SCAN;
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07004771 }
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05304772 else if (strncmp(command, "GETDWELLTIME", 12) == 0)
4773 {
4774 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
4775 char extra[32];
4776 tANI_U8 len = 0;
4777
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05304778 memset(extra, 0, sizeof(extra));
4779 ret = hdd_get_dwell_time(pCfg, command, extra, sizeof(extra), &len);
Ratnam Rachuri12d5d462015-08-07 14:10:23 +05304780 len = VOS_MIN(priv_data.total_len, len + 1);
4781 if (ret != 0 || copy_to_user(priv_data.buf, &extra, len)) {
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05304782 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4783 "%s: failed to copy data to user buffer", __func__);
4784 ret = -EFAULT;
4785 goto exit;
4786 }
4787 ret = len;
4788 }
4789 else if (strncmp(command, "SETDWELLTIME", 12) == 0)
4790 {
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05304791 ret = hdd_set_dwell_time(pAdapter, command);
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05304792 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07004793 else if ( strncasecmp(command, "MIRACAST", 8) == 0 )
4794 {
4795 tANI_U8 filterType = 0;
4796 tANI_U8 *value;
4797 value = command + 9;
4798
4799 /* Convert the value from ascii to integer */
4800 ret = kstrtou8(value, 10, &filterType);
4801 if (ret < 0)
4802 {
4803 /* If the input value is greater than max value of datatype,
4804 * then also kstrtou8 fails
4805 */
4806 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4807 "%s: kstrtou8 failed range ", __func__);
4808 ret = -EINVAL;
4809 goto exit;
4810 }
4811 if ((filterType < WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL ) ||
4812 (filterType > WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL))
4813 {
4814 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4815 "%s: Accepted Values are 0 to 2. 0-Disabled, 1-Source,"
4816 " 2-Sink ", __func__);
4817 ret = -EINVAL;
4818 goto exit;
4819 }
4820 //Filtertype value should be either 0-Disabled, 1-Source, 2-sink
4821 pHddCtx->drvr_miracast = filterType;
Kaushik, Sushant96122442014-10-21 16:40:18 +05304822 pScanInfo = &pHddCtx->scan_info;
4823 if (filterType && pScanInfo != NULL &&
4824 pHddCtx->scan_info.mScanPending)
4825 {
4826 /*Miracast Session started. Abort Scan */
4827 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4828 "%s, Aborting Scan For Miracast",__func__);
4829 hdd_abort_mac_scan(pHddCtx, pScanInfo->sessionId,
4830 eCSR_SCAN_ABORT_DEFAULT);
4831 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07004832 hdd_tx_rx_pkt_cnt_stat_timer_handler(pHddCtx);
Ganesh Kondabattini8f6e3b32014-08-25 16:07:54 +05304833 sme_SetMiracastMode(pHddCtx->hHal, pHddCtx->drvr_miracast);
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07004834 }
Leo Chang614d2072013-08-22 14:59:44 -07004835 else if (strncmp(command, "SETMCRATE", 9) == 0)
4836 {
Leo Chang614d2072013-08-22 14:59:44 -07004837 tANI_U8 *value = command;
4838 int targetRate;
Leo Chang1f98cbd2013-10-17 15:03:52 -07004839 tSirRateUpdateInd *rateUpdate;
4840 eHalStatus status;
Leo Chang614d2072013-08-22 14:59:44 -07004841
4842 /* Only valid for SAP mode */
4843 if (WLAN_HDD_SOFTAP != pAdapter->device_mode)
4844 {
4845 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4846 "%s: SAP mode is not running", __func__);
4847 ret = -EFAULT;
4848 goto exit;
4849 }
4850
4851 /* Move pointer to ahead of SETMCRATE<delimiter> */
4852 /* input value is in units of hundred kbps */
4853 value = value + 10;
4854 /* Convert the value from ascii to integer, decimal base */
4855 ret = kstrtouint(value, 10, &targetRate);
4856
Leo Chang1f98cbd2013-10-17 15:03:52 -07004857 rateUpdate = (tSirRateUpdateInd *)vos_mem_malloc(sizeof(tSirRateUpdateInd));
4858 if (NULL == rateUpdate)
Leo Chang614d2072013-08-22 14:59:44 -07004859 {
Leo Chang1f98cbd2013-10-17 15:03:52 -07004860 hddLog(VOS_TRACE_LEVEL_ERROR,
4861 "%s: SETMCRATE indication alloc fail", __func__);
4862 ret = -EFAULT;
4863 goto exit;
4864 }
4865 vos_mem_zero(rateUpdate, sizeof(tSirRateUpdateInd ));
4866
4867 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4868 "MC Target rate %d", targetRate);
4869 /* Ignore unicast */
4870 rateUpdate->ucastDataRate = -1;
4871 rateUpdate->mcastDataRate24GHz = targetRate;
4872 rateUpdate->mcastDataRate5GHz = targetRate;
4873 rateUpdate->mcastDataRate24GHzTxFlag = 0;
4874 rateUpdate->mcastDataRate5GHzTxFlag = 0;
4875 status = sme_SendRateUpdateInd(pHddCtx->hHal, rateUpdate);
4876 if (eHAL_STATUS_SUCCESS != status)
4877 {
4878 hddLog(VOS_TRACE_LEVEL_ERROR,
4879 "%s: SET_MC_RATE failed", __func__);
4880 vos_mem_free(rateUpdate);
4881 ret = -EFAULT;
4882 goto exit;
Leo Chang614d2072013-08-22 14:59:44 -07004883 }
4884 }
jge35567202017-06-21 16:39:38 +08004885 else if (strncmp(command, "MAXTXPOWER", 10) == 0)
4886 {
4887 int status;
4888 int txPower;
4889 eHalStatus smeStatus;
4890 tANI_U8 *value = command;
4891 tSirMacAddr bssid = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
4892 tSirMacAddr selfMac = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
4893
4894 status = hdd_parse_setmaxtxpower_command(value, &txPower);
4895 if (status)
4896 {
4897 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4898 "Invalid MAXTXPOWER command ");
4899 ret = -EINVAL;
4900 goto exit;
4901 }
4902
4903 hddLog(VOS_TRACE_LEVEL_INFO, "max tx power %d selfMac: "
4904 MAC_ADDRESS_STR " bssId: " MAC_ADDRESS_STR " ",
4905 txPower, MAC_ADDR_ARRAY(selfMac),
4906 MAC_ADDR_ARRAY(bssid));
4907 smeStatus = sme_SetMaxTxPower((tHalHandle)(pHddCtx->hHal),
4908 bssid, selfMac, txPower) ;
4909 if( smeStatus != eHAL_STATUS_SUCCESS )
4910 {
4911 hddLog(VOS_TRACE_LEVEL_ERROR, "%s:Set max tx power failed",
4912 __func__);
4913 ret = -EINVAL;
4914 goto exit;
4915 }
4916
4917 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Set max tx power success",
4918 __func__);
4919 }
Rajeev79dbe4c2013-10-05 11:03:42 +05304920#ifdef FEATURE_WLAN_BATCH_SCAN
Rajeev Kumar8b373292014-01-08 20:36:55 -08004921 else if (strncmp(command, "WLS_BATCHING", 12) == 0)
Rajeev79dbe4c2013-10-05 11:03:42 +05304922 {
Rajeev Kumar8b373292014-01-08 20:36:55 -08004923 ret = hdd_handle_batch_scan_ioctl(pAdapter, &priv_data, command);
Rajeev79dbe4c2013-10-05 11:03:42 +05304924 }
4925#endif
Abhishek Singh00b71972016-01-07 10:51:04 +05304926#ifdef WLAN_FEATURE_RMC
4927 else if ((strncasecmp(command, "SETIBSSBEACONOUIDATA", 20) == 0) &&
4928 (WLAN_HDD_IBSS == pAdapter->device_mode))
4929 {
4930 int i = 0;
4931 tANI_U8 *ibss_ie;
4932 tANI_U32 command_len;
4933 tANI_U8 *value = command;
4934 tHalHandle hHal = pHddCtx->hHal;
4935 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
4936 tANI_U32 ibss_ie_length;
4937 tANI_U32 len, present;
4938 tANI_U8 *addIE;
4939 tANI_U8 *addIEData;
4940
4941 hddLog(LOG1,
4942 FL(" received command %s"),((char *) value));
4943 /* validate argument of command */
4944 if (strlen(value) <= 21)
4945 {
4946 hddLog(LOGE,
4947 FL("No arguements in command length %zu"), strlen(value));
4948 ret = -EFAULT;
4949 goto exit;
4950 }
4951
4952 /* moving to arguments of commands */
4953 value = value + 21;
4954 command_len = strlen(value);
4955
4956 /* oui_data can't be less than 3 bytes */
4957 if (command_len <= (2 * WLAN_HDD_IBSS_MIN_OUI_DATA_LENGTH))
4958 {
4959 hddLog(LOGE,
4960 FL("Invalid SETIBSSBEACONOUIDATA command length %d"),
4961 command_len);
4962 ret = -EFAULT;
4963 goto exit;
4964 }
4965 ibss_ie = vos_mem_malloc(command_len);
4966 if (!ibss_ie) {
4967 hddLog(LOGE,
4968 FL("Could not allocate memory for command length %d"),
4969 command_len);
4970 ret = -ENOMEM;
4971 goto exit;
4972 }
4973 vos_mem_zero(ibss_ie, command_len);
4974
4975 ibss_ie_length = hdd_parse_set_ibss_oui_data_command(value, ibss_ie,
4976 command_len);
4977 if (ibss_ie_length < (2 * WLAN_HDD_IBSS_MIN_OUI_DATA_LENGTH)) {
4978 hddLog(LOGE, FL("Could not parse command %s return length %d"),
4979 value, ibss_ie_length);
4980 ret = -EFAULT;
4981 vos_mem_free(ibss_ie);
4982 goto exit;
4983 }
4984
4985 hddLog(LOG1, FL("ibss_ie length %d ibss_ie:"), ibss_ie_length);
4986 while (i < ibss_ie_length)
4987 hddLog(LOG1, FL("0x%x"), ibss_ie[i++]);
4988
4989 /* Populate Vendor IE in Beacon */
4990 if ((ccmCfgGetInt(hHal,
4991 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
4992 &present)) != eHAL_STATUS_SUCCESS)
4993 {
4994 hddLog(LOGE,
4995 FL("unable to ftch WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG"));
4996 ret = -EFAULT;
4997 vos_mem_free(ibss_ie);
4998 goto exit;
4999 }
5000
5001 addIE = vos_mem_malloc(WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN);
5002 if (!addIE) {
5003 hddLog(LOGE,
5004 FL("Could not allocate memory for command length %d"),
5005 command_len);
5006 vos_mem_free(ibss_ie);
5007 ret = -ENOMEM;
5008 goto exit;
5009 }
5010 vos_mem_zero(addIE, WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN);
5011
5012 if (present)
5013 {
5014 if ((wlan_cfgGetStrLen(pMac,
5015 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, &len)) != eSIR_SUCCESS)
5016 {
5017 hddLog(LOGE,
5018 FL("unable to fetch WNI_CFG_PROBE_RSP_BCN_ADDNIE_LEN"));
5019 ret = -EFAULT;
5020 vos_mem_free(ibss_ie);
5021 vos_mem_free(addIE);
5022 goto exit;
5023 }
5024
5025 if (len <= WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN && len &&
5026 ((len + ibss_ie_length) <=
5027 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN))
5028 {
5029 if ((ccmCfgGetStr(hHal,
5030 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, addIE, &len))
5031 != eHAL_STATUS_SUCCESS)
5032 {
5033 hddLog(LOGE,
5034 FL("unable to fetch WNI_PROBE_RSP_BCN_ADDNIE_DATA"));
5035 ret = -EFAULT;
5036 vos_mem_free(ibss_ie);
5037 vos_mem_free(addIE);
5038 goto exit;
5039 }
5040 else
5041 {
5042 /* Curruntly only WPA IE is added before Vendor IE
5043 * so we can blindly place the Vendor IE after WPA
5044 * IE. If no WPA IE found replace all with Vendor IE.
5045 */
5046 len = hdd_find_ibss_wpa_ie_pos(addIE, len);
5047 }
5048 }
5049 else
5050 {
5051 hddLog(LOGE,
5052 FL("IE len exceed limit len %d,ibss_ie_length %d "),
5053 len, ibss_ie_length);
5054 ret = -EFAULT;
5055 vos_mem_free(addIE);
5056 vos_mem_free(ibss_ie);
5057 goto exit;
5058 }
5059 }
5060 else {
5061 len = 0;
5062 }
5063
5064 vos_mem_copy (addIE + len , ibss_ie, ibss_ie_length);
5065 len += ibss_ie_length;
5066
5067 if (ccmCfgSetStr(hHal,
5068 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, addIE, len, NULL,
5069 eANI_BOOLEAN_FALSE) != eHAL_STATUS_SUCCESS)
5070 {
5071 hddLog(LOGE,
5072 FL("unable to set WNI_CFG_PRBE_RSP_BCN_ADDNIE_DATA"));
5073 ret = -EFAULT;
5074 vos_mem_free(ibss_ie);
5075 vos_mem_free(addIE);
5076 goto exit;
5077 }
5078 vos_mem_free(addIE);
5079 if (ccmCfgSetInt(hHal,
5080 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 1,NULL,
5081 eANI_BOOLEAN_FALSE) != eHAL_STATUS_SUCCESS)
5082 {
5083 hddLog(LOGE,
5084 FL("unble to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG"));
5085 ret = -EFAULT;
5086 vos_mem_free(ibss_ie);
5087 goto exit;
5088 }
5089
5090 /* Populate Vendor IE in probe resp */
5091 if ((ccmCfgGetInt(hHal,
5092 WNI_CFG_PROBE_RSP_ADDNIE_FLAG,
5093 &present)) != eHAL_STATUS_SUCCESS)
5094 {
5095 hddLog(LOGE,
5096 FL("unable to fetch WNI_CFG_PROBE_RSP_ADDNIE_FLAG"));
5097 ret = -EFAULT;
5098 vos_mem_free(ibss_ie);
5099 goto exit;
5100 }
5101
5102 addIEData = vos_mem_malloc(WNI_CFG_PROBE_RSP_ADDNIE_DATA1_LEN);
5103 if (!addIEData) {
5104 hddLog(LOGE,
5105 FL("Could not allocate memory for command length %d"),
5106 command_len);
5107 vos_mem_free(ibss_ie);
5108 ret = -ENOMEM;
5109 goto exit;
5110 }
5111 vos_mem_zero(addIEData, WNI_CFG_PROBE_RSP_ADDNIE_DATA1_LEN);
5112
5113 if (present) {
5114 if (eSIR_SUCCESS != wlan_cfgGetStrLen(pMac,
5115 WNI_CFG_PROBE_RSP_ADDNIE_DATA1, &len)) {
5116 hddLog(LOGE,
5117 FL("unable to fetch WNI_CFG_PROBE_RSP_ADDNIE_DATA1"));
5118 ret = -EFAULT;
5119 vos_mem_free(ibss_ie);
5120 vos_mem_free(addIEData);
5121 goto exit;
5122 }
5123 if (len < WNI_CFG_PROBE_RSP_ADDNIE_DATA1_LEN && len &&
5124 (ibss_ie_length + len) <=
5125 WNI_CFG_PROBE_RSP_ADDNIE_DATA1_LEN) {
5126
5127 if ((ccmCfgGetStr(hHal,
5128 WNI_CFG_PROBE_RSP_ADDNIE_DATA1, addIEData, &len))
5129 != eHAL_STATUS_SUCCESS) {
5130 hddLog(LOGE,
5131 FL("unable fetch WNI_CFG_PROBE_RSP_ADDNIE_DATA1"));
5132 ret = -EFAULT;
5133 vos_mem_free(ibss_ie);
5134 vos_mem_free(addIEData);
5135 goto exit;
5136 }
5137 else {
5138 /* Curruntly only WPA IE is added before Vendor IE
5139 * so we can blindly place the Vendor IE after WPA
5140 * IE. If no WPA IE found replace all with Vendor IE.
5141 */
5142 len = hdd_find_ibss_wpa_ie_pos(addIEData, len);
5143 }
5144 }
5145 else
5146 {
5147 hddLog(LOGE,
5148 FL("IE len exceed limit len %d,ibss_ie_length %d "),
5149 len, ibss_ie_length);
5150 ret = -EFAULT;
5151 vos_mem_free(addIEData);
5152 vos_mem_free(ibss_ie);
5153 goto exit;
5154 }
5155 } /* probe rsp ADD IE present */
5156 else {
5157 /* probe rsp add IE is not present */
5158 len = 0;
5159 }
5160
5161 vos_mem_copy(addIEData +len , ibss_ie, ibss_ie_length);
5162 len += ibss_ie_length;
5163
5164 vos_mem_free(ibss_ie);
5165
5166 if (ccmCfgSetStr(hHal,
5167 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,
5168 (tANI_U8*)(addIEData),
5169 len, NULL,
5170 eANI_BOOLEAN_FALSE)
5171 == eHAL_STATUS_FAILURE) {
5172 hddLog(LOGE,
5173 FL("unable to copy to WNI_CFG_PROBE_RSP_ADDNIE_DATA1"));
5174 ret = -EFAULT;
5175 vos_mem_free(addIEData);
5176 goto exit;
5177 }
5178 vos_mem_free(addIEData);
5179 if (ccmCfgSetInt(WLAN_HDD_GET_HAL_CTX(pAdapter),
5180 WNI_CFG_PROBE_RSP_ADDNIE_FLAG, 1,NULL,
5181 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
5182 {
5183 hddLog(LOGE,
5184 FL("unable to copy WNI_CFG_PROBE_RSP_ADDNIE_FLAG"));
5185 ret = -EFAULT;
5186 goto exit;
5187 }
5188 }
5189 else if (strncasecmp(command, "SETRMCENABLE", 12) == 0)
5190 {
5191 tANI_U8 *value = command;
5192 tANI_U8 ucRmcEnable = 0;
5193 int status;
5194
5195 if ((WLAN_HDD_IBSS != pAdapter->device_mode) &&
5196 (WLAN_HDD_SOFTAP != pAdapter->device_mode))
5197 {
5198 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5199 "Received SETRMCENABLE command in invalid mode %d "
5200 "SETRMCENABLE command is only allowed in IBSS or SOFTAP mode",
5201 pAdapter->device_mode);
5202 ret = -EINVAL;
5203 goto exit;
5204 }
5205
5206 status = hdd_parse_setrmcenable_command(value, &ucRmcEnable);
5207 if (status)
5208 {
5209 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5210 "Invalid SETRMCENABLE command ");
5211 ret = -EINVAL;
5212 goto exit;
5213 }
5214
5215 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5216 "%s: ucRmcEnable %d ", __func__, ucRmcEnable);
5217
5218 if (TRUE == ucRmcEnable)
5219 {
5220 status = sme_EnableRMC( (tHalHandle)(pHddCtx->hHal),
5221 pAdapter->sessionId );
5222 }
5223 else if(FALSE == ucRmcEnable)
5224 {
5225 status = sme_DisableRMC( (tHalHandle)(pHddCtx->hHal),
5226 pAdapter->sessionId );
5227 }
5228 else
5229 {
5230 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5231 "Invalid SETRMCENABLE command %d", ucRmcEnable);
5232 ret = -EINVAL;
5233 goto exit;
5234 }
5235
5236 if (VOS_STATUS_SUCCESS != status)
5237 {
5238 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5239 "%s: SETRMC %d failed status %d", __func__, ucRmcEnable,
5240 status);
5241 ret = -EINVAL;
5242 goto exit;
5243 }
5244 }
5245 else if (strncasecmp(command, "SETRMCACTIONPERIOD", 18) == 0)
5246 {
5247 tANI_U8 *value = command;
5248 tANI_U32 uActionPeriod = 0;
5249 int status;
5250
5251 if ((WLAN_HDD_IBSS != pAdapter->device_mode) &&
5252 (WLAN_HDD_SOFTAP != pAdapter->device_mode))
5253 {
5254 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5255 "Received SETRMC command in invalid mode %d "
5256 "SETRMC command is only allowed in IBSS or SOFTAP mode",
5257 pAdapter->device_mode);
5258 ret = -EINVAL;
5259 goto exit;
5260 }
5261
5262 status = hdd_parse_setrmcactionperiod_command(value, &uActionPeriod);
5263 if (status)
5264 {
5265 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5266 "Invalid SETRMCACTIONPERIOD command ");
5267 ret = -EINVAL;
5268 goto exit;
5269 }
5270
5271 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5272 "%s: uActionPeriod %d ", __func__, uActionPeriod);
5273
5274 if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY,
5275 uActionPeriod, NULL, eANI_BOOLEAN_FALSE))
5276 {
5277 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5278 "%s: Could not set SETRMCACTIONPERIOD %d", __func__, uActionPeriod);
5279 ret = -EINVAL;
5280 goto exit;
5281 }
5282
5283 }
5284 else if (strncasecmp(command, "GETIBSSPEERINFOALL", 18) == 0)
5285 {
5286 /* Peer Info All Command */
5287 int status = eHAL_STATUS_SUCCESS;
5288 hdd_station_ctx_t *pHddStaCtx = NULL;
5289 char *extra = NULL;
5290 int idx = 0, length = 0;
5291 v_MACADDR_t *macAddr;
5292 v_U32_t txRateMbps = 0, numOfBytestoPrint = 0;
5293
5294 if (WLAN_HDD_IBSS == pAdapter->device_mode)
5295 {
5296 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5297 }
5298 else
5299 {
5300 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5301 "%s: pAdapter is not valid for this device mode",
5302 __func__);
5303 ret = -EINVAL;
5304 goto exit;
5305 }
5306
5307 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5308 "%s: Received GETIBSSPEERINFOALL Command", __func__);
5309
5310
5311 /* Handle the command */
5312 status = hdd_cfg80211_get_ibss_peer_info_all(pAdapter);
5313 if (VOS_STATUS_SUCCESS == status)
5314 {
5315 /* The variable extra needed to be allocated on the heap since
5316 * amount of memory required to copy the data for 32 devices
5317 * exceeds the size of 1024 bytes of default stack size. On
5318 * 64 bit devices, the default max stack size of 2048 bytes
5319 */
5320 extra = kmalloc(WLAN_MAX_BUF_SIZE, GFP_KERNEL);
5321
5322 if (NULL == extra)
5323 {
5324 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5325 "%s:kmalloc failed", __func__);
5326 ret = -EINVAL;
5327 goto exit;
5328 }
5329
5330 /* Copy number of stations */
5331 length = scnprintf( extra, WLAN_MAX_BUF_SIZE, "%d ",
5332 pHddStaCtx->ibss_peer_info.numIBSSPeers);
5333 numOfBytestoPrint = length;
5334 for (idx = 0; idx < pHddStaCtx->ibss_peer_info.numIBSSPeers; idx++)
5335 {
5336 macAddr =
5337 hdd_wlan_get_ibss_mac_addr_from_staid(pAdapter,
5338 pHddStaCtx->ibss_peer_info.ibssPeerList[idx].staIdx);
5339 if (NULL != macAddr)
5340 {
5341 txRateMbps =
5342 ((pHddStaCtx->ibss_peer_info.ibssPeerList[idx].txRate)*500*1000)/1000000;
5343
5344 length += scnprintf( (extra + length), WLAN_MAX_BUF_SIZE - length,
5345 "%02x:%02x:%02x:%02x:%02x:%02x %d %d ",
5346 macAddr->bytes[0], macAddr->bytes[1], macAddr->bytes[2],
5347 macAddr->bytes[3], macAddr->bytes[4], macAddr->bytes[5],
5348 (int)txRateMbps,
5349 (int)pHddStaCtx->ibss_peer_info.ibssPeerList[idx].rssi);
5350 }
5351 else
5352 {
5353 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5354 "%s: MAC ADDR is NULL for staIdx: %d", __func__,
5355 pHddStaCtx->ibss_peer_info.ibssPeerList[idx].staIdx);
5356 }
5357
5358 /*
5359 * VOS_TRACE() macro has limitation of 512 bytes for the print
5360 * buffer. Hence printing the data in two chunks. The first chunk
5361 * will have the data for 16 devices and the second chunk will
5362 * have the rest.
5363 */
5364 if (idx < NUM_OF_STA_DATA_TO_PRINT)
5365 {
5366 numOfBytestoPrint = length;
5367 }
5368 }
5369
5370 /*
5371 * Copy the data back into buffer, if the data to copy is
5372 * morethan 512 bytes than we will split the data and do
5373 * it in two shots
5374 */
5375 if (copy_to_user(priv_data.buf, extra, numOfBytestoPrint))
5376 {
5377 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5378 "%s: Copy into user data buffer failed ", __func__);
5379 ret = -EFAULT;
5380 kfree(extra);
5381 goto exit;
5382 }
5383 priv_data.buf[numOfBytestoPrint] = '\0';
5384 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED,
5385 "%s", priv_data.buf);
5386
5387 if (length > numOfBytestoPrint)
5388 {
5389 if (copy_to_user(priv_data.buf + numOfBytestoPrint,
5390 extra + numOfBytestoPrint,
5391 length - numOfBytestoPrint + 1))
5392 {
5393 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5394 "%s: Copy into user data buffer failed ", __func__);
5395 ret = -EFAULT;
5396 kfree(extra);
5397 goto exit;
5398 }
5399 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED,
5400 "%s", &priv_data.buf[numOfBytestoPrint]);
5401 }
5402
5403 /* Free temporary buffer */
5404 kfree(extra);
5405 }
5406
5407 else
5408 {
5409 /* Command failed, log error */
5410 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5411 "%s: GETIBSSPEERINFOALL command failed with status code %d",
5412 __func__, status);
5413 ret = -EINVAL;
5414 goto exit;
5415 }
5416 ret = 0;
5417 }
5418 else if(strncasecmp(command, "GETIBSSPEERINFO", 15) == 0)
5419 {
5420 /* Peer Info <Peer Addr> command */
5421 tANI_U8 *value = command;
5422 VOS_STATUS status;
5423 hdd_station_ctx_t *pHddStaCtx = NULL;
5424 char extra[128] = { 0 };
5425 v_U32_t length = 0;
5426 v_U8_t staIdx = 0;
5427 v_U32_t txRateMbps = 0;
5428 v_MACADDR_t peerMacAddr;
5429
5430 if (WLAN_HDD_IBSS == pAdapter->device_mode)
5431 {
5432 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5433 }
5434 else
5435 {
5436 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5437 "%s: pAdapter is not valid for this device mode",
5438 __func__);
5439 ret = -EINVAL;
5440 goto exit;
5441 }
5442
5443 /* if there are no peers, no need to continue with the command */
5444 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5445 "%s: Received GETIBSSPEERINFO Command", __func__);
5446
5447 if (eConnectionState_IbssConnected != pHddStaCtx->conn_info.connState)
5448 {
5449 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5450 "%s:No IBSS Peers coalesced", __func__);
5451 ret = -EINVAL;
5452 goto exit;
5453 }
5454
5455 /* Parse the incoming command buffer */
5456 status = hdd_parse_get_ibss_peer_info(value, &peerMacAddr);
5457 if (VOS_STATUS_SUCCESS != status)
5458 {
5459 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5460 "%s: Invalid GETIBSSPEERINFO command", __func__);
5461 ret = -EINVAL;
5462 goto exit;
5463 }
5464
5465 /* Get station index for the peer mac address */
5466 hdd_Ibss_GetStaId(pHddStaCtx, &peerMacAddr, &staIdx);
5467
5468 if (staIdx > HDD_MAX_NUM_IBSS_STA)
5469 {
5470 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5471 "%s: Invalid StaIdx %d returned", __func__, staIdx);
5472 ret = -EINVAL;
5473 goto exit;
5474 }
5475
5476 /* Handle the command */
5477 status = hdd_cfg80211_get_ibss_peer_info(pAdapter, staIdx);
5478 if (VOS_STATUS_SUCCESS == status)
5479 {
5480 v_U32_t txRate = pHddStaCtx->ibss_peer_info.ibssPeerList[0].txRate;
5481 txRateMbps = (txRate * 500 * 1000)/1000000;
5482
5483 length = scnprintf( extra, sizeof(extra), "%d %d", (int)txRateMbps,
5484 (int)pHddStaCtx->ibss_peer_info.ibssPeerList[0].rssi);
5485
5486 /* Copy the data back into buffer */
5487 if (copy_to_user(priv_data.buf, &extra, length+ 1))
5488 {
5489 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5490 "%s: copy data to user buffer failed GETIBSSPEERINFO command",
5491 __func__);
5492 ret = -EFAULT;
5493 goto exit;
5494 }
5495 }
5496 else
5497 {
5498 /* Command failed, log error */
5499 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5500 "%s: GETIBSSPEERINFO command failed with status code %d",
5501 __func__, status);
5502 ret = -EINVAL;
5503 goto exit;
5504 }
5505
5506 /* Success ! */
5507 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED,
5508 "%s", priv_data.buf);
5509 ret = 0;
5510 }
5511 else if (strncasecmp(command, "SETRMCTXRATE", 12) == 0)
5512 {
5513 tANI_U8 *value = command;
5514 tANI_U32 uRate = 0;
5515 tTxrateinfoflags txFlags = 0;
5516 tSirRateUpdateInd *rateUpdateParams;
5517 int status;
5518
5519 if ((WLAN_HDD_IBSS != pAdapter->device_mode) &&
5520 (WLAN_HDD_SOFTAP != pAdapter->device_mode))
5521 {
5522 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5523 "Received SETRMCTXRATE command in invalid mode %d "
5524 "SETRMC command is only allowed in IBSS or SOFTAP mode",
5525 pAdapter->device_mode);
5526 ret = -EINVAL;
5527 goto exit;
5528 }
5529
5530 status = hdd_parse_setrmcrate_command(value, &uRate, &txFlags);
5531 if (status)
5532 {
5533 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5534 "Invalid SETRMCTXRATE command ");
5535 ret = -EINVAL;
5536 goto exit;
5537 }
5538
5539 rateUpdateParams = vos_mem_malloc(sizeof(tSirRateUpdateInd));
5540 if (NULL == rateUpdateParams)
5541 {
5542 ret = -EINVAL;
5543 goto exit;
5544 }
5545
5546 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5547 "%s: uRate %d ", __func__, uRate);
5548
5549 vos_mem_zero(rateUpdateParams, sizeof(tSirRateUpdateInd ));
5550
5551 /* -1 implies ignore this param */
5552 rateUpdateParams->ucastDataRate = -1;
5553
5554 /*
5555 * Fill the user specifieed RMC rate param
5556 * and the derived tx flags.
5557 */
5558 rateUpdateParams->rmcDataRate = uRate;
5559 rateUpdateParams->rmcDataRateTxFlag = txFlags;
5560
5561 status = sme_SendRateUpdateInd((tHalHandle)(pHddCtx->hHal), rateUpdateParams);
5562 }
5563 else if (strncasecmp(command, "SETIBSSTXFAILEVENT", 18) == 0 )
5564 {
5565 char *value;
5566 tANI_U8 tx_fail_count = 0;
5567 tANI_U16 pid = 0;
5568
5569 value = command;
5570
5571 ret = hdd_ParseIBSSTXFailEventParams(value, &tx_fail_count, &pid);
5572
5573 if (0 != ret)
5574 {
5575 hddLog(VOS_TRACE_LEVEL_INFO,
5576 "%s: Failed to parse SETIBSSTXFAILEVENT arguments",
5577 __func__);
5578 goto exit;
5579 }
5580
5581 hddLog(VOS_TRACE_LEVEL_INFO, "%s: tx_fail_cnt=%hhu, pid=%hu",
5582 __func__, tx_fail_count, pid);
5583
5584 if (0 == tx_fail_count)
5585 {
5586 // Disable TX Fail Indication
5587 if (eHAL_STATUS_SUCCESS ==
5588 sme_TXFailMonitorStartStopInd(pHddCtx->hHal,
5589 tx_fail_count,
5590 NULL))
5591 {
5592 cesium_pid = 0;
5593 }
5594 else
5595 {
5596 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5597 "%s: failed to disable TX Fail Event ", __func__);
5598 ret = -EINVAL;
5599 }
5600 }
5601 else
5602 {
5603 if (eHAL_STATUS_SUCCESS ==
5604 sme_TXFailMonitorStartStopInd(pHddCtx->hHal,
5605 tx_fail_count,
5606 (void*)hdd_tx_fail_ind_callback))
5607 {
5608 cesium_pid = pid;
5609 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5610 "%s: Registered Cesium pid %u", __func__,
5611 cesium_pid);
5612 }
5613 else
5614 {
5615 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5616 "%s: Failed to enable TX Fail Monitoring", __func__);
5617 ret = -EINVAL;
5618 }
5619 }
5620 }
5621
5622#endif /* WLAN_FEATURE_RMC */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08005623#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07005624 else if (strncmp(command, "SETCCXROAMSCANCHANNELS", 22) == 0)
5625 {
5626 tANI_U8 *value = command;
5627 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
5628 tANI_U8 numChannels = 0;
5629 eHalStatus status = eHAL_STATUS_SUCCESS;
5630
5631 status = hdd_parse_channellist(value, ChannelList, &numChannels);
5632 if (eHAL_STATUS_SUCCESS != status)
5633 {
5634 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5635 "%s: Failed to parse channel list information", __func__);
5636 ret = -EINVAL;
5637 goto exit;
5638 }
5639
5640 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
5641 {
5642 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5643 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
5644 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
5645 ret = -EINVAL;
5646 goto exit;
5647 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08005648 status = sme_SetEseRoamScanChannelList((tHalHandle)(pHddCtx->hHal),
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07005649 ChannelList,
5650 numChannels);
5651 if (eHAL_STATUS_SUCCESS != status)
5652 {
5653 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5654 "%s: Failed to update channel list information", __func__);
5655 ret = -EINVAL;
5656 goto exit;
5657 }
5658 }
5659 else if (strncmp(command, "GETTSMSTATS", 11) == 0)
5660 {
5661 tANI_U8 *value = command;
5662 char extra[128] = {0};
5663 int len = 0;
5664 tANI_U8 tid = 0;
5665 hdd_station_ctx_t *pHddStaCtx = NULL;
5666 tAniTrafStrmMetrics tsmMetrics;
5667 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5668
5669 /* if not associated, return error */
5670 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
5671 {
5672 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:Not associated!",__func__);
5673 ret = -EINVAL;
5674 goto exit;
5675 }
5676
5677 /* Move pointer to ahead of GETTSMSTATS<delimiter> */
5678 value = value + 12;
5679 /* Convert the value from ascii to integer */
5680 ret = kstrtou8(value, 10, &tid);
5681 if (ret < 0)
5682 {
5683 /* If the input value is greater than max value of datatype, then also
5684 kstrtou8 fails */
5685 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5686 "%s: kstrtou8 failed range [%d - %d]", __func__,
5687 TID_MIN_VALUE,
5688 TID_MAX_VALUE);
5689 ret = -EINVAL;
5690 goto exit;
5691 }
5692
5693 if ((tid < TID_MIN_VALUE) || (tid > TID_MAX_VALUE))
5694 {
5695 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5696 "tid value %d is out of range"
5697 " (Min: %d Max: %d)", tid,
5698 TID_MIN_VALUE,
5699 TID_MAX_VALUE);
5700 ret = -EINVAL;
5701 goto exit;
5702 }
5703
5704 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5705 "%s: Received Command to get tsm stats tid = %d", __func__, tid);
5706
5707 if (VOS_STATUS_SUCCESS != hdd_get_tsm_stats(pAdapter, tid, &tsmMetrics))
5708 {
5709 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5710 "%s: failed to get tsm stats", __func__);
5711 ret = -EFAULT;
5712 goto exit;
5713 }
5714
5715 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5716 "UplinkPktQueueDly(%d)\n"
5717 "UplinkPktQueueDlyHist[0](%d)\n"
5718 "UplinkPktQueueDlyHist[1](%d)\n"
5719 "UplinkPktQueueDlyHist[2](%d)\n"
5720 "UplinkPktQueueDlyHist[3](%d)\n"
Arun Kumar Khandavallie8768212014-02-17 16:43:34 +05305721 "UplinkPktTxDly(%u)\n"
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07005722 "UplinkPktLoss(%d)\n"
5723 "UplinkPktCount(%d)\n"
5724 "RoamingCount(%d)\n"
5725 "RoamingDly(%d)", tsmMetrics.UplinkPktQueueDly,
5726 tsmMetrics.UplinkPktQueueDlyHist[0],
5727 tsmMetrics.UplinkPktQueueDlyHist[1],
5728 tsmMetrics.UplinkPktQueueDlyHist[2],
5729 tsmMetrics.UplinkPktQueueDlyHist[3],
5730 tsmMetrics.UplinkPktTxDly, tsmMetrics.UplinkPktLoss,
5731 tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount, tsmMetrics.RoamingDly);
5732
5733 /* Output TSM stats is of the format
5734 GETTSMSTATS [PktQueueDly] [PktQueueDlyHist[0]]:[PktQueueDlyHist[1]] ...[RoamingDly]
5735 eg., GETTSMSTATS 10 1:0:0:161 20 1 17 8 39800 */
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08005736 len = scnprintf(extra, sizeof(extra), "%s %d %d:%d:%d:%d %u %d %d %d %d", command,
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07005737 tsmMetrics.UplinkPktQueueDly, tsmMetrics.UplinkPktQueueDlyHist[0],
5738 tsmMetrics.UplinkPktQueueDlyHist[1], tsmMetrics.UplinkPktQueueDlyHist[2],
5739 tsmMetrics.UplinkPktQueueDlyHist[3], tsmMetrics.UplinkPktTxDly,
5740 tsmMetrics.UplinkPktLoss, tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount,
5741 tsmMetrics.RoamingDly);
5742
Ratnam Rachurid53009c2015-08-07 13:59:00 +05305743 len = VOS_MIN(priv_data.total_len, len + 1);
5744 if (copy_to_user(priv_data.buf, &extra, len)) {
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07005745 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5746 "%s: failed to copy data to user buffer", __func__);
5747 ret = -EFAULT;
5748 goto exit;
5749 }
5750 }
5751 else if (strncmp(command, "SETCCKMIE", 9) == 0)
5752 {
5753 tANI_U8 *value = command;
5754 tANI_U8 *cckmIe = NULL;
5755 tANI_U8 cckmIeLen = 0;
5756 eHalStatus status = eHAL_STATUS_SUCCESS;
5757
5758 status = hdd_parse_get_cckm_ie(value, &cckmIe, &cckmIeLen);
5759 if (eHAL_STATUS_SUCCESS != status)
5760 {
5761 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5762 "%s: Failed to parse cckm ie data", __func__);
5763 ret = -EINVAL;
5764 goto exit;
5765 }
5766
5767 if (cckmIeLen > DOT11F_IE_RSN_MAX_LEN)
5768 {
5769 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5770 "%s: CCKM Ie input length is more than max[%d]", __func__,
5771 DOT11F_IE_RSN_MAX_LEN);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08005772 vos_mem_free(cckmIe);
5773 cckmIe = NULL;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07005774 ret = -EINVAL;
5775 goto exit;
5776 }
5777 sme_SetCCKMIe((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, cckmIe, cckmIeLen);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08005778 vos_mem_free(cckmIe);
5779 cckmIe = NULL;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07005780 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08005781 else if (strncmp(command, "CCXBEACONREQ", 12) == 0)
5782 {
5783 tANI_U8 *value = command;
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08005784 tCsrEseBeaconReq eseBcnReq;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08005785 eHalStatus status = eHAL_STATUS_SUCCESS;
Srinivas Girigowda0c6d7fe2014-05-28 18:18:10 -07005786
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08005787 status = hdd_parse_ese_beacon_req(value, &eseBcnReq);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08005788 if (eHAL_STATUS_SUCCESS != status)
5789 {
5790 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08005791 "%s: Failed to parse ese beacon req", __func__);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08005792 ret = -EINVAL;
5793 goto exit;
5794 }
Srinivas Girigowda0c6d7fe2014-05-28 18:18:10 -07005795 if (!hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))) {
5796 hddLog(VOS_TRACE_LEVEL_INFO, FL("Not associated"));
5797 hdd_indicateEseBcnReportNoResults (pAdapter,
5798 eseBcnReq.bcnReq[0].measurementToken,
5799 0x02, //BIT(1) set for measurement done
5800 0); // no BSS
5801 goto exit;
5802 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08005803
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08005804 status = sme_SetEseBeaconRequest((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, &eseBcnReq);
5805 if (eHAL_STATUS_SUCCESS != status)
5806 {
5807 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5808 "%s: sme_SetEseBeaconRequest failed (%d)", __func__, status);
5809 ret = -EINVAL;
5810 goto exit;
5811 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08005812 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08005813#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
c_hpothu92367912014-05-01 15:18:17 +05305814 else if (strncmp(command, "GETBCNMISSRATE", 14) == 0)
5815 {
5816 eHalStatus status;
5817 char buf[32], len;
5818 long waitRet;
5819 bcnMissRateContext_t getBcnMissRateCtx;
5820
5821 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5822
5823 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
5824 {
5825 hddLog(VOS_TRACE_LEVEL_WARN,
5826 FL("GETBCNMISSRATE: STA is not in connected state"));
5827 ret = -1;
5828 goto exit;
5829 }
5830
5831 init_completion(&(getBcnMissRateCtx.completion));
5832 getBcnMissRateCtx.magic = BCN_MISS_RATE_CONTEXT_MAGIC;
5833
5834 status = sme_getBcnMissRate((tHalHandle)(pHddCtx->hHal),
5835 pAdapter->sessionId,
5836 (void *)getBcnMissRateCB,
5837 (void *)(&getBcnMissRateCtx));
5838 if( eHAL_STATUS_SUCCESS != status)
5839 {
5840 hddLog(VOS_TRACE_LEVEL_INFO,
5841 FL("GETBCNMISSRATE: fail to post WDA cmd"));
5842 ret = -EINVAL;
5843 goto exit;
5844 }
5845
5846 waitRet = wait_for_completion_interruptible_timeout
5847 (&getBcnMissRateCtx.completion, BCN_MISS_RATE_TIME);
5848 if(waitRet <= 0)
5849 {
5850 hddLog(VOS_TRACE_LEVEL_ERROR,
5851 FL("failed to wait on bcnMissRateComp %d"), ret);
5852
5853 //Make magic number to zero so that callback is not called.
5854 spin_lock(&hdd_context_lock);
5855 getBcnMissRateCtx.magic = 0x0;
5856 spin_unlock(&hdd_context_lock);
5857 ret = -EINVAL;
5858 goto exit;
5859 }
5860
5861 hddLog(VOS_TRACE_LEVEL_INFO,
5862 FL("GETBCNMISSRATE: bcnMissRate: %d"), gbcnMissRate);
5863
5864 len = snprintf(buf, sizeof(buf), "GETBCNMISSRATE %d", gbcnMissRate);
5865 if (copy_to_user(priv_data.buf, &buf, len + 1))
5866 {
5867 hddLog(VOS_TRACE_LEVEL_ERROR,
5868 "%s: failed to copy data to user buffer", __func__);
5869 ret = -EFAULT;
5870 goto exit;
5871 }
5872 ret = len;
5873 }
Atul Mittal87ec2422014-09-24 13:12:50 +05305874#ifdef FEATURE_WLAN_TDLS
5875 else if (strncmp(command, "TDLSSECONDARYCHANNELOFFSET", 26) == 0) {
5876 tANI_U8 *value = command;
5877 int set_value;
5878 /* Move pointer to ahead of TDLSOFFCH*/
5879 value += 26;
c_manjeebbc40212015-12-08 13:52:59 +05305880 if (!(sscanf(value, "%d", &set_value))) {
5881 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5882 FL("No input identified"));
5883 ret = -EINVAL;
5884 goto exit;
5885 }
5886
Atul Mittal87ec2422014-09-24 13:12:50 +05305887 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5888 "%s: Tdls offchannel offset:%d",
5889 __func__, set_value);
5890 ret = iw_set_tdlssecoffchanneloffset(pHddCtx, set_value);
5891 if (ret < 0)
5892 {
5893 ret = -EINVAL;
5894 goto exit;
5895 }
5896
5897 } else if (strncmp(command, "TDLSOFFCHANNELMODE", 18) == 0) {
5898 tANI_U8 *value = command;
5899 int set_value;
5900 /* Move pointer to ahead of tdlsoffchnmode*/
5901 value += 18;
c_manjee82323892015-12-08 12:40:34 +05305902 ret = sscanf(value, "%d", &set_value);
5903 if (ret != 1) {
5904 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5905 FL("No input identified"));
5906 ret = -EINVAL;
5907 goto exit;
5908 }
Atul Mittal87ec2422014-09-24 13:12:50 +05305909 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5910 "%s: Tdls offchannel mode:%d",
5911 __func__, set_value);
5912 ret = iw_set_tdlsoffchannelmode(pAdapter, set_value);
5913 if (ret < 0)
5914 {
5915 ret = -EINVAL;
5916 goto exit;
5917 }
5918 } else if (strncmp(command, "TDLSOFFCHANNEL", 14) == 0) {
5919 tANI_U8 *value = command;
5920 int set_value;
5921 /* Move pointer to ahead of TDLSOFFCH*/
5922 value += 14;
c_manjeef6ccaf52015-12-08 11:52:11 +05305923 ret = sscanf(value, "%d", &set_value);
5924 if (ret != 1) {
5925 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5926 "Wrong value is given for hdd_set_tdls_offchannel");
5927 ret = -EINVAL;
5928 goto exit;
5929 }
5930
Atul Mittal87ec2422014-09-24 13:12:50 +05305931 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5932 "%s: Tdls offchannel num: %d",
5933 __func__, set_value);
5934 ret = iw_set_tdlsoffchannel(pHddCtx, set_value);
5935 if (ret < 0)
5936 {
5937 ret = -EINVAL;
5938 goto exit;
5939 }
5940 }
5941#endif
Satyanarayana Dash72806012014-12-02 14:30:08 +05305942 else if (strncmp(command, "GETFWSTATS", 10) == 0)
5943 {
5944 eHalStatus status;
5945 char *buf = NULL;
5946 char len;
5947 long waitRet;
5948 fwStatsContext_t fwStatsCtx;
Abhishek Singh08aa7762014-12-16 13:59:03 +05305949 tSirFwStatsResult *fwStatsRsp = &(pAdapter->fwStatsRsp);
Satyanarayana Dash72806012014-12-02 14:30:08 +05305950 tANI_U8 *ptr = command;
5951 int stats = *(ptr + 11) - '0';
5952
5953 hddLog(VOS_TRACE_LEVEL_INFO, FL("stats = %d "),stats);
5954 if (!IS_FEATURE_FW_STATS_ENABLE)
5955 {
5956 hddLog(VOS_TRACE_LEVEL_INFO,
5957 FL("Get Firmware stats feature not supported"));
5958 ret = -EINVAL;
5959 goto exit;
5960 }
5961
5962 if (FW_STATS_MAX <= stats || 0 >= stats)
5963 {
5964 hddLog(VOS_TRACE_LEVEL_INFO,
5965 FL(" stats %d not supported"),stats);
5966 ret = -EINVAL;
5967 goto exit;
5968 }
5969
5970 init_completion(&(fwStatsCtx.completion));
5971 fwStatsCtx.magic = FW_STATS_CONTEXT_MAGIC;
5972 fwStatsCtx.pAdapter = pAdapter;
5973 fwStatsRsp->type = 0;
5974 status = sme_GetFwStats( (tHalHandle)pHddCtx->hHal, stats,
Abhishek Singh08aa7762014-12-16 13:59:03 +05305975 &fwStatsCtx, hdd_FWStatisCB);
Satyanarayana Dash72806012014-12-02 14:30:08 +05305976 if (eHAL_STATUS_SUCCESS != status)
5977 {
5978 hddLog(VOS_TRACE_LEVEL_ERROR,
5979 FL(" fail to post WDA cmd status = %d"), status);
5980 ret = -EINVAL;
5981 goto exit;
5982 }
5983 waitRet = wait_for_completion_timeout
5984 (&(fwStatsCtx.completion), FW_STATE_WAIT_TIME);
5985 if (waitRet <= 0)
5986 {
5987 hddLog(VOS_TRACE_LEVEL_ERROR,
5988 FL("failed to wait on GwtFwstats"));
5989 //Make magic number to zero so that callback is not executed.
5990 spin_lock(&hdd_context_lock);
5991 fwStatsCtx.magic = 0x0;
5992 spin_unlock(&hdd_context_lock);
5993 ret = -EINVAL;
5994 goto exit;
5995 }
5996 if (fwStatsRsp->type)
5997 {
5998 buf = kmalloc(FW_STATE_RSP_LEN, GFP_KERNEL);
5999 if (!buf)
6000 {
6001 hddLog(VOS_TRACE_LEVEL_ERROR,
6002 FL(" failed to allocate memory"));
6003 ret = -ENOMEM;
6004 goto exit;
6005 }
6006 switch( fwStatsRsp->type )
6007 {
6008 case FW_UBSP_STATS:
6009 {
6010 len = snprintf(buf, FW_STATE_RSP_LEN,
6011 "GETFWSTATS: ubsp_enter_cnt %d ubsp_jump_ddr_cnt %d",
Abhishek Singh08aa7762014-12-16 13:59:03 +05306012 fwStatsRsp->fwStatsData.ubspStats.ubsp_enter_cnt,
6013 fwStatsRsp->fwStatsData.ubspStats.ubsp_jump_ddr_cnt);
Satyanarayana Dash72806012014-12-02 14:30:08 +05306014 }
6015 break;
6016 default:
6017 {
6018 hddLog(VOS_TRACE_LEVEL_ERROR, FL( "No handling for stats type %d"),fwStatsRsp->type);
6019 ret = -EFAULT;
6020 kfree(buf);
6021 goto exit;
6022 }
6023 }
6024 if (copy_to_user(priv_data.buf, buf, len + 1))
6025 {
6026 hddLog(VOS_TRACE_LEVEL_ERROR,
6027 FL(" failed to copy data to user buffer"));
6028 ret = -EFAULT;
6029 kfree(buf);
6030 goto exit;
6031 }
6032 ret = len;
6033 kfree(buf);
6034 }
6035 else
6036 {
6037 hddLog(VOS_TRACE_LEVEL_ERROR,
6038 FL("failed to fetch the stats"));
6039 ret = -EFAULT;
6040 goto exit;
6041 }
6042
6043 }
Agarwal Ashish8bd53ae2015-06-12 18:03:45 +05306044 else if (strncasecmp(command, "SET_FCC_CHANNEL", 15) == 0)
6045 {
6046 /*
6047 * this command wld be called by user-space when it detects WLAN
6048 * ON after airplane mode is set. When APM is set, WLAN turns off.
6049 * But it can be turned back on. Otherwise; when APM is turned back
6050 * off, WLAN wld turn back on. So at that point the command is
6051 * expected to come down. 0 means disable, 1 means enable. The
6052 * constraint is removed when parameter 1 is set or different
6053 * country code is set
6054 */
6055 ret = hdd_cmd_setFccChannel(pHddCtx, command, 15);
6056 }
Mahesh A Saptasagarbeca12c2015-09-07 16:21:06 +05306057 else if (strncasecmp(command, "DISABLE_CA_EVENT", 16) == 0)
6058 {
6059 ret = hdd_enable_disable_ca_event(pHddCtx, command, 16);
6060 }
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07006061 else {
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05306062 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
6063 TRACE_CODE_HDD_UNSUPPORTED_IOCTL,
6064 pAdapter->sessionId, 0));
Satyanarayana Dash72806012014-12-02 14:30:08 +05306065 hddLog( VOS_TRACE_LEVEL_WARN, FL("Unsupported GUI command %s"),
6066 command);
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07006067 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006068 }
6069exit:
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05306070 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07006071 if (command)
6072 {
6073 kfree(command);
6074 }
6075 return ret;
6076}
6077
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07006078#ifdef CONFIG_COMPAT
6079static int hdd_driver_compat_ioctl(hdd_adapter_t *pAdapter, struct ifreq *ifr)
6080{
6081 struct {
6082 compat_uptr_t buf;
6083 int used_len;
6084 int total_len;
6085 } compat_priv_data;
6086 hdd_priv_data_t priv_data;
6087 int ret = 0;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006088
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07006089 /*
6090 * Note that pAdapter and ifr have already been verified by caller,
6091 * and HDD context has also been validated
6092 */
6093 if (copy_from_user(&compat_priv_data, ifr->ifr_data,
6094 sizeof(compat_priv_data))) {
6095 ret = -EFAULT;
6096 goto exit;
6097 }
6098 priv_data.buf = compat_ptr(compat_priv_data.buf);
6099 priv_data.used_len = compat_priv_data.used_len;
6100 priv_data.total_len = compat_priv_data.total_len;
6101 ret = hdd_driver_command(pAdapter, &priv_data);
6102 exit:
6103 return ret;
6104}
6105#else /* CONFIG_COMPAT */
6106static int hdd_driver_compat_ioctl(hdd_adapter_t *pAdapter, struct ifreq *ifr)
6107{
6108 /* will never be invoked */
6109 return 0;
6110}
6111#endif /* CONFIG_COMPAT */
6112
6113static int hdd_driver_ioctl(hdd_adapter_t *pAdapter, struct ifreq *ifr)
6114{
6115 hdd_priv_data_t priv_data;
6116 int ret = 0;
6117
6118 /*
6119 * Note that pAdapter and ifr have already been verified by caller,
6120 * and HDD context has also been validated
6121 */
6122 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(priv_data))) {
6123 ret = -EFAULT;
6124 } else {
6125 ret = hdd_driver_command(pAdapter, &priv_data);
6126 }
6127 return ret;
6128}
6129
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05306130int __hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07006131{
6132 hdd_adapter_t *pAdapter;
6133 hdd_context_t *pHddCtx;
6134 int ret;
6135
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05306136 ENTER();
6137
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07006138 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6139 if (NULL == pAdapter) {
6140 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6141 "%s: HDD adapter context is Null", __func__);
6142 ret = -ENODEV;
6143 goto exit;
6144 }
6145 if (dev != pAdapter->dev) {
6146 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6147 "%s: HDD adapter/dev inconsistency", __func__);
6148 ret = -ENODEV;
6149 goto exit;
6150 }
6151
6152 if ((!ifr) || (!ifr->ifr_data)) {
6153 ret = -EINVAL;
6154 goto exit;
6155 }
6156
6157 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6158 ret = wlan_hdd_validate_context(pHddCtx);
6159 if (ret) {
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07006160 ret = -EBUSY;
6161 goto exit;
6162 }
6163
6164 switch (cmd) {
6165 case (SIOCDEVPRIVATE + 1):
6166 if (is_compat_task())
6167 ret = hdd_driver_compat_ioctl(pAdapter, ifr);
6168 else
6169 ret = hdd_driver_ioctl(pAdapter, ifr);
6170 break;
6171 default:
6172 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unknown ioctl %d",
6173 __func__, cmd);
6174 ret = -EINVAL;
6175 break;
6176 }
6177 exit:
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05306178 EXIT();
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07006179 return ret;
6180}
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006181
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05306182int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
6183{
6184 int ret;
6185
6186 vos_ssr_protect(__func__);
6187 ret = __hdd_ioctl(dev, ifr, cmd);
6188 vos_ssr_unprotect(__func__);
6189
6190 return ret;
6191}
6192
Katya Nigame7b69a82015-04-28 15:24:06 +05306193int hdd_mon_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
6194{
6195 return 0;
6196}
6197
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006198#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006199/**---------------------------------------------------------------------------
6200
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006201 \brief hdd_parse_ese_beacon_req() - Parse ese beacon request
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006202
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006203 This function parses the ese beacon request passed in the format
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006204 CCXBEACONREQ<space><Number of fields><space><Measurement token>
6205 <space>Channel 1<space>Scan Mode <space>Meas Duration<space>Channel N
6206 <space>Scan Mode N<space>Meas Duration N
6207 if the Number of bcn req fields (N) does not match with the actual number of fields passed
6208 then take N.
6209 <Meas Token><Channel><Scan Mode> and <Meas Duration> are treated as one pair
6210 For example, CCXBEACONREQ 2 1 1 1 30 2 44 0 40.
6211 This function does not take care of removing duplicate channels from the list
6212
6213 \param - pValue Pointer to data
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006214 \param - pEseBcnReq output pointer to store parsed ie information
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006215
6216 \return - 0 for success non-zero for failure
6217
6218 --------------------------------------------------------------------------*/
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006219static VOS_STATUS hdd_parse_ese_beacon_req(tANI_U8 *pValue,
6220 tCsrEseBeaconReq *pEseBcnReq)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006221{
6222 tANI_U8 *inPtr = pValue;
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306223 uint8_t input = 0;
6224 uint32_t tempInt = 0;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006225 int j = 0, i = 0, v = 0;
6226 char buf[32];
6227
6228 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
6229 /*no argument after the command*/
6230 if (NULL == inPtr)
6231 {
6232 return -EINVAL;
6233 }
6234 /*no space after the command*/
6235 else if (SPACE_ASCII_VALUE != *inPtr)
6236 {
6237 return -EINVAL;
6238 }
6239
6240 /*removing empty spaces*/
6241 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
6242
6243 /*no argument followed by spaces*/
6244 if ('\0' == *inPtr) return -EINVAL;
6245
6246 /*getting the first argument ie measurement token*/
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08006247 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006248 if (1 != v) return -EINVAL;
6249
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306250 v = kstrtos8(buf, 10, &input);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006251 if ( v < 0) return -EINVAL;
6252
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306253 input = VOS_MIN(input, SIR_ESE_MAX_MEAS_IE_REQS);
6254 pEseBcnReq->numBcnReqIe = input;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006255
Srinivas Girigowda725a88e2016-03-31 19:24:25 +05306256 hddLog(LOG1, "Number of Bcn Req Ie fields: %d", pEseBcnReq->numBcnReqIe);
6257
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006258
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006259 for (j = 0; j < (pEseBcnReq->numBcnReqIe); j++)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006260 {
6261 for (i = 0; i < 4; i++)
6262 {
6263 /*inPtr pointing to the beginning of first space after number of ie fields*/
6264 inPtr = strpbrk( inPtr, " " );
6265 /*no ie data after the number of ie fields argument*/
6266 if (NULL == inPtr) return -EINVAL;
6267
6268 /*removing empty space*/
6269 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
6270
6271 /*no ie data after the number of ie fields argument and spaces*/
6272 if ( '\0' == *inPtr ) return -EINVAL;
6273
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08006274 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006275 if (1 != v) return -EINVAL;
6276
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306277 v = kstrtou32(buf, 10, &tempInt);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006278 if (v < 0) return -EINVAL;
6279
6280 switch (i)
6281 {
6282 case 0: /* Measurement token */
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306283 if (!tempInt)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006284 {
6285 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306286 "Invalid Measurement Token: %u", tempInt);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006287 return -EINVAL;
6288 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006289 pEseBcnReq->bcnReq[j].measurementToken = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006290 break;
6291
6292 case 1: /* Channel number */
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306293 if ((!tempInt) ||
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006294 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
6295 {
6296 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306297 "Invalid Channel Number: %u", tempInt);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006298 return -EINVAL;
6299 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006300 pEseBcnReq->bcnReq[j].channel = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006301 break;
6302
6303 case 2: /* Scan mode */
Varun Reddy Yeturu0b18d5a2013-12-04 11:42:23 -08006304 if ((tempInt < eSIR_PASSIVE_SCAN) || (tempInt > eSIR_BEACON_TABLE))
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006305 {
6306 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306307 "Invalid Scan Mode(%u) Expected{0|1|2}", tempInt);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006308 return -EINVAL;
6309 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006310 pEseBcnReq->bcnReq[j].scanMode= tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006311 break;
6312
6313 case 3: /* Measurement duration */
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306314 if (((!tempInt) && (pEseBcnReq->bcnReq[j].scanMode != eSIR_BEACON_TABLE)) ||
6315 ((pEseBcnReq->bcnReq[j].scanMode == eSIR_BEACON_TABLE)))
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006316 {
6317 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306318 "Invalid Measurement Duration: %u", tempInt);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006319 return -EINVAL;
6320 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006321 pEseBcnReq->bcnReq[j].measurementDuration = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006322 break;
6323 }
6324 }
6325 }
6326
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006327 for (j = 0; j < pEseBcnReq->numBcnReqIe; j++)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006328 {
6329 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arun Kumar Khandavallie8768212014-02-17 16:43:34 +05306330 "Index(%d) Measurement Token(%u)Channel(%u) Scan Mode(%u) Measurement Duration(%u)\n",
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006331 j,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006332 pEseBcnReq->bcnReq[j].measurementToken,
6333 pEseBcnReq->bcnReq[j].channel,
6334 pEseBcnReq->bcnReq[j].scanMode,
6335 pEseBcnReq->bcnReq[j].measurementDuration);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006336 }
6337
6338 return VOS_STATUS_SUCCESS;
6339}
6340
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006341static void hdd_GetTsmStatsCB( tAniTrafStrmMetrics tsmMetrics, const tANI_U32 staId, void *pContext )
6342{
6343 struct statsContext *pStatsContext = NULL;
6344 hdd_adapter_t *pAdapter = NULL;
6345
6346 if (NULL == pContext)
6347 {
6348 hddLog(VOS_TRACE_LEVEL_ERROR,
6349 "%s: Bad param, pContext [%p]",
6350 __func__, pContext);
6351 return;
6352 }
6353
Jeff Johnson72a40512013-12-19 10:14:15 -08006354 /* there is a race condition that exists between this callback
6355 function and the caller since the caller could time out either
6356 before or while this code is executing. we use a spinlock to
6357 serialize these actions */
6358 spin_lock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006359
6360 pStatsContext = pContext;
6361 pAdapter = pStatsContext->pAdapter;
6362 if ((NULL == pAdapter) || (STATS_CONTEXT_MAGIC != pStatsContext->magic))
6363 {
6364 /* the caller presumably timed out so there is nothing we can do */
Jeff Johnson72a40512013-12-19 10:14:15 -08006365 spin_unlock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006366 hddLog(VOS_TRACE_LEVEL_WARN,
6367 "%s: Invalid context, pAdapter [%p] magic [%08x]",
6368 __func__, pAdapter, pStatsContext->magic);
6369 return;
6370 }
6371
Jeff Johnson72a40512013-12-19 10:14:15 -08006372 /* context is valid so caller is still waiting */
6373
6374 /* paranoia: invalidate the magic */
6375 pStatsContext->magic = 0;
6376
6377 /* copy over the tsm stats */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006378 pAdapter->tsmStats.UplinkPktQueueDly = tsmMetrics.UplinkPktQueueDly;
6379 vos_mem_copy(pAdapter->tsmStats.UplinkPktQueueDlyHist,
6380 tsmMetrics.UplinkPktQueueDlyHist,
6381 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
6382 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
6383 pAdapter->tsmStats.UplinkPktTxDly = tsmMetrics.UplinkPktTxDly;
6384 pAdapter->tsmStats.UplinkPktLoss = tsmMetrics.UplinkPktLoss;
6385 pAdapter->tsmStats.UplinkPktCount = tsmMetrics.UplinkPktCount;
6386 pAdapter->tsmStats.RoamingCount = tsmMetrics.RoamingCount;
6387 pAdapter->tsmStats.RoamingDly = tsmMetrics.RoamingDly;
6388
Jeff Johnson72a40512013-12-19 10:14:15 -08006389 /* notify the caller */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006390 complete(&pStatsContext->completion);
Jeff Johnson72a40512013-12-19 10:14:15 -08006391
6392 /* serialization is complete */
6393 spin_unlock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006394}
6395
6396
6397
6398static VOS_STATUS hdd_get_tsm_stats(hdd_adapter_t *pAdapter, const tANI_U8 tid,
6399 tAniTrafStrmMetrics* pTsmMetrics)
6400{
6401 hdd_station_ctx_t *pHddStaCtx = NULL;
6402 eHalStatus hstatus;
Jeff Johnson72a40512013-12-19 10:14:15 -08006403 VOS_STATUS vstatus = VOS_STATUS_SUCCESS;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006404 long lrc;
6405 struct statsContext context;
6406 hdd_context_t *pHddCtx = NULL;
6407
6408 if (NULL == pAdapter)
6409 {
6410 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: pAdapter is NULL", __func__);
6411 return VOS_STATUS_E_FAULT;
6412 }
6413
6414 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6415 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6416
6417 /* we are connected prepare our callback context */
6418 init_completion(&context.completion);
6419 context.pAdapter = pAdapter;
6420 context.magic = STATS_CONTEXT_MAGIC;
6421
6422 /* query tsm stats */
6423 hstatus = sme_GetTsmStats(pHddCtx->hHal, hdd_GetTsmStatsCB,
6424 pHddStaCtx->conn_info.staId[ 0 ],
6425 pHddStaCtx->conn_info.bssId,
6426 &context, pHddCtx->pvosContext, tid);
6427
6428 if (eHAL_STATUS_SUCCESS != hstatus)
6429 {
Jeff Johnson72a40512013-12-19 10:14:15 -08006430 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unable to retrieve statistics",
6431 __func__);
6432 vstatus = VOS_STATUS_E_FAULT;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006433 }
6434 else
6435 {
6436 /* request was sent -- wait for the response */
6437 lrc = wait_for_completion_interruptible_timeout(&context.completion,
6438 msecs_to_jiffies(WLAN_WAIT_TIME_STATS));
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006439 if (lrc <= 0)
6440 {
6441 hddLog(VOS_TRACE_LEVEL_ERROR,
6442 "%s: SME %s while retrieving statistics",
6443 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson72a40512013-12-19 10:14:15 -08006444 vstatus = VOS_STATUS_E_TIMEOUT;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006445 }
6446 }
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006447
Jeff Johnson72a40512013-12-19 10:14:15 -08006448 /* either we never sent a request, we sent a request and received a
6449 response or we sent a request and timed out. if we never sent a
6450 request or if we sent a request and got a response, we want to
6451 clear the magic out of paranoia. if we timed out there is a
6452 race condition such that the callback function could be
6453 executing at the same time we are. of primary concern is if the
6454 callback function had already verified the "magic" but had not
6455 yet set the completion variable when a timeout occurred. we
6456 serialize these activities by invalidating the magic while
6457 holding a shared spinlock which will cause us to block if the
6458 callback is currently executing */
6459 spin_lock(&hdd_context_lock);
6460 context.magic = 0;
6461 spin_unlock(&hdd_context_lock);
6462
6463 if (VOS_STATUS_SUCCESS == vstatus)
6464 {
6465 pTsmMetrics->UplinkPktQueueDly = pAdapter->tsmStats.UplinkPktQueueDly;
6466 vos_mem_copy(pTsmMetrics->UplinkPktQueueDlyHist,
6467 pAdapter->tsmStats.UplinkPktQueueDlyHist,
6468 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
6469 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
6470 pTsmMetrics->UplinkPktTxDly = pAdapter->tsmStats.UplinkPktTxDly;
6471 pTsmMetrics->UplinkPktLoss = pAdapter->tsmStats.UplinkPktLoss;
6472 pTsmMetrics->UplinkPktCount = pAdapter->tsmStats.UplinkPktCount;
6473 pTsmMetrics->RoamingCount = pAdapter->tsmStats.RoamingCount;
6474 pTsmMetrics->RoamingDly = pAdapter->tsmStats.RoamingDly;
6475 }
6476 return vstatus;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006477}
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006478#endif /*FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006479
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006480#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -08006481void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
6482{
6483 eCsrBand band = -1;
6484 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
6485 switch (band)
6486 {
6487 case eCSR_BAND_ALL:
6488 *pBand = WLAN_HDD_UI_BAND_AUTO;
6489 break;
6490
6491 case eCSR_BAND_24:
6492 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
6493 break;
6494
6495 case eCSR_BAND_5G:
6496 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
6497 break;
6498
6499 default:
6500 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
6501 *pBand = -1;
6502 break;
6503 }
6504}
6505
6506/**---------------------------------------------------------------------------
6507
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006508 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
6509
6510 This function parses the send action frame data passed in the format
6511 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
6512
Srinivas Girigowda56076852013-08-20 14:00:50 -07006513 \param - pValue Pointer to input data
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006514 \param - pTargetApBssid Pointer to target Ap bssid
6515 \param - pChannel Pointer to the Target AP channel
6516 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
6517 \param - pBuf Pointer to data
6518 \param - pBufLen Pointer to data length
6519
6520 \return - 0 for success non-zero for failure
6521
6522 --------------------------------------------------------------------------*/
6523VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
6524 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
6525{
6526 tANI_U8 *inPtr = pValue;
6527 tANI_U8 *dataEnd;
6528 int tempInt;
6529 int j = 0;
6530 int i = 0;
6531 int v = 0;
6532 tANI_U8 tempBuf[32];
6533 tANI_U8 tempByte = 0;
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08006534 /* 12 hexa decimal digits, 5 ':' and '\0' */
6535 tANI_U8 macAddress[18];
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006536
6537 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
6538 /*no argument after the command*/
6539 if (NULL == inPtr)
6540 {
6541 return -EINVAL;
6542 }
6543
6544 /*no space after the command*/
6545 else if (SPACE_ASCII_VALUE != *inPtr)
6546 {
6547 return -EINVAL;
6548 }
6549
6550 /*removing empty spaces*/
6551 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
6552
6553 /*no argument followed by spaces*/
6554 if ('\0' == *inPtr)
6555 {
6556 return -EINVAL;
6557 }
6558
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07006559 v = sscanf(inPtr, "%17s", macAddress);
6560 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006561 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07006562 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6563 "Invalid MAC address or All hex inputs are not read (%d)", v);
6564 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006565 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07006566
6567 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
6568 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
6569 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
6570 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
6571 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
6572 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006573
6574 /* point to the next argument */
6575 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
6576 /*no argument after the command*/
6577 if (NULL == inPtr) return -EINVAL;
6578
6579 /*removing empty spaces*/
6580 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
6581
6582 /*no argument followed by spaces*/
6583 if ('\0' == *inPtr)
6584 {
6585 return -EINVAL;
6586 }
6587
6588 /*getting the next argument ie the channel number */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08006589 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07006590 if (1 != v) return -EINVAL;
6591
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006592 v = kstrtos32(tempBuf, 10, &tempInt);
Agarwal Ashish353b3a82014-04-08 14:55:11 +05306593 if ( v < 0 || tempInt <= 0 || tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX )
Kiet Lambe150c22013-11-21 16:30:32 +05306594 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006595
6596 *pChannel = tempInt;
6597
6598 /* point to the next argument */
6599 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
6600 /*no argument after the command*/
6601 if (NULL == inPtr) return -EINVAL;
6602 /*removing empty spaces*/
6603 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
6604
6605 /*no argument followed by spaces*/
6606 if ('\0' == *inPtr)
6607 {
6608 return -EINVAL;
6609 }
6610
6611 /*getting the next argument ie the dwell time */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08006612 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07006613 if (1 != v) return -EINVAL;
6614
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006615 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda5a6e0672014-01-09 14:42:57 -08006616 if ( v < 0 || tempInt < 0) return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006617
6618 *pDwellTime = tempInt;
6619
6620 /* point to the next argument */
6621 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
6622 /*no argument after the command*/
6623 if (NULL == inPtr) return -EINVAL;
6624 /*removing empty spaces*/
6625 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
6626
6627 /*no argument followed by spaces*/
6628 if ('\0' == *inPtr)
6629 {
6630 return -EINVAL;
6631 }
6632
6633 /* find the length of data */
6634 dataEnd = inPtr;
6635 while(('\0' != *dataEnd) )
6636 {
6637 dataEnd++;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006638 }
Kiet Lambe150c22013-11-21 16:30:32 +05306639 *pBufLen = dataEnd - inPtr ;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006640 if ( *pBufLen <= 0) return -EINVAL;
6641
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07006642 /* Allocate the number of bytes based on the number of input characters
6643 whether it is even or odd.
6644 if the number of input characters are even, then we need N/2 byte.
6645 if the number of input characters are odd, then we need do (N+1)/2 to
6646 compensate rounding off.
6647 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
6648 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
6649 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006650 if (NULL == *pBuf)
6651 {
6652 hddLog(VOS_TRACE_LEVEL_FATAL,
6653 "%s: vos_mem_alloc failed ", __func__);
6654 return -EINVAL;
6655 }
6656
6657 /* the buffer received from the upper layer is character buffer,
6658 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
6659 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
6660 and f0 in 3rd location */
6661 for (i = 0, j = 0; j < *pBufLen; j += 2)
6662 {
Kiet Lambe150c22013-11-21 16:30:32 +05306663 if( j+1 == *pBufLen)
6664 {
6665 tempByte = hdd_parse_hex(inPtr[j]);
6666 }
6667 else
6668 {
6669 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
6670 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006671 (*pBuf)[i++] = tempByte;
6672 }
6673 *pBufLen = i;
6674 return VOS_STATUS_SUCCESS;
6675}
6676
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006677/**---------------------------------------------------------------------------
6678
Srinivas Girigowdade697412013-02-14 16:31:48 -08006679 \brief hdd_parse_channellist() - HDD Parse channel list
6680
6681 This function parses the channel list passed in the format
6682 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07006683 if the Number of channels (N) does not match with the actual number of channels passed
6684 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
6685 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
6686 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
6687 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08006688
6689 \param - pValue Pointer to input channel list
6690 \param - ChannelList Pointer to local output array to record channel list
6691 \param - pNumChannels Pointer to number of roam scan channels
6692
6693 \return - 0 for success non-zero for failure
6694
6695 --------------------------------------------------------------------------*/
6696VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
6697{
6698 tANI_U8 *inPtr = pValue;
6699 int tempInt;
6700 int j = 0;
6701 int v = 0;
6702 char buf[32];
6703
6704 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
6705 /*no argument after the command*/
6706 if (NULL == inPtr)
6707 {
6708 return -EINVAL;
6709 }
6710
6711 /*no space after the command*/
6712 else if (SPACE_ASCII_VALUE != *inPtr)
6713 {
6714 return -EINVAL;
6715 }
6716
6717 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07006718 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08006719
6720 /*no argument followed by spaces*/
6721 if ('\0' == *inPtr)
6722 {
6723 return -EINVAL;
6724 }
6725
6726 /*getting the first argument ie the number of channels*/
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08006727 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07006728 if (1 != v) return -EINVAL;
6729
Srinivas Girigowdade697412013-02-14 16:31:48 -08006730 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07006731 if ((v < 0) ||
6732 (tempInt <= 0) ||
6733 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
6734 {
6735 return -EINVAL;
6736 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08006737
6738 *pNumChannels = tempInt;
6739
6740 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
6741 "Number of channels are: %d", *pNumChannels);
6742
6743 for (j = 0; j < (*pNumChannels); j++)
6744 {
6745 /*inPtr pointing to the beginning of first space after number of channels*/
6746 inPtr = strpbrk( inPtr, " " );
6747 /*no channel list after the number of channels argument*/
6748 if (NULL == inPtr)
6749 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07006750 if (0 != j)
6751 {
6752 *pNumChannels = j;
6753 return VOS_STATUS_SUCCESS;
6754 }
6755 else
6756 {
6757 return -EINVAL;
6758 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08006759 }
6760
6761 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07006762 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08006763
6764 /*no channel list after the number of channels argument and spaces*/
6765 if ( '\0' == *inPtr )
6766 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07006767 if (0 != j)
6768 {
6769 *pNumChannels = j;
6770 return VOS_STATUS_SUCCESS;
6771 }
6772 else
6773 {
6774 return -EINVAL;
6775 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08006776 }
6777
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08006778 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07006779 if (1 != v) return -EINVAL;
6780
Srinivas Girigowdade697412013-02-14 16:31:48 -08006781 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07006782 if ((v < 0) ||
6783 (tempInt <= 0) ||
6784 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
6785 {
6786 return -EINVAL;
6787 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08006788 pChannelList[j] = tempInt;
6789
6790 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
6791 "Channel %d added to preferred channel list",
6792 pChannelList[j] );
6793 }
6794
Srinivas Girigowdade697412013-02-14 16:31:48 -08006795 return VOS_STATUS_SUCCESS;
6796}
6797
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07006798
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05306799/**
6800 * hdd_parse_reassoc_command_v1_data() - HDD Parse reassoc command data
6801 * This function parses the reasoc command data passed in the format
6802 * REASSOC<space><bssid><space><channel>
6803 *
6804 * @pValue: Pointer to input data (its a NUL terminated string)
6805 * @pTargetApBssid: Pointer to target Ap bssid
6806 * @pChannel: Pointer to the Target AP channel
6807 *
6808 * Return: 0 for success non-zero for failure
6809 */
6810static int hdd_parse_reassoc_command_v1_data(const tANI_U8 *pValue,
6811 tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07006812{
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05306813 const tANI_U8 *inPtr = pValue;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07006814 int tempInt;
6815 int v = 0;
6816 tANI_U8 tempBuf[32];
Kiet Lamaa8e15a2014-02-11 23:30:06 -08006817 /* 12 hexa decimal digits, 5 ':' and '\0' */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08006818 tANI_U8 macAddress[18];
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07006819
6820 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
6821 /*no argument after the command*/
6822 if (NULL == inPtr)
6823 {
6824 return -EINVAL;
6825 }
6826
6827 /*no space after the command*/
6828 else if (SPACE_ASCII_VALUE != *inPtr)
6829 {
6830 return -EINVAL;
6831 }
6832
6833 /*removing empty spaces*/
6834 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
6835
6836 /*no argument followed by spaces*/
6837 if ('\0' == *inPtr)
6838 {
6839 return -EINVAL;
6840 }
6841
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07006842 v = sscanf(inPtr, "%17s", macAddress);
6843 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07006844 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07006845 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6846 "Invalid MAC address or All hex inputs are not read (%d)", v);
6847 return -EINVAL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07006848 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07006849
6850 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
6851 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
6852 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
6853 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
6854 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
6855 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07006856
6857 /* point to the next argument */
6858 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
6859 /*no argument after the command*/
6860 if (NULL == inPtr) return -EINVAL;
6861
6862 /*removing empty spaces*/
6863 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
6864
6865 /*no argument followed by spaces*/
6866 if ('\0' == *inPtr)
6867 {
6868 return -EINVAL;
6869 }
6870
6871 /*getting the next argument ie the channel number */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08006872 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07006873 if (1 != v) return -EINVAL;
6874
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07006875 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07006876 if ((v < 0) ||
Padma, Santhosh Kumar0fa809b2014-11-13 14:56:56 +05306877 (tempInt < 0) ||
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07006878 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
6879 {
6880 return -EINVAL;
6881 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07006882
6883 *pChannel = tempInt;
6884 return VOS_STATUS_SUCCESS;
6885}
6886
6887#endif
6888
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006889#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006890/**---------------------------------------------------------------------------
6891
6892 \brief hdd_parse_get_cckm_ie() - HDD Parse and fetch the CCKM IE
6893
6894 This function parses the SETCCKM IE command
6895 SETCCKMIE<space><ie data>
6896
6897 \param - pValue Pointer to input data
6898 \param - pCckmIe Pointer to output cckm Ie
6899 \param - pCckmIeLen Pointer to output cckm ie length
6900
6901 \return - 0 for success non-zero for failure
6902
6903 --------------------------------------------------------------------------*/
6904VOS_STATUS hdd_parse_get_cckm_ie(tANI_U8 *pValue, tANI_U8 **pCckmIe,
6905 tANI_U8 *pCckmIeLen)
6906{
6907 tANI_U8 *inPtr = pValue;
6908 tANI_U8 *dataEnd;
6909 int j = 0;
6910 int i = 0;
6911 tANI_U8 tempByte = 0;
6912
6913 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
6914 /*no argument after the command*/
6915 if (NULL == inPtr)
6916 {
6917 return -EINVAL;
6918 }
6919
6920 /*no space after the command*/
6921 else if (SPACE_ASCII_VALUE != *inPtr)
6922 {
6923 return -EINVAL;
6924 }
6925
6926 /*removing empty spaces*/
6927 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
6928
6929 /*no argument followed by spaces*/
6930 if ('\0' == *inPtr)
6931 {
6932 return -EINVAL;
6933 }
6934
6935 /* find the length of data */
6936 dataEnd = inPtr;
6937 while(('\0' != *dataEnd) )
6938 {
6939 dataEnd++;
6940 ++(*pCckmIeLen);
6941 }
6942 if ( *pCckmIeLen <= 0) return -EINVAL;
6943
6944 /* Allocate the number of bytes based on the number of input characters
6945 whether it is even or odd.
6946 if the number of input characters are even, then we need N/2 byte.
6947 if the number of input characters are odd, then we need do (N+1)/2 to
6948 compensate rounding off.
6949 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
6950 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
6951 *pCckmIe = vos_mem_malloc((*pCckmIeLen + 1)/2);
6952 if (NULL == *pCckmIe)
6953 {
6954 hddLog(VOS_TRACE_LEVEL_FATAL,
6955 "%s: vos_mem_alloc failed ", __func__);
6956 return -EINVAL;
6957 }
6958 vos_mem_zero(*pCckmIe, (*pCckmIeLen + 1)/2);
6959 /* the buffer received from the upper layer is character buffer,
6960 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
6961 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
6962 and f0 in 3rd location */
6963 for (i = 0, j = 0; j < *pCckmIeLen; j += 2)
6964 {
6965 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
6966 (*pCckmIe)[i++] = tempByte;
6967 }
6968 *pCckmIeLen = i;
6969
6970 return VOS_STATUS_SUCCESS;
6971}
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006972#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006973
Jeff Johnson295189b2012-06-20 16:38:30 -07006974/**---------------------------------------------------------------------------
6975
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07006976 \brief hdd_is_valid_mac_address() - Validate MAC address
6977
6978 This function validates whether the given MAC address is valid or not
6979 Expected MAC address is of the format XX:XX:XX:XX:XX:XX
6980 where X is the hexa decimal digit character and separated by ':'
6981 This algorithm works even if MAC address is not separated by ':'
6982
6983 This code checks given input string mac contains exactly 12 hexadecimal digits.
6984 and a separator colon : appears in the input string only after
6985 an even number of hex digits.
6986
6987 \param - pMacAddr pointer to the input MAC address
6988 \return - 1 for valid and 0 for invalid
6989
6990 --------------------------------------------------------------------------*/
6991
6992v_BOOL_t hdd_is_valid_mac_address(const tANI_U8 *pMacAddr)
6993{
6994 int xdigit = 0;
6995 int separator = 0;
6996 while (*pMacAddr)
6997 {
6998 if (isxdigit(*pMacAddr))
6999 {
7000 xdigit++;
7001 }
7002 else if (':' == *pMacAddr)
7003 {
7004 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
7005 break;
7006
7007 ++separator;
7008 }
7009 else
7010 {
7011 separator = -1;
7012 /* Invalid MAC found */
7013 return 0;
7014 }
7015 ++pMacAddr;
7016 }
7017 return (xdigit == 12 && (separator == 5 || separator == 0));
7018}
7019
7020/**---------------------------------------------------------------------------
7021
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307022 \brief __hdd_open() - HDD Open function
Jeff Johnson295189b2012-06-20 16:38:30 -07007023
7024 \param - dev Pointer to net_device structure
7025
7026 \return - 0 for success non-zero for failure
7027
7028 --------------------------------------------------------------------------*/
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307029int __hdd_open(struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07007030{
7031 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7032 hdd_context_t *pHddCtx;
7033 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7034 VOS_STATUS status;
7035 v_BOOL_t in_standby = TRUE;
7036
7037 if (NULL == pAdapter)
7038 {
7039 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Agarwal Ashish971c2882013-10-30 20:11:12 +05307040 "%s: pAdapter is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007041 return -ENODEV;
7042 }
7043
7044 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05307045 MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_OPEN_REQUEST,
7046 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson295189b2012-06-20 16:38:30 -07007047 if (NULL == pHddCtx)
7048 {
7049 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007050 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007051 return -ENODEV;
7052 }
7053
7054 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7055 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
7056 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07007057 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
7058 {
7059 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307060 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07007061 in_standby = FALSE;
7062 break;
7063 }
7064 else
7065 {
7066 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7067 pAdapterNode = pNext;
7068 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007069 }
7070
7071 if (TRUE == in_standby)
7072 {
7073 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
7074 {
7075 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
7076 "wlan out of power save", __func__);
7077 return -EINVAL;
7078 }
7079 }
7080
Jeff Johnson6a81ca42013-04-05 10:37:08 -07007081 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07007082 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
7083 {
7084 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007085 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007086 /* Enable TX queues only when we are connected */
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05307087 hddLog(VOS_TRACE_LEVEL_INFO, FL("Enabling queues"));
Jeff Johnson295189b2012-06-20 16:38:30 -07007088 netif_tx_start_all_queues(dev);
7089 }
7090
7091 return 0;
7092}
7093
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307094/**---------------------------------------------------------------------------
7095
7096 \brief hdd_open() - Wrapper function for __hdd_open to protect it from SSR
7097
7098 This is called in response to ifconfig up
7099
7100 \param - dev Pointer to net_device structure
7101
7102 \return - 0 for success non-zero for failure
7103
7104 --------------------------------------------------------------------------*/
7105int hdd_open(struct net_device *dev)
7106{
7107 int ret;
7108
7109 vos_ssr_protect(__func__);
7110 ret = __hdd_open(dev);
7111 vos_ssr_unprotect(__func__);
7112
7113 return ret;
7114}
7115
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +05307116int __hdd_mon_open (struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07007117{
7118 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7119
7120 if(pAdapter == NULL) {
7121 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007122 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007123 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007124 }
7125
Jeff Johnson295189b2012-06-20 16:38:30 -07007126 return 0;
7127}
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +05307128
7129int hdd_mon_open (struct net_device *dev)
7130{
7131 int ret;
7132
7133 vos_ssr_protect(__func__);
7134 ret = __hdd_mon_open(dev);
7135 vos_ssr_unprotect(__func__);
7136
7137 return ret;
7138}
7139
Katya Nigame7b69a82015-04-28 15:24:06 +05307140int hdd_mon_stop(struct net_device *dev)
7141{
7142 return 0;
7143}
7144
Jeff Johnson295189b2012-06-20 16:38:30 -07007145/**---------------------------------------------------------------------------
7146
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307147 \brief __hdd_stop() - HDD stop function
Jeff Johnson295189b2012-06-20 16:38:30 -07007148
7149 \param - dev Pointer to net_device structure
7150
7151 \return - 0 for success non-zero for failure
7152
7153 --------------------------------------------------------------------------*/
7154
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307155int __hdd_stop (struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07007156{
Vinay Krishna Eranna90f43532014-10-27 16:45:54 +05307157 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07007158 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7159 hdd_context_t *pHddCtx;
7160 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7161 VOS_STATUS status;
7162 v_BOOL_t enter_standby = TRUE;
7163
7164 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07007165 if (NULL == pAdapter)
7166 {
7167 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Agarwal Ashish971c2882013-10-30 20:11:12 +05307168 "%s: pAdapter is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007169 return -ENODEV;
7170 }
Sachin Ahuja9b4958f2015-01-15 21:37:00 +05307171 MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_STOP_REQUEST,
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05307172 pAdapter->sessionId, pAdapter->device_mode));
Vinay Krishna Eranna90f43532014-10-27 16:45:54 +05307173
7174 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7175 ret = wlan_hdd_validate_context(pHddCtx);
7176 if (ret)
Jeff Johnson295189b2012-06-20 16:38:30 -07007177 {
Vinay Krishna Eranna90f43532014-10-27 16:45:54 +05307178 return ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07007179 }
7180
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307181 /* Nothing to be done if the interface is not opened */
7182 if (VOS_FALSE == test_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags))
7183 {
7184 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7185 "%s: NETDEV Interface is not OPENED", __func__);
7186 return -ENODEV;
7187 }
7188
7189 /* Make sure the interface is marked as closed */
Jeff Johnson6a81ca42013-04-05 10:37:08 -07007190 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07007191 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307192
7193 /* Disable TX on the interface, after this hard_start_xmit() will not
7194 * be called on that interface
7195 */
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05307196 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
Jeff Johnson295189b2012-06-20 16:38:30 -07007197 netif_tx_disable(pAdapter->dev);
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307198
7199 /* Mark the interface status as "down" for outside world */
Jeff Johnson295189b2012-06-20 16:38:30 -07007200 netif_carrier_off(pAdapter->dev);
7201
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307202 /* The interface is marked as down for outside world (aka kernel)
7203 * But the driver is pretty much alive inside. The driver needs to
7204 * tear down the existing connection on the netdev (session)
7205 * cleanup the data pipes and wait until the control plane is stabilized
7206 * for this interface. The call also needs to wait until the above
7207 * mentioned actions are completed before returning to the caller.
7208 * Notice that the hdd_stop_adapter is requested not to close the session
7209 * That is intentional to be able to scan if it is a STA/P2P interface
7210 */
7211 hdd_stop_adapter(pHddCtx, pAdapter, VOS_FALSE);
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05307212#ifdef FEATURE_WLAN_TDLS
7213 mutex_lock(&pHddCtx->tdls_lock);
7214#endif
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307215 /* DeInit the adapter. This ensures datapath cleanup as well */
c_hpothu002231a2015-02-05 14:58:51 +05307216 hdd_deinit_adapter(pHddCtx, pAdapter, TRUE);
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05307217#ifdef FEATURE_WLAN_TDLS
7218 mutex_unlock(&pHddCtx->tdls_lock);
7219#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007220 /* SoftAP ifaces should never go in power save mode
7221 making sure same here. */
7222 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
7223 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07007224 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07007225 )
7226 {
7227 /* SoftAP mode, so return from here */
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307228 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
7229 "%s: In SAP MODE", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007230 EXIT();
7231 return 0;
7232 }
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307233 /* Find if any iface is up. If any iface is up then can't put device to
7234 * sleep/power save mode
7235 */
Jeff Johnson295189b2012-06-20 16:38:30 -07007236 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7237 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
7238 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07007239 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
7240 {
7241 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307242 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07007243 enter_standby = FALSE;
7244 break;
7245 }
7246 else
7247 {
7248 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7249 pAdapterNode = pNext;
7250 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007251 }
7252
7253 if (TRUE == enter_standby)
7254 {
7255 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
7256 "entering standby", __func__);
7257 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
7258 {
7259 /*log and return success*/
7260 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
7261 "wlan in power save", __func__);
7262 }
7263 }
7264
7265 EXIT();
7266 return 0;
7267}
7268
7269/**---------------------------------------------------------------------------
7270
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307271 \brief hdd_stop() - wrapper_function for __hdd_stop to protect it from SSR
Jeff Johnson295189b2012-06-20 16:38:30 -07007272
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307273 This is called in response to ifconfig down
7274
7275 \param - dev Pointer to net_device structure
7276
7277 \return - 0 for success non-zero for failure
7278-----------------------------------------------------------------------------*/
7279int hdd_stop (struct net_device *dev)
7280{
7281 int ret;
7282
7283 vos_ssr_protect(__func__);
7284 ret = __hdd_stop(dev);
7285 vos_ssr_unprotect(__func__);
7286
7287 return ret;
7288}
7289
7290/**---------------------------------------------------------------------------
7291
7292 \brief __hdd_uninit() - HDD uninit function
Jeff Johnson295189b2012-06-20 16:38:30 -07007293
7294 \param - dev Pointer to net_device structure
7295
7296 \return - void
7297
7298 --------------------------------------------------------------------------*/
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307299static void __hdd_uninit (struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07007300{
7301 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05307302 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07007303 ENTER();
7304
7305 do
7306 {
7307 if (NULL == pAdapter)
7308 {
7309 hddLog(VOS_TRACE_LEVEL_FATAL,
7310 "%s: NULL pAdapter", __func__);
7311 break;
7312 }
7313
7314 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
7315 {
7316 hddLog(VOS_TRACE_LEVEL_FATAL,
7317 "%s: Invalid magic", __func__);
7318 break;
7319 }
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05307320 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7321 if (NULL == pHddCtx)
Jeff Johnson295189b2012-06-20 16:38:30 -07007322 {
7323 hddLog(VOS_TRACE_LEVEL_FATAL,
7324 "%s: NULL pHddCtx", __func__);
7325 break;
7326 }
7327
7328 if (dev != pAdapter->dev)
7329 {
7330 hddLog(VOS_TRACE_LEVEL_FATAL,
7331 "%s: Invalid device reference", __func__);
7332 /* we haven't validated all cases so let this go for now */
7333 }
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05307334#ifdef FEATURE_WLAN_TDLS
7335 mutex_lock(&pHddCtx->tdls_lock);
7336#endif
c_hpothu002231a2015-02-05 14:58:51 +05307337 hdd_deinit_adapter(pHddCtx, pAdapter, TRUE);
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05307338#ifdef FEATURE_WLAN_TDLS
7339 mutex_unlock(&pHddCtx->tdls_lock);
7340#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007341
7342 /* after uninit our adapter structure will no longer be valid */
7343 pAdapter->dev = NULL;
7344 pAdapter->magic = 0;
Manjeet Singh47ee8472016-04-11 11:57:18 +05307345 pAdapter->pHddCtx = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007346 } while (0);
7347
7348 EXIT();
7349}
7350
7351/**---------------------------------------------------------------------------
7352
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307353 \brief hdd_uninit() - Wrapper function to protect __hdd_uninit from SSR
7354
7355 This is called during the netdev unregister to uninitialize all data
7356associated with the device
7357
7358 \param - dev Pointer to net_device structure
7359
7360 \return - void
7361
7362 --------------------------------------------------------------------------*/
7363static void hdd_uninit (struct net_device *dev)
7364{
7365 vos_ssr_protect(__func__);
7366 __hdd_uninit(dev);
7367 vos_ssr_unprotect(__func__);
7368}
7369
7370/**---------------------------------------------------------------------------
7371
Jeff Johnson295189b2012-06-20 16:38:30 -07007372 \brief hdd_release_firmware() -
7373
7374 This function calls the release firmware API to free the firmware buffer.
7375
7376 \param - pFileName Pointer to the File Name.
7377 pCtx - Pointer to the adapter .
7378
7379
7380 \return - 0 for success, non zero for failure
7381
7382 --------------------------------------------------------------------------*/
7383
7384VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
7385{
7386 VOS_STATUS status = VOS_STATUS_SUCCESS;
7387 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
7388 ENTER();
7389
7390
7391 if (!strcmp(WLAN_FW_FILE, pFileName)) {
7392
7393 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
7394
7395 if(pHddCtx->fw) {
7396 release_firmware(pHddCtx->fw);
7397 pHddCtx->fw = NULL;
7398 }
7399 else
7400 status = VOS_STATUS_E_FAILURE;
7401 }
7402 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
7403 if(pHddCtx->nv) {
7404 release_firmware(pHddCtx->nv);
7405 pHddCtx->nv = NULL;
7406 }
7407 else
7408 status = VOS_STATUS_E_FAILURE;
7409
7410 }
7411
7412 EXIT();
7413 return status;
7414}
7415
7416/**---------------------------------------------------------------------------
7417
7418 \brief hdd_request_firmware() -
7419
7420 This function reads the firmware file using the request firmware
7421 API and returns the the firmware data and the firmware file size.
7422
7423 \param - pfileName - Pointer to the file name.
7424 - pCtx - Pointer to the adapter .
7425 - ppfw_data - Pointer to the pointer of the firmware data.
7426 - pSize - Pointer to the file size.
7427
7428 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
7429
7430 --------------------------------------------------------------------------*/
7431
7432
7433VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
7434{
7435 int status;
7436 VOS_STATUS retval = VOS_STATUS_SUCCESS;
7437 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
7438 ENTER();
7439
7440 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
7441
7442 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
7443
7444 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
7445 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
7446 __func__, pfileName);
7447 retval = VOS_STATUS_E_FAILURE;
7448 }
7449
7450 else {
7451 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
7452 *pSize = pHddCtx->fw->size;
7453 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
7454 __func__, *pSize);
7455 }
7456 }
7457 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
7458
7459 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
7460
7461 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
7462 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
7463 __func__, pfileName);
7464 retval = VOS_STATUS_E_FAILURE;
7465 }
7466
7467 else {
7468 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
7469 *pSize = pHddCtx->nv->size;
7470 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
7471 __func__, *pSize);
7472 }
7473 }
7474
7475 EXIT();
7476 return retval;
7477}
7478/**---------------------------------------------------------------------------
7479 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
7480
7481 This is the function invoked by SME to inform the result of a full power
7482 request issued by HDD
7483
7484 \param - callbackcontext - Pointer to cookie
7485 status - result of request
7486
7487 \return - None
7488
7489--------------------------------------------------------------------------*/
7490void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
7491{
7492 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
7493
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07007494 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07007495 if(&pHddCtx->full_pwr_comp_var)
7496 {
7497 complete(&pHddCtx->full_pwr_comp_var);
7498 }
7499}
7500
Abhishek Singh00b71972016-01-07 10:51:04 +05307501#ifdef WLAN_FEATURE_RMC
7502static void hdd_tx_fail_ind_callback(v_U8_t *MacAddr, v_U8_t seqNo)
7503{
7504 int payload_len;
7505 struct sk_buff *skb;
7506 struct nlmsghdr *nlh;
7507 v_U8_t *data;
7508
7509 payload_len = ETH_ALEN;
7510
7511 if (0 == cesium_pid)
7512 {
7513 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: cesium process not registered",
7514 __func__);
7515 return;
7516 }
7517
7518 if ((skb = nlmsg_new(payload_len,GFP_ATOMIC)) == NULL)
7519 {
7520 hddLog(VOS_TRACE_LEVEL_ERROR,
7521 "%s: nlmsg_new() failed for msg size[%d]",
7522 __func__, NLMSG_SPACE(payload_len));
7523 return;
7524 }
7525
7526 nlh = nlmsg_put(skb, cesium_pid, seqNo, 0, payload_len, NLM_F_REQUEST);
7527
7528 if (NULL == nlh)
7529 {
7530 hddLog(VOS_TRACE_LEVEL_ERROR,
7531 "%s: nlmsg_put() failed for msg size[%d]",
7532 __func__, NLMSG_SPACE(payload_len));
7533
7534 kfree_skb(skb);
7535 return;
7536 }
7537
7538 data = nlmsg_data(nlh);
7539 memcpy(data, MacAddr, ETH_ALEN);
7540
7541 if (nlmsg_unicast(cesium_nl_srv_sock, skb, cesium_pid) < 0)
7542 {
7543 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: nlmsg_unicast() failed for msg size[%d]",
7544 __func__, NLMSG_SPACE(payload_len));
7545 }
7546
7547 return;
7548}
7549
7550/**---------------------------------------------------------------------------
7551 \brief hdd_ParseuserParams - return a pointer to the next argument
7552
7553 \return - status
7554
7555--------------------------------------------------------------------------*/
7556static int hdd_ParseUserParams(tANI_U8 *pValue, tANI_U8 **ppArg)
7557{
7558 tANI_U8 *pVal;
7559
7560 pVal = strchr(pValue, ' ');
7561
7562 if (NULL == pVal)
7563 {
7564 /* no argument remains */
7565 return -EINVAL;
7566 }
7567 else if (SPACE_ASCII_VALUE != *pVal)
7568 {
7569 /* no space after the current argument */
7570 return -EINVAL;
7571 }
7572
7573 pVal++;
7574
7575 /* remove empty spaces */
7576 while ((SPACE_ASCII_VALUE == *pVal) && ('\0' != *pVal))
7577 {
7578 pVal++;
7579 }
7580
7581 /* no argument followed by spaces */
7582 if ('\0' == *pVal)
7583 {
7584 return -EINVAL;
7585 }
7586
7587 *ppArg = pVal;
7588
7589 return 0;
7590}
7591
7592/**----------------------------------------------------------------------------
7593 \brief hdd_ParseIBSSTXFailEventParams - Parse params for SETIBSSTXFAILEVENT
7594
7595 \return - status
7596
7597------------------------------------------------------------------------------*/
7598static int hdd_ParseIBSSTXFailEventParams(tANI_U8 *pValue,
7599 tANI_U8 *tx_fail_count,
7600 tANI_U16 *pid)
7601{
7602 tANI_U8 *param = NULL;
7603 int ret;
7604
7605 ret = hdd_ParseUserParams(pValue, &param);
7606
7607 if (0 == ret && NULL != param)
7608 {
7609 if (1 != sscanf(param, "%hhu", tx_fail_count))
7610 {
7611 ret = -EINVAL;
7612 goto done;
7613 }
7614 }
7615 else
7616 {
7617 goto done;
7618 }
7619
7620 if (0 == *tx_fail_count)
7621 {
7622 *pid = 0;
7623 goto done;
7624 }
7625
7626 pValue = param;
7627 pValue++;
7628
7629 ret = hdd_ParseUserParams(pValue, &param);
7630
7631 if (0 == ret)
7632 {
7633 if (1 != sscanf(param, "%hu", pid))
7634 {
7635 ret = -EINVAL;
7636 goto done;
7637 }
7638 }
7639 else
7640 {
7641 goto done;
7642 }
7643
7644done:
7645 return ret;
7646}
7647
7648static int hdd_open_cesium_nl_sock()
7649{
7650#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
7651 struct netlink_kernel_cfg cfg = {
7652 .groups = WLAN_NLINK_MCAST_GRP_ID,
7653 .input = NULL
7654 };
7655#endif
7656 int ret = 0;
7657
7658#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
7659 cesium_nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_CESIUM,
7660#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0))
7661 THIS_MODULE,
7662#endif
7663 &cfg);
7664#else
7665 cesium_nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_CESIUM,
7666 WLAN_NLINK_MCAST_GRP_ID, NULL, NULL, THIS_MODULE);
7667#endif
7668
7669 if (cesium_nl_srv_sock == NULL)
7670 {
7671 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7672 "NLINK: cesium netlink_kernel_create failed");
7673 ret = -ECONNREFUSED;
7674 }
7675
7676 return ret;
7677}
7678
7679static void hdd_close_cesium_nl_sock()
7680{
7681 if (NULL != cesium_nl_srv_sock)
7682 {
7683 netlink_kernel_release(cesium_nl_srv_sock);
7684 cesium_nl_srv_sock = NULL;
7685 }
7686}
7687#endif /* WLAN_FEATURE_RMC */
Jeff Johnson295189b2012-06-20 16:38:30 -07007688/**---------------------------------------------------------------------------
7689
7690 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
7691
7692 This is the function invoked by SME to inform the result of BMPS
7693 request issued by HDD
7694
7695 \param - callbackcontext - Pointer to cookie
7696 status - result of request
7697
7698 \return - None
7699
7700--------------------------------------------------------------------------*/
7701void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
7702{
7703
7704 struct completion *completion_var = (struct completion*) callbackContext;
7705
Arif Hussain6d2a3322013-11-17 19:50:10 -08007706 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07007707 if(completion_var != NULL)
7708 {
7709 complete(completion_var);
7710 }
7711}
7712
7713/**---------------------------------------------------------------------------
7714
7715 \brief hdd_get_cfg_file_size() -
7716
7717 This function reads the configuration file using the request firmware
7718 API and returns the configuration file size.
7719
7720 \param - pCtx - Pointer to the adapter .
7721 - pFileName - Pointer to the file name.
7722 - pBufSize - Pointer to the buffer size.
7723
7724 \return - 0 for success, non zero for failure
7725
7726 --------------------------------------------------------------------------*/
7727
7728VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
7729{
7730 int status;
7731 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
7732
7733 ENTER();
7734
7735 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
7736
7737 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
7738 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
7739 status = VOS_STATUS_E_FAILURE;
7740 }
7741 else {
7742 *pBufSize = pHddCtx->fw->size;
7743 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
7744 release_firmware(pHddCtx->fw);
7745 pHddCtx->fw = NULL;
7746 }
7747
7748 EXIT();
7749 return VOS_STATUS_SUCCESS;
7750}
7751
7752/**---------------------------------------------------------------------------
7753
7754 \brief hdd_read_cfg_file() -
7755
7756 This function reads the configuration file using the request firmware
7757 API and returns the cfg data and the buffer size of the configuration file.
7758
7759 \param - pCtx - Pointer to the adapter .
7760 - pFileName - Pointer to the file name.
7761 - pBuffer - Pointer to the data buffer.
7762 - pBufSize - Pointer to the buffer size.
7763
7764 \return - 0 for success, non zero for failure
7765
7766 --------------------------------------------------------------------------*/
7767
7768VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
7769 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
7770{
7771 int status;
7772 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
7773
7774 ENTER();
7775
7776 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
7777
7778 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
7779 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
7780 return VOS_STATUS_E_FAILURE;
7781 }
7782 else {
7783 if(*pBufSize != pHddCtx->fw->size) {
7784 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
7785 "file size", __func__);
7786 release_firmware(pHddCtx->fw);
7787 pHddCtx->fw = NULL;
7788 return VOS_STATUS_E_FAILURE;
7789 }
7790 else {
7791 if(pBuffer) {
7792 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
7793 }
7794 release_firmware(pHddCtx->fw);
7795 pHddCtx->fw = NULL;
7796 }
7797 }
7798
7799 EXIT();
7800
7801 return VOS_STATUS_SUCCESS;
7802}
7803
7804/**---------------------------------------------------------------------------
7805
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307806 \brief __hdd_set_mac_address() -
Jeff Johnson295189b2012-06-20 16:38:30 -07007807
7808 This function sets the user specified mac address using
7809 the command ifconfig wlanX hw ether <mac adress>.
7810
7811 \param - dev - Pointer to the net device.
7812 - addr - Pointer to the sockaddr.
7813 \return - 0 for success, non zero for failure
7814
7815 --------------------------------------------------------------------------*/
7816
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307817static int __hdd_set_mac_address(struct net_device *dev, void *addr)
Jeff Johnson295189b2012-06-20 16:38:30 -07007818{
Mahesh A Saptasagar74088392015-02-05 17:22:09 +05307819 hdd_adapter_t *pAdapter;
7820 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07007821 struct sockaddr *psta_mac_addr = addr;
7822 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
Mahesh A Saptasagar74088392015-02-05 17:22:09 +05307823 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07007824
7825 ENTER();
Mahesh A Saptasagar74088392015-02-05 17:22:09 +05307826 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7827 if (NULL == pAdapter)
7828 {
7829 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7830 "%s: Adapter is NULL",__func__);
7831 return -EINVAL;
7832 }
7833 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7834 ret = wlan_hdd_validate_context(pHddCtx);
7835 if (0 != ret)
7836 {
Mahesh A Saptasagar74088392015-02-05 17:22:09 +05307837 return ret;
7838 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007839
7840 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
Jeff Johnson295189b2012-06-20 16:38:30 -07007841 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
7842
7843 EXIT();
7844 return halStatus;
7845}
7846
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307847/**---------------------------------------------------------------------------
7848
7849 \brief hdd_set_mac_address() -
7850
7851 Wrapper function to protect __hdd_set_mac_address() function from ssr
7852
7853 \param - dev - Pointer to the net device.
7854 - addr - Pointer to the sockaddr.
7855 \return - 0 for success, non zero for failure
7856
7857 --------------------------------------------------------------------------*/
7858static int hdd_set_mac_address(struct net_device *dev, void *addr)
7859{
7860 int ret;
7861
7862 vos_ssr_protect(__func__);
7863 ret = __hdd_set_mac_address(dev, addr);
7864 vos_ssr_unprotect(__func__);
7865
7866 return ret;
7867}
7868
Jeff Johnson295189b2012-06-20 16:38:30 -07007869tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
7870{
7871 int i;
7872 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
7873 {
Abhishek Singheb183782014-02-06 13:37:21 +05307874 if( 0 == ((pHddCtx->cfg_ini->intfAddrMask) & (1 << i)) )
Jeff Johnson295189b2012-06-20 16:38:30 -07007875 break;
7876 }
7877
7878 if( VOS_MAX_CONCURRENCY_PERSONA == i)
7879 return NULL;
7880
7881 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
7882 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
7883}
7884
7885void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
7886{
7887 int i;
7888 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
7889 {
7890 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
7891 {
7892 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
7893 break;
7894 }
7895 }
7896 return;
7897}
7898
7899#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
7900 static struct net_device_ops wlan_drv_ops = {
7901 .ndo_open = hdd_open,
7902 .ndo_stop = hdd_stop,
7903 .ndo_uninit = hdd_uninit,
7904 .ndo_start_xmit = hdd_hard_start_xmit,
7905 .ndo_tx_timeout = hdd_tx_timeout,
7906 .ndo_get_stats = hdd_stats,
7907 .ndo_do_ioctl = hdd_ioctl,
7908 .ndo_set_mac_address = hdd_set_mac_address,
7909 .ndo_select_queue = hdd_select_queue,
7910#ifdef WLAN_FEATURE_PACKET_FILTERING
7911#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
7912 .ndo_set_rx_mode = hdd_set_multicast_list,
7913#else
7914 .ndo_set_multicast_list = hdd_set_multicast_list,
7915#endif //LINUX_VERSION_CODE
7916#endif
7917 };
Jeff Johnson295189b2012-06-20 16:38:30 -07007918 static struct net_device_ops wlan_mon_drv_ops = {
7919 .ndo_open = hdd_mon_open,
Katya Nigame7b69a82015-04-28 15:24:06 +05307920 .ndo_stop = hdd_mon_stop,
Jeff Johnson295189b2012-06-20 16:38:30 -07007921 .ndo_uninit = hdd_uninit,
7922 .ndo_start_xmit = hdd_mon_hard_start_xmit,
7923 .ndo_tx_timeout = hdd_tx_timeout,
7924 .ndo_get_stats = hdd_stats,
Katya Nigame7b69a82015-04-28 15:24:06 +05307925 .ndo_do_ioctl = hdd_mon_ioctl,
Jeff Johnson295189b2012-06-20 16:38:30 -07007926 .ndo_set_mac_address = hdd_set_mac_address,
7927 };
Mahesh A Saptasagar305e2632015-03-04 12:57:33 +05307928
Jeff Johnson295189b2012-06-20 16:38:30 -07007929#endif
7930
7931void hdd_set_station_ops( struct net_device *pWlanDev )
7932{
7933#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
Jeff Johnson295189b2012-06-20 16:38:30 -07007934 pWlanDev->netdev_ops = &wlan_drv_ops;
7935#else
7936 pWlanDev->open = hdd_open;
7937 pWlanDev->stop = hdd_stop;
7938 pWlanDev->uninit = hdd_uninit;
7939 pWlanDev->hard_start_xmit = NULL;
7940 pWlanDev->tx_timeout = hdd_tx_timeout;
7941 pWlanDev->get_stats = hdd_stats;
7942 pWlanDev->do_ioctl = hdd_ioctl;
Jeff Johnson295189b2012-06-20 16:38:30 -07007943 pWlanDev->set_mac_address = hdd_set_mac_address;
7944#endif
7945}
7946
Katya Nigam1fd24402015-02-16 14:52:19 +05307947void hdd_set_ibss_ops( hdd_adapter_t *pAdapter )
7948{
7949 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
7950 wlan_drv_ops.ndo_start_xmit = hdd_ibss_hard_start_xmit;
7951 #else
7952 pAdapter->dev->hard_start_xmit = hdd_ibss_hard_start_xmit;
7953 #endif
7954}
7955
Jeff Johnsoneed415b2013-01-18 16:11:20 -08007956static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07007957{
7958 struct net_device *pWlanDev = NULL;
7959 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007960 /*
7961 * cfg80211 initialization and registration....
7962 */
Anand N Sunkadc34abbd2015-07-29 09:52:59 +05307963 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name,
7964#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0))
7965 NET_NAME_UNKNOWN,
7966#endif
7967 ether_setup, NUM_TX_QUEUES);
Jeff Johnson295189b2012-06-20 16:38:30 -07007968 if(pWlanDev != NULL)
7969 {
7970
7971 //Save the pointer to the net_device in the HDD adapter
7972 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
7973
Jeff Johnson295189b2012-06-20 16:38:30 -07007974 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
7975
7976 pAdapter->dev = pWlanDev;
7977 pAdapter->pHddCtx = pHddCtx;
7978 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
Agarwal Ashish47d18112014-08-04 19:55:07 +05307979 spin_lock_init(&pAdapter->lock_for_active_session);
Jeff Johnson295189b2012-06-20 16:38:30 -07007980
Rajeev79dbe4c2013-10-05 11:03:42 +05307981#ifdef FEATURE_WLAN_BATCH_SCAN
Rajeev79dbe4c2013-10-05 11:03:42 +05307982 pAdapter->pBatchScanRsp = NULL;
7983 pAdapter->numScanList = 0;
Rajeev Kumar20140c12013-10-21 19:39:02 -07007984 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
Kiet Lamaa8e15a2014-02-11 23:30:06 -08007985 pAdapter->prev_batch_id = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05307986 mutex_init(&pAdapter->hdd_batch_scan_lock);
7987#endif
7988
Jeff Johnson295189b2012-06-20 16:38:30 -07007989 pAdapter->isLinkUpSvcNeeded = FALSE;
7990 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
7991 //Init the net_device structure
7992 strlcpy(pWlanDev->name, name, IFNAMSIZ);
7993
7994 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
7995 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
7996 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
7997 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
7998
7999 hdd_set_station_ops( pAdapter->dev );
8000
8001 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07008002 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
8003 pAdapter->wdev.wiphy = pHddCtx->wiphy;
8004 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07008005 /* set pWlanDev's parent to underlying device */
8006 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
Kumar Anand82c009f2014-05-29 00:29:42 -07008007
8008 hdd_wmm_init( pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07008009 }
8010
8011 return pAdapter;
8012}
8013
8014VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
8015{
8016 struct net_device *pWlanDev = pAdapter->dev;
8017 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
8018 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
8019 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
8020
8021 if( rtnl_lock_held )
8022 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08008023 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07008024 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
8025 {
8026 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
8027 return VOS_STATUS_E_FAILURE;
8028 }
8029 }
8030 if (register_netdevice(pWlanDev))
8031 {
8032 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
8033 return VOS_STATUS_E_FAILURE;
8034 }
8035 }
8036 else
8037 {
8038 if(register_netdev(pWlanDev))
8039 {
8040 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
8041 return VOS_STATUS_E_FAILURE;
8042 }
8043 }
8044 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
8045
8046 return VOS_STATUS_SUCCESS;
8047}
8048
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008049static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07008050{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008051 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07008052
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008053 if (NULL == pAdapter)
8054 {
8055 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
8056 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07008057 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008058
8059 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
8060 {
8061 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
8062 return eHAL_STATUS_NOT_INITIALIZED;
8063 }
8064
8065 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
8066
Sameer Thalappilbee426e2013-10-30 10:30:30 -07008067#ifndef WLAN_OPEN_SOURCE
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008068 /* need to make sure all of our scheduled work has completed.
8069 * This callback is called from MC thread context, so it is safe to
8070 * to call below flush workqueue API from here.
Sameer Thalappilbee426e2013-10-30 10:30:30 -07008071 *
8072 * Even though this is called from MC thread context, if there is a faulty
8073 * work item in the system, that can hang this call forever. So flushing
8074 * this global work queue is not safe; and now we make sure that
8075 * individual work queues are stopped correctly. But the cancel work queue
8076 * is a GPL only API, so the proprietary version of the driver would still
8077 * rely on the global work queue flush.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008078 */
8079 flush_scheduled_work();
Sameer Thalappilbee426e2013-10-30 10:30:30 -07008080#endif
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008081
8082 /* We can be blocked while waiting for scheduled work to be
8083 * flushed, and the adapter structure can potentially be freed, in
8084 * which case the magic will have been reset. So make sure the
8085 * magic is still good, and hence the adapter structure is still
8086 * valid, before signaling completion */
8087 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
8088 {
8089 complete(&pAdapter->session_close_comp_var);
8090 }
8091
Jeff Johnson295189b2012-06-20 16:38:30 -07008092 return eHAL_STATUS_SUCCESS;
8093}
Manjeet Singh47ee8472016-04-11 11:57:18 +05308094/**
8095 * hdd_close_tx_queues() - close tx queues
8096 * @hdd_ctx: hdd global context
8097 *
8098 * Return: None
8099 */
8100static void hdd_close_tx_queues(hdd_context_t *hdd_ctx)
8101{
8102 VOS_STATUS status;
8103 hdd_adapter_t *adapter;
8104 hdd_adapter_list_node_t *adapter_node = NULL, *next_adapter = NULL;
8105 /* Not validating hdd_ctx as it's already done by the caller */
8106 ENTER();
8107 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
8108 while (NULL != adapter_node && VOS_STATUS_SUCCESS == status) {
8109 adapter = adapter_node->pAdapter;
8110 if (adapter && adapter->dev) {
8111 netif_tx_disable (adapter->dev);
8112 netif_carrier_off(adapter->dev);
8113 }
8114 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
8115 &next_adapter);
8116 adapter_node = next_adapter;
8117 }
8118 EXIT();
8119}
Jeff Johnson295189b2012-06-20 16:38:30 -07008120
8121VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
8122{
8123 struct net_device *pWlanDev = pAdapter->dev;
8124 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
8125 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
8126 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
8127 VOS_STATUS status = VOS_STATUS_E_FAILURE;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308128 long rc = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07008129
Nirav Shah7e3c8132015-06-22 23:51:42 +05308130 spin_lock_init( &pAdapter->sta_hash_lock);
8131 pAdapter->is_sta_id_hash_initialized = VOS_FALSE;
8132
Jeff Johnson295189b2012-06-20 16:38:30 -07008133 INIT_COMPLETION(pAdapter->session_open_comp_var);
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07008134 sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07008135 //Open a SME session for future operation
8136 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07008137 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07008138 if ( !HAL_STATUS_SUCCESS( halStatus ) )
8139 {
8140 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07008141 "sme_OpenSession() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07008142 halStatus, halStatus );
8143 status = VOS_STATUS_E_FAILURE;
8144 goto error_sme_open;
8145 }
8146
8147 //Block on a completion variable. Can't wait forever though.
Vinay Krishna Eranna0fe2e7c2014-04-09 21:32:08 +05308148 rc = wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07008149 &pAdapter->session_open_comp_var,
8150 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308151 if (rc <= 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07008152 {
8153 hddLog(VOS_TRACE_LEVEL_FATAL,
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308154 "Session is not opened within timeout period code %ld", rc );
Jeff Johnson295189b2012-06-20 16:38:30 -07008155 status = VOS_STATUS_E_FAILURE;
8156 goto error_sme_open;
8157 }
8158
8159 // Register wireless extensions
8160 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
8161 {
8162 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07008163 "hdd_register_wext() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07008164 halStatus, halStatus );
8165 status = VOS_STATUS_E_FAILURE;
8166 goto error_register_wext;
8167 }
Katya Nigam1fd24402015-02-16 14:52:19 +05308168
Jeff Johnson295189b2012-06-20 16:38:30 -07008169 //Safe to register the hard_start_xmit function again
Katya Nigam1fd24402015-02-16 14:52:19 +05308170 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
8171 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
8172 #else
8173 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
8174 #endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008175
8176 //Set the Connection State to Not Connected
Abhishek Singhf4669da2014-05-26 15:07:49 +05308177 hddLog(VOS_TRACE_LEVEL_INFO,
8178 "%s: Set HDD connState to eConnectionState_NotConnected",
8179 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008180 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
8181
8182 //Set the default operation channel
8183 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
8184
8185 /* Make the default Auth Type as OPEN*/
8186 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
8187
8188 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
8189 {
8190 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07008191 "hdd_init_tx_rx() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07008192 status, status );
8193 goto error_init_txrx;
8194 }
8195
8196 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
8197
8198 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
8199 {
8200 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07008201 "hdd_wmm_adapter_init() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07008202 status, status );
8203 goto error_wmm_init;
8204 }
8205
8206 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
8207
8208 return VOS_STATUS_SUCCESS;
8209
8210error_wmm_init:
8211 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
8212 hdd_deinit_tx_rx(pAdapter);
8213error_init_txrx:
8214 hdd_UnregisterWext(pWlanDev);
8215error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008216 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07008217 {
8218 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008219 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Agrawal Ashish5a3522c2016-03-02 15:08:28 +05308220 pAdapter->sessionId, FALSE, VOS_TRUE,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008221 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07008222 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308223 unsigned long rc;
8224
Jeff Johnson295189b2012-06-20 16:38:30 -07008225 //Block on a completion variable. Can't wait forever though.
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308226 rc = wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07008227 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008228 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308229 if (rc <= 0)
8230 hddLog(VOS_TRACE_LEVEL_ERROR,
8231 FL("Session is not opened within timeout period code %ld"), rc);
Jeff Johnson295189b2012-06-20 16:38:30 -07008232 }
8233}
8234error_sme_open:
8235 return status;
8236}
8237
Jeff Johnson295189b2012-06-20 16:38:30 -07008238void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
8239{
8240 hdd_cfg80211_state_t *cfgState;
8241
8242 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
8243
8244 if( NULL != cfgState->buf )
8245 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308246 long rc;
Jeff Johnson295189b2012-06-20 16:38:30 -07008247 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
8248 rc = wait_for_completion_interruptible_timeout(
8249 &pAdapter->tx_action_cnf_event,
8250 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308251 if (rc <= 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07008252 {
Deepthi Gowri91b3e9c2015-08-25 13:14:58 +05308253 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8254 "%s ERROR: HDD Wait for Action Confirmation Failed!! %ld"
8255 , __func__, rc);
8256
8257 // Inform tx status as FAILURE to upper layer and free cfgState->buf
8258 hdd_sendActionCnf( pAdapter, FALSE );
Jeff Johnson295189b2012-06-20 16:38:30 -07008259 }
8260 }
8261 return;
8262}
Jeff Johnson295189b2012-06-20 16:38:30 -07008263
c_hpothu002231a2015-02-05 14:58:51 +05308264void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
Jeff Johnson295189b2012-06-20 16:38:30 -07008265{
8266 ENTER();
8267 switch ( pAdapter->device_mode )
8268 {
Katya Nigam1fd24402015-02-16 14:52:19 +05308269 case WLAN_HDD_IBSS:
8270 {
8271 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
8272 {
8273 hdd_ibss_deinit_tx_rx( pAdapter );
8274 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
8275 }
8276 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008277 case WLAN_HDD_INFRA_STATION:
8278 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07008279 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07008280 {
8281 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
8282 {
8283 hdd_deinit_tx_rx( pAdapter );
8284 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
8285 }
8286
8287 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
8288 {
8289 hdd_wmm_adapter_close( pAdapter );
8290 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
8291 }
8292
Jeff Johnson295189b2012-06-20 16:38:30 -07008293 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07008294 break;
8295 }
8296
8297 case WLAN_HDD_SOFTAP:
8298 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07008299 {
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05308300
8301 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
8302 {
8303 hdd_wmm_adapter_close( pAdapter );
8304 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
8305 }
8306
Jeff Johnson295189b2012-06-20 16:38:30 -07008307 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07008308
c_hpothu002231a2015-02-05 14:58:51 +05308309 hdd_unregister_hostapd(pAdapter, rtnl_held);
Agrawal Ashisha0584d42016-09-29 13:03:45 +05308310 /* set con_mode to STA only when no SAP concurrency mode */
8311 if (!(hdd_get_concurrency_mode() & (VOS_SAP | VOS_P2P_GO)))
8312 hdd_set_conparam(0);
Jeff Johnson295189b2012-06-20 16:38:30 -07008313 break;
8314 }
8315
8316 case WLAN_HDD_MONITOR:
8317 {
Jeff Johnson295189b2012-06-20 16:38:30 -07008318 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
8319 {
8320 hdd_deinit_tx_rx( pAdapter );
8321 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
8322 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008323 break;
8324 }
8325
8326
8327 default:
8328 break;
8329 }
8330
8331 EXIT();
8332}
8333
8334void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
8335{
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -08008336 struct net_device *pWlanDev = NULL;
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05308337
8338 ENTER();
8339 if (NULL == pAdapter)
8340 {
8341 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8342 "%s: HDD adapter is Null", __func__);
8343 return;
8344 }
8345
8346 pWlanDev = pAdapter->dev;
Jeff Johnson295189b2012-06-20 16:38:30 -07008347
Rajeev79dbe4c2013-10-05 11:03:42 +05308348#ifdef FEATURE_WLAN_BATCH_SCAN
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05308349 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
8350 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Rajeev Kumarf999e582014-01-09 17:33:29 -08008351 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05308352 || (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)
8353 )
8354 {
Rajeev Kumarf999e582014-01-09 17:33:29 -08008355 if (pAdapter)
Rajeev79dbe4c2013-10-05 11:03:42 +05308356 {
Rajeev Kumarf999e582014-01-09 17:33:29 -08008357 if (eHDD_BATCH_SCAN_STATE_STARTED == pAdapter->batchScanState)
8358 {
8359 hdd_deinit_batch_scan(pAdapter);
8360 }
Rajeev79dbe4c2013-10-05 11:03:42 +05308361 }
Rajeev Kumarf999e582014-01-09 17:33:29 -08008362 }
Rajeev79dbe4c2013-10-05 11:03:42 +05308363#endif
8364
Jeff Johnson295189b2012-06-20 16:38:30 -07008365 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
8366 if( rtnl_held )
8367 {
8368 unregister_netdevice(pWlanDev);
8369 }
8370 else
8371 {
8372 unregister_netdev(pWlanDev);
8373 }
8374 // note that the pAdapter is no longer valid at this point
8375 // since the memory has been reclaimed
8376 }
8377
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05308378 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07008379}
8380
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008381void hdd_set_pwrparams(hdd_context_t *pHddCtx)
8382{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308383 VOS_STATUS status;
8384 hdd_adapter_t *pAdapter = NULL;
8385 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008386
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308387 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008388
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308389 /*loop through all adapters.*/
8390 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008391 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308392 pAdapter = pAdapterNode->pAdapter;
8393 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
8394 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008395
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308396 { // we skip this registration for modes other than STA and P2P client modes.
8397 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
8398 pAdapterNode = pNext;
8399 continue;
8400 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008401
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308402 //Apply Dynamic DTIM For P2P
8403 //Only if ignoreDynamicDtimInP2pMode is not set in ini
8404 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
8405 pHddCtx->cfg_ini->enableModulatedDTIM) &&
8406 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
8407 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
8408 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
8409 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
8410 (eConnectionState_Associated ==
8411 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
8412 (pHddCtx->cfg_ini->fIsBmpsEnabled))
8413 {
8414 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008415
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308416 powerRequest.uIgnoreDTIM = 1;
8417 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
8418
8419 if (pHddCtx->cfg_ini->enableModulatedDTIM)
8420 {
8421 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
8422 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
8423 }
8424 else
8425 {
8426 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
8427 }
8428
8429 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
8430 * specified during Enter/Exit BMPS when LCD off*/
8431 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
8432 NULL, eANI_BOOLEAN_FALSE);
8433 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
8434 NULL, eANI_BOOLEAN_FALSE);
8435
8436 /* switch to the DTIM specified in cfg.ini */
8437 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Abhishek Singh1e390cf2015-10-27 13:45:17 +05308438 "Switch to DTIM %d Listen interval %d",
8439 powerRequest.uDTIMPeriod,
8440 powerRequest.uListenInterval);
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308441 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
8442 break;
8443
8444 }
8445
8446 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
8447 pAdapterNode = pNext;
8448 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008449}
8450
8451void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
8452{
8453 /*Switch back to DTIM 1*/
8454 tSirSetPowerParamsReq powerRequest = { 0 };
8455
8456 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
8457 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07008458 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008459
8460 /* Update ignoreDTIM and ListedInterval in CFG with default values */
8461 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
8462 NULL, eANI_BOOLEAN_FALSE);
8463 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
8464 NULL, eANI_BOOLEAN_FALSE);
8465
8466 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8467 "Switch to DTIM%d",powerRequest.uListenInterval);
8468 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
8469
8470}
8471
Jeff Johnson295189b2012-06-20 16:38:30 -07008472VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
8473{
8474 VOS_STATUS status = VOS_STATUS_SUCCESS;
Sushant Kaushik4928e542014-12-29 15:25:54 +05308475 if (WLAN_HDD_IS_UNLOAD_IN_PROGRESS(pHddCtx))
8476 {
8477 hddLog( LOGE, FL("Wlan Unload in progress"));
8478 return VOS_STATUS_E_PERM;
8479 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008480 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
8481 {
8482 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
8483 }
8484
8485 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
8486 {
8487 sme_StartAutoBmpsTimer(pHddCtx->hHal);
8488 }
8489
8490 if (pHddCtx->cfg_ini->fIsImpsEnabled)
8491 {
8492 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
8493 }
8494
8495 return status;
8496}
8497
8498VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
8499{
8500 hdd_adapter_t *pAdapter = NULL;
8501 eHalStatus halStatus;
8502 VOS_STATUS status = VOS_STATUS_E_INVAL;
8503 v_BOOL_t disableBmps = FALSE;
8504 v_BOOL_t disableImps = FALSE;
8505
8506 switch(session_type)
8507 {
8508 case WLAN_HDD_INFRA_STATION:
8509 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07008510 case WLAN_HDD_P2P_CLIENT:
8511 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07008512 //Exit BMPS -> Is Sta/P2P Client is already connected
8513 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
8514 if((NULL != pAdapter)&&
8515 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
8516 {
8517 disableBmps = TRUE;
8518 }
8519
8520 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
8521 if((NULL != pAdapter)&&
8522 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
8523 {
8524 disableBmps = TRUE;
8525 }
8526
8527 //Exit both Bmps and Imps incase of Go/SAP Mode
8528 if((WLAN_HDD_SOFTAP == session_type) ||
8529 (WLAN_HDD_P2P_GO == session_type))
8530 {
8531 disableBmps = TRUE;
8532 disableImps = TRUE;
8533 }
8534
8535 if(TRUE == disableImps)
8536 {
8537 if (pHddCtx->cfg_ini->fIsImpsEnabled)
8538 {
8539 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
8540 }
8541 }
8542
8543 if(TRUE == disableBmps)
8544 {
8545 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
8546 {
8547 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
8548
8549 if(eHAL_STATUS_SUCCESS != halStatus)
8550 {
8551 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08008552 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008553 VOS_ASSERT(0);
8554 return status;
8555 }
8556 }
8557
8558 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
8559 {
8560 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
8561
8562 if(eHAL_STATUS_SUCCESS != halStatus)
8563 {
8564 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08008565 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008566 VOS_ASSERT(0);
8567 return status;
8568 }
8569 }
8570 }
8571
8572 if((TRUE == disableBmps) ||
8573 (TRUE == disableImps))
8574 {
8575 /* Now, get the chip into Full Power now */
8576 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
8577 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
8578 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
8579
8580 if(halStatus != eHAL_STATUS_SUCCESS)
8581 {
8582 if(halStatus == eHAL_STATUS_PMC_PENDING)
8583 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308584 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07008585 //Block on a completion variable. Can't wait forever though
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308586 ret = wait_for_completion_interruptible_timeout(
8587 &pHddCtx->full_pwr_comp_var,
8588 msecs_to_jiffies(1000));
8589 if (ret <= 0)
8590 {
8591 hddLog(VOS_TRACE_LEVEL_ERROR,
8592 "%s: wait on full_pwr_comp_var failed %ld",
8593 __func__, ret);
8594 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008595 }
8596 else
8597 {
8598 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08008599 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008600 VOS_ASSERT(0);
8601 return status;
8602 }
8603 }
8604
8605 status = VOS_STATUS_SUCCESS;
8606 }
8607
8608 break;
8609 }
8610 return status;
8611}
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +05308612
8613void hdd_monPostMsgCb(tANI_U32 *magic, struct completion *cmpVar)
8614{
8615 if (magic == NULL || cmpVar == NULL) {
8616 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8617 FL("invalid arguments %p %p"), magic, cmpVar);
8618 return;
8619 }
8620 if (*magic != MON_MODE_MSG_MAGIC) {
8621 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8622 FL("maic: %x"), *magic);
8623 return;
8624 }
8625
8626 complete(cmpVar);
8627 return;
8628}
8629
Katya Nigame7b69a82015-04-28 15:24:06 +05308630void hdd_init_mon_mode (hdd_adapter_t *pAdapter)
8631 {
8632 hdd_mon_ctx_t *pMonCtx = NULL;
8633 pMonCtx = WLAN_HDD_GET_MONITOR_CTX_PTR(pAdapter);
8634
8635 pMonCtx->state = 0;
8636 pMonCtx->ChannelNo = 1;
8637 pMonCtx->ChannelBW = 20;
Katya Nigamd7d3a1f2015-06-11 14:04:24 +05308638 pMonCtx->crcCheckEnabled = 1;
8639 pMonCtx->typeSubtypeBitmap = 0xFFFF00000000;
8640 pMonCtx->is80211to803ConReq = 1;
Katya Nigame7b69a82015-04-28 15:24:06 +05308641 pMonCtx->numOfMacFilters = 0;
8642 }
8643
Jeff Johnson295189b2012-06-20 16:38:30 -07008644
8645hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08008646 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07008647 tANI_U8 rtnl_held )
8648{
8649 hdd_adapter_t *pAdapter = NULL;
8650 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
8651 VOS_STATUS status = VOS_STATUS_E_FAILURE;
8652 VOS_STATUS exitbmpsStatus;
8653
Arif Hussain6d2a3322013-11-17 19:50:10 -08008654 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d",__func__,iface_name,session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07008655
Nirav Shah436658f2014-02-28 17:05:45 +05308656 if(macAddr == NULL)
8657 {
8658 /* Not received valid macAddr */
8659 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8660 "%s:Unable to add virtual intf: Not able to get"
8661 "valid mac address",__func__);
8662 return NULL;
8663 }
8664
Jeff Johnson295189b2012-06-20 16:38:30 -07008665 //Disable BMPS incase of Concurrency
8666 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
8667
8668 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
8669 {
8670 //Fail to Exit BMPS
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308671 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Exit BMPS", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008672 VOS_ASSERT(0);
8673 return NULL;
8674 }
8675
8676 switch(session_type)
8677 {
8678 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07008679 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07008680 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07008681 {
8682 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
8683
8684 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308685 {
8686 hddLog(VOS_TRACE_LEVEL_FATAL,
8687 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07008688 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308689 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008690
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05308691#ifdef FEATURE_WLAN_TDLS
8692 /* A Mutex Lock is introduced while changing/initializing the mode to
8693 * protect the concurrent access for the Adapters by TDLS module.
8694 */
Rajesh Chauhana34c6e62014-03-25 16:37:58 +05308695 mutex_lock(&pHddCtx->tdls_lock);
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05308696#endif
8697
Jeff Johnsone7245742012-09-05 17:12:55 -07008698 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
8699 NL80211_IFTYPE_P2P_CLIENT:
8700 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07008701
Jeff Johnson295189b2012-06-20 16:38:30 -07008702 pAdapter->device_mode = session_type;
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05308703#ifdef FEATURE_WLAN_TDLS
8704 mutex_unlock(&pHddCtx->tdls_lock);
8705#endif
Sunil Dutt66485cb2013-12-19 19:05:03 +05308706
Mahesh A Saptasagar67ab9222015-10-21 15:38:41 +05308707 hdd_initialize_adapter_common(pAdapter);
Sunil Dutt66485cb2013-12-19 19:05:03 +05308708 status = hdd_init_station_mode( pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07008709 if( VOS_STATUS_SUCCESS != status )
8710 goto err_free_netdev;
8711
8712 status = hdd_register_interface( pAdapter, rtnl_held );
8713 if( VOS_STATUS_SUCCESS != status )
8714 {
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05308715#ifdef FEATURE_WLAN_TDLS
8716 mutex_lock(&pHddCtx->tdls_lock);
8717#endif
c_hpothu002231a2015-02-05 14:58:51 +05308718 hdd_deinit_adapter(pHddCtx, pAdapter, rtnl_held);
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05308719#ifdef FEATURE_WLAN_TDLS
8720 mutex_unlock(&pHddCtx->tdls_lock);
8721#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008722 goto err_free_netdev;
8723 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05308724
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05308725 // Workqueue which gets scheduled in IPv4 notification callback.
Anand N Sunkaddc63c792015-06-03 14:33:24 +05308726 vos_init_work(&pAdapter->ipv4NotifierWorkQueue, hdd_ipv4_notifier_work_queue);
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05308727
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05308728#ifdef WLAN_NS_OFFLOAD
8729 // Workqueue which gets scheduled in IPv6 notification callback.
Anand N Sunkaddc63c792015-06-03 14:33:24 +05308730 vos_init_work(&pAdapter->ipv6NotifierWorkQueue, hdd_ipv6_notifier_work_queue);
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05308731#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008732 //Stop the Interface TX queue.
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05308733 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
Jeff Johnson295189b2012-06-20 16:38:30 -07008734 netif_tx_disable(pAdapter->dev);
8735 //netif_tx_disable(pWlanDev);
8736 netif_carrier_off(pAdapter->dev);
8737
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +05308738 if (WLAN_HDD_P2P_CLIENT == session_type ||
8739 WLAN_HDD_P2P_DEVICE == session_type)
8740 {
8741 /* Initialize the work queue to defer the
8742 * back to back RoC request */
Anand N Sunkaddc63c792015-06-03 14:33:24 +05308743 vos_init_delayed_work(&pAdapter->roc_work,
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +05308744 hdd_p2p_roc_work_queue);
8745 }
8746
Jeff Johnson295189b2012-06-20 16:38:30 -07008747 break;
8748 }
8749
Jeff Johnson295189b2012-06-20 16:38:30 -07008750 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07008751 case WLAN_HDD_SOFTAP:
8752 {
8753 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
8754 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308755 {
8756 hddLog(VOS_TRACE_LEVEL_FATAL,
8757 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07008758 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308759 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008760
Jeff Johnson295189b2012-06-20 16:38:30 -07008761 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
8762 NL80211_IFTYPE_AP:
8763 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07008764 pAdapter->device_mode = session_type;
8765
Mahesh A Saptasagar67ab9222015-10-21 15:38:41 +05308766 hdd_initialize_adapter_common(pAdapter);
Hanumanth Reddy Pothula15bc0fa2017-02-03 17:24:17 +05308767 status = hdd_init_ap_mode(pAdapter, false);
Jeff Johnson295189b2012-06-20 16:38:30 -07008768 if( VOS_STATUS_SUCCESS != status )
8769 goto err_free_netdev;
8770
Nirav Shah7e3c8132015-06-22 23:51:42 +05308771 status = hdd_sta_id_hash_attach(pAdapter);
8772 if (VOS_STATUS_SUCCESS != status)
8773 {
8774 hddLog(VOS_TRACE_LEVEL_FATAL,
8775 FL("failed to attach hash for session %d"), session_type);
8776 hdd_deinit_adapter(pHddCtx, pAdapter, rtnl_held);
8777 goto err_free_netdev;
8778 }
8779
Jeff Johnson295189b2012-06-20 16:38:30 -07008780 status = hdd_register_hostapd( pAdapter, rtnl_held );
8781 if( VOS_STATUS_SUCCESS != status )
8782 {
c_hpothu002231a2015-02-05 14:58:51 +05308783 hdd_deinit_adapter(pHddCtx, pAdapter, rtnl_held);
Jeff Johnson295189b2012-06-20 16:38:30 -07008784 goto err_free_netdev;
8785 }
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05308786 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
Jeff Johnson295189b2012-06-20 16:38:30 -07008787 netif_tx_disable(pAdapter->dev);
8788 netif_carrier_off(pAdapter->dev);
8789
8790 hdd_set_conparam( 1 );
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +05308791
8792 if (WLAN_HDD_P2P_GO == session_type)
8793 {
8794 /* Initialize the work queue to
8795 * defer the back to back RoC request */
8796 INIT_DELAYED_WORK(&pAdapter->roc_work,
8797 hdd_p2p_roc_work_queue);
8798 }
Bhargav Shahd0715912015-10-01 18:17:37 +05308799
Jeff Johnson295189b2012-06-20 16:38:30 -07008800 break;
8801 }
8802 case WLAN_HDD_MONITOR:
8803 {
Jeff Johnson295189b2012-06-20 16:38:30 -07008804 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
8805 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308806 {
8807 hddLog(VOS_TRACE_LEVEL_FATAL,
8808 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07008809 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308810 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008811
Katya Nigame7b69a82015-04-28 15:24:06 +05308812 // Register wireless extensions
8813 if( VOS_STATUS_SUCCESS != (status = hdd_register_wext(pAdapter->dev)))
8814 {
8815 hddLog(VOS_TRACE_LEVEL_FATAL,
8816 "hdd_register_wext() failed with status code %08d [x%08x]",
8817 status, status );
8818 status = VOS_STATUS_E_FAILURE;
8819 }
8820
Jeff Johnson295189b2012-06-20 16:38:30 -07008821 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
8822 pAdapter->device_mode = session_type;
Jeff Johnson295189b2012-06-20 16:38:30 -07008823#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
8824 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
8825#else
8826 pAdapter->dev->open = hdd_mon_open;
8827 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
Katya Nigame7b69a82015-04-28 15:24:06 +05308828 pAdapter->dev->stop = hdd_mon_stop;
8829 pAdapter->dev->do_ioctl = hdd_mon_ioctl;
Jeff Johnson295189b2012-06-20 16:38:30 -07008830#endif
Katya Nigame7b69a82015-04-28 15:24:06 +05308831 status = hdd_register_interface( pAdapter, rtnl_held );
8832 hdd_init_mon_mode( pAdapter );
Mahesh A Saptasagar67ab9222015-10-21 15:38:41 +05308833 hdd_initialize_adapter_common(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07008834 hdd_init_tx_rx( pAdapter );
8835 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
Katya Nigame7b69a82015-04-28 15:24:06 +05308836 //Stop the Interface TX queue.
8837 netif_tx_disable(pAdapter->dev);
8838 netif_carrier_off(pAdapter->dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07008839 }
8840 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07008841 case WLAN_HDD_FTM:
8842 {
8843 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
8844
8845 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308846 {
8847 hddLog(VOS_TRACE_LEVEL_FATAL,
8848 FL("failed to allocate adapter for session %d"), session_type);
8849 return NULL;
8850 }
8851
Jeff Johnson295189b2012-06-20 16:38:30 -07008852 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
8853 * message while loading driver in FTM mode. */
8854 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
8855 pAdapter->device_mode = session_type;
8856 status = hdd_register_interface( pAdapter, rtnl_held );
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05308857
Mahesh A Saptasagar67ab9222015-10-21 15:38:41 +05308858 hdd_initialize_adapter_common(pAdapter);
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05308859 hdd_init_tx_rx( pAdapter );
8860
8861 //Stop the Interface TX queue.
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05308862 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05308863 netif_tx_disable(pAdapter->dev);
8864 netif_carrier_off(pAdapter->dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07008865 }
8866 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07008867 default:
8868 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308869 hddLog(VOS_TRACE_LEVEL_FATAL,"%s Invalid session type %d",
8870 __func__, session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07008871 VOS_ASSERT(0);
8872 return NULL;
8873 }
8874 }
8875
Jeff Johnson295189b2012-06-20 16:38:30 -07008876 if( VOS_STATUS_SUCCESS == status )
8877 {
Mahesh A Saptasagar67ab9222015-10-21 15:38:41 +05308878 //Add it to the hdd's session list.
Jeff Johnson295189b2012-06-20 16:38:30 -07008879 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
8880 if( NULL == pHddAdapterNode )
8881 {
8882 status = VOS_STATUS_E_NOMEM;
8883 }
8884 else
8885 {
8886 pHddAdapterNode->pAdapter = pAdapter;
8887 status = hdd_add_adapter_back ( pHddCtx,
8888 pHddAdapterNode );
8889 }
8890 }
8891
8892 if( VOS_STATUS_SUCCESS != status )
8893 {
8894 if( NULL != pAdapter )
8895 {
8896 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
8897 pAdapter = NULL;
8898 }
8899 if( NULL != pHddAdapterNode )
8900 {
8901 vos_mem_free( pHddAdapterNode );
8902 }
8903
8904 goto resume_bmps;
8905 }
8906
8907 if(VOS_STATUS_SUCCESS == status)
8908 {
8909 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07008910 //Initialize the WoWL service
8911 if(!hdd_init_wowl(pAdapter))
8912 {
8913 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
8914 goto err_free_netdev;
8915 }
Manjeet Singh3ed79242017-01-11 19:04:32 +05308916 //Initialize the TSF capture data
8917 wlan_hdd_tsf_init(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07008918 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008919 return pAdapter;
8920
8921err_free_netdev:
8922 free_netdev(pAdapter->dev);
8923 wlan_hdd_release_intf_addr( pHddCtx,
8924 pAdapter->macAddressCurrent.bytes );
8925
8926resume_bmps:
8927 //If bmps disabled enable it
8928 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
8929 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308930 if (pHddCtx->hdd_wlan_suspended)
8931 {
8932 hdd_set_pwrparams(pHddCtx);
8933 }
8934 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07008935 }
8936 return NULL;
8937}
8938
8939VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
8940 tANI_U8 rtnl_held )
8941{
8942 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
8943 VOS_STATUS status;
8944
8945 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
8946 if( VOS_STATUS_SUCCESS != status )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308947 {
8948 hddLog(VOS_TRACE_LEVEL_WARN,"%s: adapter list empty %d",
8949 __func__, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07008950 return status;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308951 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008952
8953 while ( pCurrent->pAdapter != pAdapter )
8954 {
8955 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
8956 if( VOS_STATUS_SUCCESS != status )
8957 break;
8958
8959 pCurrent = pNext;
8960 }
8961 pAdapterNode = pCurrent;
8962 if( VOS_STATUS_SUCCESS == status )
8963 {
8964 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
8965 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05308966
8967#ifdef FEATURE_WLAN_TDLS
8968
8969 /* A Mutex Lock is introduced while changing/initializing the mode to
8970 * protect the concurrent access for the Adapters by TDLS module.
8971 */
Rajesh Chauhana34c6e62014-03-25 16:37:58 +05308972 mutex_lock(&pHddCtx->tdls_lock);
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05308973#endif
8974
Jeff Johnson295189b2012-06-20 16:38:30 -07008975 hdd_remove_adapter( pHddCtx, pAdapterNode );
8976 vos_mem_free( pAdapterNode );
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08008977 pAdapterNode = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07008978
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05308979#ifdef FEATURE_WLAN_TDLS
8980 mutex_unlock(&pHddCtx->tdls_lock);
8981#endif
8982
Jeff Johnson295189b2012-06-20 16:38:30 -07008983
8984 /* If there is a single session of STA/P2P client, re-enable BMPS */
Agarwal Ashish51325b52014-06-16 16:50:49 +05308985 if ((!vos_concurrent_open_sessions_running()) &&
8986 ((pHddCtx->no_of_open_sessions[VOS_STA_MODE] >= 1) ||
8987 (pHddCtx->no_of_open_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
Jeff Johnson295189b2012-06-20 16:38:30 -07008988 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308989 if (pHddCtx->hdd_wlan_suspended)
8990 {
8991 hdd_set_pwrparams(pHddCtx);
8992 }
8993 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07008994 }
8995
8996 return VOS_STATUS_SUCCESS;
8997 }
8998
8999 return VOS_STATUS_E_FAILURE;
9000}
9001
9002VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
9003{
9004 hdd_adapter_list_node_t *pHddAdapterNode;
9005 VOS_STATUS status;
9006
9007 ENTER();
9008
9009 do
9010 {
9011 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
9012 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
9013 {
9014 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
9015 vos_mem_free( pHddAdapterNode );
9016 }
9017 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
9018
9019 EXIT();
9020
9021 return VOS_STATUS_SUCCESS;
9022}
9023
9024void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
9025{
9026 v_U8_t addIE[1] = {0};
9027
9028 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
9029 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
9030 eANI_BOOLEAN_FALSE) )
9031 {
9032 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08009033 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07009034 }
9035
9036 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
9037 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
9038 eANI_BOOLEAN_FALSE) )
9039 {
9040 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08009041 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07009042 }
9043
9044 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
9045 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
9046 eANI_BOOLEAN_FALSE) )
9047 {
9048 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08009049 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07009050 }
9051}
9052
Anurag Chouhan83026002016-12-13 22:46:21 +05309053VOS_STATUS hdd_cleanup_ap_events(hdd_adapter_t *adapter)
9054{
9055#ifdef DHCP_SERVER_OFFLOAD
9056 vos_event_destroy(&adapter->dhcp_status.vos_event);
9057#endif
Anurag Chouhan0b29de02016-12-16 13:18:40 +05309058#ifdef MDNS_OFFLOAD
9059 vos_event_destroy(&adapter->mdns_status.vos_event);
9060#endif
Anurag Chouhan83026002016-12-13 22:46:21 +05309061 return VOS_STATUS_SUCCESS;
9062}
9063
9064
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05309065VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
9066 const v_BOOL_t bCloseSession )
Jeff Johnson295189b2012-06-20 16:38:30 -07009067{
9068 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
9069 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
Kaushik, Sushant4975a572014-10-21 16:07:48 +05309070 hdd_scaninfo_t *pScanInfo = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07009071 union iwreq_data wrqu;
Kaushik, Sushant7005e372014-04-08 11:36:54 +05309072 v_U8_t retry = 0;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309073 long ret;
Nirav Shah7e3c8132015-06-22 23:51:42 +05309074 VOS_STATUS status;
Jeff Johnson295189b2012-06-20 16:38:30 -07009075
Anand N Sunkad26d71b92014-12-24 18:08:22 +05309076 if (pHddCtx->isLogpInProgress) {
9077 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
9078 "%s:LOGP in Progress. Ignore!!!",__func__);
9079 return VOS_STATUS_E_FAILURE;
9080 }
9081
Jeff Johnson295189b2012-06-20 16:38:30 -07009082 ENTER();
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +05309083
Kaushik, Sushant4975a572014-10-21 16:07:48 +05309084 pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07009085 switch(pAdapter->device_mode)
9086 {
Nirav Shah0cf4d892015-11-05 16:27:27 +05309087 case WLAN_HDD_IBSS:
9088 if ( VOS_TRUE == bCloseSession )
9089 {
9090 status = hdd_sta_id_hash_detach(pAdapter);
9091 if (status != VOS_STATUS_SUCCESS)
9092 hddLog(VOS_TRACE_LEVEL_ERROR,
9093 FL("sta id hash detach failed"));
9094 }
9095
Jeff Johnson295189b2012-06-20 16:38:30 -07009096 case WLAN_HDD_INFRA_STATION:
9097 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07009098 case WLAN_HDD_P2P_DEVICE:
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05309099 {
9100 hdd_station_ctx_t *pstation = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Mahesh A Saptasagare4d05d42015-07-02 16:17:20 +05309101#ifdef FEATURE_WLAN_TDLS
9102 mutex_lock(&pHddCtx->tdls_lock);
9103 wlan_hdd_tdls_exit(pAdapter, TRUE);
9104 mutex_unlock(&pHddCtx->tdls_lock);
9105#endif
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05309106 if( hdd_connIsConnected(pstation) ||
9107 (pstation->conn_info.connState == eConnectionState_Connecting) )
Jeff Johnson295189b2012-06-20 16:38:30 -07009108 {
Abhishek Singhe21a5212017-06-09 09:42:58 +05309109 /*
9110 * Indicate sme of disconnect so that in progress connection
9111 * or preauth can be aborted.
9112 */
9113 sme_abortConnection(WLAN_HDD_GET_HAL_CTX(pAdapter),
9114 pAdapter->sessionId);
Abhishek Singh99f17b82017-02-06 16:57:56 +05309115 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07009116 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
9117 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
9118 pAdapter->sessionId,
9119 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
9120 else
9121 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
9122 pAdapter->sessionId,
9123 eCSR_DISCONNECT_REASON_UNSPECIFIED);
Abhishek Singh7b52ed52016-02-11 17:45:54 +05309124 /* Success implies disconnect command got queued up successfully
9125 * Or cmd not queued as scan for SSID is in progress
9126 */
9127 if((eHAL_STATUS_SUCCESS == halStatus) ||
9128 (eHAL_STATUS_CMD_NOT_QUEUED == halStatus))
Jeff Johnson295189b2012-06-20 16:38:30 -07009129 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309130 ret = wait_for_completion_interruptible_timeout(
9131 &pAdapter->disconnect_comp_var,
9132 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Abhishek Singh7b52ed52016-02-11 17:45:54 +05309133 if (ret <= 0 &&
9134 (eHAL_STATUS_CMD_NOT_QUEUED != halStatus))
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309135 {
9136 hddLog(VOS_TRACE_LEVEL_ERROR,
9137 "%s: wait on disconnect_comp_var failed %ld",
9138 __func__, ret);
9139 }
9140 }
9141 else
9142 {
9143 hddLog(LOGE, "%s: failed to post disconnect event to SME",
9144 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009145 }
9146 memset(&wrqu, '\0', sizeof(wrqu));
9147 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
9148 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
9149 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
9150 }
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05309151 else if(pstation->conn_info.connState ==
9152 eConnectionState_Disconnecting)
9153 {
9154 ret = wait_for_completion_interruptible_timeout(
9155 &pAdapter->disconnect_comp_var,
9156 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
9157 if (ret <= 0)
9158 {
9159 hddLog(VOS_TRACE_LEVEL_ERROR,
9160 FL("wait on disconnect_comp_var failed %ld"), ret);
9161 }
9162 }
Sachin Ahuja27dd2402016-08-01 20:30:31 +05309163 if(pScanInfo != NULL && pHddCtx->scan_info.mScanPending)
Jeff Johnson295189b2012-06-20 16:38:30 -07009164 {
Mahesh A Saptasagar0b61dcc2016-02-15 14:23:38 +05309165 wlan_hdd_scan_abort(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07009166 }
Abhishek Singh3ac179b2015-09-21 10:01:34 +05309167 if ((pAdapter->device_mode != WLAN_HDD_INFRA_STATION) &&
9168 (pAdapter->device_mode != WLAN_HDD_IBSS))
Kaushik, Sushant7005e372014-04-08 11:36:54 +05309169 {
9170 while (pAdapter->is_roc_inprogress)
9171 {
9172 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9173 "%s: ROC in progress for session %d!!!",
9174 __func__, pAdapter->sessionId);
9175 // waiting for ROC to expire
9176 msleep(500);
9177 /* In GO present case , if retry exceeds 3,
9178 it means something went wrong. */
9179 if ( retry++ > MAX_WAIT_FOR_ROC_COMPLETION )
9180 {
9181 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9182 "%s: ROC completion is not received.!!!", __func__);
Deepthi Gowri70498252015-01-20 15:56:45 +05309183 if (eHAL_STATUS_SUCCESS !=
9184 sme_CancelRemainOnChannel( WLAN_HDD_GET_HAL_CTX( pAdapter),
9185 pAdapter->sessionId ))
9186 {
9187 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9188 FL("Failed to Cancel Remain on Channel"));
9189 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +05309190 wait_for_completion_interruptible_timeout(
9191 &pAdapter->cancel_rem_on_chan_var,
9192 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
9193 break;
9194 }
9195 }
Anand N Sunkaddc63c792015-06-03 14:33:24 +05309196 vos_flush_delayed_work(&pAdapter->roc_work);
Kaushik, Sushant7005e372014-04-08 11:36:54 +05309197 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05309198#ifdef WLAN_NS_OFFLOAD
Anand N Sunkaddc63c792015-06-03 14:33:24 +05309199 vos_flush_work(&pAdapter->ipv6NotifierWorkQueue);
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05309200#endif
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +05309201
Anand N Sunkaddc63c792015-06-03 14:33:24 +05309202 vos_flush_work(&pAdapter->ipv4NotifierWorkQueue);
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +05309203
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05309204 /* It is possible that the caller of this function does not
9205 * wish to close the session
9206 */
9207 if (VOS_TRUE == bCloseSession &&
9208 test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07009209 {
9210 INIT_COMPLETION(pAdapter->session_close_comp_var);
9211 if (eHAL_STATUS_SUCCESS ==
Agrawal Ashish5a3522c2016-03-02 15:08:28 +05309212 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId, FALSE,
9213 VOS_FALSE, hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07009214 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309215 unsigned long ret;
9216
Jeff Johnson295189b2012-06-20 16:38:30 -07009217 //Block on a completion variable. Can't wait forever though.
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309218 ret = wait_for_completion_timeout(
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05309219 &pAdapter->session_close_comp_var,
9220 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309221 if ( 0 >= ret)
9222 {
9223 hddLog(LOGE, "%s: failure waiting for session_close_comp_var %ld",
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05309224 __func__, ret);
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309225 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009226 }
9227 }
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05309228 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009229 break;
9230
9231 case WLAN_HDD_SOFTAP:
9232 case WLAN_HDD_P2P_GO:
Nirav Shah0cf4d892015-11-05 16:27:27 +05309233 if ( VOS_TRUE == bCloseSession )
9234 {
9235 status = hdd_sta_id_hash_detach(pAdapter);
9236 if (status != VOS_STATUS_SUCCESS)
9237 hddLog(VOS_TRACE_LEVEL_ERROR,
9238 FL("sta id hash detach failed"));
9239 }
9240
Jeff Johnson295189b2012-06-20 16:38:30 -07009241 //Any softap specific cleanup here...
Anurag Chouhan83026002016-12-13 22:46:21 +05309242 hdd_cleanup_ap_events(pAdapter);
Kaushik, Sushant7005e372014-04-08 11:36:54 +05309243 if (pAdapter->device_mode == WLAN_HDD_P2P_GO) {
9244 while (pAdapter->is_roc_inprogress) {
9245 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9246 "%s: ROC in progress for session %d!!!",
9247 __func__, pAdapter->sessionId);
9248 msleep(500);
9249 if ( retry++ > MAX_WAIT_FOR_ROC_COMPLETION ) {
9250 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9251 "%s: ROC completion is not received.!!!", __func__);
9252 WLANSAP_CancelRemainOnChannel(
9253 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
9254 wait_for_completion_interruptible_timeout(
9255 &pAdapter->cancel_rem_on_chan_var,
9256 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
9257 break;
9258 }
9259 }
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +05309260
Anand N Sunkaddc63c792015-06-03 14:33:24 +05309261 vos_flush_delayed_work(&pAdapter->roc_work);
Kaushik, Sushant7005e372014-04-08 11:36:54 +05309262 }
Agrawal Ashish17ef5082016-10-17 18:33:21 +05309263#ifdef SAP_AUTH_OFFLOAD
9264 if (pHddCtx->cfg_ini->enable_sap_auth_offload)
9265 hdd_set_sap_auth_offload(pAdapter, FALSE);
9266#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009267 mutex_lock(&pHddCtx->sap_lock);
9268 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
9269 {
9270 VOS_STATUS status;
9271 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9272
9273 //Stop Bss.
9274 status = WLANSAP_StopBss(pHddCtx->pvosContext);
9275 if (VOS_IS_STATUS_SUCCESS(status))
9276 {
9277 hdd_hostapd_state_t *pHostapdState =
9278 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
9279
9280 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
9281
9282 if (!VOS_IS_STATUS_SUCCESS(status))
9283 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309284 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss %d",
9285 __func__, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07009286 }
9287 }
9288 else
9289 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07009290 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009291 }
9292 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
Agarwal Ashish51325b52014-06-16 16:50:49 +05309293 wlan_hdd_decr_active_session(pHddCtx, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07009294
9295 if (eHAL_STATUS_FAILURE ==
9296 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
9297 0, NULL, eANI_BOOLEAN_FALSE))
9298 {
9299 hddLog(LOGE,
9300 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07009301 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009302 }
9303
9304 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
9305 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
9306 eANI_BOOLEAN_FALSE) )
9307 {
9308 hddLog(LOGE,
9309 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
9310 }
9311
9312 // Reset WNI_CFG_PROBE_RSP Flags
9313 wlan_hdd_reset_prob_rspies(pAdapter);
9314 kfree(pAdapter->sessionCtx.ap.beacon);
9315 pAdapter->sessionCtx.ap.beacon = NULL;
9316 }
9317 mutex_unlock(&pHddCtx->sap_lock);
9318 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07009319
Jeff Johnson295189b2012-06-20 16:38:30 -07009320 case WLAN_HDD_MONITOR:
9321 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07009322
Jeff Johnson295189b2012-06-20 16:38:30 -07009323 default:
9324 break;
9325 }
9326
9327 EXIT();
9328 return VOS_STATUS_SUCCESS;
9329}
9330
Kapil Gupta137ef892016-12-13 19:38:00 +05309331/**
9332 * wlan_hdd_restart_sap() - to restart SAP in driver internally
9333 * @ap_adapter: - Pointer to SAP hdd_adapter_t structure
9334 *
9335 * wlan_hdd_restart_sap first delete SAP and do cleanup.
9336 * After that WLANSAP_StartBss start re-start process of SAP.
9337 *
9338 * Return: None
9339 */
9340static void wlan_hdd_restart_sap(hdd_adapter_t *ap_adapter)
9341{
9342 hdd_ap_ctx_t *pHddApCtx;
9343 hdd_hostapd_state_t *pHostapdState;
9344 VOS_STATUS vos_status;
9345 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(ap_adapter);
9346#ifdef CFG80211_DEL_STA_V2
9347 struct station_del_parameters delStaParams;
9348#endif
9349 tsap_Config_t *pConfig;
9350
9351 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
9352 pConfig = &pHddApCtx->sapConfig;
9353
9354 mutex_lock(&pHddCtx->sap_lock);
9355 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags)) {
9356#ifdef CFG80211_DEL_STA_V2
9357 delStaParams.mac = NULL;
9358 delStaParams.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
9359 delStaParams.reason_code = eCsrForcedDeauthSta;
9360 wlan_hdd_cfg80211_del_station(ap_adapter->wdev.wiphy, ap_adapter->dev,
9361 &delStaParams);
9362#else
9363 wlan_hdd_cfg80211_del_station(ap_adapter->wdev.wiphy, ap_adapter->dev,
9364 NULL);
9365#endif
9366 hdd_cleanup_actionframe(pHddCtx, ap_adapter);
9367
9368 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
9369 vos_event_reset(&pHostapdState->vosEvent);
9370
9371 if (VOS_STATUS_SUCCESS == WLANSAP_StopBss(pHddCtx->pvosContext)) {
9372 vos_status = vos_wait_single_event(&pHostapdState->vosEvent,
9373 10000);
9374 if (!VOS_IS_STATUS_SUCCESS(vos_status)) {
9375 hddLog(LOGE, FL("SAP Stop Failed"));
9376 goto end;
9377 }
9378 }
9379 clear_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
9380 wlan_hdd_decr_active_session(pHddCtx, ap_adapter->device_mode);
9381 hddLog(LOG1, FL("SAP Stop Success"));
9382
9383 if (0 != wlan_hdd_cfg80211_update_apies(ap_adapter)) {
9384 hddLog(LOGE, FL("SAP Not able to set AP IEs"));
9385 goto end;
9386 }
9387
9388 if (WLANSAP_StartBss(pHddCtx->pvosContext, hdd_hostapd_SAPEventCB,
9389 pConfig, (v_PVOID_t)ap_adapter->dev) != VOS_STATUS_SUCCESS) {
9390 hddLog(LOGE, FL("SAP Start Bss fail"));
9391 goto end;
9392 }
9393
9394 hddLog(LOG1, FL("Waiting for SAP to start"));
9395 vos_status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
9396 if (!VOS_IS_STATUS_SUCCESS(vos_status)) {
9397 hddLog(LOGE, FL("SAP Start failed"));
9398 goto end;
9399 }
9400 hddLog(LOG1, FL("SAP Start Success"));
9401 set_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
9402 wlan_hdd_incr_active_session(pHddCtx, ap_adapter->device_mode);
9403 pHostapdState->bCommit = TRUE;
Anurag Chouhanb2951ae2017-03-12 13:41:35 +05309404 if (!VOS_IS_STATUS_SUCCESS(hdd_dhcp_mdns_offload(ap_adapter))) {
9405 hddLog(VOS_TRACE_LEVEL_ERROR, FL("DHCP/MDNS offload Failed!!"));
9406 vos_event_reset(&pHostapdState->vosEvent);
9407 if (VOS_STATUS_SUCCESS == WLANSAP_StopBss(pHddCtx->pvosContext)) {
9408 vos_status = vos_wait_single_event(&pHostapdState->vosEvent,
9409 10000);
9410 if (!VOS_IS_STATUS_SUCCESS(vos_status)) {
9411 hddLog(LOGE, FL("SAP Stop Failed"));
9412 goto end;
9413 }
9414 }
9415 }
Kapil Gupta137ef892016-12-13 19:38:00 +05309416 }
9417end:
9418 mutex_unlock(&pHddCtx->sap_lock);
9419 return;
9420}
9421
9422/**
9423 * __hdd_sap_restart_handle() - to handle restarting of SAP
9424 * @work: name of the work
9425 *
9426 * Purpose of this function is to trigger sap start. this function
9427 * will be called from workqueue.
9428 *
9429 * Return: void.
9430 */
9431static void __hdd_sap_restart_handle(struct work_struct *work)
9432{
9433 hdd_adapter_t *sap_adapter;
9434 hdd_context_t *hdd_ctx = container_of(work,
9435 hdd_context_t,
9436 sap_start_work);
9437 if (0 != wlan_hdd_validate_context(hdd_ctx)) {
9438 vos_ssr_unprotect(__func__);
9439 return;
9440 }
9441 sap_adapter = hdd_get_adapter(hdd_ctx,
9442 WLAN_HDD_SOFTAP);
9443 if (sap_adapter == NULL) {
9444 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9445 FL("sap_adapter is NULL"));
9446 vos_ssr_unprotect(__func__);
9447 return;
9448 }
9449
9450 if (hdd_ctx->is_ch_avoid_in_progress) {
9451 sap_adapter->sessionCtx.ap.sapConfig.channel = AUTO_CHANNEL_SELECT;
9452 wlan_hdd_restart_sap(sap_adapter);
9453 hdd_change_ch_avoidance_status(hdd_ctx, false);
9454 }
Agrawal Ashish574b3e62017-02-09 18:58:34 +05309455 if (hdd_ctx->cfg_ini->enable_sap_auth_offload)
9456 wlan_hdd_restart_sap(sap_adapter);
Kapil Gupta137ef892016-12-13 19:38:00 +05309457}
9458
9459/**
9460 * hdd_sap_restart_handle() - to handle restarting of SAP
9461 * @work: name of the work
9462 *
9463 * Purpose of this function is to trigger sap start. this function
9464 * will be called from workqueue.
9465 *
9466 * Return: void.
9467 */
9468static void hdd_sap_restart_handle(struct work_struct *work)
9469{
9470 vos_ssr_protect(__func__);
9471 __hdd_sap_restart_handle(work);
9472 vos_ssr_unprotect(__func__);
9473}
9474
9475
Jeff Johnson295189b2012-06-20 16:38:30 -07009476VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
9477{
9478 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
9479 VOS_STATUS status;
9480 hdd_adapter_t *pAdapter;
9481
9482 ENTER();
9483
9484 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
9485
9486 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
9487 {
9488 pAdapter = pAdapterNode->pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07009489
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05309490 hdd_stop_adapter( pHddCtx, pAdapter, VOS_TRUE );
Jeff Johnson295189b2012-06-20 16:38:30 -07009491
9492 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
9493 pAdapterNode = pNext;
9494 }
9495
9496 EXIT();
9497
9498 return VOS_STATUS_SUCCESS;
9499}
9500
Rajeev Kumarf999e582014-01-09 17:33:29 -08009501
9502#ifdef FEATURE_WLAN_BATCH_SCAN
9503/**---------------------------------------------------------------------------
9504
9505 \brief hdd_deinit_batch_scan () - This function cleans up batch scan data
9506 structures
9507
9508 \param - pAdapter Pointer to HDD adapter
9509
9510 \return - None
9511
9512 --------------------------------------------------------------------------*/
9513void hdd_deinit_batch_scan(hdd_adapter_t *pAdapter)
9514{
9515 tHddBatchScanRsp *pNode;
9516 tHddBatchScanRsp *pPrev;
9517
Siddharth Bhalb3e9b792014-02-24 15:14:16 +05309518 if (NULL == pAdapter)
Rajeev Kumarf999e582014-01-09 17:33:29 -08009519 {
Siddharth Bhalb3e9b792014-02-24 15:14:16 +05309520 hddLog(VOS_TRACE_LEVEL_ERROR,
9521 "%s: Adapter context is Null", __func__);
9522 return;
9523 }
9524
9525 pNode = pAdapter->pBatchScanRsp;
9526 while (pNode)
9527 {
9528 pPrev = pNode;
9529 pNode = pNode->pNext;
9530 vos_mem_free((v_VOID_t * )pPrev);
Rajeev Kumarf999e582014-01-09 17:33:29 -08009531 }
9532
9533 pAdapter->pBatchScanRsp = NULL;
9534 pAdapter->numScanList = 0;
9535 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
9536 pAdapter->prev_batch_id = 0;
9537
9538 return;
9539}
9540#endif
9541
9542
Jeff Johnson295189b2012-06-20 16:38:30 -07009543VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
9544{
9545 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
9546 VOS_STATUS status;
9547 hdd_adapter_t *pAdapter;
9548
9549 ENTER();
9550
9551 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
9552
9553 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
9554 {
9555 pAdapter = pAdapterNode->pAdapter;
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05309556 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
Jeff Johnson295189b2012-06-20 16:38:30 -07009557 netif_tx_disable(pAdapter->dev);
Hanumanth Reddy Pothulad864f312017-01-18 16:16:08 +05309558
9559 if (pHddCtx->cfg_ini->sap_internal_restart &&
9560 pAdapter->device_mode == WLAN_HDD_SOFTAP) {
9561 hddLog(LOG1, FL("driver supports sap restart"));
9562 vos_flush_work(&pHddCtx->sap_start_work);
9563 hdd_sap_indicate_disconnect_for_sta(pAdapter);
9564 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Hanumanth Reddy Pothula15bc0fa2017-02-03 17:24:17 +05309565 hdd_softap_deinit_tx_rx(pAdapter, true);
9566 hdd_sap_destroy_timers(pAdapter);
Hanumanth Reddy Pothulad864f312017-01-18 16:16:08 +05309567 } else {
9568 netif_carrier_off(pAdapter->dev);
9569 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009570
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07009571 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
9572
Jeff Johnson295189b2012-06-20 16:38:30 -07009573 hdd_deinit_tx_rx(pAdapter);
Agarwal Ashish6267caa2014-08-06 19:16:21 +05309574
Katya Nigam1fd24402015-02-16 14:52:19 +05309575 if(pAdapter->device_mode == WLAN_HDD_IBSS )
9576 hdd_ibss_deinit_tx_rx(pAdapter);
9577
Nirav Shah7e3c8132015-06-22 23:51:42 +05309578 status = hdd_sta_id_hash_detach(pAdapter);
9579 if (status != VOS_STATUS_SUCCESS)
9580 hddLog(VOS_TRACE_LEVEL_ERROR,
9581 FL("sta id hash detach failed for session id %d"),
9582 pAdapter->sessionId);
9583
Agarwal Ashish6267caa2014-08-06 19:16:21 +05309584 wlan_hdd_decr_active_session(pHddCtx, pAdapter->device_mode);
9585
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05309586 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
9587 {
9588 hdd_wmm_adapter_close( pAdapter );
9589 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
9590 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009591
Siddharth Bhal2db319d2014-12-03 12:37:18 +05309592 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
9593 {
9594 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
9595 }
9596
Rajeev Kumarf999e582014-01-09 17:33:29 -08009597#ifdef FEATURE_WLAN_BATCH_SCAN
9598 if (eHDD_BATCH_SCAN_STATE_STARTED == pAdapter->batchScanState)
9599 {
9600 hdd_deinit_batch_scan(pAdapter);
9601 }
9602#endif
9603
Mahesh A Saptasagarf5b8eff2015-01-31 01:07:07 +05309604#ifdef FEATURE_WLAN_TDLS
9605 mutex_lock(&pHddCtx->tdls_lock);
Pradeep Reddy POTTETI2d4d5c42015-03-03 14:34:19 +05309606 wlan_hdd_tdls_exit(pAdapter, TRUE);
Mahesh A Saptasagarf5b8eff2015-01-31 01:07:07 +05309607 mutex_unlock(&pHddCtx->tdls_lock);
9608#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009609 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
9610 pAdapterNode = pNext;
9611 }
9612
9613 EXIT();
9614
9615 return VOS_STATUS_SUCCESS;
9616}
9617
Abhishek Singhbbe0b2a2016-12-05 11:57:36 +05309618/**
Abhishek Singh5a597e62016-12-05 15:16:30 +05309619 * hdd_get_bss_entry() - Get the bss entry matching the chan, bssid and ssid
9620 * @wiphy: wiphy
9621 * @channel: channel of the BSS to find
9622 * @bssid: bssid of the BSS to find
9623 * @ssid: ssid of the BSS to find
9624 * @ssid_len: ssid len of of the BSS to find
9625 *
9626 * The API is a wrapper to get bss from kernel matching the chan,
9627 * bssid and ssid
9628 *
9629 * Return: Void
9630 */
9631#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) \
9632 && !defined(WITH_BACKPORTS) && !defined(IEEE80211_PRIVACY)
9633
9634struct cfg80211_bss* hdd_get_bss_entry(struct wiphy *wiphy,
9635 struct ieee80211_channel *channel,
9636 const u8 *bssid,
9637 const u8 *ssid, size_t ssid_len)
9638{
9639 return cfg80211_get_bss(wiphy, channel, bssid,
9640 ssid, ssid_len,
9641 WLAN_CAPABILITY_ESS,
9642 WLAN_CAPABILITY_ESS);
9643}
9644#else
9645struct cfg80211_bss* hdd_get_bss_entry(struct wiphy *wiphy,
9646 struct ieee80211_channel *channel,
9647 const u8 *bssid,
9648 const u8 *ssid, size_t ssid_len)
9649{
9650 return cfg80211_get_bss(wiphy, channel, bssid,
9651 ssid, ssid_len,
9652 IEEE80211_BSS_TYPE_ESS,
9653 IEEE80211_PRIVACY_ANY);
9654}
9655#endif
9656
9657/**
Abhishek Singhbbe0b2a2016-12-05 11:57:36 +05309658 * hdd_connect_result() - API to send connection status to supplicant
9659 * @dev: network device
9660 * @bssid: bssid to which we want to associate
9661 * @roam_info: information about connected bss
9662 * @req_ie: Request Information Element
9663 * @req_ie_len: len of the req IE
9664 * @resp_ie: Response IE
9665 * @resp_ie_len: len of ht response IE
9666 * @status: status
9667 * @gfp: Kernel Flag
9668 *
9669 * The API is a wrapper to send connection status to supplicant
9670 *
9671 * Return: Void
9672 */
9673#if defined CFG80211_CONNECT_BSS
9674void hdd_connect_result(struct net_device *dev,
9675 const u8 *bssid,
9676 tCsrRoamInfo *roam_info,
9677 const u8 *req_ie,
9678 size_t req_ie_len,
9679 const u8 *resp_ie,
9680 size_t resp_ie_len,
9681 u16 status,
9682 gfp_t gfp)
9683{
9684 hdd_adapter_t *padapter = (hdd_adapter_t *) netdev_priv(dev);
9685 struct cfg80211_bss *bss = NULL;
9686
9687 if (WLAN_STATUS_SUCCESS == status) {
9688 struct ieee80211_channel *chan;
9689 int freq;
9690 int chan_no = roam_info->pBssDesc->channelId;;
9691
9692 if (chan_no <= 14)
9693 freq = ieee80211_channel_to_frequency(chan_no,
9694 IEEE80211_BAND_2GHZ);
9695 else
9696 freq = ieee80211_channel_to_frequency(chan_no,
9697 IEEE80211_BAND_5GHZ);
9698
9699 chan = ieee80211_get_channel(padapter->wdev.wiphy, freq);
Abhishek Singh5a597e62016-12-05 15:16:30 +05309700 bss = hdd_get_bss_entry(padapter->wdev.wiphy,
9701 chan, bssid,
9702 roam_info->u.pConnectedProfile->SSID.ssId,
9703 roam_info->u.pConnectedProfile->SSID.length);
Abhishek Singhbbe0b2a2016-12-05 11:57:36 +05309704 }
9705
9706 cfg80211_connect_bss(dev, bssid, bss, req_ie, req_ie_len,
9707 resp_ie, resp_ie_len, status, gfp);
9708}
9709#else
9710void hdd_connect_result(struct net_device *dev,
9711 const u8 *bssid,
9712 tCsrRoamInfo *roam_info,
9713 const u8 *req_ie,
9714 size_t req_ie_len,
9715 const u8 * resp_ie,
9716 size_t resp_ie_len,
9717 u16 status,
9718 gfp_t gfp)
9719{
9720 cfg80211_connect_result(dev, bssid, req_ie, req_ie_len,
9721 resp_ie, resp_ie_len, status, gfp);
9722}
9723#endif
9724
Jeff Johnson295189b2012-06-20 16:38:30 -07009725VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
9726{
9727 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
9728 VOS_STATUS status;
9729 hdd_adapter_t *pAdapter;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05309730 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -07009731
9732 ENTER();
9733
9734 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
9735
9736 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
9737 {
9738 pAdapter = pAdapterNode->pAdapter;
9739
Kumar Anand82c009f2014-05-29 00:29:42 -07009740 hdd_wmm_init( pAdapter );
9741
Jeff Johnson295189b2012-06-20 16:38:30 -07009742 switch(pAdapter->device_mode)
9743 {
9744 case WLAN_HDD_INFRA_STATION:
9745 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07009746 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05309747
9748 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
9749
Jeff Johnson295189b2012-06-20 16:38:30 -07009750 hdd_init_station_mode(pAdapter);
9751 /* Open the gates for HDD to receive Wext commands */
9752 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07009753 pHddCtx->scan_info.mScanPending = FALSE;
9754 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07009755
9756 //Trigger the initial scan
Mukul Sharmae74e42c2015-08-06 23:55:49 +05309757 if (!pHddCtx->isLogpInProgress)
9758 hdd_wlan_initial_scan(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07009759
9760 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05309761 if (eConnectionState_Associated == connState ||
9762 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -07009763 {
9764 union iwreq_data wrqu;
9765 memset(&wrqu, '\0', sizeof(wrqu));
9766 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
9767 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
9768 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07009769 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07009770
Jeff Johnson295189b2012-06-20 16:38:30 -07009771 /* indicate disconnected event to nl80211 */
Mahesh A Saptasagar9ff4bcc2016-06-01 17:17:50 +05309772 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, false,
Mahesh A Saptasagarb5a15142016-05-25 11:27:43 +05309773 WLAN_REASON_UNSPECIFIED);
Jeff Johnson295189b2012-06-20 16:38:30 -07009774 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05309775 else if (eConnectionState_Connecting == connState)
9776 {
9777 /*
9778 * Indicate connect failure to supplicant if we were in the
9779 * process of connecting
9780 */
Abhishek Singhbbe0b2a2016-12-05 11:57:36 +05309781 hdd_connect_result(pAdapter->dev, NULL, NULL,
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05309782 NULL, 0, NULL, 0,
9783 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
9784 GFP_KERNEL);
9785 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009786 break;
9787
9788 case WLAN_HDD_SOFTAP:
Hanumanth Reddy Pothulad864f312017-01-18 16:16:08 +05309789 if (pHddCtx->cfg_ini->sap_internal_restart) {
Hanumanth Reddy Pothula15bc0fa2017-02-03 17:24:17 +05309790 hdd_init_ap_mode(pAdapter, true);
Hanumanth Reddy Pothulad864f312017-01-18 16:16:08 +05309791 status = hdd_sta_id_hash_attach(pAdapter);
9792 if (VOS_STATUS_SUCCESS != status)
9793 {
9794 hddLog(VOS_TRACE_LEVEL_FATAL,
9795 FL("failed to attach hash for"));
9796 }
9797 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009798 break;
9799
9800 case WLAN_HDD_P2P_GO:
Sameer Thalappiledf0d792013-08-09 14:31:03 -07009801 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send stop ap to supplicant",
Jeff Johnson295189b2012-06-20 16:38:30 -07009802 __func__);
Sameer Thalappiledf0d792013-08-09 14:31:03 -07009803 cfg80211_ap_stopped(pAdapter->dev, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07009804 break;
9805
9806 case WLAN_HDD_MONITOR:
9807 /* monitor interface start */
9808 break;
9809 default:
9810 break;
9811 }
9812
9813 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
9814 pAdapterNode = pNext;
9815 }
9816
9817 EXIT();
9818
9819 return VOS_STATUS_SUCCESS;
9820}
9821
9822VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
9823{
9824 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
9825 hdd_adapter_t *pAdapter;
9826 VOS_STATUS status;
9827 v_U32_t roamId;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309828 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07009829
9830 ENTER();
9831
9832 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
9833
9834 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
9835 {
9836 pAdapter = pAdapterNode->pAdapter;
9837
9838 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
9839 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
9840 {
9841 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9842 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
9843
Abhishek Singhf4669da2014-05-26 15:07:49 +05309844 hddLog(VOS_TRACE_LEVEL_INFO,
9845 "%s: Set HDD connState to eConnectionState_NotConnected",
9846 __func__);
Ganesh Kondabattini04338412015-09-14 15:39:09 +05309847 spin_lock_bh(&pAdapter->lock_for_active_session);
9848 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState)
9849 {
9850 wlan_hdd_decr_active_session(pHddCtx, pAdapter->device_mode);
9851 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009852 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
Ganesh Kondabattini04338412015-09-14 15:39:09 +05309853 spin_unlock_bh(&pAdapter->lock_for_active_session);
Jeff Johnson295189b2012-06-20 16:38:30 -07009854 init_completion(&pAdapter->disconnect_comp_var);
9855 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
9856 eCSR_DISCONNECT_REASON_UNSPECIFIED);
9857
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309858 ret = wait_for_completion_interruptible_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07009859 &pAdapter->disconnect_comp_var,
9860 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309861 if (0 >= ret)
9862 hddLog(LOGE, "%s: failure waiting for disconnect_comp_var %ld",
9863 __func__, ret);
Jeff Johnson295189b2012-06-20 16:38:30 -07009864
9865 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
9866 pHddCtx->isAmpAllowed = VOS_FALSE;
9867 sme_RoamConnect(pHddCtx->hHal,
9868 pAdapter->sessionId, &(pWextState->roamProfile),
9869 &roamId);
9870 }
9871
9872 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
9873 pAdapterNode = pNext;
9874 }
9875
9876 EXIT();
9877
9878 return VOS_STATUS_SUCCESS;
9879}
9880
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07009881void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
9882{
9883 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
9884 VOS_STATUS status;
9885 hdd_adapter_t *pAdapter;
9886 hdd_station_ctx_t *pHddStaCtx;
9887 hdd_ap_ctx_t *pHddApCtx;
9888 hdd_hostapd_state_t * pHostapdState;
9889 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
9890 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
9891 const char *p2pMode = "DEV";
9892 const char *ccMode = "Standalone";
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07009893
9894 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
9895 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
9896 {
9897 pAdapter = pAdapterNode->pAdapter;
9898 switch (pAdapter->device_mode) {
9899 case WLAN_HDD_INFRA_STATION:
9900 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9901 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
9902 staChannel = pHddStaCtx->conn_info.operationChannel;
9903 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
9904 }
9905 break;
9906 case WLAN_HDD_P2P_CLIENT:
9907 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9908 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
9909 p2pChannel = pHddStaCtx->conn_info.operationChannel;
9910 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
9911 p2pMode = "CLI";
9912 }
9913 break;
9914 case WLAN_HDD_P2P_GO:
9915 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
9916 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
9917 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
9918 p2pChannel = pHddApCtx->operatingChannel;
9919 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
9920 }
9921 p2pMode = "GO";
9922 break;
9923 case WLAN_HDD_SOFTAP:
9924 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
9925 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
9926 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
9927 apChannel = pHddApCtx->operatingChannel;
9928 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
9929 }
9930 break;
9931 default:
9932 break;
9933 }
9934 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
9935 pAdapterNode = pNext;
9936 }
9937 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
9938 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
9939 }
SaidiReddy Yenugaa8b32f92016-07-27 19:29:18 +05309940 hddLog(VOS_TRACE_LEVEL_INFO, "wlan(%d) " MAC_ADDRESS_STR " %s",
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07009941 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
9942 if (p2pChannel > 0) {
Sushant Kaushikdc3184b2015-10-09 12:00:21 +05309943 hddLog(VOS_TRACE_LEVEL_ERROR, "p2p-%s(%d) " MAC_ADDRESS_STR,
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07009944 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
9945 }
9946 if (apChannel > 0) {
Sushant Kaushikdc3184b2015-10-09 12:00:21 +05309947 hddLog(VOS_TRACE_LEVEL_ERROR, "AP(%d) " MAC_ADDRESS_STR,
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07009948 apChannel, MAC_ADDR_ARRAY(apBssid));
9949 }
9950
9951 if (p2pChannel > 0 && apChannel > 0) {
9952 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
9953 }
9954}
9955
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07009956bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07009957{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07009958 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07009959}
9960
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07009961/* Once SSR is disabled then it cannot be set. */
9962void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07009963{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07009964 if (HDD_SSR_DISABLED == isSsrRequired)
9965 return;
9966
Jeff Johnson295189b2012-06-20 16:38:30 -07009967 isSsrRequired = value;
9968}
9969
Hema Aparna Medicharla6b4d4f32015-06-23 04:09:12 +05309970void hdd_set_pre_close( hdd_context_t *pHddCtx)
9971{
9972 sme_PreClose(pHddCtx->hHal);
9973}
9974
Jeff Johnson295189b2012-06-20 16:38:30 -07009975VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
9976 hdd_adapter_list_node_t** ppAdapterNode)
9977{
9978 VOS_STATUS status;
Mukul Sharmaae1266d2015-06-26 15:29:53 +05309979 spin_lock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07009980 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
9981 (hdd_list_node_t**) ppAdapterNode );
Mukul Sharmaae1266d2015-06-26 15:29:53 +05309982 spin_unlock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07009983 return status;
9984}
9985
9986VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
9987 hdd_adapter_list_node_t* pAdapterNode,
9988 hdd_adapter_list_node_t** pNextAdapterNode)
9989{
9990 VOS_STATUS status;
Mukul Sharmaae1266d2015-06-26 15:29:53 +05309991 spin_lock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07009992 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
9993 (hdd_list_node_t*) pAdapterNode,
9994 (hdd_list_node_t**)pNextAdapterNode );
9995
Mukul Sharmaae1266d2015-06-26 15:29:53 +05309996 spin_unlock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07009997 return status;
9998}
9999
10000VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
10001 hdd_adapter_list_node_t* pAdapterNode)
10002{
10003 VOS_STATUS status;
Mukul Sharmaae1266d2015-06-26 15:29:53 +053010004 spin_lock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010005 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
10006 &pAdapterNode->node );
Mukul Sharmaae1266d2015-06-26 15:29:53 +053010007 spin_unlock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010008 return status;
10009}
10010
10011VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
10012 hdd_adapter_list_node_t** ppAdapterNode)
10013{
10014 VOS_STATUS status;
Mukul Sharmaae1266d2015-06-26 15:29:53 +053010015 spin_lock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010016 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
10017 (hdd_list_node_t**) ppAdapterNode );
Mukul Sharmaae1266d2015-06-26 15:29:53 +053010018 spin_unlock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010019 return status;
10020}
10021
10022VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
10023 hdd_adapter_list_node_t* pAdapterNode)
10024{
10025 VOS_STATUS status;
Mukul Sharmaae1266d2015-06-26 15:29:53 +053010026 spin_lock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010027 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
10028 (hdd_list_node_t*) pAdapterNode );
Mukul Sharmaae1266d2015-06-26 15:29:53 +053010029 spin_unlock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010030 return status;
10031}
10032
10033VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
10034 hdd_adapter_list_node_t* pAdapterNode)
10035{
10036 VOS_STATUS status;
Mukul Sharmaae1266d2015-06-26 15:29:53 +053010037 spin_lock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010038 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
10039 (hdd_list_node_t*) pAdapterNode );
Mukul Sharmaae1266d2015-06-26 15:29:53 +053010040 spin_unlock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010041 return status;
10042}
10043
10044hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
10045 tSirMacAddr macAddr )
10046{
10047 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
10048 hdd_adapter_t *pAdapter;
10049 VOS_STATUS status;
10050
10051 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10052
10053 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
10054 {
10055 pAdapter = pAdapterNode->pAdapter;
10056
10057 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
10058 macAddr, sizeof(tSirMacAddr) ) )
10059 {
10060 return pAdapter;
10061 }
10062 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10063 pAdapterNode = pNext;
10064 }
10065
10066 return NULL;
10067
10068}
10069
10070hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
10071{
10072 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
10073 hdd_adapter_t *pAdapter;
10074 VOS_STATUS status;
10075
10076 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10077
10078 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
10079 {
10080 pAdapter = pAdapterNode->pAdapter;
10081
10082 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
10083 IFNAMSIZ ) )
10084 {
10085 return pAdapter;
10086 }
10087 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10088 pAdapterNode = pNext;
10089 }
10090
10091 return NULL;
10092
10093}
10094
Ganesh Kondabattinicbfdc392015-09-11 19:12:59 +053010095hdd_adapter_t *hdd_get_adapter_by_sme_session_id( hdd_context_t *pHddCtx,
10096 tANI_U32 sme_session_id )
10097{
10098 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
10099 hdd_adapter_t *pAdapter;
10100 VOS_STATUS vos_status;
10101
10102
10103 vos_status = hdd_get_front_adapter( pHddCtx, &pAdapterNode);
10104
10105 while ((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == vos_status))
10106 {
10107 pAdapter = pAdapterNode->pAdapter;
10108
10109 if (pAdapter->sessionId == sme_session_id)
10110 return pAdapter;
10111
10112 vos_status = hdd_get_next_adapter(pHddCtx, pAdapterNode, &pNext);
10113 pAdapterNode = pNext;
10114 }
10115
10116 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
10117 "%s: sme_session_id %d does not exist with host",
10118 __func__, sme_session_id);
10119
10120 return NULL;
10121}
10122
Jeff Johnson295189b2012-06-20 16:38:30 -070010123hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
10124{
10125 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
10126 hdd_adapter_t *pAdapter;
10127 VOS_STATUS status;
10128
10129 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10130
10131 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
10132 {
10133 pAdapter = pAdapterNode->pAdapter;
10134
10135 if( pAdapter && (mode == pAdapter->device_mode) )
10136 {
10137 return pAdapter;
10138 }
10139 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10140 pAdapterNode = pNext;
10141 }
10142
10143 return NULL;
10144
10145}
10146
10147//Remove this function later
10148hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
10149{
10150 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
10151 hdd_adapter_t *pAdapter;
10152 VOS_STATUS status;
10153
10154 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10155
10156 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
10157 {
10158 pAdapter = pAdapterNode->pAdapter;
10159
10160 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
10161 {
10162 return pAdapter;
10163 }
10164
10165 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10166 pAdapterNode = pNext;
10167 }
10168
10169 return NULL;
10170
10171}
10172
Jeff Johnson295189b2012-06-20 16:38:30 -070010173/**---------------------------------------------------------------------------
10174
Mahesh A Saptasgar64534612014-09-23 13:13:33 +053010175 \brief hdd_get_operating_channel() -
Jeff Johnson295189b2012-06-20 16:38:30 -070010176
10177 This API returns the operating channel of the requested device mode
10178
10179 \param - pHddCtx - Pointer to the HDD context.
10180 - mode - Device mode for which operating channel is required
10181 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
10182 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
10183 \return - channel number. "0" id the requested device is not found OR it is not connected.
10184 --------------------------------------------------------------------------*/
10185v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
10186{
10187 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
10188 VOS_STATUS status;
10189 hdd_adapter_t *pAdapter;
10190 v_U8_t operatingChannel = 0;
10191
10192 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10193
10194 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
10195 {
10196 pAdapter = pAdapterNode->pAdapter;
10197
10198 if( mode == pAdapter->device_mode )
10199 {
10200 switch(pAdapter->device_mode)
10201 {
10202 case WLAN_HDD_INFRA_STATION:
10203 case WLAN_HDD_P2P_CLIENT:
10204 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
10205 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
10206 break;
10207 case WLAN_HDD_SOFTAP:
10208 case WLAN_HDD_P2P_GO:
10209 /*softap connection info */
10210 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
10211 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
10212 break;
10213 default:
10214 break;
10215 }
10216
10217 break; //Found the device of interest. break the loop
10218 }
10219
10220 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10221 pAdapterNode = pNext;
10222 }
10223 return operatingChannel;
10224}
10225
10226#ifdef WLAN_FEATURE_PACKET_FILTERING
10227/**---------------------------------------------------------------------------
10228
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +053010229 \brief __hdd_set_multicast_list() -
Jeff Johnson295189b2012-06-20 16:38:30 -070010230
10231 This used to set the multicast address list.
10232
10233 \param - dev - Pointer to the WLAN device.
10234 - skb - Pointer to OS packet (sk_buff).
Mahesh A Saptasagar74088392015-02-05 17:22:09 +053010235 \return - success/fail
Jeff Johnson295189b2012-06-20 16:38:30 -070010236
10237 --------------------------------------------------------------------------*/
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +053010238static void __hdd_set_multicast_list(struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -070010239{
Mahesh A Saptasagar74088392015-02-05 17:22:09 +053010240 hdd_adapter_t *pAdapter;
10241 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -070010242 int mc_count;
Mahesh A Saptasagar74088392015-02-05 17:22:09 +053010243 int i = 0, ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -070010244 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +053010245
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +053010246 ENTER();
10247
Mahesh A Saptasagar74088392015-02-05 17:22:09 +053010248 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Gopichand Nakkala0f276812013-02-24 14:45:51 +053010249 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -070010250 {
10251 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +053010252 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -070010253 return;
10254 }
Mahesh A Saptasagar74088392015-02-05 17:22:09 +053010255 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10256 ret = wlan_hdd_validate_context(pHddCtx);
10257 if (0 != ret)
10258 {
Mahesh A Saptasagar74088392015-02-05 17:22:09 +053010259 return;
10260 }
Jeff Johnson295189b2012-06-20 16:38:30 -070010261 if (dev->flags & IFF_ALLMULTI)
10262 {
10263 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070010264 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +053010265 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -070010266 }
Mahesh A Saptasagar74088392015-02-05 17:22:09 +053010267 else
Jeff Johnson295189b2012-06-20 16:38:30 -070010268 {
10269 mc_count = netdev_mc_count(dev);
10270 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070010271 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -070010272 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
10273 {
10274 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070010275 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +053010276 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -070010277 return;
10278 }
10279
Gopichand Nakkala0f276812013-02-24 14:45:51 +053010280 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -070010281
10282 netdev_for_each_mc_addr(ha, dev) {
10283 if (i == mc_count)
10284 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +053010285 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
10286 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
Arif Hussain6d2a3322013-11-17 19:50:10 -080010287 hddLog(VOS_TRACE_LEVEL_INFO, "%s: mlist[%d] = "MAC_ADDRESS_STR,
Mahesh A Saptasagar74088392015-02-05 17:22:09 +053010288 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +053010289 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -070010290 i++;
10291 }
10292 }
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +053010293
Ganesh Kondabattinifb37e652015-10-09 15:46:47 +053010294 if (pHddCtx->hdd_wlan_suspended)
10295 {
10296 /*
10297 * Configure the Mcast address list to FW
10298 * If wlan is already in suspend mode
10299 */
10300 wlan_hdd_set_mc_addr_list(pAdapter, TRUE);
10301 }
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +053010302 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -070010303 return;
10304}
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +053010305
10306static void hdd_set_multicast_list(struct net_device *dev)
10307{
10308 vos_ssr_protect(__func__);
10309 __hdd_set_multicast_list(dev);
10310 vos_ssr_unprotect(__func__);
10311}
Jeff Johnson295189b2012-06-20 16:38:30 -070010312#endif
10313
10314/**---------------------------------------------------------------------------
10315
10316 \brief hdd_select_queue() -
10317
10318 This function is registered with the Linux OS for network
10319 core to decide which queue to use first.
10320
10321 \param - dev - Pointer to the WLAN device.
10322 - skb - Pointer to OS packet (sk_buff).
10323 \return - ac, Queue Index/access category corresponding to UP in IP header
10324
10325 --------------------------------------------------------------------------*/
10326v_U16_t hdd_select_queue(struct net_device *dev,
Anand N Sunkade9adb1b2015-07-29 09:56:45 +053010327 struct sk_buff *skb
10328#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0))
10329 , void *accel_priv
10330#endif
10331#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0))
10332 , select_queue_fallback_t fallback
10333#endif
10334)
Jeff Johnson295189b2012-06-20 16:38:30 -070010335{
10336 return hdd_wmm_select_queue(dev, skb);
10337}
10338
10339
10340/**---------------------------------------------------------------------------
10341
10342 \brief hdd_wlan_initial_scan() -
10343
10344 This function triggers the initial scan
10345
10346 \param - pAdapter - Pointer to the HDD adapter.
10347
10348 --------------------------------------------------------------------------*/
10349void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
10350{
10351 tCsrScanRequest scanReq;
10352 tCsrChannelInfo channelInfo;
10353 eHalStatus halStatus;
Jeff Johnson02797792013-10-26 19:17:13 -070010354 tANI_U32 scanId;
Jeff Johnson295189b2012-06-20 16:38:30 -070010355 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10356
10357 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
10358 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
10359 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
10360
10361 if(sme_Is11dSupported(pHddCtx->hHal))
10362 {
10363 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
10364 if ( HAL_STATUS_SUCCESS( halStatus ) )
10365 {
10366 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
10367 if( !scanReq.ChannelInfo.ChannelList )
10368 {
10369 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
10370 vos_mem_free(channelInfo.ChannelList);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -080010371 channelInfo.ChannelList = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -070010372 return;
10373 }
10374 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
10375 channelInfo.numOfChannels);
10376 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
10377 vos_mem_free(channelInfo.ChannelList);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -080010378 channelInfo.ChannelList = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -070010379 }
10380
10381 scanReq.scanType = eSIR_PASSIVE_SCAN;
10382 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
10383 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
10384 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
10385 }
10386 else
10387 {
10388 scanReq.scanType = eSIR_ACTIVE_SCAN;
10389 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
10390 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
10391 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
10392 }
10393
10394 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
10395 if ( !HAL_STATUS_SUCCESS( halStatus ) )
10396 {
10397 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
10398 __func__, halStatus );
10399 }
10400
10401 if(sme_Is11dSupported(pHddCtx->hHal))
10402 vos_mem_free(scanReq.ChannelInfo.ChannelList);
10403}
10404
Jeff Johnson295189b2012-06-20 16:38:30 -070010405/**---------------------------------------------------------------------------
10406
10407 \brief hdd_full_power_callback() - HDD full power callback function
10408
10409 This is the function invoked by SME to inform the result of a full power
10410 request issued by HDD
10411
10412 \param - callbackcontext - Pointer to cookie
10413 \param - status - result of request
10414
10415 \return - None
10416
10417 --------------------------------------------------------------------------*/
10418static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
10419{
Jeff Johnson72a40512013-12-19 10:14:15 -080010420 struct statsContext *pContext = callbackContext;
Jeff Johnson295189b2012-06-20 16:38:30 -070010421
10422 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +053010423 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -070010424
10425 if (NULL == callbackContext)
10426 {
10427 hddLog(VOS_TRACE_LEVEL_ERROR,
10428 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070010429 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -070010430 return;
10431 }
10432
Jeff Johnson72a40512013-12-19 10:14:15 -080010433 /* there is a race condition that exists between this callback
10434 function and the caller since the caller could time out either
10435 before or while this code is executing. we use a spinlock to
10436 serialize these actions */
10437 spin_lock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010438
10439 if (POWER_CONTEXT_MAGIC != pContext->magic)
10440 {
10441 /* the caller presumably timed out so there is nothing we can do */
Jeff Johnson72a40512013-12-19 10:14:15 -080010442 spin_unlock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010443 hddLog(VOS_TRACE_LEVEL_WARN,
10444 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070010445 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -070010446 return;
10447 }
10448
Jeff Johnson72a40512013-12-19 10:14:15 -080010449 /* context is valid so caller is still waiting */
10450
10451 /* paranoia: invalidate the magic */
10452 pContext->magic = 0;
10453
10454 /* notify the caller */
Jeff Johnson295189b2012-06-20 16:38:30 -070010455 complete(&pContext->completion);
Jeff Johnson72a40512013-12-19 10:14:15 -080010456
10457 /* serialization is complete */
10458 spin_unlock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010459}
10460
Katya Nigamf0511f62015-05-05 16:40:57 +053010461void wlan_hdd_mon_set_typesubtype( hdd_mon_ctx_t *pMonCtx,int type)
10462{
10463 pMonCtx->typeSubtypeBitmap = 0;
10464 if( type%10 ) /* Management Packets */
10465 pMonCtx->typeSubtypeBitmap |= 0xFFFF;
10466 type/=10;
10467 if( type%10 ) /* Control Packets */
10468 pMonCtx->typeSubtypeBitmap |= 0xFFFF0000;
10469 type/=10;
10470 if( type%10 ) /* Data Packets */
10471 pMonCtx->typeSubtypeBitmap |= 0xFFFF00000000;
10472}
10473
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053010474VOS_STATUS wlan_hdd_mon_postMsg(tANI_U32 *magic, struct completion *cmpVar,
10475 hdd_mon_ctx_t *pMonCtx , void* callback)
Katya Nigamf0511f62015-05-05 16:40:57 +053010476{
10477 vos_msg_t monMsg;
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053010478 tSirMonModeReq *pMonModeReq;
Katya Nigamf0511f62015-05-05 16:40:57 +053010479
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053010480 if (MON_MODE_START == pMonCtx->state)
10481 monMsg.type = WDA_MON_START_REQ;
10482 else if (MON_MODE_STOP == pMonCtx->state)
10483 monMsg.type = WDA_MON_STOP_REQ;
10484 else {
10485 hddLog(VOS_TRACE_LEVEL_ERROR,
10486 FL("invalid monitor state %d"), pMonCtx->state);
Katya Nigamf0511f62015-05-05 16:40:57 +053010487 return VOS_STATUS_E_FAILURE;
10488 }
10489
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053010490 pMonModeReq = vos_mem_malloc(sizeof(tSirMonModeReq));
10491 if (pMonModeReq == NULL) {
10492 hddLog(VOS_TRACE_LEVEL_ERROR,
10493 FL("fail to allocate memory for monitor mode req"));
10494 return VOS_STATUS_E_FAILURE;
10495 }
Katya Nigamf0511f62015-05-05 16:40:57 +053010496
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053010497 pMonModeReq->magic = magic;
10498 pMonModeReq->cmpVar = cmpVar;
10499 pMonModeReq->data = pMonCtx;
10500 pMonModeReq->callback = callback;
Katya Nigamf0511f62015-05-05 16:40:57 +053010501
Katya Nigamf0511f62015-05-05 16:40:57 +053010502 monMsg.reserved = 0;
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053010503 monMsg.bodyptr = pMonModeReq;
Katya Nigamf0511f62015-05-05 16:40:57 +053010504 monMsg.bodyval = 0;
10505
10506 if (VOS_STATUS_SUCCESS != vos_mq_post_message(
10507 VOS_MODULE_ID_WDA,(vos_msg_t *)&monMsg)) {
10508 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: : Failed to post Msg to HAL",__func__);
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053010509 vos_mem_free(pMonModeReq);
Katya Nigamf0511f62015-05-05 16:40:57 +053010510 }
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053010511 return VOS_STATUS_SUCCESS;
Katya Nigamf0511f62015-05-05 16:40:57 +053010512}
10513
Katya Nigame7b69a82015-04-28 15:24:06 +053010514void wlan_hdd_mon_close(hdd_context_t *pHddCtx)
10515{
10516 VOS_STATUS vosStatus;
10517 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053010518 long ret;
10519 hdd_mon_ctx_t *pMonCtx = NULL;
10520 v_U32_t magic;
10521 struct completion cmpVar;
Hanumantha Reddy Pothulac99bc062015-09-08 14:59:26 +053010522
Katya Nigame7b69a82015-04-28 15:24:06 +053010523 hdd_adapter_t *pAdapter = hdd_get_adapter(pHddCtx,WLAN_HDD_MONITOR);
10524 if(pAdapter == NULL || pVosContext == NULL)
10525 {
10526 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:pAdapter is NULL",__func__);
10527 return ;
10528 }
Katya Nigamf0511f62015-05-05 16:40:57 +053010529
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053010530 pMonCtx = WLAN_HDD_GET_MONITOR_CTX_PTR(pAdapter);
10531 if (pMonCtx!= NULL && pMonCtx->state == MON_MODE_START) {
10532 pMonCtx->state = MON_MODE_STOP;
10533 magic = MON_MODE_MSG_MAGIC;
10534 init_completion(&cmpVar);
10535 if (VOS_STATUS_SUCCESS !=
10536 wlan_hdd_mon_postMsg(&magic, &cmpVar,
10537 pMonCtx, hdd_monPostMsgCb)) {
10538 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
10539 FL("failed to post MON MODE REQ"));
10540 pMonCtx->state = MON_MODE_START;
10541 magic = 0;
10542 return;
10543 }
10544 ret = wait_for_completion_timeout(&cmpVar, MON_MODE_MSG_TIMEOUT);
10545 magic = 0;
10546 if (ret <= 0 ) {
10547 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
10548 FL("timeout on monitor mode completion %ld"), ret);
10549 }
10550 }
10551
Katya Nigame7b69a82015-04-28 15:24:06 +053010552 hdd_UnregisterWext(pAdapter->dev);
10553
10554 vos_mon_stop( pVosContext );
10555
10556 vosStatus = vos_sched_close( pVosContext );
10557 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
10558 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
10559 "%s: Failed to close VOSS Scheduler",__func__);
10560 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
10561 }
10562
10563 vosStatus = vos_nv_close();
10564 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
10565 {
10566 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
10567 "%s: Failed to close NV", __func__);
10568 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
10569 }
10570
10571 vos_close(pVosContext);
10572
10573 #ifdef WLAN_KD_READY_NOTIFIER
10574 nl_srv_exit(pHddCtx->ptt_pid);
10575 #else
10576 nl_srv_exit();
10577 #endif
10578
Katya Nigame7b69a82015-04-28 15:24:06 +053010579 hdd_close_all_adapters( pHddCtx );
Katya Nigame7b69a82015-04-28 15:24:06 +053010580}
Agrawal Ashish33ec71e2015-11-26 20:20:58 +053010581/**
10582 * hdd_wlan_free_wiphy_channels - free Channel pointer for wiphy
10583 * @ wiphy: the wiphy to validate against
10584 *
10585 * Return: void
10586 */
10587void hdd_wlan_free_wiphy_channels(struct wiphy *wiphy)
10588{
10589 int i =0;
10590 for (i = 0; i < IEEE80211_NUM_BANDS; i++)
10591 {
10592 if (NULL != wiphy->bands[i] &&
10593 (NULL != wiphy->bands[i]->channels))
10594 {
10595 vos_mem_free(wiphy->bands[i]->channels);
10596 wiphy->bands[i]->channels = NULL;
10597 }
10598 }
10599}
Jeff Johnson295189b2012-06-20 16:38:30 -070010600/**---------------------------------------------------------------------------
10601
10602 \brief hdd_wlan_exit() - HDD WLAN exit function
10603
10604 This is the driver exit point (invoked during rmmod)
10605
10606 \param - pHddCtx - Pointer to the HDD Context
10607
10608 \return - None
10609
10610 --------------------------------------------------------------------------*/
10611void hdd_wlan_exit(hdd_context_t *pHddCtx)
10612{
10613 eHalStatus halStatus;
10614 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
10615 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +053010616 struct wiphy *wiphy = pHddCtx->wiphy;
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -080010617 hdd_adapter_t* pAdapter = NULL;
Jeff Johnson72a40512013-12-19 10:14:15 -080010618 struct statsContext powerContext;
Jeff Johnson295189b2012-06-20 16:38:30 -070010619 long lrc;
c_hpothu5ab05e92014-06-13 17:34:05 +053010620 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -070010621
10622 ENTER();
10623
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053010624
Katya Nigame7b69a82015-04-28 15:24:06 +053010625 if (VOS_MONITOR_MODE == hdd_get_conparam())
10626 {
10627 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: MONITOR MODE",__func__);
10628 wlan_hdd_mon_close(pHddCtx);
Hanumantha Reddy Pothulac99bc062015-09-08 14:59:26 +053010629 goto free_hdd_ctx;
Katya Nigame7b69a82015-04-28 15:24:06 +053010630 }
10631 else if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -080010632 {
10633 // Unloading, restart logic is no more required.
10634 wlan_hdd_restart_deinit(pHddCtx);
Jeff Johnsone7245742012-09-05 17:12:55 -070010635
Agarwal Ashishb20e0ff2014-12-17 22:50:19 +053010636#ifdef FEATURE_WLAN_TDLS
10637 /* At the time of driver unloading; if tdls connection is present;
10638 * hdd_rx_packet_cbk calls wlan_hdd_tdls_find_peer.
10639 * wlan_hdd_tdls_find_peer always checks for valid context;
10640 * as load/unload in progress there can be a race condition.
10641 * hdd_rx_packet_cbk calls wlan_hdd_tdls_find_peer only
10642 * when tdls state is enabled.
10643 * As soon as driver set load/unload flag; tdls flag also needs
10644 * to be disabled so that hdd_rx_packet_cbk won't call
10645 * wlan_hdd_tdls_find_peer.
10646 */
Masti, Narayanraddi20494af2015-12-17 20:56:42 +053010647 wlan_hdd_tdls_set_mode(pHddCtx, eTDLS_SUPPORT_DISABLED, FALSE,
10648 HDD_SET_TDLS_MODE_SOURCE_USER);
Agarwal Ashishb20e0ff2014-12-17 22:50:19 +053010649#endif
10650
c_hpothu5ab05e92014-06-13 17:34:05 +053010651 vosStatus = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10652 while (NULL != pAdapterNode && VOS_STATUS_E_EMPTY != vosStatus)
Jeff Johnson295189b2012-06-20 16:38:30 -070010653 {
c_hpothu5ab05e92014-06-13 17:34:05 +053010654 pAdapter = pAdapterNode->pAdapter;
10655 if (NULL != pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -070010656 {
Mahesh A Saptasagar305e2632015-03-04 12:57:33 +053010657 /* Disable TX on the interface, after this hard_start_xmit() will
10658 * not be called on that interface
10659 */
10660 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
10661 netif_tx_disable(pAdapter->dev);
10662
10663 /* Mark the interface status as "down" for outside world */
10664 netif_carrier_off(pAdapter->dev);
10665
Agarwal Ashish9ffa5b92014-11-18 21:07:02 +053010666 /* DeInit the adapter. This ensures that all data packets
10667 * are freed.
10668 */
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +053010669#ifdef FEATURE_WLAN_TDLS
10670 mutex_lock(&pHddCtx->tdls_lock);
10671#endif
c_hpothu002231a2015-02-05 14:58:51 +053010672 hdd_deinit_adapter(pHddCtx, pAdapter, FALSE);
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +053010673#ifdef FEATURE_WLAN_TDLS
10674 mutex_unlock(&pHddCtx->tdls_lock);
10675#endif
Masti, Narayanraddi26378462016-01-05 18:20:28 +053010676 vos_flush_delayed_work(&pHddCtx->scan_ctxt.scan_work);
10677
10678 wlan_hdd_init_deinit_defer_scan_context(&pHddCtx->scan_ctxt);
Agarwal Ashish9ffa5b92014-11-18 21:07:02 +053010679
c_hpothu5ab05e92014-06-13 17:34:05 +053010680 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode ||
10681 WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)
10682 {
10683 wlan_hdd_cfg80211_deregister_frames(pAdapter);
10684 hdd_UnregisterWext(pAdapter->dev);
10685 }
Kaushik, Sushant4975a572014-10-21 16:07:48 +053010686
Jeff Johnson295189b2012-06-20 16:38:30 -070010687 }
c_hpothu5ab05e92014-06-13 17:34:05 +053010688 vosStatus = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10689 pAdapterNode = pNext;
Jeff Johnson295189b2012-06-20 16:38:30 -070010690 }
mukul sharmabab477d2015-06-11 17:14:55 +053010691
Kaushik, Sushant4975a572014-10-21 16:07:48 +053010692 // Cancel any outstanding scan requests. We are about to close all
10693 // of our adapters, but an adapter structure is what SME passes back
10694 // to our callback function. Hence if there are any outstanding scan
10695 // requests then there is a race condition between when the adapter
10696 // is closed and when the callback is invoked.We try to resolve that
10697 // race condition here by canceling any outstanding scans before we
10698 // close the adapters.
10699 // Note that the scans may be cancelled in an asynchronous manner,
10700 // so ideally there needs to be some kind of synchronization. Rather
10701 // than introduce a new synchronization here, we will utilize the
10702 // fact that we are about to Request Full Power, and since that is
10703 // synchronized, the expectation is that by the time Request Full
10704 // Power has completed all scans will be cancelled.
10705 if (pHddCtx->scan_info.mScanPending)
10706 {
Hema Aparna Medicharlaf05f6cd2015-01-21 14:44:19 +053010707 if(NULL != pAdapter)
10708 {
10709 hddLog(VOS_TRACE_LEVEL_INFO,
10710 FL("abort scan mode: %d sessionId: %d"),
10711 pAdapter->device_mode,
10712 pAdapter->sessionId);
10713 }
10714 hdd_abort_mac_scan(pHddCtx,
10715 pHddCtx->scan_info.sessionId,
10716 eCSR_SCAN_ABORT_DEFAULT);
Kaushik, Sushant4975a572014-10-21 16:07:48 +053010717 }
Jeff Johnson295189b2012-06-20 16:38:30 -070010718 }
c_hpothu5ab05e92014-06-13 17:34:05 +053010719 else
Jeff Johnson88ba7742013-02-27 14:36:02 -080010720 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +053010721 hddLog(VOS_TRACE_LEVEL_INFO,"%s: FTM MODE",__func__);
Hanumantha Reddy Pothula45af96b2015-02-12 16:07:58 +053010722 if (pHddCtx->ftm.ftm_state == WLAN_FTM_STARTING)
10723 {
10724 INIT_COMPLETION(pHddCtx->ftm.startCmpVar);
10725 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
10726 "%s: in middle of FTM START", __func__);
10727 lrc = wait_for_completion_timeout(&pHddCtx->ftm.startCmpVar,
10728 msecs_to_jiffies(20000));
10729 if(!lrc)
10730 {
10731 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
10732 "%s: timedout on ftmStartCmpVar fatal error", __func__);
10733 }
10734 }
Jeff Johnson88ba7742013-02-27 14:36:02 -080010735 wlan_hdd_ftm_close(pHddCtx);
10736 goto free_hdd_ctx;
10737 }
c_hpothu6ff1c3c2013-10-01 19:01:57 +053010738
Jeff Johnson295189b2012-06-20 16:38:30 -070010739 /* DeRegister with platform driver as client for Suspend/Resume */
10740 vosStatus = hddDeregisterPmOps(pHddCtx);
10741 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
10742 {
10743 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
10744 VOS_ASSERT(0);
10745 }
10746
10747 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
10748 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
10749 {
10750 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
10751 }
Jeff Johnson295189b2012-06-20 16:38:30 -070010752
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -070010753 //Stop the traffic monitor timer
Mahesh A Saptasagard461e432016-07-20 15:01:40 +053010754 if ((pHddCtx->cfg_ini->dynSplitscan) && (VOS_TIMER_STATE_RUNNING ==
10755 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr)))
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -070010756 {
10757 vos_timer_stop(&pHddCtx->tx_rx_trafficTmr);
10758 }
10759
10760 // Destroy the traffic monitor timer
Mahesh A Saptasagard461e432016-07-20 15:01:40 +053010761 if ((pHddCtx->cfg_ini->dynSplitscan) &&
10762 (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
10763 &pHddCtx->tx_rx_trafficTmr))))
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -070010764 {
10765 hddLog(VOS_TRACE_LEVEL_ERROR,
10766 "%s: Cannot deallocate Traffic monitor timer", __func__);
10767 }
10768
Bhargav Shahd0715912015-10-01 18:17:37 +053010769 if (VOS_TIMER_STATE_RUNNING ==
10770 vos_timer_getCurrentState(&pHddCtx->delack_timer)) {
10771 vos_timer_stop(&pHddCtx->delack_timer);
10772 }
10773
10774 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
10775 &pHddCtx->delack_timer))) {
10776 hddLog(VOS_TRACE_LEVEL_ERROR,
10777 "%s: Cannot deallocate Bus bandwidth timer", __func__);
10778 }
10779
Masti, Narayanraddi44b0db02015-12-22 11:54:35 +053010780 if (VOS_TIMER_STATE_RUNNING ==
10781 vos_timer_getCurrentState(&pHddCtx->tdls_source_timer)) {
10782 vos_timer_stop(&pHddCtx->tdls_source_timer);
10783 }
10784
Abhishek Singh8a3e4dc2017-01-02 10:39:18 +053010785 vos_set_snoc_high_freq_voting(false);
10786
Masti, Narayanraddi44b0db02015-12-22 11:54:35 +053010787 vos_timer_destroy(&pHddCtx->tdls_source_timer);
10788
Jeff Johnson295189b2012-06-20 16:38:30 -070010789 //Disable IMPS/BMPS as we do not want the device to enter any power
10790 //save mode during shutdown
10791 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
10792 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
10793 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
10794
10795 //Ensure that device is in full power as we will touch H/W during vos_Stop
10796 init_completion(&powerContext.completion);
10797 powerContext.magic = POWER_CONTEXT_MAGIC;
10798
10799 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
10800 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
10801
10802 if (eHAL_STATUS_SUCCESS != halStatus)
10803 {
10804 if (eHAL_STATUS_PMC_PENDING == halStatus)
10805 {
10806 /* request was sent -- wait for the response */
10807 lrc = wait_for_completion_interruptible_timeout(
10808 &powerContext.completion,
10809 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
Jeff Johnson295189b2012-06-20 16:38:30 -070010810 if (lrc <= 0)
10811 {
10812 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070010813 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -070010814 }
10815 }
10816 else
10817 {
10818 hddLog(VOS_TRACE_LEVEL_ERROR,
10819 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070010820 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -070010821 /* continue -- need to clean up as much as possible */
10822 }
10823 }
Hanumantha Reddy Pothula81b42b22015-05-12 13:52:00 +053010824 if ((eHAL_STATUS_SUCCESS == halStatus) ||
10825 (eHAL_STATUS_PMC_PENDING == halStatus && lrc > 0))
10826 {
10827 /* This will issue a dump command which will clean up
10828 BTQM queues and unblock MC thread */
10829 vos_fwDumpReq(274, 0, 0, 0, 0, 1);
10830 }
Jeff Johnson295189b2012-06-20 16:38:30 -070010831
Jeff Johnson72a40512013-12-19 10:14:15 -080010832 /* either we never sent a request, we sent a request and received a
10833 response or we sent a request and timed out. if we never sent a
10834 request or if we sent a request and got a response, we want to
10835 clear the magic out of paranoia. if we timed out there is a
10836 race condition such that the callback function could be
10837 executing at the same time we are. of primary concern is if the
10838 callback function had already verified the "magic" but had not
10839 yet set the completion variable when a timeout occurred. we
10840 serialize these activities by invalidating the magic while
10841 holding a shared spinlock which will cause us to block if the
10842 callback is currently executing */
10843 spin_lock(&hdd_context_lock);
10844 powerContext.magic = 0;
10845 spin_unlock(&hdd_context_lock);
10846
Hema Aparna Medicharlaa6cf65e2015-06-01 16:23:28 +053010847 /* If Device is shutdown, no point for SME to wait for responses
10848 from device. Pre Close SME */
10849 if(wcnss_device_is_shutdown())
10850 {
10851 sme_PreClose(pHddCtx->hHal);
10852 }
Yue Ma0d4891e2013-08-06 17:01:45 -070010853 hdd_debugfs_exit(pHddCtx);
10854
Ratheesh S P35ed8b12015-04-27 14:01:07 +053010855#ifdef WLAN_NS_OFFLOAD
Ratheesh S P36dbc932015-08-07 14:28:57 +053010856 hddLog(LOG1, FL("Unregister IPv6 notifier"));
Ratheesh S P35ed8b12015-04-27 14:01:07 +053010857 unregister_inet6addr_notifier(&pHddCtx->ipv6_notifier);
10858#endif
Ratheesh S P36dbc932015-08-07 14:28:57 +053010859 hddLog(LOG1, FL("Unregister IPv4 notifier"));
Ratheesh S P35ed8b12015-04-27 14:01:07 +053010860 unregister_inetaddr_notifier(&pHddCtx->ipv4_notifier);
10861
Jeff Johnson295189b2012-06-20 16:38:30 -070010862 // Unregister the Net Device Notifier
10863 unregister_netdevice_notifier(&hdd_netdev_notifier);
10864
Jeff Johnson295189b2012-06-20 16:38:30 -070010865 hdd_stop_all_adapters( pHddCtx );
10866
Jeff Johnson295189b2012-06-20 16:38:30 -070010867#ifdef WLAN_BTAMP_FEATURE
10868 vosStatus = WLANBAP_Stop(pVosContext);
10869 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
10870 {
10871 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
10872 "%s: Failed to stop BAP",__func__);
10873 }
10874#endif //WLAN_BTAMP_FEATURE
10875
10876 //Stop all the modules
10877 vosStatus = vos_stop( pVosContext );
10878 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
10879 {
10880 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
10881 "%s: Failed to stop VOSS",__func__);
10882 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
Hanumantha Reddy Pothulabd9601a2016-02-12 13:22:27 +053010883 if (isSsrPanicOnFailure())
10884 VOS_BUG(0);
Jeff Johnson295189b2012-06-20 16:38:30 -070010885 }
10886
Jeff Johnson295189b2012-06-20 16:38:30 -070010887 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -070010888 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -070010889
10890 //Close the scheduler before calling vos_close to make sure no thread is
10891 // scheduled after the each module close is called i.e after all the data
10892 // structures are freed.
10893 vosStatus = vos_sched_close( pVosContext );
10894 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
10895 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
10896 "%s: Failed to close VOSS Scheduler",__func__);
10897 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
10898 }
Jeff Johnsone7245742012-09-05 17:12:55 -070010899#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
10900 /* Destroy the wake lock */
Sushant Kaushik83392fa2015-05-05 17:44:40 +053010901 vos_wake_lock_destroy(&pHddCtx->rx_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -070010902#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -080010903 /* Destroy the wake lock */
Sushant Kaushik83392fa2015-05-05 17:44:40 +053010904 vos_wake_lock_destroy(&pHddCtx->sap_wake_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010905
Mihir Shete7a24b5f2013-12-21 12:18:31 +053010906#ifdef CONFIG_ENABLE_LINUX_REG
10907 vosStatus = vos_nv_close();
10908 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
10909 {
10910 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
10911 "%s: Failed to close NV", __func__);
10912 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
10913 }
10914#endif
10915
Jeff Johnson295189b2012-06-20 16:38:30 -070010916 //Close VOSS
10917 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
10918 vos_close(pVosContext);
10919
Jeff Johnson295189b2012-06-20 16:38:30 -070010920 //Close Watchdog
10921 if(pHddCtx->cfg_ini->fIsLogpEnabled)
10922 vos_watchdog_close(pVosContext);
10923
Gopichand Nakkalaa0358482013-06-12 17:05:47 +053010924 //Clean up HDD Nlink Service
10925 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Gopichand Nakkalaa0358482013-06-12 17:05:47 +053010926
Manjeet Singh47ee8472016-04-11 11:57:18 +053010927 hdd_close_tx_queues(pHddCtx);
c_manjeecfd1efb2015-09-25 19:32:34 +053010928 wlan_free_fwr_mem_dump_buffer();
10929 memdump_deinit();
10930
Vinay Krishna Erannad938c422014-03-10 17:14:21 +053010931#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +053010932 if (pHddCtx->cfg_ini->wlanLoggingEnable)
Vinay Krishna Erannad938c422014-03-10 17:14:21 +053010933 {
10934 wlan_logging_sock_deactivate_svc();
10935 }
10936#endif
10937
Vinay Krishna Erannaef30b522014-08-26 17:48:16 +053010938#ifdef WLAN_KD_READY_NOTIFIER
10939 nl_srv_exit(pHddCtx->ptt_pid);
10940#else
10941 nl_srv_exit();
10942#endif /* WLAN_KD_READY_NOTIFIER */
10943
Abhishek Singh00b71972016-01-07 10:51:04 +053010944#ifdef WLAN_FEATURE_RMC
10945 hdd_close_cesium_nl_sock();
10946#endif /* WLAN_FEATURE_RMC */
Vinay Krishna Erannaef30b522014-08-26 17:48:16 +053010947
Jeff Johnson295189b2012-06-20 16:38:30 -070010948 hdd_close_all_adapters( pHddCtx );
10949
Padma, Santhosh Kumar9cd38332015-11-17 12:18:10 +053010950 vos_flush_delayed_work(&pHddCtx->spoof_mac_addr_work);
Kapil Gupta137ef892016-12-13 19:38:00 +053010951 vos_flush_work(&pHddCtx->sap_start_work);
Padma, Santhosh Kumar9cd38332015-11-17 12:18:10 +053010952
Hanumantha Reddy Pothula97f9bc92015-08-10 17:21:20 +053010953free_hdd_ctx:
Jeff Johnson295189b2012-06-20 16:38:30 -070010954 /* free the power on lock from platform driver */
10955 if (free_riva_power_on_lock("wlan"))
10956 {
10957 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
10958 __func__);
10959 }
10960
c_hpothu78c7b602014-05-17 17:35:49 +053010961 //Free up dynamically allocated members inside HDD Adapter
10962 if (pHddCtx->cfg_ini)
10963 {
10964 kfree(pHddCtx->cfg_ini);
10965 pHddCtx->cfg_ini= NULL;
10966 }
10967
Hanumantha Reddy Pothula6fe221c2016-01-28 15:01:09 +053010968 /* FTM/MONITOR mode, WIPHY did not registered
Leo Changf04ddad2013-09-18 13:46:38 -070010969 If un-register here, system crash will happen */
Hanumantha Reddy Pothula6fe221c2016-01-28 15:01:09 +053010970 if (!(VOS_FTM_MODE == hdd_get_conparam() ||
10971 VOS_MONITOR_MODE == hdd_get_conparam()))
Leo Changf04ddad2013-09-18 13:46:38 -070010972 {
10973 wiphy_unregister(wiphy) ;
Agrawal Ashish33ec71e2015-11-26 20:20:58 +053010974 hdd_wlan_free_wiphy_channels(wiphy);
Leo Changf04ddad2013-09-18 13:46:38 -070010975 }
Jeff Johnson295189b2012-06-20 16:38:30 -070010976 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -070010977 if (hdd_is_ssr_required())
10978 {
10979 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -070010980 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -070010981 msleep(5000);
10982 }
10983 hdd_set_ssr_required (VOS_FALSE);
10984}
10985
10986
10987/**---------------------------------------------------------------------------
10988
10989 \brief hdd_update_config_from_nv() - Function to update the contents of
10990 the running configuration with parameters taken from NV storage
10991
10992 \param - pHddCtx - Pointer to the HDD global context
10993
10994 \return - VOS_STATUS_SUCCESS if successful
10995
10996 --------------------------------------------------------------------------*/
10997static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
10998{
Jeff Johnson295189b2012-06-20 16:38:30 -070010999 v_BOOL_t itemIsValid = VOS_FALSE;
11000 VOS_STATUS status;
11001 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
11002 v_U8_t macLoop;
11003
11004 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
11005 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
11006 if(status != VOS_STATUS_SUCCESS)
11007 {
Arif Hussain6d2a3322013-11-17 19:50:10 -080011008 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed");
Jeff Johnson295189b2012-06-20 16:38:30 -070011009 return VOS_STATUS_E_FAILURE;
11010 }
11011
11012 if (itemIsValid == VOS_TRUE)
11013 {
Arif Hussain6d2a3322013-11-17 19:50:10 -080011014 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV");
Jeff Johnson295189b2012-06-20 16:38:30 -070011015 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
11016 VOS_MAX_CONCURRENCY_PERSONA);
11017 if(status != VOS_STATUS_SUCCESS)
11018 {
11019 /* Get MAC from NV fail, not update CFG info
11020 * INI MAC value will be used for MAC setting */
Arif Hussain6d2a3322013-11-17 19:50:10 -080011021 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed");
Jeff Johnson295189b2012-06-20 16:38:30 -070011022 return VOS_STATUS_E_FAILURE;
11023 }
11024
11025 /* If first MAC is not valid, treat all others are not valid
11026 * Then all MACs will be got from ini file */
11027 if(vos_is_macaddr_zero(&macFromNV[0]))
11028 {
11029 /* MAC address in NV file is not configured yet */
11030 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
11031 return VOS_STATUS_E_INVAL;
11032 }
11033
11034 /* Get MAC address from NV, update CFG info */
11035 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
11036 {
11037 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
11038 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +053011039 hddLog(VOS_TRACE_LEVEL_ERROR,"not valid MAC from NV for %d", macLoop);
Jeff Johnson295189b2012-06-20 16:38:30 -070011040 /* This MAC is not valid, skip it
11041 * This MAC will be got from ini file */
11042 }
11043 else
11044 {
11045 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
11046 (v_U8_t *)&macFromNV[macLoop].bytes[0],
11047 VOS_MAC_ADDR_SIZE);
11048 }
11049 }
11050 }
11051 else
11052 {
11053 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
11054 return VOS_STATUS_E_FAILURE;
11055 }
Jeff Johnson295189b2012-06-20 16:38:30 -070011056
Jeff Johnson295189b2012-06-20 16:38:30 -070011057
11058 return VOS_STATUS_SUCCESS;
11059}
11060
11061/**---------------------------------------------------------------------------
11062
11063 \brief hdd_post_voss_start_config() - HDD post voss start config helper
11064
11065 \param - pAdapter - Pointer to the HDD
11066
11067 \return - None
11068
11069 --------------------------------------------------------------------------*/
11070VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
11071{
11072 eHalStatus halStatus;
11073 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +053011074 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -070011075
Jeff Johnson295189b2012-06-20 16:38:30 -070011076
11077 // Send ready indication to the HDD. This will kick off the MAC
11078 // into a 'running' state and should kick off an initial scan.
11079 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
11080 if ( !HAL_STATUS_SUCCESS( halStatus ) )
11081 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +053011082 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -070011083 "code %08d [x%08x]",__func__, halStatus, halStatus );
11084 return VOS_STATUS_E_FAILURE;
11085 }
11086
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +053011087 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -070011088 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
11089 // And RIVA will crash
11090 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
11091 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +053011092 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
11093 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
11094
11095
Jeff Johnson295189b2012-06-20 16:38:30 -070011096 return VOS_STATUS_SUCCESS;
11097}
11098
Jeff Johnson295189b2012-06-20 16:38:30 -070011099/* wake lock APIs for HDD */
Sushant Kaushik83392fa2015-05-05 17:44:40 +053011100void hdd_prevent_suspend(uint32_t reason)
Jeff Johnson295189b2012-06-20 16:38:30 -070011101{
Sushant Kaushik83392fa2015-05-05 17:44:40 +053011102
11103 vos_wake_lock_acquire(&wlan_wake_lock, reason);
11104
Jeff Johnson295189b2012-06-20 16:38:30 -070011105}
11106
Sushant Kaushik83392fa2015-05-05 17:44:40 +053011107void hdd_allow_suspend(uint32_t reason)
Jeff Johnson295189b2012-06-20 16:38:30 -070011108{
Sushant Kaushik83392fa2015-05-05 17:44:40 +053011109
11110 vos_wake_lock_release(&wlan_wake_lock, reason);
11111
Jeff Johnson295189b2012-06-20 16:38:30 -070011112}
11113
Sushant Kaushik83392fa2015-05-05 17:44:40 +053011114void hdd_prevent_suspend_timeout(v_U32_t timeout, uint32_t reason)
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -070011115{
Sushant Kaushik83392fa2015-05-05 17:44:40 +053011116
11117 vos_wake_lock_timeout_release(&wlan_wake_lock, timeout,
11118 reason);
11119
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -070011120}
11121
Jeff Johnson295189b2012-06-20 16:38:30 -070011122/**---------------------------------------------------------------------------
11123
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070011124 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
11125 information between Host and Riva
11126
11127 This function gets reported version of FW
11128 It also finds the version of Riva headers used to compile the host
11129 It compares the above two and prints a warning if they are different
11130 It gets the SW and HW version string
11131 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
11132 indicating the features they support through a bitmap
11133
11134 \param - pHddCtx - Pointer to HDD context
11135
11136 \return - void
11137
11138 --------------------------------------------------------------------------*/
11139
11140void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
11141{
11142
11143 tSirVersionType versionCompiled;
11144 tSirVersionType versionReported;
11145 tSirVersionString versionString;
11146 tANI_U8 fwFeatCapsMsgSupported = 0;
11147 VOS_STATUS vstatus;
11148
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -080011149 memset(&versionCompiled, 0, sizeof(versionCompiled));
11150 memset(&versionReported, 0, sizeof(versionReported));
11151
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070011152 /* retrieve and display WCNSS version information */
11153 do {
11154
11155 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
11156 &versionCompiled);
11157 if (!VOS_IS_STATUS_SUCCESS(vstatus))
11158 {
11159 hddLog(VOS_TRACE_LEVEL_FATAL,
11160 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070011161 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070011162 break;
11163 }
11164
11165 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
11166 &versionReported);
11167 if (!VOS_IS_STATUS_SUCCESS(vstatus))
11168 {
11169 hddLog(VOS_TRACE_LEVEL_FATAL,
11170 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070011171 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070011172 break;
11173 }
11174
11175 if ((versionCompiled.major != versionReported.major) ||
11176 (versionCompiled.minor != versionReported.minor) ||
11177 (versionCompiled.version != versionReported.version) ||
11178 (versionCompiled.revision != versionReported.revision))
11179 {
11180 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
11181 "Host expected %u.%u.%u.%u\n",
11182 WLAN_MODULE_NAME,
11183 (int)versionReported.major,
11184 (int)versionReported.minor,
11185 (int)versionReported.version,
11186 (int)versionReported.revision,
11187 (int)versionCompiled.major,
11188 (int)versionCompiled.minor,
11189 (int)versionCompiled.version,
11190 (int)versionCompiled.revision);
11191 }
11192 else
11193 {
11194 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
11195 WLAN_MODULE_NAME,
11196 (int)versionReported.major,
11197 (int)versionReported.minor,
11198 (int)versionReported.version,
11199 (int)versionReported.revision);
11200 }
11201
11202 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
11203 versionString,
11204 sizeof(versionString));
11205 if (!VOS_IS_STATUS_SUCCESS(vstatus))
11206 {
11207 hddLog(VOS_TRACE_LEVEL_FATAL,
11208 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070011209 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070011210 break;
11211 }
11212
11213 pr_info("%s: WCNSS software version %s\n",
11214 WLAN_MODULE_NAME, versionString);
Sushant Kaushik084f6592015-09-10 13:11:56 +053011215 vos_mem_copy(pHddCtx->fw_Version, versionString, sizeof(versionString));
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070011216
11217 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
11218 versionString,
11219 sizeof(versionString));
11220 if (!VOS_IS_STATUS_SUCCESS(vstatus))
11221 {
11222 hddLog(VOS_TRACE_LEVEL_FATAL,
11223 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070011224 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070011225 break;
11226 }
11227
11228 pr_info("%s: WCNSS hardware version %s\n",
11229 WLAN_MODULE_NAME, versionString);
11230
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -070011231 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
11232 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070011233 send the message only if it the riva is 1.1
11234 minor numbers for different riva branches:
11235 0 -> (1.0)Mainline Build
11236 1 -> (1.1)Mainline Build
11237 2->(1.04) Stability Build
11238 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -070011239 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070011240 ((versionReported.minor>=1) && (versionReported.version>=1)))
11241 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
11242 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -070011243
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070011244 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -080011245 {
11246#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
11247 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
11248 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
11249#endif
Ravi Joshid2ca7c42013-07-23 08:37:49 -070011250 /* Indicate if IBSS heartbeat monitoring needs to be offloaded */
11251 if (!pHddCtx->cfg_ini->enableIbssHeartBeatOffload)
11252 {
11253 sme_disableFeatureCapablity(IBSS_HEARTBEAT_OFFLOAD);
11254 }
11255
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070011256 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -080011257 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070011258
11259 } while (0);
11260
11261}
Neelansh Mittaledafed22014-09-04 18:54:39 +053011262void wlan_hdd_send_svc_nlink_msg(int type, void *data, int len)
11263{
11264 struct sk_buff *skb;
11265 struct nlmsghdr *nlh;
11266 tAniMsgHdr *ani_hdr;
Hanumantha Reddy Pothulacf2c7ea2015-04-27 14:50:47 +053011267 int flags = GFP_KERNEL;
Bhargav shah23c94942015-10-13 12:48:35 +053011268 void *nl_data = NULL;
Neelansh Mittaledafed22014-09-04 18:54:39 +053011269
Hanumantha Reddy Pothulacf2c7ea2015-04-27 14:50:47 +053011270 if (in_interrupt() || irqs_disabled() || in_atomic())
11271 flags = GFP_ATOMIC;
11272
11273 skb = alloc_skb(NLMSG_SPACE(WLAN_NL_MAX_PAYLOAD), flags);
Neelansh Mittaledafed22014-09-04 18:54:39 +053011274
11275 if(skb == NULL) {
11276 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
11277 "%s: alloc_skb failed", __func__);
11278 return;
11279 }
11280
11281 nlh = (struct nlmsghdr *)skb->data;
11282 nlh->nlmsg_pid = 0; /* from kernel */
11283 nlh->nlmsg_flags = 0;
11284 nlh->nlmsg_seq = 0;
11285 nlh->nlmsg_type = WLAN_NL_MSG_SVC;
11286
11287 ani_hdr = NLMSG_DATA(nlh);
11288 ani_hdr->type = type;
11289
11290 switch(type) {
11291 case WLAN_SVC_SAP_RESTART_IND:
11292 ani_hdr->length = 0;
11293 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr)));
11294 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr)));
11295 break;
Bhargav Shahd0715912015-10-01 18:17:37 +053011296 case WLAN_SVC_WLAN_TP_IND:
11297 ani_hdr->length = len;
11298 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr)
11299 + len));
11300 nl_data = (char *)ani_hdr + sizeof(tAniMsgHdr);
11301 memcpy(nl_data, data, len);
11302 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + len));
11303 break;
Bhargav shah23c94942015-10-13 12:48:35 +053011304 case WLAN_MSG_RPS_ENABLE_IND:
11305 ani_hdr->length = len;
11306 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + len));
11307 nl_data = (char *)ani_hdr + sizeof(tAniMsgHdr);
11308 memcpy(nl_data, data, len);
11309 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + len));
11310 break;
Neelansh Mittaledafed22014-09-04 18:54:39 +053011311 default:
11312 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
11313 "Attempt to send unknown nlink message %d", type);
11314 kfree_skb(skb);
11315 return;
11316 }
11317
11318 nl_srv_bcast(skb);
11319
11320 return;
11321}
11322
Bhargav Shahd0715912015-10-01 18:17:37 +053011323/**
11324 * hdd_request_tcp_delack() - Find the Delack value based on RX packet
11325 * @pHddCtx: Valid Global HDD context pointer
11326 * @rx_packets: Number of RX packet in perticular time
11327 *
11328 * Based on the RX packet this function calculate next value of tcp delack.
11329 * This function compare rx packet value to high and low threshold limit.
11330 *
11331 * Return: void
11332 */
11333void hdd_request_tcp_delack(hdd_context_t *pHddCtx, uint64_t rx_packets)
11334{
11335 /* average of rx_packets and prev_rx is taken so that
11336 bus width doesnot fluctuate much */
11337 uint64_t temp_rx = (rx_packets + pHddCtx->prev_rx)/2;
11338 TP_IND_TYPE next_rx_level = pHddCtx->cur_rx_level;
Neelansh Mittaledafed22014-09-04 18:54:39 +053011339
Bhargav Shahd0715912015-10-01 18:17:37 +053011340 pHddCtx->prev_rx = rx_packets;
11341 if (temp_rx > pHddCtx->cfg_ini->tcpDelAckThresholdHigh)
11342 next_rx_level = TP_IND_HIGH;
11343 else if (temp_rx <= pHddCtx->cfg_ini->tcpDelAckThresholdLow)
11344 next_rx_level = TP_IND_LOW;
11345
11346 hdd_set_delack_value(pHddCtx, next_rx_level);
11347}
11348
11349#define HDD_BW_GET_DIFF(x, y) ((x) >= (y) ? (x) - (y) : (ULONG_MAX - (y) + (x)))
11350
11351/**
11352 * hdd_tcp_delack_compute_function() - get link status
11353 * @priv: Valid Global HDD context pointer
11354 *
11355 * This function find number of RX packet during timer life span.
11356 * It request tcp delack with number of RX packet and re-configure delack timer
11357 * for tcpDelAckComputeInterval timer interval.
11358 *
11359 * Return: void
11360 */
11361void hdd_tcp_delack_compute_function(void *priv)
11362{
11363 hdd_context_t *pHddCtx = (hdd_context_t *)priv;
11364 hdd_adapter_t *pAdapter = NULL;
11365 v_U32_t rx_packets = 0;
11366 hdd_adapter_list_node_t *pAdapterNode = NULL;
11367 VOS_STATUS status = 0;
11368
11369 for (status = hdd_get_front_adapter(pHddCtx, &pAdapterNode);
11370 NULL != pAdapterNode && VOS_STATUS_SUCCESS == status;
11371 status = hdd_get_next_adapter(pHddCtx, pAdapterNode, &pAdapterNode)) {
11372 if ((pAdapter = pAdapterNode->pAdapter) == NULL)
11373 continue;
11374
11375 rx_packets += HDD_BW_GET_DIFF(pAdapter->stats.rx_packets,
11376 pAdapter->prev_rx_packets);
11377 pAdapter->prev_rx_packets = pAdapter->stats.rx_packets;
11378 }
11379
11380 hdd_request_tcp_delack(pHddCtx, rx_packets);
11381
11382 vos_timer_start(&pHddCtx->delack_timer,
11383 pHddCtx->cfg_ini->tcpDelAckComputeInterval);
11384}
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070011385
11386/**---------------------------------------------------------------------------
11387
Gopichand Nakkalafce506f2013-07-03 23:55:16 +053011388 \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
11389
11390 \param - pHddCtx - Pointer to the hdd context
11391
11392 \return - true if hardware supports 5GHz
11393
11394 --------------------------------------------------------------------------*/
Vinay Krishna Erannafacf5e22014-02-24 13:16:25 +053011395boolean hdd_is_5g_supported(hdd_context_t * pHddCtx)
Gopichand Nakkalafce506f2013-07-03 23:55:16 +053011396{
11397 /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
11398 * then hardware support 5Ghz.
11399 */
11400 if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode())
11401 {
Ratheesh S P36dbc932015-08-07 14:28:57 +053011402 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware supports 5Ghz", __func__);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +053011403 return true;
11404 }
11405 else
11406 {
Ratheesh S P36dbc932015-08-07 14:28:57 +053011407 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware doesn't supports 5Ghz",
Gopichand Nakkalafce506f2013-07-03 23:55:16 +053011408 __func__);
11409 return false;
11410 }
11411}
11412
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053011413/**---------------------------------------------------------------------------
11414
11415 \brief hdd_generate_iface_mac_addr_auto() - HDD Mac Interface Auto
11416 generate function
11417
11418 This is generate the random mac address for WLAN interface
11419
11420 \param - pHddCtx - Pointer to HDD context
11421 idx - Start interface index to get auto
11422 generated mac addr.
11423 mac_addr - Mac address
11424
11425 \return - 0 for success, < 0 for failure
11426
11427 --------------------------------------------------------------------------*/
11428
11429static int hdd_generate_iface_mac_addr_auto(hdd_context_t *pHddCtx,
11430 int idx, v_MACADDR_t mac_addr)
11431{
11432 int i;
11433 unsigned int serialno;
11434 serialno = wcnss_get_serial_number();
11435
11436 if (0 != serialno)
11437 {
11438 /* MAC address has 3 bytes of OUI so we have a maximum of 3
11439 bytes of the serial number that can be used to generate
11440 the other 3 bytes of the MAC address. Mask off all but
11441 the lower 3 bytes (this will also make sure we don't
11442 overflow in the next step) */
11443 serialno &= 0x00FFFFFF;
11444
11445 /* we need a unique address for each session */
11446 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
11447
11448 /* autogen other Mac addresses */
11449 for (i = idx; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
11450 {
11451 /* start with the entire default address */
11452 pHddCtx->cfg_ini->intfMacAddr[i] = mac_addr;
11453 /* then replace the lower 3 bytes */
11454 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
11455 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
11456 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
11457
11458 serialno++;
11459 hddLog(VOS_TRACE_LEVEL_ERROR,
11460 "%s: Derived Mac Addr: "
11461 MAC_ADDRESS_STR, __func__,
11462 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[i].bytes));
11463 }
11464
11465 }
11466 else
11467 {
11468 hddLog(LOGE, FL("Failed to Get Serial NO"));
11469 return -1;
11470 }
11471 return 0;
11472}
Gopichand Nakkalafce506f2013-07-03 23:55:16 +053011473
Katya Nigame7b69a82015-04-28 15:24:06 +053011474int wlan_hdd_mon_open(hdd_context_t *pHddCtx)
11475{
11476 VOS_STATUS status;
11477 v_CONTEXT_t pVosContext= NULL;
11478 hdd_adapter_t *pAdapter= NULL;
11479
11480 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
11481
11482 if (NULL == pVosContext)
11483 {
11484 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
11485 "%s: Trying to open VOSS without a PreOpen", __func__);
11486 VOS_ASSERT(0);
11487 return VOS_STATUS_E_FAILURE;
11488 }
11489
11490 status = vos_nv_open();
11491 if (!VOS_IS_STATUS_SUCCESS(status))
11492 {
11493 /* NV module cannot be initialized */
11494 hddLog( VOS_TRACE_LEVEL_FATAL,
11495 "%s: vos_nv_open failed", __func__);
11496 return VOS_STATUS_E_FAILURE;
11497 }
11498
11499 status = vos_init_wiphy_from_nv_bin();
11500 if (!VOS_IS_STATUS_SUCCESS(status))
11501 {
11502 /* NV module cannot be initialized */
11503 hddLog( VOS_TRACE_LEVEL_FATAL,
11504 "%s: vos_init_wiphy failed", __func__);
11505 goto err_vos_nv_close;
11506 }
11507
11508 status = vos_open( &pVosContext, pHddCtx->parent_dev);
11509 if ( !VOS_IS_STATUS_SUCCESS( status ))
11510 {
11511 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
11512 goto err_vos_nv_close;
11513 }
11514
11515 status = vos_mon_start( pVosContext );
11516 if ( !VOS_IS_STATUS_SUCCESS( status ) )
11517 {
11518 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
11519 goto err_vosclose;
11520 }
11521
11522 WLANTL_SetMonRxCbk( pVosContext, hdd_rx_packet_monitor_cbk );
11523 WDA_featureCapsExchange(pVosContext);
11524 wcnss_wlan_set_drvdata(pHddCtx->parent_dev, pHddCtx);
11525
11526 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_MONITOR, "wlan%d",
11527 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
11528 if( pAdapter == NULL )
11529 {
11530 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
11531 goto err_close_adapter;
11532 }
11533
11534 //Initialize the nlink service
11535 if(nl_srv_init() != 0)
11536 {
11537 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
11538 goto err_close_adapter;
11539 }
11540 return VOS_STATUS_SUCCESS;
11541
11542err_close_adapter:
11543 hdd_close_all_adapters( pHddCtx );
11544 vos_mon_stop( pVosContext );
11545err_vosclose:
11546 status = vos_sched_close( pVosContext );
11547 if (!VOS_IS_STATUS_SUCCESS(status)) {
11548 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
11549 "%s: Failed to close VOSS Scheduler", __func__);
11550 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
11551 }
11552 vos_close(pVosContext );
11553
11554err_vos_nv_close:
11555 vos_nv_close();
11556
11557return status;
11558}
Gopichand Nakkalafce506f2013-07-03 23:55:16 +053011559/**---------------------------------------------------------------------------
11560
Mihir Shetefc7ff5b2014-01-27 11:30:05 +053011561 \brief hdd_11d_scan_done - callback to be executed when 11d scan is
11562 completed to flush out the scan results
11563
11564 11d scan is done during driver load and is a passive scan on all
11565 channels supported by the device, 11d scans may find some APs on
11566 frequencies which are forbidden to be used in the regulatory domain
11567 the device is operating in. If these APs are notified to the supplicant
11568 it may try to connect to these APs, thus flush out all the scan results
11569 which are present in SME after 11d scan is done.
11570
11571 \return - eHalStatus
11572
11573 --------------------------------------------------------------------------*/
11574static eHalStatus hdd_11d_scan_done(tHalHandle halHandle, void *pContext,
11575 tANI_U32 scanId, eCsrScanStatus status)
11576{
11577 ENTER();
11578
11579 sme_ScanFlushResult(halHandle, 0);
11580
11581 EXIT();
11582
11583 return eHAL_STATUS_SUCCESS;
11584}
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011585/**---------------------------------------------------------------------------
11586
11587 \brief hdd_init_frame_logging_done - callback to be executed when mgmt frame
11588 logging is completed successfully.
11589
11590 \return - None
11591
11592 --------------------------------------------------------------------------*/
c_manjeecfd1efb2015-09-25 19:32:34 +053011593void hdd_init_frame_logging_done(void *fwlogInitCbContext, tAniLoggingInitRsp *pRsp)
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011594{
Siddharth Bhald1be97f2015-05-27 22:39:59 +053011595 hdd_context_t* pHddCtx = (hdd_context_t*)fwlogInitCbContext;
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011596
11597 if (NULL == pHddCtx)
11598 {
11599 hddLog(VOS_TRACE_LEVEL_ERROR,
11600 "%s: HDD context is NULL",__func__);
11601 return;
11602 }
11603
c_manjeecfd1efb2015-09-25 19:32:34 +053011604 if ((pRsp->status == VOS_STATUS_SUCCESS) &&
Mahesh A Saptasagarfabb1a02015-06-29 12:17:04 +053011605 (TRUE == pHddCtx->cfg_ini->enableMgmtLogging))
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011606 {
11607 hddLog(VOS_TRACE_LEVEL_INFO, FL("Mgmt Frame Logging init successful"));
11608 pHddCtx->mgmt_frame_logging = TRUE;
11609 }
11610 else
11611 {
11612 hddLog(VOS_TRACE_LEVEL_INFO, FL("Mgmt Frame Logging init not success"));
11613 pHddCtx->mgmt_frame_logging = FALSE;
c_manjeecfd1efb2015-09-25 19:32:34 +053011614 return;
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011615 }
11616
c_manjeecfd1efb2015-09-25 19:32:34 +053011617 /*Check feature supported by FW*/
11618 if(TRUE == sme_IsFeatureSupportedByFW(MEMORY_DUMP_SUPPORTED))
11619 {
11620 //Store fwr mem dump size given by firmware.
11621 wlan_store_fwr_mem_dump_size(pRsp->fw_mem_dump_max_size);
11622 }
11623 else
11624 {
11625 wlan_store_fwr_mem_dump_size(0);
11626 }
11627
11628
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011629}
11630/**---------------------------------------------------------------------------
11631
11632 \brief hdd_init_frame_logging - function to initialize frame logging.
11633 Currently only Mgmt Frames are logged in both TX
11634 and Rx direction and are sent to userspace
11635 application using logger thread when queried.
11636
11637 \return - None
11638
11639 --------------------------------------------------------------------------*/
Siddharth Bhald1be97f2015-05-27 22:39:59 +053011640void hdd_init_frame_logging(hdd_context_t* pHddCtx)
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011641{
11642 eHalStatus halStatus = eHAL_STATUS_FAILURE;
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053011643 tSirFWLoggingInitParam wlanFWLoggingInitParam = {0};
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011644
Siddharth Bhald1be97f2015-05-27 22:39:59 +053011645 if (TRUE != sme_IsFeatureSupportedByFW(MGMT_FRAME_LOGGING) &&
11646 TRUE != sme_IsFeatureSupportedByFW(LOGGING_ENHANCEMENT))
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011647 {
11648 hddLog(VOS_TRACE_LEVEL_INFO, FL("MGMT_FRAME_LOGGING not supp by FW"));
11649 return;
11650 }
11651
c_manjeecfd1efb2015-09-25 19:32:34 +053011652 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Configuring %s %s %s %s Logging",__func__,
Siddharth Bhald1be97f2015-05-27 22:39:59 +053011653 pHddCtx->cfg_ini->enableFWLogging?"FW Log,":"",
11654 pHddCtx->cfg_ini->enableContFWLogging ? "Cont FW log,":"",
c_manjeecfd1efb2015-09-25 19:32:34 +053011655 pHddCtx->cfg_ini->enableMgmtLogging ? "Mgmt Pkt Log":"",
11656 pHddCtx->cfg_ini->enableFwrMemDump ? "Fw Mem dump":"");
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011657
Siddharth Bhald1be97f2015-05-27 22:39:59 +053011658 if (pHddCtx->cfg_ini->enableFWLogging ||
11659 pHddCtx->cfg_ini->enableContFWLogging)
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011660 {
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053011661 wlanFWLoggingInitParam.enableFlag |= WLAN_QXDM_LOG_EN;
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011662 }
11663
Sushant Kaushik46804902015-07-08 14:46:03 +053011664 if (pHddCtx->cfg_ini->enableMgmtLogging)
11665 {
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053011666 wlanFWLoggingInitParam.enableFlag |= WLAN_FRAME_LOG_EN;
Sushant Kaushik46804902015-07-08 14:46:03 +053011667 }
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011668 if (pHddCtx->cfg_ini->enableBMUHWtracing)
11669 {
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053011670 wlanFWLoggingInitParam.enableFlag |= WLAN_BMUHW_TRACE_LOG_EN;
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011671 }
c_manjeecfd1efb2015-09-25 19:32:34 +053011672 if(pHddCtx->cfg_ini->enableFwrMemDump &&
11673 (TRUE == sme_IsFeatureSupportedByFW(MEMORY_DUMP_SUPPORTED)))
11674 {
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053011675 wlanFWLoggingInitParam.enableFlag |= WLAN_FW_MEM_DUMP_EN;
c_manjeecfd1efb2015-09-25 19:32:34 +053011676 }
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053011677 if( wlanFWLoggingInitParam.enableFlag == 0 )
c_manjeecfd1efb2015-09-25 19:32:34 +053011678 {
11679 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Logging not enabled", __func__);
11680 return;
11681 }
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053011682 wlanFWLoggingInitParam.frameType = WLAN_FRAME_LOGGING_FRAMETYPE_MGMT;
11683 wlanFWLoggingInitParam.frameSize = WLAN_MGMT_LOGGING_FRAMESIZE_128BYTES;
11684 wlanFWLoggingInitParam.bufferMode = WLAN_FRAME_LOGGING_BUFFERMODE_CIRCULAR;
11685 wlanFWLoggingInitParam.continuousFrameLogging =
Siddharth Bhald1be97f2015-05-27 22:39:59 +053011686 pHddCtx->cfg_ini->enableContFWLogging;
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011687
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053011688 wlanFWLoggingInitParam.enableFlag &= ~WLAN_DPU_TXP_LOG_EN;
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011689
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053011690 wlanFWLoggingInitParam.minLogBufferSize =
Siddharth Bhald1be97f2015-05-27 22:39:59 +053011691 pHddCtx->cfg_ini->minLoggingBufferSize;
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053011692 wlanFWLoggingInitParam.maxLogBufferSize =
Siddharth Bhald1be97f2015-05-27 22:39:59 +053011693 pHddCtx->cfg_ini->maxLoggingBufferSize;
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053011694 wlanFWLoggingInitParam.fwlogInitCallback = hdd_init_frame_logging_done;
11695 wlanFWLoggingInitParam.fwlogInitCbContext= pHddCtx;
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011696
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053011697 halStatus = sme_InitMgmtFrameLogging(pHddCtx->hHal, &wlanFWLoggingInitParam);
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011698
11699 if (eHAL_STATUS_SUCCESS != halStatus)
11700 {
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053011701 hddLog(LOGE, FL("sme_InitMgmtFrameLogging failed, returned %d"),
11702 halStatus);
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011703 }
11704
11705 return;
11706}
Mihir Shetefc7ff5b2014-01-27 11:30:05 +053011707
Bhargav shah23c94942015-10-13 12:48:35 +053011708static void hdd_dp_util_send_rps_ind(hdd_context_t *hdd_ctxt)
11709{
11710 hdd_adapter_t *adapter;
11711 hdd_adapter_list_node_t *adapter_node, *next;
11712 VOS_STATUS status = VOS_STATUS_SUCCESS;
11713 struct wlan_rps_data rps_data;
11714 int count;
11715
11716 if(!hdd_ctxt->cfg_ini->rps_mask)
11717 {
11718 return;
11719 }
11720
11721 for (count=0; count < WLAN_SVC_IFACE_NUM_QUEUES; count++)
11722 {
11723 rps_data.cpu_map[count] = hdd_ctxt->cfg_ini->rps_mask;
11724 }
11725
11726 rps_data.num_queues = WLAN_SVC_IFACE_NUM_QUEUES;
11727
11728 hddLog(LOG1, FL("0x%x 0x%x 0x%x 0x%x 0x%x 0x%x"),
11729 rps_data.cpu_map[0], rps_data.cpu_map[1],rps_data.cpu_map[2],
11730 rps_data.cpu_map[3], rps_data.cpu_map[4], rps_data.cpu_map[5]);
11731
11732 status = hdd_get_front_adapter (hdd_ctxt, &adapter_node);
11733
11734 while (NULL != adapter_node && VOS_STATUS_SUCCESS == status)
11735 {
11736 adapter = adapter_node->pAdapter;
11737 if (NULL != adapter) {
11738 strlcpy(rps_data.ifname, adapter->dev->name,
11739 sizeof(rps_data.ifname));
11740 wlan_hdd_send_svc_nlink_msg(WLAN_MSG_RPS_ENABLE_IND,
11741 (void *)&rps_data,sizeof(rps_data));
11742 }
11743 status = hdd_get_next_adapter (hdd_ctxt, adapter_node, &next);
11744 adapter_node = next;
11745 }
11746}
11747
Masti, Narayanraddi26378462016-01-05 18:20:28 +053011748void wlan_hdd_schedule_defer_scan(struct work_struct *work)
11749{
11750 scan_context_t *scan_ctx =
11751 container_of(work, scan_context_t, scan_work.work);
11752
11753 if (NULL == scan_ctx)
11754 {
11755 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
11756 FL("scan_ctx is NULL"));
11757 return;
11758 }
11759
11760 if (unlikely(TDLS_CTX_MAGIC != scan_ctx->magic))
11761 return;
11762
11763 scan_ctx->attempt++;
11764
11765 wlan_hdd_cfg80211_scan(scan_ctx->wiphy,
11766#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
11767 scan_ctx->dev,
11768#endif
11769 scan_ctx->scan_request);
11770}
11771
11772int wlan_hdd_copy_defer_scan_context(hdd_context_t *pHddCtx,
11773 struct wiphy *wiphy,
11774#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
11775 struct net_device *dev,
11776#endif
11777 struct cfg80211_scan_request *request)
11778{
11779 scan_context_t *scan_ctx;
11780
11781 ENTER();
11782 if (0 != (wlan_hdd_validate_context(pHddCtx)))
11783 {
11784 return -1;
11785 }
11786
11787 scan_ctx = &pHddCtx->scan_ctxt;
11788
11789 scan_ctx->wiphy = wiphy;
11790#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
11791 scan_ctx->dev = dev;
11792#endif
11793
11794 scan_ctx->scan_request = request;
11795
11796 EXIT();
11797 return 0;
11798}
11799
11800void wlan_hdd_defer_scan_init_work(hdd_context_t *pHddCtx,
11801 struct wiphy *wiphy,
11802#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
11803 struct net_device *dev,
11804#endif
11805 struct cfg80211_scan_request *request,
11806 unsigned long delay)
11807{
11808 if (TDLS_CTX_MAGIC != pHddCtx->scan_ctxt.magic)
11809 {
11810#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
11811 wlan_hdd_copy_defer_scan_context(pHddCtx, wiphy, dev, request);
11812#else
11813 wlan_hdd_copy_defer_scan_context(pHddCtx, wiphy, request);
11814#endif
11815 pHddCtx->scan_ctxt.attempt = 0;
11816 pHddCtx->scan_ctxt.magic = TDLS_CTX_MAGIC;
11817 }
11818 schedule_delayed_work(&pHddCtx->scan_ctxt.scan_work, delay);
11819}
11820
11821void wlan_hdd_init_deinit_defer_scan_context(scan_context_t *scan_ctx)
11822{
11823 scan_ctx->magic = 0;
11824 scan_ctx->attempt = 0;
11825 scan_ctx->reject = 0;
11826 scan_ctx->scan_request = NULL;
11827
11828 return;
11829}
11830
Mihir Shetefc7ff5b2014-01-27 11:30:05 +053011831/**---------------------------------------------------------------------------
11832
Jeff Johnson295189b2012-06-20 16:38:30 -070011833 \brief hdd_wlan_startup() - HDD init function
11834
11835 This is the driver startup code executed once a WLAN device has been detected
11836
11837 \param - dev - Pointer to the underlying device
11838
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -080011839 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -070011840
11841 --------------------------------------------------------------------------*/
11842
11843int hdd_wlan_startup(struct device *dev )
11844{
11845 VOS_STATUS status;
11846 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -070011847 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -070011848 hdd_context_t *pHddCtx = NULL;
11849 v_CONTEXT_t pVosContext= NULL;
11850#ifdef WLAN_BTAMP_FEATURE
11851 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
11852 WLANBAP_ConfigType btAmpConfig;
11853 hdd_config_t *pConfig;
11854#endif
11855 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -070011856 struct wiphy *wiphy;
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053011857 v_MACADDR_t mac_addr;
Jeff Johnson295189b2012-06-20 16:38:30 -070011858
11859 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -070011860 /*
11861 * cfg80211: wiphy allocation
11862 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +053011863 wiphy = wlan_hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t)) ;
Jeff Johnson295189b2012-06-20 16:38:30 -070011864
11865 if(wiphy == NULL)
11866 {
11867 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -080011868 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -070011869 }
Jeff Johnson295189b2012-06-20 16:38:30 -070011870 pHddCtx = wiphy_priv(wiphy);
11871
Jeff Johnson295189b2012-06-20 16:38:30 -070011872 //Initialize the adapter context to zeros.
11873 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
11874
Jeff Johnson295189b2012-06-20 16:38:30 -070011875 pHddCtx->wiphy = wiphy;
Sushant Kaushik83392fa2015-05-05 17:44:40 +053011876 hdd_prevent_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_INIT);
Mihir Shete18156292014-03-11 15:38:30 +053011877 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_LOAD_IN_PROGRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -070011878
11879 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
11880
Siddharth Bhalcd92b782015-06-29 12:25:40 +053011881 /* register for riva power on lock to platform driver
11882 * Locking power early to ensure FW doesn't reset by kernel while
11883 * host driver is busy initializing itself */
11884 if (req_riva_power_on_lock("wlan"))
11885 {
11886 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
11887 __func__);
11888 goto err_free_hdd_context;
11889 }
11890
Jeff Johnson295189b2012-06-20 16:38:30 -070011891 /*Get vos context here bcoz vos_open requires it*/
11892 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
11893
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -080011894 if(pVosContext == NULL)
11895 {
11896 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
11897 goto err_free_hdd_context;
11898 }
11899
Jeff Johnson295189b2012-06-20 16:38:30 -070011900 //Save the Global VOSS context in adapter context for future.
11901 pHddCtx->pvosContext = pVosContext;
11902
11903 //Save the adapter context in global context for future.
11904 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
11905
Jeff Johnson295189b2012-06-20 16:38:30 -070011906 pHddCtx->parent_dev = dev;
Sreelakshmi Konamkif0646d52016-12-09 12:35:31 +053011907 pHddCtx->last_scan_reject_session_id = 0xFF;
11908 pHddCtx->last_scan_reject_reason = 0;
Sreelakshmi Konamki20ebed92016-10-27 12:13:30 +053011909 pHddCtx->last_scan_reject_timestamp = 0;
Abhishek Singhe4b12562017-06-20 16:53:39 +053011910 pHddCtx->scan_reject_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -070011911
11912 init_completion(&pHddCtx->full_pwr_comp_var);
11913 init_completion(&pHddCtx->standby_comp_var);
11914 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -070011915 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -080011916 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Kiet Lam46b8e4e2013-11-06 21:49:53 +053011917 init_completion(&pHddCtx->wiphy_channel_update_event);
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +053011918 init_completion(&pHddCtx->ssr_comp_var);
Mahesh A Saptasagar67ab9222015-10-21 15:38:41 +053011919 init_completion(&pHddCtx->mc_sus_event_var);
11920 init_completion(&pHddCtx->tx_sus_event_var);
11921 init_completion(&pHddCtx->rx_sus_event_var);
11922
Amar Singhala49cbc52013-10-08 18:37:44 -070011923
mukul sharma4bd8d2e2015-08-13 20:33:25 +053011924 hdd_init_ll_stats_ctx(pHddCtx);
Anurag Chouhan6ee81542017-02-09 18:09:27 +053011925 hdd_init_nud_stats_ctx(pHddCtx);
mukul sharma4bd8d2e2015-08-13 20:33:25 +053011926
Amar Singhala49cbc52013-10-08 18:37:44 -070011927#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhalfddc28c2013-09-05 13:03:40 -070011928 init_completion(&pHddCtx->linux_reg_req);
Amar Singhala49cbc52013-10-08 18:37:44 -070011929#else
11930 init_completion(&pHddCtx->driver_crda_req);
11931#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070011932
Padma, Santhosh Kumara1aa4a32015-06-19 19:00:46 +053011933#ifdef WLAN_FEATURE_EXTSCAN
11934 init_completion(&pHddCtx->ext_scan_context.response_event);
11935#endif /* WLAN_FEATURE_EXTSCAN */
11936
Kamath Vinayak4000c9a2013-08-23 14:24:27 +053011937 spin_lock_init(&pHddCtx->schedScan_lock);
Kapil Gupta137ef892016-12-13 19:38:00 +053011938 vos_spin_lock_init(&pHddCtx->sap_update_info_lock);
Kamath Vinayak4000c9a2013-08-23 14:24:27 +053011939
Jeff Johnson295189b2012-06-20 16:38:30 -070011940 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
11941
Padma, Santhosh Kumar9cd38332015-11-17 12:18:10 +053011942 vos_init_delayed_work(&pHddCtx->spoof_mac_addr_work,
11943 hdd_processSpoofMacAddrRequest);
Kapil Gupta137ef892016-12-13 19:38:00 +053011944 vos_init_work(&pHddCtx->sap_start_work, hdd_sap_restart_handle);
Padma, Santhosh Kumar9cd38332015-11-17 12:18:10 +053011945
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +053011946#ifdef FEATURE_WLAN_TDLS
11947 /* tdls_lock is initialized before an hdd_open_adapter ( which is
11948 * invoked by other instances also) to protect the concurrent
11949 * access for the Adapters by TDLS module.
11950 */
11951 mutex_init(&pHddCtx->tdls_lock);
11952#endif
Siddharth Bhal76972212014-10-15 16:22:51 +053011953 mutex_init(&pHddCtx->spoofMacAddr.macSpoofingLock);
Mukul Sharma1fd6efd2015-02-14 00:29:14 +053011954 mutex_init(&pHddCtx->wmmLock);
11955
Srinivas Girigowda8bf64cb2015-09-30 19:50:09 +053011956 hdd_init_offloaded_packets_ctx(pHddCtx);
Agarwal Ashish1f422872014-07-22 00:11:55 +053011957 /* By default Strict Regulatory For FCC should be false */
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +053011958
Agarwal Ashish1f422872014-07-22 00:11:55 +053011959 pHddCtx->nEnableStrictRegulatoryForFCC = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -070011960 // Load all config first as TL config is needed during vos_open
11961 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
11962 if(pHddCtx->cfg_ini == NULL)
11963 {
11964 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
11965 goto err_free_hdd_context;
11966 }
11967
11968 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
11969
11970 // Read and parse the qcom_cfg.ini file
11971 status = hdd_parse_config_ini( pHddCtx );
11972 if ( VOS_STATUS_SUCCESS != status )
11973 {
11974 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
11975 __func__, WLAN_INI_FILE);
11976 goto err_config;
11977 }
Arif Hussaind5218912013-12-05 01:10:55 -080011978#ifdef MEMORY_DEBUG
11979 if (pHddCtx->cfg_ini->IsMemoryDebugSupportEnabled)
11980 vos_mem_init();
11981
11982 hddLog(VOS_TRACE_LEVEL_INFO, "%s: gEnableMemoryDebug=%d",
11983 __func__, pHddCtx->cfg_ini->IsMemoryDebugSupportEnabled);
11984#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070011985
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +053011986 /* INI has been read, initialise the configuredMcastBcastFilter with
11987 * INI value as this will serve as the default value
11988 */
11989 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
11990 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
11991 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +053011992
11993 if (false == hdd_is_5g_supported(pHddCtx))
11994 {
11995 //5Ghz is not supported.
11996 if (1 != pHddCtx->cfg_ini->nBandCapability)
11997 {
11998 hddLog(VOS_TRACE_LEVEL_INFO,
11999 "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__);
12000 pHddCtx->cfg_ini->nBandCapability = 1;
12001 }
12002 }
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +053012003
12004 /* If SNR Monitoring is enabled, FW has to parse all beacons
12005 * for calcaluting and storing the average SNR, so set Nth beacon
12006 * filter to 1 to enable FW to parse all the beaocons
12007 */
12008 if (1 == pHddCtx->cfg_ini->fEnableSNRMonitoring)
12009 {
12010 /* The log level is deliberately set to WARN as overriding
12011 * nthBeaconFilter to 1 will increase power cosumption and this
12012 * might just prove helpful to detect the power issue.
12013 */
12014 hddLog(VOS_TRACE_LEVEL_WARN,
12015 "%s: Setting pHddCtx->cfg_ini->nthBeaconFilter = 1", __func__);
12016 pHddCtx->cfg_ini->nthBeaconFilter = 1;
12017 }
Jeff Johnson295189b2012-06-20 16:38:30 -070012018 /*
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +053012019 * cfg80211: Initialization ...
Jeff Johnson295189b2012-06-20 16:38:30 -070012020 */
Manjeet Singh61016fa2016-12-02 11:10:19 +053012021 if (0 < wlan_hdd_cfg80211_init(dev, wiphy, pHddCtx->cfg_ini))
Jeff Johnson295189b2012-06-20 16:38:30 -070012022 {
Manjeet Singh61016fa2016-12-02 11:10:19 +053012023 hddLog(VOS_TRACE_LEVEL_FATAL,
12024 "%s: wlan_hdd_cfg80211_init return failure", __func__);
12025 goto err_config;
Jeff Johnson295189b2012-06-20 16:38:30 -070012026 }
Jeff Johnson295189b2012-06-20 16:38:30 -070012027
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -080012028 // Update VOS trace levels based upon the cfg.ini
12029 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
12030 pHddCtx->cfg_ini->vosTraceEnableBAP);
12031 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
12032 pHddCtx->cfg_ini->vosTraceEnableTL);
12033 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
12034 pHddCtx->cfg_ini->vosTraceEnableWDI);
12035 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
12036 pHddCtx->cfg_ini->vosTraceEnableHDD);
12037 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
12038 pHddCtx->cfg_ini->vosTraceEnableSME);
12039 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
12040 pHddCtx->cfg_ini->vosTraceEnablePE);
Katya Nigam70d68332013-09-16 16:49:45 +053012041 hdd_vos_trace_enable(VOS_MODULE_ID_PMC,
12042 pHddCtx->cfg_ini->vosTraceEnablePMC);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -080012043 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
12044 pHddCtx->cfg_ini->vosTraceEnableWDA);
12045 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
12046 pHddCtx->cfg_ini->vosTraceEnableSYS);
12047 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
12048 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -080012049 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
12050 pHddCtx->cfg_ini->vosTraceEnableSAP);
12051 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
12052 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -080012053
Jeff Johnson295189b2012-06-20 16:38:30 -070012054 // Update WDI trace levels based upon the cfg.ini
12055 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
12056 pHddCtx->cfg_ini->wdiTraceEnableDAL);
12057 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
12058 pHddCtx->cfg_ini->wdiTraceEnableCTL);
12059 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
12060 pHddCtx->cfg_ini->wdiTraceEnableDAT);
12061 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
12062 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -070012063
Jeff Johnson88ba7742013-02-27 14:36:02 -080012064 if (VOS_FTM_MODE == hdd_get_conparam())
12065 {
Jeff Johnson295189b2012-06-20 16:38:30 -070012066 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
12067 {
12068 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
12069 goto err_free_hdd_context;
12070 }
12071 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
Sachin Ahuja38ef5e02015-03-13 17:31:16 +053012072 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_NO_LOAD_UNLOAD_IN_PROGRESS;
c_hpothu2de0ef62014-04-15 16:16:15 +053012073 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -070012074 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -080012075 }
Jeff Johnson295189b2012-06-20 16:38:30 -070012076
Katya Nigame7b69a82015-04-28 15:24:06 +053012077 if( VOS_MONITOR_MODE == hdd_get_conparam())
12078 {
12079 if ( VOS_STATUS_SUCCESS != wlan_hdd_mon_open(pHddCtx))
12080 {
12081 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_mon_open Failed",__func__);
12082 goto err_free_hdd_context;
12083 }
12084 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Driver loaded in Monitor Mode",__func__);
12085 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_NO_LOAD_UNLOAD_IN_PROGRESS;
12086 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
12087 return VOS_STATUS_SUCCESS;
12088 }
12089
Jeff Johnson88ba7742013-02-27 14:36:02 -080012090 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -070012091 if(pHddCtx->cfg_ini->fIsLogpEnabled)
12092 {
12093 status = vos_watchdog_open(pVosContext,
12094 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
12095
12096 if(!VOS_IS_STATUS_SUCCESS( status ))
12097 {
12098 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Ashish Kumar Dhanotiya532bdef2017-05-09 17:31:59 +053012099 goto err_config;
Jeff Johnson295189b2012-06-20 16:38:30 -070012100 }
12101 }
12102
12103 pHddCtx->isLogpInProgress = FALSE;
12104 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
12105
Amar Singhala49cbc52013-10-08 18:37:44 -070012106#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -070012107 /* initialize the NV module. This is required so that
12108 we can initialize the channel information in wiphy
12109 from the NV.bin data. The channel information in
12110 wiphy needs to be initialized before wiphy registration */
12111
12112 status = vos_nv_open();
12113 if (!VOS_IS_STATUS_SUCCESS(status))
12114 {
12115 /* NV module cannot be initialized */
12116 hddLog( VOS_TRACE_LEVEL_FATAL,
12117 "%s: vos_nv_open failed", __func__);
Vinay Krishna Eranna2025d892014-09-18 16:51:42 +053012118 goto err_wdclose;
Amar Singhal0a402232013-10-11 20:57:16 -070012119 }
12120
12121 status = vos_init_wiphy_from_nv_bin();
12122 if (!VOS_IS_STATUS_SUCCESS(status))
12123 {
12124 /* NV module cannot be initialized */
12125 hddLog( VOS_TRACE_LEVEL_FATAL,
12126 "%s: vos_init_wiphy failed", __func__);
12127 goto err_vos_nv_close;
12128 }
12129
Amar Singhala49cbc52013-10-08 18:37:44 -070012130#endif
Mahesh A Saptasagarc3ed0122016-01-19 16:45:11 +053012131 //Initialize the nlink service
12132 if(nl_srv_init() != 0)
12133 {
12134 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
12135 goto err_vos_nv_close;
12136 }
12137
12138#ifdef WLAN_KD_READY_NOTIFIER
12139 pHddCtx->kd_nl_init = 1;
12140#endif /* WLAN_KD_READY_NOTIFIER */
12141
Girish Gowlibf0e1ab2015-01-19 16:05:16 +053012142 vos_set_roam_delay_stats_enabled(pHddCtx->cfg_ini->gEnableRoamDelayStats);
Arun Kumar Khandavalliebb19482014-03-25 13:56:53 +053012143 status = vos_open( &pVosContext, pHddCtx->parent_dev);
Jeff Johnson295189b2012-06-20 16:38:30 -070012144 if ( !VOS_IS_STATUS_SUCCESS( status ))
12145 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -080012146 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
Mahesh A Saptasagarc3ed0122016-01-19 16:45:11 +053012147 goto err_nl_srv;
Jeff Johnson295189b2012-06-20 16:38:30 -070012148 }
12149
Jeff Johnson295189b2012-06-20 16:38:30 -070012150 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
12151
12152 if ( NULL == pHddCtx->hHal )
12153 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -080012154 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -070012155 goto err_vosclose;
12156 }
12157
Jeff Johnsonbc676b42013-02-14 16:04:08 -080012158 status = vos_preStart( pHddCtx->pvosContext );
12159 if ( !VOS_IS_STATUS_SUCCESS( status ) )
12160 {
12161 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053012162 goto err_vosclose;
Jeff Johnsonbc676b42013-02-14 16:04:08 -080012163 }
Jeff Johnsone7245742012-09-05 17:12:55 -070012164
Arif Hussaineaf68602013-12-30 23:10:44 -080012165 if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan)
12166 {
12167 pHddCtx->cfg_ini->enableDFSChnlScan = enable_dfs_chan_scan;
12168 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_dfs_chan_scan set to %d",
12169 __func__, enable_dfs_chan_scan);
12170 }
12171 if (0 == enable_11d || 1 == enable_11d)
12172 {
12173 pHddCtx->cfg_ini->Is11dSupportEnabled = enable_11d;
12174 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_11d set to %d",
12175 __func__, enable_11d);
12176 }
12177
Jeff Johnsonbc676b42013-02-14 16:04:08 -080012178 /* Note that the vos_preStart() sequence triggers the cfg download.
12179 The cfg download must occur before we update the SME config
12180 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -070012181 status = hdd_set_sme_config( pHddCtx );
12182
12183 if ( VOS_STATUS_SUCCESS != status )
12184 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -080012185 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053012186 goto err_vosclose;
Jeff Johnsonbc676b42013-02-14 16:04:08 -080012187 }
Jeff Johnson295189b2012-06-20 16:38:30 -070012188
Jeff Johnson295189b2012-06-20 16:38:30 -070012189 /* In the integrated architecture we update the configuration from
12190 the INI file and from NV before vOSS has been started so that
12191 the final contents are available to send down to the cCPU */
12192
12193 // Apply the cfg.ini to cfg.dat
12194 if (FALSE == hdd_update_config_dat(pHddCtx))
12195 {
12196 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053012197 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -070012198 }
12199
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053012200 // Get mac addr from platform driver
12201 ret = wcnss_get_wlan_mac_address((char*)&mac_addr.bytes);
12202
12203 if ((0 == ret) && (!vos_is_macaddr_zero(&mac_addr)))
Jeff Johnson295189b2012-06-20 16:38:30 -070012204 {
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053012205 /* Store the mac addr for first interface */
12206 pHddCtx->cfg_ini->intfMacAddr[0] = mac_addr;
12207
12208 hddLog(VOS_TRACE_LEVEL_ERROR,
12209 "%s: WLAN Mac Addr: "
12210 MAC_ADDRESS_STR, __func__,
12211 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
12212
12213 /* Here, passing Arg2 as 1 because we do not want to change the
12214 last 3 bytes (means non OUI bytes) of first interface mac
12215 addr.
12216 */
12217 if (0 != hdd_generate_iface_mac_addr_auto(pHddCtx, 1, mac_addr))
12218 {
12219 hddLog(VOS_TRACE_LEVEL_ERROR,
12220 "%s: Failed to generate wlan interface mac addr "
12221 "using MAC from ini file ", __func__);
12222 }
12223 }
12224 else if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
12225 {
12226 // Apply the NV to cfg.dat
12227 /* Prima Update MAC address only at here */
Jeff Johnson295189b2012-06-20 16:38:30 -070012228#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
12229 /* There was not a valid set of MAC Addresses in NV. See if the
12230 default addresses were modified by the cfg.ini settings. If so,
12231 we'll use them, but if not, we'll autogenerate a set of MAC
12232 addresses based upon the device serial number */
12233
12234 static const v_MACADDR_t default_address =
12235 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
Jeff Johnson295189b2012-06-20 16:38:30 -070012236
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053012237 if (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
12238 sizeof(default_address)))
Jeff Johnson295189b2012-06-20 16:38:30 -070012239 {
12240 /* cfg.ini has the default address, invoke autogen logic */
12241
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053012242 /* Here, passing Arg2 as 0 because we want to change the
12243 last 3 bytes (means non OUI bytes) of all the interfaces
12244 mac addr.
12245 */
12246 if (0 != hdd_generate_iface_mac_addr_auto(pHddCtx, 0,
12247 default_address))
Jeff Johnson295189b2012-06-20 16:38:30 -070012248 {
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053012249 hddLog(VOS_TRACE_LEVEL_ERROR,
12250 "%s: Failed to generate wlan interface mac addr "
12251 "using MAC from ini file " MAC_ADDRESS_STR, __func__,
12252 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
Jeff Johnson295189b2012-06-20 16:38:30 -070012253 }
Jeff Johnson295189b2012-06-20 16:38:30 -070012254 }
12255 else
12256#endif //WLAN_AUTOGEN_MACADDR_FEATURE
12257 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -080012258 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -070012259 "%s: Invalid MAC address in NV, using MAC from ini file "
12260 MAC_ADDRESS_STR, __func__,
12261 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
12262 }
12263 }
12264 {
12265 eHalStatus halStatus;
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053012266
12267 /* Set the MAC Address Currently this is used by HAL to
12268 * add self sta. Remove this once self sta is added as
12269 * part of session open.
12270 */
Jeff Johnson295189b2012-06-20 16:38:30 -070012271 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
12272 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
12273 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053012274
Jeff Johnson295189b2012-06-20 16:38:30 -070012275 if (!HAL_STATUS_SUCCESS( halStatus ))
12276 {
12277 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
12278 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053012279 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -070012280 }
12281 }
Jeff Johnson295189b2012-06-20 16:38:30 -070012282
12283 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
12284 Note: Firmware image will be read and downloaded inside vos_start API */
12285 status = vos_start( pHddCtx->pvosContext );
12286 if ( !VOS_IS_STATUS_SUCCESS( status ) )
12287 {
12288 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
Hanumantha Reddy Pothulabd9601a2016-02-12 13:22:27 +053012289 if (isSsrPanicOnFailure())
12290 VOS_BUG(0);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053012291 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -070012292 }
12293
Leo Chang6cec3e22014-01-21 15:33:49 -080012294#ifdef FEATURE_WLAN_CH_AVOID
12295 /* Plug in avoid channel notification callback
12296 * This should happen before ADD_SELF_STA
12297 * FW will send first IND with ADD_SELF_STA REQ from host */
Pradeep Reddy POTTETI5c2e16d2014-06-27 16:47:38 +053012298
12299 /* check the Channel Avoidance is enabled */
12300 if (TRUE == pHddCtx->cfg_ini->fenableCHAvoidance)
12301 {
12302 sme_AddChAvoidCallback(pHddCtx->hHal,
12303 hdd_hostapd_ch_avoid_cb);
12304 }
Leo Chang6cec3e22014-01-21 15:33:49 -080012305#endif /* FEATURE_WLAN_CH_AVOID */
12306
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070012307 /* Exchange capability info between Host and FW and also get versioning info from FW */
12308 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -070012309
Agarwal Ashishad9281b2014-06-10 14:57:30 +053012310#ifdef CONFIG_ENABLE_LINUX_REG
12311 status = wlan_hdd_init_channels(pHddCtx);
12312 if ( !VOS_IS_STATUS_SUCCESS( status ) )
12313 {
12314 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: wlan_hdd_init_channels failed",
12315 __func__);
12316 goto err_vosstop;
12317 }
12318#endif
12319
Jeff Johnson295189b2012-06-20 16:38:30 -070012320 status = hdd_post_voss_start_config( pHddCtx );
12321 if ( !VOS_IS_STATUS_SUCCESS( status ) )
12322 {
12323 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
12324 __func__);
12325 goto err_vosstop;
12326 }
Amar Singhala49cbc52013-10-08 18:37:44 -070012327
12328#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +053012329 wlan_hdd_cfg80211_update_reg_info( wiphy );
12330
12331 /* registration of wiphy dev with cfg80211 */
12332 if (0 > wlan_hdd_cfg80211_register(wiphy))
12333 {
12334 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
12335 goto err_vosstop;
12336 }
Amar Singhala49cbc52013-10-08 18:37:44 -070012337#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070012338
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053012339#ifdef CONFIG_ENABLE_LINUX_REG
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053012340 /* registration of wiphy dev with cfg80211 */
12341 if (0 > wlan_hdd_cfg80211_register(wiphy))
12342 {
12343 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
12344 goto err_vosstop;
12345 }
12346
Agarwal Ashish6db9d532014-09-30 18:19:10 +053012347 status = wlan_hdd_init_channels_for_cc(pHddCtx, INIT);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053012348 if ( !VOS_IS_STATUS_SUCCESS( status ) )
12349 {
12350 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: wlan_hdd_init_channels_for_cc failed",
12351 __func__);
12352 goto err_unregister_wiphy;
12353 }
12354#endif
12355
c_hpothu4a298be2014-12-22 21:12:51 +053012356 wcnss_wlan_set_drvdata(pHddCtx->parent_dev, pHddCtx);
12357
Jeff Johnson295189b2012-06-20 16:38:30 -070012358 if (VOS_STA_SAP_MODE == hdd_get_conparam())
12359 {
12360 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
12361 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
12362 }
12363 else
12364 {
Jeff Johnson295189b2012-06-20 16:38:30 -070012365 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
12366 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
12367 if (pAdapter != NULL)
12368 {
Katya Nigama7d81d72014-11-12 12:44:34 +053012369 if (pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated && !(pHddCtx->cfg_ini->intfMacAddr[0].bytes[0] & 0x02))
Jeff Johnson295189b2012-06-20 16:38:30 -070012370 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +053012371 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
12372 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
12373 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -070012374
Gopichand Nakkala49f96f62013-02-06 14:38:17 +053012375 /* Generate the P2P Device Address. This consists of the device's
12376 * primary MAC address with the locally administered bit set.
12377 */
12378 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -070012379 }
12380 else
12381 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +053012382 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
12383 if (p2p_dev_addr != NULL)
12384 {
12385 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
12386 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
12387 }
12388 else
12389 {
12390 hddLog(VOS_TRACE_LEVEL_FATAL,
12391 "%s: Failed to allocate mac_address for p2p_device",
12392 __func__);
12393 goto err_close_adapter;
12394 }
Jeff Johnson295189b2012-06-20 16:38:30 -070012395 }
Jeff Johnsone7245742012-09-05 17:12:55 -070012396
12397 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
12398 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
12399 if ( NULL == pP2pAdapter )
12400 {
12401 hddLog(VOS_TRACE_LEVEL_FATAL,
12402 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070012403 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -070012404 goto err_close_adapter;
12405 }
Jeff Johnsone7245742012-09-05 17:12:55 -070012406 }
Jeff Johnson295189b2012-06-20 16:38:30 -070012407 }
Jeff Johnson295189b2012-06-20 16:38:30 -070012408
12409 if( pAdapter == NULL )
12410 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -080012411 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
12412 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -070012413 }
Jeff Johnsone7245742012-09-05 17:12:55 -070012414
Arif Hussain66559122013-11-21 10:11:40 -080012415 if (country_code)
12416 {
12417 eHalStatus ret;
Arif Hussaincb607082013-12-20 11:57:42 -080012418 INIT_COMPLETION(pAdapter->change_country_code);
Arif Hussain66559122013-11-21 10:11:40 -080012419 hdd_checkandupdate_dfssetting(pAdapter, country_code);
12420#ifndef CONFIG_ENABLE_LINUX_REG
12421 hdd_checkandupdate_phymode(pAdapter, country_code);
12422#endif
Arif Hussaineaf68602013-12-30 23:10:44 -080012423 ret = sme_ChangeCountryCode(pHddCtx->hHal,
12424 (void *)(tSmeChangeCountryCallback)
12425 wlan_hdd_change_country_code_callback,
Arif Hussain66559122013-11-21 10:11:40 -080012426 country_code,
12427 pAdapter, pHddCtx->pvosContext,
Abhishek Singha306a442013-11-07 18:39:01 +053012428 eSIR_TRUE, eSIR_TRUE);
Arif Hussain66559122013-11-21 10:11:40 -080012429 if (eHAL_STATUS_SUCCESS == ret)
12430 {
Arif Hussaincb607082013-12-20 11:57:42 -080012431 ret = wait_for_completion_interruptible_timeout(
12432 &pAdapter->change_country_code,
12433 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
12434
12435 if (0 >= ret)
12436 {
12437 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
12438 "%s: SME while setting country code timed out", __func__);
12439 }
Arif Hussain66559122013-11-21 10:11:40 -080012440 }
12441 else
12442 {
Arif Hussaincb607082013-12-20 11:57:42 -080012443 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
12444 "%s: SME Change Country code from module param fail ret=%d",
12445 __func__, ret);
Arif Hussain66559122013-11-21 10:11:40 -080012446 }
12447 }
12448
Jeff Johnson295189b2012-06-20 16:38:30 -070012449#ifdef WLAN_BTAMP_FEATURE
12450 vStatus = WLANBAP_Open(pVosContext);
12451 if(!VOS_IS_STATUS_SUCCESS(vStatus))
12452 {
12453 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
12454 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -070012455 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -070012456 }
12457
12458 vStatus = BSL_Init(pVosContext);
12459 if(!VOS_IS_STATUS_SUCCESS(vStatus))
12460 {
12461 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
12462 "%s: Failed to Init BSL",__func__);
12463 goto err_bap_close;
12464 }
12465 vStatus = WLANBAP_Start(pVosContext);
12466 if (!VOS_IS_STATUS_SUCCESS(vStatus))
12467 {
12468 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
12469 "%s: Failed to start TL",__func__);
12470 goto err_bap_close;
12471 }
12472
12473 pConfig = pHddCtx->cfg_ini;
12474 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
12475 status = WLANBAP_SetConfig(&btAmpConfig);
12476
12477#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -070012478
Mihir Shete9c238772014-10-15 14:35:16 +053012479 /*
12480 * UapsdMask is 0xf if U-APSD is enbaled for all AC's...
12481 * The value of CFG_QOS_WMM_UAPSD_MASK_DEFAULT is 0xaa(Magic Value)
12482 * which is greater than 0xf. So the below check is safe to make
12483 * sure that there is no entry for UapsdMask in the ini
12484 */
12485 if (CFG_QOS_WMM_UAPSD_MASK_DEFAULT == pHddCtx->cfg_ini->UapsdMask)
12486 {
12487 if(IS_DYNAMIC_WMM_PS_ENABLED)
12488 {
12489 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: Enable UAPSD for VI & VO",
12490 __func__);
12491 pHddCtx->cfg_ini->UapsdMask =
12492 CFG_QOS_WMM_UAPSD_MASK_DYMANIC_WMM_PS_DEFAULT;
12493 }
12494 else
12495 {
12496 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: Do not enable UAPSD",
12497 __func__);
12498 pHddCtx->cfg_ini->UapsdMask =
12499 CFG_QOS_WMM_UAPSD_MASK_LEGACY_WMM_PS_DEFAULT;
12500 }
12501 }
12502
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -070012503#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
12504 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
12505 {
12506 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
12507 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
12508 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
12509 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
12510 }
12511#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070012512
Agarwal Ashish4b87f922014-06-18 03:03:21 +053012513 wlan_hdd_tdls_init(pHddCtx);
12514
Masti, Narayanraddi26378462016-01-05 18:20:28 +053012515 wlan_hdd_init_deinit_defer_scan_context(&pHddCtx->scan_ctxt);
12516
12517 vos_init_delayed_work(&pHddCtx->scan_ctxt.scan_work,
12518 wlan_hdd_schedule_defer_scan);
12519
Mihir Shetefc7ff5b2014-01-27 11:30:05 +053012520 sme_Register11dScanDoneCallback(pHddCtx->hHal, hdd_11d_scan_done);
12521
Jeff Johnson295189b2012-06-20 16:38:30 -070012522 /* Register with platform driver as client for Suspend/Resume */
12523 status = hddRegisterPmOps(pHddCtx);
12524 if ( !VOS_IS_STATUS_SUCCESS( status ) )
12525 {
12526 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
12527#ifdef WLAN_BTAMP_FEATURE
12528 goto err_bap_stop;
12529#else
Jeff Johnsone7245742012-09-05 17:12:55 -070012530 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -070012531#endif //WLAN_BTAMP_FEATURE
12532 }
12533
Yue Ma0d4891e2013-08-06 17:01:45 -070012534 /* Open debugfs interface */
12535 if (VOS_STATUS_SUCCESS != hdd_debugfs_init(pAdapter))
12536 {
12537 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
12538 "%s: hdd_debugfs_init failed!", __func__);
Yue Ma0d4891e2013-08-06 17:01:45 -070012539 }
12540
Jeff Johnson295189b2012-06-20 16:38:30 -070012541 /* Register TM level change handler function to the platform */
12542 status = hddDevTmRegisterNotifyCallback(pHddCtx);
12543 if ( !VOS_IS_STATUS_SUCCESS( status ) )
12544 {
12545 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
12546 goto err_unregister_pmops;
12547 }
Jeff Johnson295189b2012-06-20 16:38:30 -070012548
Jeff Johnson295189b2012-06-20 16:38:30 -070012549 // register net device notifier for device change notification
12550 ret = register_netdevice_notifier(&hdd_netdev_notifier);
12551
12552 if(ret < 0)
12553 {
12554 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
Siddharth Bhalcd92b782015-06-29 12:25:40 +053012555 goto err_unregister_pmops;
Jeff Johnson295189b2012-06-20 16:38:30 -070012556 }
12557
Jeff Johnson295189b2012-06-20 16:38:30 -070012558 //Initialize the BTC service
12559 if(btc_activate_service(pHddCtx) != 0)
12560 {
12561 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
Mahesh A Saptasagarc3ed0122016-01-19 16:45:11 +053012562 goto err_reg_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -070012563 }
12564
Padma, Santhosh Kumar2762e9d2015-10-20 15:02:57 +053012565#ifdef FEATURE_OEM_DATA_SUPPORT
12566 //Initialize the OEM service
12567 if (oem_activate_service(pHddCtx) != 0)
12568 {
12569 hddLog(VOS_TRACE_LEVEL_FATAL,
12570 "%s: oem_activate_service failed", __func__);
Mahesh A Saptasagarc3ed0122016-01-19 16:45:11 +053012571 goto err_reg_netdev;
Padma, Santhosh Kumar2762e9d2015-10-20 15:02:57 +053012572 }
12573#endif
12574
Jeff Johnson295189b2012-06-20 16:38:30 -070012575#ifdef PTT_SOCK_SVC_ENABLE
12576 //Initialize the PTT service
12577 if(ptt_sock_activate_svc(pHddCtx) != 0)
12578 {
12579 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
Mahesh A Saptasagarc3ed0122016-01-19 16:45:11 +053012580 goto err_reg_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -070012581 }
12582#endif
12583
Abhishek Singh00b71972016-01-07 10:51:04 +053012584#ifdef WLAN_FEATURE_RMC
12585 if (hdd_open_cesium_nl_sock() < 0)
12586 {
12587 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_open_cesium_nl_sock failed", __func__);
12588 goto err_reg_netdev;
12589 }
12590#endif
12591
Vinay Krishna Erannad938c422014-03-10 17:14:21 +053012592#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
12593 if(pHddCtx->cfg_ini && pHddCtx->cfg_ini->wlanLoggingEnable)
12594 {
Deepthi Gowri78083a32014-11-04 12:55:51 +053012595 if(wlan_logging_sock_activate_svc(
12596 pHddCtx->cfg_ini->wlanLoggingFEToConsole,
Sushant Kaushik33200572015-08-05 16:46:20 +053012597 pHddCtx->cfg_ini->wlanLoggingNumBuf,
12598 pHddCtx->cfg_ini->wlanPerPktStatsLogEnable,
12599 pHddCtx->cfg_ini->wlanPerPktStatsNumBuf))
Deepthi Gowri78083a32014-11-04 12:55:51 +053012600 {
12601 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wlan_logging_sock_activate_svc"
12602 " failed", __func__);
Mahesh A Saptasagarc3ed0122016-01-19 16:45:11 +053012603 goto err_reg_netdev;
Deepthi Gowri78083a32014-11-04 12:55:51 +053012604 }
12605 //TODO: To Remove enableDhcpDebug and use gEnableDebugLog for
12606 //EAPOL and DHCP
Sachin Ahuja8c65f382014-12-12 15:34:21 +053012607 if (!pHddCtx->cfg_ini->gEnableDebugLog)
12608 pHddCtx->cfg_ini->gEnableDebugLog =
Sushant Kaushik6e4e2bc2015-10-05 17:23:07 +053012609 VOS_PKT_PROTO_TYPE_EAPOL | VOS_PKT_PROTO_TYPE_DHCP |
12610 VOS_PKT_PROTO_TYPE_ARP;
Vinay Krishna Erannad938c422014-03-10 17:14:21 +053012611 }
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012612
Siddharth Bhald1be97f2015-05-27 22:39:59 +053012613 if (pHddCtx->cfg_ini->wlanLoggingEnable &&
12614 (pHddCtx->cfg_ini->enableFWLogging ||
Siddharth Bhaldb963232015-06-25 19:34:35 +053012615 pHddCtx->cfg_ini->enableMgmtLogging ||
c_manjeecfd1efb2015-09-25 19:32:34 +053012616 pHddCtx->cfg_ini->enableContFWLogging ||
12617 pHddCtx->cfg_ini->enableFwrMemDump )
12618 )
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012619 {
Siddharth Bhald1be97f2015-05-27 22:39:59 +053012620 hdd_init_frame_logging(pHddCtx);
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012621 }
12622 else
12623 {
Siddharth Bhald1be97f2015-05-27 22:39:59 +053012624 hddLog(VOS_TRACE_LEVEL_INFO, FL("Logging disabled in ini"));
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012625 }
12626
Vinay Krishna Erannad938c422014-03-10 17:14:21 +053012627#endif
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012628
Agrawal Ashish17ef5082016-10-17 18:33:21 +053012629#ifdef SAP_AUTH_OFFLOAD
12630 if (!sme_IsFeatureSupportedByFW(SAP_OFFLOADS))
12631 {
12632 hddLog(VOS_TRACE_LEVEL_INFO, FL(" SAP AUTH OFFLOAD not supp by FW"));
12633 pHddCtx->cfg_ini->enable_sap_auth_offload = 0;
12634 }
12635#endif
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012636
Sushant Kaushik215778f2015-05-21 14:05:36 +053012637 if (vos_is_multicast_logging())
12638 wlan_logging_set_log_level();
12639
Jeff Johnson295189b2012-06-20 16:38:30 -070012640 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -070012641 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -070012642 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -070012643 /* Action frame registered in one adapter which will
12644 * applicable to all interfaces
12645 */
Agarwal Ashish8fa0e9a2014-05-23 00:40:12 +053012646 wlan_hdd_cfg80211_register_frames(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -070012647 }
Jeff Johnson295189b2012-06-20 16:38:30 -070012648
12649 mutex_init(&pHddCtx->sap_lock);
Mahesh A Saptasagar60627942014-10-13 13:55:14 +053012650 mutex_init(&pHddCtx->roc_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070012651
Jeff Johnsone7245742012-09-05 17:12:55 -070012652#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
12653 /* Initialize the wake lcok */
Sushant Kaushik83392fa2015-05-05 17:44:40 +053012654 vos_wake_lock_init(&pHddCtx->rx_wake_lock,
Jeff Johnsone7245742012-09-05 17:12:55 -070012655 "qcom_rx_wakelock");
Sushant Kaushik83392fa2015-05-05 17:44:40 +053012656
Jeff Johnsone7245742012-09-05 17:12:55 -070012657#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -080012658 /* Initialize the wake lcok */
Sushant Kaushik83392fa2015-05-05 17:44:40 +053012659 vos_wake_lock_init(&pHddCtx->sap_wake_lock,
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -080012660 "qcom_sap_wakelock");
Sushant Kaushik83392fa2015-05-05 17:44:40 +053012661
Jeff Johnsone7245742012-09-05 17:12:55 -070012662
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -070012663 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
12664 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -070012665
Katya Nigam5c306ea2014-06-19 15:39:54 +053012666 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_NO_LOAD_UNLOAD_IN_PROGRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -070012667 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
Sushant Kaushik83392fa2015-05-05 17:44:40 +053012668 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_INIT);
Katya Nigam5c306ea2014-06-19 15:39:54 +053012669
12670#ifdef FEATURE_WLAN_SCAN_PNO
12671 /*SME must send channel update configuration to RIVA*/
12672 sme_UpdateChannelConfig(pHddCtx->hHal);
12673#endif
Abhishek Singhf644b272014-08-21 02:59:39 +053012674 /* Send the update default channel list to the FW*/
12675 sme_UpdateChannelList(pHddCtx->hHal);
Mukul Sharma45063942015-04-01 20:07:59 +053012676
12677 /* Fwr capabilities received, Set the Dot11 mode */
Abhishek Singh41ebce12016-02-03 10:43:21 +053012678 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter),
12679 hdd_cfg_xlate_to_csr_phy_mode(pHddCtx->cfg_ini->dot11Mode));
Mukul Sharma45063942015-04-01 20:07:59 +053012680 sme_SetDefDot11Mode(pHddCtx->hHal);
12681
Abhishek Singha306a442013-11-07 18:39:01 +053012682#ifndef CONFIG_ENABLE_LINUX_REG
12683 /*updating wiphy so that regulatory user hints can be processed*/
12684 if (wiphy)
12685 {
12686 regulatory_hint(wiphy, "00");
12687 }
12688#endif
Jeff Johnsone7245742012-09-05 17:12:55 -070012689 // Initialize the restart logic
12690 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +053012691
Hanumanth Reddy Pothula146bca42016-11-08 12:01:07 +053012692 if (pHddCtx->cfg_ini->fIsLogpEnabled) {
12693 vos_wdthread_init_timer_work(vos_process_wd_timer);
12694 /* Initialize the timer to detect thread stuck issues */
12695 vos_thread_stuck_timer_init(
12696 &((VosContextType*)pVosContext)->vosWatchdog);
12697 }
12698
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -070012699 //Register the traffic monitor timer now
12700 if ( pHddCtx->cfg_ini->dynSplitscan)
12701 {
12702 vos_timer_init(&pHddCtx->tx_rx_trafficTmr,
12703 VOS_TIMER_TYPE_SW,
12704 hdd_tx_rx_pkt_cnt_stat_timer_handler,
12705 (void *)pHddCtx);
12706 }
Srinivas Dasari030bad32015-02-18 23:23:54 +053012707 wlan_hdd_cfg80211_nan_init(pHddCtx);
12708
Bhargav Shahd0715912015-10-01 18:17:37 +053012709 mutex_init(&pHddCtx->cur_rx_level_lock);
12710 vos_timer_init(&pHddCtx->delack_timer, VOS_TIMER_TYPE_SW,
12711 hdd_tcp_delack_compute_function,(void *)pHddCtx);
Masti, Narayanraddi44b0db02015-12-22 11:54:35 +053012712 vos_timer_init(&pHddCtx->tdls_source_timer, VOS_TIMER_TYPE_SW,
12713 wlan_hdd_change_tdls_mode, (void *)pHddCtx);
Bhargav Shahd0715912015-10-01 18:17:37 +053012714
Dino Mycle6fb96c12014-06-10 11:52:40 +053012715#ifdef WLAN_FEATURE_EXTSCAN
12716 sme_EXTScanRegisterCallback(pHddCtx->hHal,
12717 wlan_hdd_cfg80211_extscan_callback,
12718 pHddCtx);
12719#endif /* WLAN_FEATURE_EXTSCAN */
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053012720
Padma, Santhosh Kumar2ccac212015-10-20 17:27:27 +053012721#ifdef FEATURE_OEM_DATA_SUPPORT
12722 sme_OemDataRegisterCallback(pHddCtx->hHal,
12723 wlan_hdd_cfg80211_oemdata_callback,
12724 pHddCtx);
12725#endif /* FEATURE_OEM_DATA_SUPPORT */
12726
Gupta, Kapil7c34b322015-09-30 13:12:35 +053012727 sme_set_rssi_threshold_breached_cb(pHddCtx->hHal, hdd_rssi_threshold_breached_cb);
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053012728#ifdef WLAN_NS_OFFLOAD
12729 // Register IPv6 notifier to notify if any change in IP
12730 // So that we can reconfigure the offload parameters
12731 pHddCtx->ipv6_notifier.notifier_call = wlan_hdd_ipv6_changed;
12732 ret = register_inet6addr_notifier(&pHddCtx->ipv6_notifier);
12733 if (ret)
12734 {
Ratheesh S P36dbc932015-08-07 14:28:57 +053012735 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Failed to register IPv6 notifier"));
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053012736 }
12737 else
12738 {
Ratheesh S P36dbc932015-08-07 14:28:57 +053012739 hddLog(VOS_TRACE_LEVEL_INFO, FL("Registered IPv6 notifier"));
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053012740 }
12741#endif
12742
Sravan Kumar Kairamb0edc612016-10-26 13:55:24 +053012743 vos_mem_set((uint8_t *)&pHddCtx->bad_sta, HDD_MAX_STA_COUNT, 0);
12744
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053012745 // Register IPv4 notifier to notify if any change in IP
12746 // So that we can reconfigure the offload parameters
12747 pHddCtx->ipv4_notifier.notifier_call = wlan_hdd_ipv4_changed;
12748 ret = register_inetaddr_notifier(&pHddCtx->ipv4_notifier);
12749 if (ret)
12750 {
Ratheesh S P36dbc932015-08-07 14:28:57 +053012751 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Failed to register IPv4 notifier"));
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053012752 }
12753 else
12754 {
Ratheesh S P36dbc932015-08-07 14:28:57 +053012755 hddLog(VOS_TRACE_LEVEL_INFO, FL("Registered IPv4 notifier"));
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053012756 }
c_manjeecfd1efb2015-09-25 19:32:34 +053012757 /*Fw mem dump procfs initialization*/
12758 memdump_init();
Bhargav shah23c94942015-10-13 12:48:35 +053012759 hdd_dp_util_send_rps_ind(pHddCtx);
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053012760
Nishank Aggarwalc11826c2016-12-15 18:54:10 +053012761 pHddCtx->is_ap_mode_wow_supported =
12762 sme_IsFeatureSupportedByFW(SAP_MODE_WOW);
Sravan Kumar Kairam091e5b62017-01-23 14:14:20 +053012763
Hanumanth Reddy Pothulae92bcc12017-05-19 13:56:35 +053012764 pHddCtx->is_fatal_event_log_sup =
12765 sme_IsFeatureSupportedByFW(FATAL_EVENT_LOGGING);
12766 hddLog(VOS_TRACE_LEVEL_INFO, FL("FATAL_EVENT_LOGGING: %d"),
12767 pHddCtx->is_fatal_event_log_sup);
12768
Sravan Kumar Kairam091e5b62017-01-23 14:14:20 +053012769 hdd_assoc_registerFwdEapolCB(pVosContext);
12770
Jeff Johnson295189b2012-06-20 16:38:30 -070012771 goto success;
12772
Jeff Johnson295189b2012-06-20 16:38:30 -070012773err_reg_netdev:
12774 unregister_netdevice_notifier(&hdd_netdev_notifier);
12775
Jeff Johnson295189b2012-06-20 16:38:30 -070012776err_unregister_pmops:
12777 hddDevTmUnregisterNotifyCallback(pHddCtx);
12778 hddDeregisterPmOps(pHddCtx);
12779
Yue Ma0d4891e2013-08-06 17:01:45 -070012780 hdd_debugfs_exit(pHddCtx);
12781
Jeff Johnson295189b2012-06-20 16:38:30 -070012782#ifdef WLAN_BTAMP_FEATURE
12783err_bap_stop:
12784 WLANBAP_Stop(pVosContext);
12785#endif
12786
12787#ifdef WLAN_BTAMP_FEATURE
12788err_bap_close:
12789 WLANBAP_Close(pVosContext);
12790#endif
12791
Jeff Johnson295189b2012-06-20 16:38:30 -070012792err_close_adapter:
12793 hdd_close_all_adapters( pHddCtx );
Mahesh A Saptasagar9ecefe42014-07-15 18:43:49 +053012794#ifdef CONFIG_ENABLE_LINUX_REG
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053012795err_unregister_wiphy:
Mahesh A Saptasagar9ecefe42014-07-15 18:43:49 +053012796#endif
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +053012797 wiphy_unregister(wiphy) ;
Agrawal Ashish33ec71e2015-11-26 20:20:58 +053012798 hdd_wlan_free_wiphy_channels(wiphy);
12799
Jeff Johnson295189b2012-06-20 16:38:30 -070012800err_vosstop:
12801 vos_stop(pVosContext);
12802
Amar Singhala49cbc52013-10-08 18:37:44 -070012803err_vosclose:
Jeff Johnson295189b2012-06-20 16:38:30 -070012804 status = vos_sched_close( pVosContext );
12805 if (!VOS_IS_STATUS_SUCCESS(status)) {
12806 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
12807 "%s: Failed to close VOSS Scheduler", __func__);
12808 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
12809 }
Amar Singhala49cbc52013-10-08 18:37:44 -070012810 vos_close(pVosContext );
12811
Mahesh A Saptasagarc3ed0122016-01-19 16:45:11 +053012812err_nl_srv:
12813#ifdef WLAN_KD_READY_NOTIFIER
12814 nl_srv_exit(pHddCtx->ptt_pid);
12815#else
12816 nl_srv_exit();
12817#endif /* WLAN_KD_READY_NOTIFIER */
Amar Singhal0a402232013-10-11 20:57:16 -070012818err_vos_nv_close:
12819
c_hpothue6a36282014-03-19 12:27:38 +053012820#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -070012821 vos_nv_close();
12822
c_hpothu70f8d812014-03-22 22:59:23 +053012823#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070012824
12825err_wdclose:
12826 if(pHddCtx->cfg_ini->fIsLogpEnabled)
12827 vos_watchdog_close(pVosContext);
12828
Jeff Johnson295189b2012-06-20 16:38:30 -070012829err_config:
12830 kfree(pHddCtx->cfg_ini);
12831 pHddCtx->cfg_ini= NULL;
12832
12833err_free_hdd_context:
Sushant Kaushik83392fa2015-05-05 17:44:40 +053012834 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_INIT);
Siddharth Bhalcd92b782015-06-29 12:25:40 +053012835 free_riva_power_on_lock("wlan");
Jeff Johnson295189b2012-06-20 16:38:30 -070012836 wiphy_free(wiphy) ;
12837 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -070012838 VOS_BUG(1);
12839
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -080012840 if (hdd_is_ssr_required())
12841 {
12842 /* WDI timeout had happened during load, so SSR is needed here */
12843 subsystem_restart("wcnss");
12844 msleep(5000);
12845 }
12846 hdd_set_ssr_required (VOS_FALSE);
12847
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -080012848 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -070012849
12850success:
12851 EXIT();
12852 return 0;
12853}
12854
12855/**---------------------------------------------------------------------------
12856
Jeff Johnson32d95a32012-09-10 13:15:23 -070012857 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -070012858
Jeff Johnson32d95a32012-09-10 13:15:23 -070012859 This is the driver entry point - called in different timeline depending
12860 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -070012861
12862 \param - None
12863
12864 \return - 0 for success, non zero for failure
12865
12866 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -070012867static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -070012868{
12869 VOS_STATUS status;
12870 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -070012871 struct device *dev = NULL;
12872 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -070012873#ifdef HAVE_WCNSS_CAL_DOWNLOAD
12874 int max_retries = 0;
12875#endif
Siddharth Bhalc7e79b62014-10-10 22:37:38 +053012876#ifdef HAVE_CBC_DONE
12877 int max_cbc_retries = 0;
12878#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070012879
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +053012880#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
12881 wlan_logging_sock_init_svc();
12882#endif
12883
Jeff Johnson295189b2012-06-20 16:38:30 -070012884 ENTER();
12885
Sushant Kaushik83392fa2015-05-05 17:44:40 +053012886 vos_wake_lock_init(&wlan_wake_lock, "wlan");
Jeff Johnson295189b2012-06-20 16:38:30 -070012887
12888 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
12889 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
12890
Jeff Johnson295189b2012-06-20 16:38:30 -070012891#ifdef ANI_BUS_TYPE_PCI
12892
12893 dev = wcnss_wlan_get_device();
12894
12895#endif // ANI_BUS_TYPE_PCI
12896
12897#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -070012898
12899#ifdef HAVE_WCNSS_CAL_DOWNLOAD
12900 /* wait until WCNSS driver downloads NV */
Ravi Kumar Bokka7a139e62016-11-17 21:32:55 +053012901 while (!wcnss_device_ready() && 10 >= ++max_retries) {
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -070012902 msleep(1000);
12903 }
Siddharth Bhalc7e79b62014-10-10 22:37:38 +053012904
Ravi Kumar Bokka7a139e62016-11-17 21:32:55 +053012905 if (max_retries >= 10) {
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -070012906 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
Sushant Kaushik83392fa2015-05-05 17:44:40 +053012907 vos_wake_lock_destroy(&wlan_wake_lock);
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +053012908#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
12909 wlan_logging_sock_deinit_svc();
12910#endif
12911
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -070012912 return -ENODEV;
12913 }
12914#endif
12915
Siddharth Bhalc7e79b62014-10-10 22:37:38 +053012916#ifdef HAVE_CBC_DONE
12917 while (!wcnss_cbc_complete() && 10 >= ++max_cbc_retries) {
12918 msleep(1000);
12919 }
12920 if (max_cbc_retries >= 10) {
12921 hddLog(VOS_TRACE_LEVEL_FATAL, "%s:CBC not completed", __func__);
12922 }
12923#endif
12924
Jeff Johnson295189b2012-06-20 16:38:30 -070012925 dev = wcnss_wlan_get_device();
12926#endif // ANI_BUS_TYPE_PLATFORM
12927
12928
12929 do {
12930 if (NULL == dev) {
12931 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
12932 ret_status = -1;
12933 break;
12934 }
12935
Jeff Johnson295189b2012-06-20 16:38:30 -070012936#ifdef TIMER_MANAGER
12937 vos_timer_manager_init();
12938#endif
12939
12940 /* Preopen VOSS so that it is ready to start at least SAL */
12941 status = vos_preOpen(&pVosContext);
12942
12943 if (!VOS_IS_STATUS_SUCCESS(status))
12944 {
12945 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
12946 ret_status = -1;
12947 break;
12948 }
12949
Sushant Kaushik02beb352015-06-04 15:15:01 +053012950 hddTraceInit();
Padma, Santhosh Kumar9093b202015-07-21 15:37:38 +053012951 hdd_register_debug_callback();
12952
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070012953#ifndef MODULE
12954 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
12955 */
12956 hdd_set_conparam((v_UINT_t)con_mode);
12957#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070012958
12959 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -080012960 if (hdd_wlan_startup(dev))
12961 {
Jeff Johnson295189b2012-06-20 16:38:30 -070012962 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -080012963 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -070012964 vos_preClose( &pVosContext );
12965 ret_status = -1;
12966 break;
12967 }
12968
Jeff Johnson295189b2012-06-20 16:38:30 -070012969 } while (0);
12970
12971 if (0 != ret_status)
12972 {
Jeff Johnson295189b2012-06-20 16:38:30 -070012973#ifdef TIMER_MANAGER
12974 vos_timer_exit();
12975#endif
12976#ifdef MEMORY_DEBUG
12977 vos_mem_exit();
12978#endif
Sushant Kaushik83392fa2015-05-05 17:44:40 +053012979 vos_wake_lock_destroy(&wlan_wake_lock);
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +053012980#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
12981 wlan_logging_sock_deinit_svc();
12982#endif
12983
Jeff Johnson295189b2012-06-20 16:38:30 -070012984 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
12985 }
12986 else
12987 {
12988 //Send WLAN UP indication to Nlink Service
12989 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
12990
12991 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Jeff Johnson295189b2012-06-20 16:38:30 -070012992 }
12993
12994 EXIT();
12995
12996 return ret_status;
12997}
12998
Jeff Johnson32d95a32012-09-10 13:15:23 -070012999/**---------------------------------------------------------------------------
13000
13001 \brief hdd_module_init() - Init Function
13002
13003 This is the driver entry point (invoked when module is loaded using insmod)
13004
13005 \param - None
13006
13007 \return - 0 for success, non zero for failure
13008
13009 --------------------------------------------------------------------------*/
13010#ifdef MODULE
13011static int __init hdd_module_init ( void)
13012{
13013 return hdd_driver_init();
13014}
Jeff Johnson32d95a32012-09-10 13:15:23 -070013015#else /* #ifdef MODULE */
13016static int __init hdd_module_init ( void)
13017{
13018 /* Driver initialization is delayed to fwpath_changed_handler */
13019 return 0;
13020}
Jeff Johnson32d95a32012-09-10 13:15:23 -070013021#endif /* #ifdef MODULE */
13022
Jeff Johnson295189b2012-06-20 16:38:30 -070013023
13024/**---------------------------------------------------------------------------
13025
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070013026 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -070013027
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070013028 This is the driver exit point (invoked when module is unloaded using rmmod
13029 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -070013030
13031 \param - None
13032
13033 \return - None
13034
13035 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070013036static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -070013037{
13038 hdd_context_t *pHddCtx = NULL;
13039 v_CONTEXT_t pVosContext = NULL;
Agarwal Ashish5e414792014-06-08 15:25:23 +053013040 v_REGDOMAIN_t regId;
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +053013041 unsigned long rc = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -070013042
13043 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
13044
13045 //Get the global vos context
13046 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
13047
13048 if(!pVosContext)
13049 {
13050 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
13051 goto done;
13052 }
13053
13054 //Get the HDD context.
13055 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
13056
13057 if(!pHddCtx)
13058 {
13059 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
13060 }
Katya Nigame7b69a82015-04-28 15:24:06 +053013061 else if (VOS_MONITOR_MODE == hdd_get_conparam())
13062 {
13063 hddLog(VOS_TRACE_LEVEL_INFO,"%s: MONITOR MODE",__func__);
13064 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_UNLOAD_IN_PROGRESS;
13065 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
13066 hdd_wlan_exit(pHddCtx);
13067 vos_preClose( &pVosContext );
13068 goto done;
13069 }
Jeff Johnson295189b2012-06-20 16:38:30 -070013070 else
13071 {
Siddharth Bhal2e5871b2015-03-24 16:20:51 +053013072 /* We wait for active entry threads to exit from driver
13073 * by waiting until rtnl_lock is available.
13074 */
13075 rtnl_lock();
13076 rtnl_unlock();
13077
Siddharth Bhal3c29dca2015-02-19 00:41:40 +053013078 INIT_COMPLETION(pHddCtx->ssr_comp_var);
13079 if ((pHddCtx->isLogpInProgress) && (FALSE ==
13080 vos_is_wlan_in_badState(VOS_MODULE_ID_HDD, NULL)))
13081 {
Siddharth Bhala204f572015-01-17 02:03:36 +053013082 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Siddharth Bhal3c29dca2015-02-19 00:41:40 +053013083 "%s:SSR in Progress; block rmmod !!!", __func__);
Siddharth Bhala204f572015-01-17 02:03:36 +053013084 rc = wait_for_completion_timeout(&pHddCtx->ssr_comp_var,
13085 msecs_to_jiffies(30000));
13086 if(!rc)
13087 {
13088 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
13089 "%s:SSR timedout, fatal error", __func__);
13090 VOS_BUG(0);
13091 }
13092 }
13093
Siddharth Bhal3c29dca2015-02-19 00:41:40 +053013094 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_UNLOAD_IN_PROGRESS;
13095 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
Jeff Johnson295189b2012-06-20 16:38:30 -070013096
c_hpothu8adb97b2014-12-08 19:38:20 +053013097 /* Driver Need to send country code 00 in below condition
13098 * 1) If gCountryCodePriority is set to 1; and last country
13099 * code set is through 11d. This needs to be done in case
13100 * when NV country code is 00.
13101 * This Needs to be done as when kernel store last country
13102 * code and if stored country code is not through 11d,
13103 * in sme_HandleChangeCountryCodeByUser we will disable 11d
13104 * in next load/unload as soon as we get any country through
13105 * 11d. In sme_HandleChangeCountryCodeByUser
13106 * pMsg->countryCode will be last countryCode and
13107 * pMac->scan.countryCode11d will be country through 11d so
13108 * due to mismatch driver will disable 11d.
13109 *
13110 */
Agarwal Ashish8db39882014-07-30 21:56:07 +053013111
c_hpothu8adb97b2014-12-08 19:38:20 +053013112 if ((eANI_BOOLEAN_TRUE == sme_Is11dCountrycode(pHddCtx->hHal) &&
Agarwal Ashish8dcd2862014-07-25 11:58:52 +053013113 pHddCtx->cfg_ini->fSupplicantCountryCodeHasPriority &&
Abhishek Singh2a705962014-10-30 14:47:28 +053013114 sme_Is11dSupported(pHddCtx->hHal)))
c_hpothu8adb97b2014-12-08 19:38:20 +053013115 {
13116 hddLog(VOS_TRACE_LEVEL_INFO,
Agarwal Ashish8dcd2862014-07-25 11:58:52 +053013117 FL("CountryCode 00 is being set while unloading driver"));
c_hpothu8adb97b2014-12-08 19:38:20 +053013118 vos_nv_getRegDomainFromCountryCode(&regId , "00", COUNTRY_USER);
13119 }
Agarwal Ashish5e414792014-06-08 15:25:23 +053013120
c_hpothu8adb97b2014-12-08 19:38:20 +053013121 //Do all the cleanup before deregistering the driver
13122 hdd_wlan_exit(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -070013123 }
13124
Jeff Johnson295189b2012-06-20 16:38:30 -070013125 vos_preClose( &pVosContext );
13126
13127#ifdef TIMER_MANAGER
13128 vos_timer_exit();
13129#endif
13130#ifdef MEMORY_DEBUG
13131 vos_mem_exit();
13132#endif
13133
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +053013134#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
13135 wlan_logging_sock_deinit_svc();
13136#endif
13137
Jeff Johnson295189b2012-06-20 16:38:30 -070013138done:
Sushant Kaushik83392fa2015-05-05 17:44:40 +053013139 vos_wake_lock_destroy(&wlan_wake_lock);
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +053013140
Jeff Johnson295189b2012-06-20 16:38:30 -070013141 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
13142}
13143
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070013144/**---------------------------------------------------------------------------
13145
13146 \brief hdd_module_exit() - Exit function
13147
13148 This is the driver exit point (invoked when module is unloaded using rmmod)
13149
13150 \param - None
13151
13152 \return - None
13153
13154 --------------------------------------------------------------------------*/
13155static void __exit hdd_module_exit(void)
13156{
13157 hdd_driver_exit();
13158}
13159
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070013160#ifdef MODULE
13161static int fwpath_changed_handler(const char *kmessage,
13162 struct kernel_param *kp)
13163{
Jeff Johnson76052702013-04-16 13:55:05 -070013164 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070013165}
13166
13167static int con_mode_handler(const char *kmessage,
13168 struct kernel_param *kp)
13169{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -070013170 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070013171}
13172#else /* #ifdef MODULE */
13173/**---------------------------------------------------------------------------
13174
Jeff Johnson76052702013-04-16 13:55:05 -070013175 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070013176
Jeff Johnson76052702013-04-16 13:55:05 -070013177 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070013178 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -070013179 - invoked when module parameter fwpath is modified from userspace to signal
13180 initializing the WLAN driver or when con_mode is modified from userspace
13181 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070013182
13183 \return - 0 for success, non zero for failure
13184
13185 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -070013186static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070013187{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -070013188 int ret_status;
13189
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070013190 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -070013191 ret_status = hdd_driver_init();
13192 wlan_hdd_inited = ret_status ? 0 : 1;
13193 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070013194 }
13195
13196 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -070013197
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070013198 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -070013199
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -070013200 ret_status = hdd_driver_init();
13201 wlan_hdd_inited = ret_status ? 0 : 1;
13202 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070013203}
13204
Jeff Johnson295189b2012-06-20 16:38:30 -070013205/**---------------------------------------------------------------------------
13206
Jeff Johnson76052702013-04-16 13:55:05 -070013207 \brief fwpath_changed_handler() - Handler Function
13208
13209 Handle changes to the fwpath parameter
13210
13211 \return - 0 for success, non zero for failure
13212
13213 --------------------------------------------------------------------------*/
13214static int fwpath_changed_handler(const char *kmessage,
13215 struct kernel_param *kp)
13216{
13217 int ret;
13218
13219 ret = param_set_copystring(kmessage, kp);
13220 if (0 == ret)
13221 ret = kickstart_driver();
13222 return ret;
13223}
13224
13225/**---------------------------------------------------------------------------
13226
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070013227 \brief con_mode_handler() -
13228
13229 Handler function for module param con_mode when it is changed by userspace
13230 Dynamically linked - do nothing
13231 Statically linked - exit and init driver, as in rmmod and insmod
13232
Jeff Johnson76052702013-04-16 13:55:05 -070013233 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070013234
Jeff Johnson76052702013-04-16 13:55:05 -070013235 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070013236
13237 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -070013238static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070013239{
Jeff Johnson76052702013-04-16 13:55:05 -070013240 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070013241
Jeff Johnson76052702013-04-16 13:55:05 -070013242 ret = param_set_int(kmessage, kp);
13243 if (0 == ret)
13244 ret = kickstart_driver();
13245 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070013246}
13247#endif /* #ifdef MODULE */
13248
13249/**---------------------------------------------------------------------------
13250
Jeff Johnson295189b2012-06-20 16:38:30 -070013251 \brief hdd_get_conparam() -
13252
13253 This is the driver exit point (invoked when module is unloaded using rmmod)
13254
13255 \param - None
13256
13257 \return - tVOS_CON_MODE
13258
13259 --------------------------------------------------------------------------*/
13260tVOS_CON_MODE hdd_get_conparam ( void )
13261{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070013262#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -070013263 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070013264#else
13265 return (tVOS_CON_MODE)curr_con_mode;
13266#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070013267}
13268void hdd_set_conparam ( v_UINT_t newParam )
13269{
13270 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070013271#ifndef MODULE
13272 curr_con_mode = con_mode;
13273#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070013274}
13275/**---------------------------------------------------------------------------
13276
13277 \brief hdd_softap_sta_deauth() - function
13278
13279 This to take counter measure to handle deauth req from HDD
13280
13281 \param - pAdapter - Pointer to the HDD
13282
13283 \param - enable - boolean value
13284
13285 \return - None
13286
13287 --------------------------------------------------------------------------*/
13288
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +053013289VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter,
13290 struct tagCsrDelStaParams *pDelStaParams)
Jeff Johnson295189b2012-06-20 16:38:30 -070013291{
Jeff Johnson295189b2012-06-20 16:38:30 -070013292 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -080013293 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -070013294
13295 ENTER();
13296
Rajesh Chauhan18488fc2013-08-22 10:15:03 -070013297 hddLog(LOG1, "hdd_softap_sta_deauth:(%p, false)",
13298 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -070013299
13300 //Ignore request to deauth bcmc station
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +053013301 if (pDelStaParams->peerMacAddr[0] & 0x1)
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -080013302 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -070013303
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +053013304 vosStatus = WLANSAP_DeauthSta(pVosContext, pDelStaParams);
Jeff Johnson295189b2012-06-20 16:38:30 -070013305
13306 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -080013307 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -070013308}
13309
13310/**---------------------------------------------------------------------------
13311
Rashmi Ramanna1f0948d2014-08-28 15:33:48 +053013312 \brief hdd_del_all_sta() - function
13313
13314 This function removes all the stations associated on stopping AP/P2P GO.
13315
13316 \param - pAdapter - Pointer to the HDD
13317
13318 \return - None
13319
13320 --------------------------------------------------------------------------*/
13321
13322int hdd_del_all_sta(hdd_adapter_t *pAdapter)
13323{
13324 v_U16_t i;
13325 VOS_STATUS vos_status;
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +053013326 v_CONTEXT_t pVosContext = ( WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
13327 ptSapContext pSapCtx = NULL;
13328 pSapCtx = VOS_GET_SAP_CB(pVosContext);
13329 if(pSapCtx == NULL){
13330 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
13331 FL("psapCtx is NULL"));
13332 return 1;
13333 }
Rashmi Ramanna1f0948d2014-08-28 15:33:48 +053013334 ENTER();
13335
13336 hddLog(VOS_TRACE_LEVEL_INFO,
13337 "%s: Delete all STAs associated.",__func__);
13338 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
13339 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
13340 )
13341 {
13342 for(i = 0; i < WLAN_MAX_STA_COUNT; i++)
13343 {
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +053013344 if ((pSapCtx->aStaInfo[i].isUsed) &&
13345 (!pSapCtx->aStaInfo[i].isDeauthInProgress))
Rashmi Ramanna1f0948d2014-08-28 15:33:48 +053013346 {
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +053013347 struct tagCsrDelStaParams delStaParams;
13348
13349 WLANSAP_PopulateDelStaParams(
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +053013350 pSapCtx->aStaInfo[i].macAddrSTA.bytes,
Sushant Kaushik4cd28f62014-12-26 14:23:50 +053013351 eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
13352 SIR_MAC_MGMT_DEAUTH >> 4,
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +053013353 &delStaParams);
13354 vos_status = hdd_softap_sta_deauth(pAdapter, &delStaParams);
Rashmi Ramanna1f0948d2014-08-28 15:33:48 +053013355 if (VOS_IS_STATUS_SUCCESS(vos_status))
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +053013356 pSapCtx->aStaInfo[i].isDeauthInProgress = TRUE;
Rashmi Ramanna1f0948d2014-08-28 15:33:48 +053013357 }
13358 }
13359 }
13360
13361 EXIT();
13362 return 0;
13363}
13364
13365/**---------------------------------------------------------------------------
13366
Jeff Johnson295189b2012-06-20 16:38:30 -070013367 \brief hdd_softap_sta_disassoc() - function
13368
13369 This to take counter measure to handle deauth req from HDD
13370
13371 \param - pAdapter - Pointer to the HDD
13372
13373 \param - enable - boolean value
13374
13375 \return - None
13376
13377 --------------------------------------------------------------------------*/
13378
13379void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
13380{
13381 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
13382
13383 ENTER();
13384
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +053013385 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -070013386
13387 //Ignore request to disassoc bcmc station
13388 if( pDestMacAddress[0] & 0x1 )
13389 return;
13390
13391 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
13392}
13393
13394void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
13395{
13396 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
13397
13398 ENTER();
13399
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +053013400 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -070013401
13402 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
13403}
13404
Jeff Johnson295189b2012-06-20 16:38:30 -070013405/**---------------------------------------------------------------------------
13406 *
13407 * \brief hdd_get__concurrency_mode() -
13408 *
13409 *
13410 * \param - None
13411 *
13412 * \return - CONCURRENCY MODE
13413 *
13414 * --------------------------------------------------------------------------*/
13415tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
13416{
13417 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
13418 hdd_context_t *pHddCtx;
13419
13420 if (NULL != pVosContext)
13421 {
13422 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
13423 if (NULL != pHddCtx)
13424 {
13425 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
13426 }
13427 }
13428
13429 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070013430 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -070013431 return VOS_STA;
13432}
Sushant Kaushikabb7ee62014-07-18 16:20:12 +053013433v_BOOL_t
13434wlan_hdd_is_GO_power_collapse_allowed (hdd_context_t* pHddCtx)
13435{
13436 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -070013437
Sushant Kaushikabb7ee62014-07-18 16:20:12 +053013438 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_GO);
13439 if (pAdapter == NULL)
13440 {
13441 hddLog(VOS_TRACE_LEVEL_INFO,
13442 FL("GO doesn't exist"));
13443 return TRUE;
13444 }
13445 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
13446 {
13447 hddLog(VOS_TRACE_LEVEL_INFO,
13448 FL("GO started"));
13449 return TRUE;
13450 }
13451 else
13452 /* wait till GO changes its interface to p2p device */
13453 hddLog(VOS_TRACE_LEVEL_INFO,
13454 FL("Del_bss called, avoid apps suspend"));
13455 return FALSE;
13456
13457}
Jeff Johnson295189b2012-06-20 16:38:30 -070013458/* Decide whether to allow/not the apps power collapse.
13459 * Allow apps power collapse if we are in connected state.
13460 * if not, allow only if we are in IMPS */
13461v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
13462{
13463 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -080013464 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -080013465 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -070013466 hdd_config_t *pConfig = pHddCtx->cfg_ini;
13467 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
13468 hdd_adapter_t *pAdapter = NULL;
13469 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -080013470 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -070013471
Jeff Johnson295189b2012-06-20 16:38:30 -070013472 if (VOS_STA_SAP_MODE == hdd_get_conparam())
13473 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -070013474
Yathish9f22e662012-12-10 14:21:35 -080013475 concurrent_state = hdd_get_concurrency_mode();
13476
Sushant Kaushikabb7ee62014-07-18 16:20:12 +053013477 if ((concurrent_state == (VOS_STA | VOS_P2P_GO)) &&
13478 !(wlan_hdd_is_GO_power_collapse_allowed(pHddCtx)))
13479 return FALSE;
Yathish9f22e662012-12-10 14:21:35 -080013480#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
Sushant Kaushikabb7ee62014-07-18 16:20:12 +053013481
Yathish9f22e662012-12-10 14:21:35 -080013482 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
Sushant Kaushikabb7ee62014-07-18 16:20:12 +053013483 (concurrent_state == (VOS_STA | VOS_P2P_GO)))&&
Yathish9f22e662012-12-10 14:21:35 -080013484 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
13485 return TRUE;
13486#endif
13487
Jeff Johnson295189b2012-06-20 16:38:30 -070013488 /*loop through all adapters. TBD fix for Concurrency */
13489 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
13490 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
13491 {
13492 pAdapter = pAdapterNode->pAdapter;
13493 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
13494 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
13495 {
Srikant Kuppafef66a72013-01-30 17:32:44 -080013496 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
c_hpothu4e8faac2014-05-16 17:38:44 +053013497 && (pmcState != IMPS && pmcState != BMPS && pmcState != UAPSD
c_hpothu1c6957d2015-01-06 18:19:47 +053013498 && pmcState != STOPPED && pmcState != STANDBY &&
13499 pmcState != WOWL)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -080013500 (eANI_BOOLEAN_TRUE == scanRspPending) ||
13501 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -070013502 {
Mukul Sharma4be88422015-03-09 20:29:07 +053013503 if(pmcState == FULL_POWER &&
13504 sme_IsCoexScoIndicationSet(pHddCtx->hHal))
13505 {
13506 /*
13507 * When SCO indication comes from Coex module , host will
13508 * enter in to full power mode, but this should not prevent
13509 * apps processor power collapse.
13510 */
13511 hddLog(LOG1,
13512 FL("Allow apps power collapse"
13513 "even when sco indication is set"));
13514 return TRUE;
13515 }
Srikant Kuppafef66a72013-01-30 17:32:44 -080013516 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Deepthi Gowri03a979f2016-11-03 15:20:19 +053013517 "pmcState = %d scanRspPending = %d "
13518 "inMiddleOfRoaming = %d connected = %d",
13519 __func__, pmcState, scanRspPending,
13520 inMiddleOfRoaming, hdd_connIsConnected(
13521 WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )));
13522 wlan_hdd_get_tdls_stats(pAdapter);
13523 return FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -070013524 }
13525 }
13526 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
13527 pAdapterNode = pNext;
13528 }
13529 return TRUE;
13530}
13531
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -080013532/* Decides whether to send suspend notification to Riva
13533 * if any adapter is in BMPS; then it is required */
13534v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
13535{
13536 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
13537 hdd_config_t *pConfig = pHddCtx->cfg_ini;
13538
13539 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
13540 {
13541 return TRUE;
13542 }
13543 return FALSE;
13544}
13545
Jeff Johnson295189b2012-06-20 16:38:30 -070013546void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
13547{
13548 switch(mode)
13549 {
Chilam Ngc4244af2013-04-01 15:37:32 -070013550 case VOS_STA_MODE:
13551 case VOS_P2P_CLIENT_MODE:
13552 case VOS_P2P_GO_MODE:
13553 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -070013554 pHddCtx->concurrency_mode |= (1 << mode);
Agarwal Ashish51325b52014-06-16 16:50:49 +053013555 pHddCtx->no_of_open_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -070013556 break;
13557 default:
13558 break;
Jeff Johnson295189b2012-06-20 16:38:30 -070013559 }
Agarwal Ashish51325b52014-06-16 16:50:49 +053013560 hddLog(VOS_TRACE_LEVEL_INFO, FL("concurrency_mode = 0x%x "
13561 "Number of open sessions for mode %d = %d"),
13562 pHddCtx->concurrency_mode, mode,
13563 pHddCtx->no_of_open_sessions[mode]);
Jeff Johnson295189b2012-06-20 16:38:30 -070013564}
13565
13566
13567void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
13568{
13569 switch(mode)
13570 {
Chilam Ngc4244af2013-04-01 15:37:32 -070013571 case VOS_STA_MODE:
13572 case VOS_P2P_CLIENT_MODE:
13573 case VOS_P2P_GO_MODE:
13574 case VOS_STA_SAP_MODE:
Agarwal Ashish51325b52014-06-16 16:50:49 +053013575 pHddCtx->no_of_open_sessions[mode]--;
13576 if (!(pHddCtx->no_of_open_sessions[mode]))
13577 pHddCtx->concurrency_mode &= (~(1 << mode));
Jeff Johnson295189b2012-06-20 16:38:30 -070013578 break;
13579 default:
13580 break;
13581 }
Agarwal Ashish51325b52014-06-16 16:50:49 +053013582 hddLog(VOS_TRACE_LEVEL_INFO, FL("concurrency_mode = 0x%x "
13583 "Number of open sessions for mode %d = %d"),
13584 pHddCtx->concurrency_mode, mode, pHddCtx->no_of_open_sessions[mode]);
13585
13586}
13587/**---------------------------------------------------------------------------
13588 *
13589 * \brief wlan_hdd_incr_active_session()
13590 *
13591 * This function increments the number of active sessions
13592 * maintained per device mode
13593 * Incase of STA/P2P CLI/IBSS upon connection indication it is incremented
13594 * Incase of SAP/P2P GO upon bss start it is incremented
13595 *
13596 * \param pHddCtx - HDD Context
13597 * \param mode - device mode
13598 *
13599 * \return - None
13600 *
13601 * --------------------------------------------------------------------------*/
13602void wlan_hdd_incr_active_session(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
13603{
13604 switch (mode) {
13605 case VOS_STA_MODE:
13606 case VOS_P2P_CLIENT_MODE:
13607 case VOS_P2P_GO_MODE:
13608 case VOS_STA_SAP_MODE:
13609 pHddCtx->no_of_active_sessions[mode]++;
13610 break;
13611 default:
13612 hddLog(VOS_TRACE_LEVEL_INFO, FL("Not Expected Mode %d"), mode);
13613 break;
13614 }
13615 hddLog(VOS_TRACE_LEVEL_INFO, FL("No.# of active sessions for mode %d = %d"),
13616 mode,
13617 pHddCtx->no_of_active_sessions[mode]);
13618}
13619
13620/**---------------------------------------------------------------------------
13621 *
13622 * \brief wlan_hdd_decr_active_session()
13623 *
13624 * This function decrements the number of active sessions
13625 * maintained per device mode
13626 * Incase of STA/P2P CLI/IBSS upon disconnection it is decremented
13627 * Incase of SAP/P2P GO upon bss stop it is decremented
13628 *
13629 * \param pHddCtx - HDD Context
13630 * \param mode - device mode
13631 *
13632 * \return - None
13633 *
13634 * --------------------------------------------------------------------------*/
13635void wlan_hdd_decr_active_session(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
13636{
Bhargav Shahd0715912015-10-01 18:17:37 +053013637
Agarwal Ashish51325b52014-06-16 16:50:49 +053013638 switch (mode) {
13639 case VOS_STA_MODE:
13640 case VOS_P2P_CLIENT_MODE:
13641 case VOS_P2P_GO_MODE:
13642 case VOS_STA_SAP_MODE:
Agarwal Ashish5325f522014-08-06 00:58:44 +053013643 if (pHddCtx->no_of_active_sessions[mode] > 0)
13644 pHddCtx->no_of_active_sessions[mode]--;
13645 else
13646 hddLog(VOS_TRACE_LEVEL_INFO, FL(" No.# of Active sessions"
13647 "is already Zero"));
Agarwal Ashish51325b52014-06-16 16:50:49 +053013648 break;
13649 default:
13650 hddLog(VOS_TRACE_LEVEL_INFO, FL("Not Expected Mode %d"), mode);
13651 break;
13652 }
13653 hddLog(VOS_TRACE_LEVEL_INFO, FL("No.# of active sessions for mode %d = %d"),
13654 mode,
13655 pHddCtx->no_of_active_sessions[mode]);
Jeff Johnson295189b2012-06-20 16:38:30 -070013656}
13657
Jeff Johnsone7245742012-09-05 17:12:55 -070013658/**---------------------------------------------------------------------------
13659 *
13660 * \brief wlan_hdd_restart_init
13661 *
13662 * This function initalizes restart timer/flag. An internal function.
13663 *
13664 * \param - pHddCtx
13665 *
13666 * \return - None
13667 *
13668 * --------------------------------------------------------------------------*/
13669
13670static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
13671{
13672 /* Initialize */
13673 pHddCtx->hdd_restart_retries = 0;
13674 atomic_set(&pHddCtx->isRestartInProgress, 0);
13675 vos_timer_init(&pHddCtx->hdd_restart_timer,
13676 VOS_TIMER_TYPE_SW,
13677 wlan_hdd_restart_timer_cb,
13678 pHddCtx);
13679}
13680/**---------------------------------------------------------------------------
13681 *
13682 * \brief wlan_hdd_restart_deinit
13683 *
13684 * This function cleans up the resources used. An internal function.
13685 *
13686 * \param - pHddCtx
13687 *
13688 * \return - None
13689 *
13690 * --------------------------------------------------------------------------*/
13691
13692static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
13693{
13694
13695 VOS_STATUS vos_status;
13696 /* Block any further calls */
13697 atomic_set(&pHddCtx->isRestartInProgress, 1);
13698 /* Cleanup */
13699 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
13700 if (!VOS_IS_STATUS_SUCCESS(vos_status))
c_hpothu6ff1c3c2013-10-01 19:01:57 +053013701 hddLog(LOGE, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -070013702 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
13703 if (!VOS_IS_STATUS_SUCCESS(vos_status))
c_hpothu6ff1c3c2013-10-01 19:01:57 +053013704 hddLog(LOGE, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -070013705
13706}
13707
13708/**---------------------------------------------------------------------------
13709 *
13710 * \brief wlan_hdd_framework_restart
13711 *
13712 * This function uses a cfg80211 API to start a framework initiated WLAN
13713 * driver module unload/load.
13714 *
13715 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
13716 *
13717 *
13718 * \param - pHddCtx
13719 *
13720 * \return - VOS_STATUS_SUCCESS: Success
13721 * VOS_STATUS_E_EMPTY: Adapter is Empty
13722 * VOS_STATUS_E_NOMEM: No memory
13723
13724 * --------------------------------------------------------------------------*/
13725
13726static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
13727{
13728 VOS_STATUS status = VOS_STATUS_SUCCESS;
13729 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -070013730 int len = (sizeof (struct ieee80211_mgmt));
13731 struct ieee80211_mgmt *mgmt = NULL;
13732
13733 /* Prepare the DEAUTH managment frame with reason code */
13734 mgmt = kzalloc(len, GFP_KERNEL);
13735 if(mgmt == NULL)
13736 {
13737 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
13738 "%s: memory allocation failed (%d bytes)", __func__, len);
13739 return VOS_STATUS_E_NOMEM;
13740 }
13741 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -070013742
13743 /* Iterate over all adapters/devices */
13744 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Hanumantha Reddy Pothulada0fe362015-02-27 18:37:03 +053013745 if ((NULL == pAdapterNode) || (VOS_STATUS_SUCCESS != status))
13746 {
13747 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
13748 FL("fail to get adapter: %p %d"), pAdapterNode, status);
13749 goto end;
13750 }
13751
Jeff Johnsone7245742012-09-05 17:12:55 -070013752 do
13753 {
Hanumantha Reddy Pothulada0fe362015-02-27 18:37:03 +053013754 if(pAdapterNode->pAdapter &&
13755 WLAN_HDD_ADAPTER_MAGIC == pAdapterNode->pAdapter->magic)
Jeff Johnsone7245742012-09-05 17:12:55 -070013756 {
13757 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
13758 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
13759 pAdapterNode->pAdapter->dev->name,
13760 pAdapterNode->pAdapter->device_mode,
13761 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -070013762 /*
13763 * CFG80211 event to restart the driver
13764 *
13765 * 'cfg80211_send_unprot_deauth' sends a
13766 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
13767 * of SME(Linux Kernel) state machine.
13768 *
13769 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
13770 * the driver.
13771 *
13772 */
Abhishek Singh00b71972016-01-07 10:51:04 +053013773
Anand N Sunkade9adb1b2015-07-29 09:56:45 +053013774#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
13775 cfg80211_rx_unprot_mlme_mgmt(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len);
13776#else
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -070013777 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Anand N Sunkade9adb1b2015-07-29 09:56:45 +053013778#endif
Jeff Johnsone7245742012-09-05 17:12:55 -070013779 }
13780 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
13781 pAdapterNode = pNext;
13782 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
13783
Hanumantha Reddy Pothulada0fe362015-02-27 18:37:03 +053013784 end:
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -070013785 /* Free the allocated management frame */
13786 kfree(mgmt);
13787
Jeff Johnsone7245742012-09-05 17:12:55 -070013788 /* Retry until we unload or reach max count */
13789 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
13790 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
13791
13792 return status;
13793
13794}
13795/**---------------------------------------------------------------------------
13796 *
13797 * \brief wlan_hdd_restart_timer_cb
13798 *
13799 * Restart timer callback. An internal function.
13800 *
13801 * \param - User data:
13802 *
13803 * \return - None
13804 *
13805 * --------------------------------------------------------------------------*/
13806
13807void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
13808{
13809 hdd_context_t *pHddCtx = usrDataForCallback;
13810 wlan_hdd_framework_restart(pHddCtx);
13811 return;
13812
13813}
13814
13815
13816/**---------------------------------------------------------------------------
13817 *
13818 * \brief wlan_hdd_restart_driver
13819 *
13820 * This function sends an event to supplicant to restart the WLAN driver.
13821 *
13822 * This function is called from vos_wlanRestart.
13823 *
13824 * \param - pHddCtx
13825 *
13826 * \return - VOS_STATUS_SUCCESS: Success
13827 * VOS_STATUS_E_EMPTY: Adapter is Empty
13828 * VOS_STATUS_E_ALREADY: Request already in progress
13829
13830 * --------------------------------------------------------------------------*/
13831VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
13832{
13833 VOS_STATUS status = VOS_STATUS_SUCCESS;
13834
13835 /* A tight check to make sure reentrancy */
13836 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
13837 {
Mihir Shetefd528652014-06-23 19:07:50 +053013838 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnsone7245742012-09-05 17:12:55 -070013839 "%s: WLAN restart is already in progress", __func__);
13840
13841 return VOS_STATUS_E_ALREADY;
13842 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -070013843 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -080013844#ifdef HAVE_WCNSS_RESET_INTR
Siddharth Bhal864e7e82015-04-07 20:07:24 +053013845 wcnss_reset_fiq(TRUE);
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -070013846#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -070013847
Jeff Johnsone7245742012-09-05 17:12:55 -070013848 return status;
13849}
13850
Bhargav Shahd0715912015-10-01 18:17:37 +053013851/**
13852 * hdd_get_total_sessions() - provide total number of active sessions
13853 * @pHddCtx: Valid Global HDD context pointer
13854 *
13855 * This function iterates through pAdaptors and find the number of all active
13856 * sessions. This active sessions includes connected sta, p2p client and number
13857 * of client connected to sap/p2p go.
13858 *
13859 * Return: Total number of active sessions.
13860 */
13861v_U8_t hdd_get_total_sessions(hdd_context_t *pHddCtx)
13862{
13863 v_U8_t active_session = 0;
13864 hdd_station_ctx_t *pHddStaCtx;
13865 hdd_adapter_list_node_t *pAdapterNode, *pNext;
13866 hdd_adapter_t *pAdapter;
13867 VOS_STATUS status;
13868
13869 status = hdd_get_front_adapter(pHddCtx, &pAdapterNode);
13870 while (NULL != pAdapterNode && VOS_STATUS_SUCCESS == status) {
13871 pAdapter = pAdapterNode->pAdapter;
13872 switch (pAdapter->device_mode) {
13873 case VOS_STA_MODE:
13874 case VOS_P2P_CLIENT_MODE:
13875 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13876 if(eConnectionState_Associated == pHddStaCtx->conn_info.connState)
13877 active_session += 1;
13878 break;
13879 case VOS_STA_SAP_MODE:
13880 case VOS_P2P_GO_MODE:
13881 active_session += hdd_softap_get_connected_sta(pAdapter);
13882 break;
13883 default:
13884 break;
13885 }
13886
13887 status = hdd_get_next_adapter(pHddCtx, pAdapterNode, &pNext);
13888 pAdapterNode = pNext;
13889 }
13890
13891 return active_session;
13892}
13893
13894/**
13895 * hdd_set_delack_value() - Set delack value
13896 * @pHddCtx: Valid Global HDD context pointer
13897 * @next_rx_level: Value to set for delack
13898 *
13899 * This function compare present value and next value of delack. If the both
13900 * are diffrent then it sets next value .
13901 *
13902 * Return: void.
13903 */
13904void hdd_set_delack_value(hdd_context_t *pHddCtx, v_U32_t next_rx_level)
13905{
13906 if (pHddCtx->cur_rx_level != next_rx_level) {
13907 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_DEBUG,
13908 "%s: TCP DELACK trigger level %d",
13909 __func__, next_rx_level);
13910 mutex_lock(&pHddCtx->cur_rx_level_lock);
13911 pHddCtx->cur_rx_level = next_rx_level;
13912 mutex_unlock(&pHddCtx->cur_rx_level_lock);
13913 wlan_hdd_send_svc_nlink_msg(WLAN_SVC_WLAN_TP_IND, &next_rx_level,
13914 sizeof(next_rx_level));
13915 }
13916}
13917
13918/**
13919 * hdd_set_default_stop_delack_timer() - Start delack timer
13920 * @pHddCtx: Valid Global HDD context pointer
13921 *
13922 * This function stop delack timer and set delack value to default..
13923 *
13924 * Return: void.
13925 */
13926
13927void hdd_set_default_stop_delack_timer(hdd_context_t *pHddCtx)
13928{
13929 if (VOS_TIMER_STATE_RUNNING !=
13930 vos_timer_getCurrentState(&pHddCtx->delack_timer)) {
13931 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_DEBUG,
13932 "%s: Can not stop timer", __func__);
13933 return;
13934 }
13935
13936 vos_timer_stop(&pHddCtx->delack_timer);
13937 hdd_set_delack_value(pHddCtx, TP_IND_LOW);
13938}
13939
13940/**
13941 * hdd_start_delack_timer() - Start delack timer
13942 * @pHddCtx: Valid Global HDD context pointer
13943 *
13944 * This function starts the delack timer for tcpDelAckComputeInterval time
13945 * interval.The default timer value is 2 second.
13946 *
13947 * Return: void.
13948 */
13949void hdd_start_delack_timer(hdd_context_t *pHddCtx)
13950{
13951 if (VOS_TIMER_STATE_RUNNING ==
13952 vos_timer_getCurrentState(&pHddCtx->delack_timer)) {
13953 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_DEBUG,
13954 "%s: Timer is already running", __func__);
13955 return;
13956 }
13957
13958 vos_timer_start(&pHddCtx->delack_timer,
13959 pHddCtx->cfg_ini->tcpDelAckComputeInterval);
13960}
13961
13962/**
13963 * hdd_update_prev_rx_packet_count() - Update previous rx packet count
13964 * @pHddCtx: Valid Global HDD context pointer
13965 *
13966 * This function updates the prev_rx_packets count from the corresponding
13967 * pAdapter states. This prev_rx_packets will diffed with the packet count
13968 * at the end of delack timer. That can give number of RX packet is spacific
13969 * time.
13970 *
13971 * Return: void.
13972 */
13973void hdd_update_prev_rx_packet_count(hdd_context_t *pHddCtx)
13974{
13975 hdd_adapter_list_node_t *pAdapterNode, *pNext;
13976 hdd_adapter_t *pAdapter;
13977 VOS_STATUS status;
13978
13979 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
13980 while (NULL != pAdapterNode && VOS_STATUS_SUCCESS == status) {
13981 pAdapter = pAdapterNode->pAdapter;
13982 pAdapter->prev_rx_packets = pAdapter->stats.rx_packets;
13983 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
13984 pAdapterNode = pNext;
13985 }
13986}
13987
13988/**
13989 * hdd_manage_delack_timer() - start\stop delack timer
13990 * @pHddCtx: Valid Global HDD context pointer
13991 *
13992 * This function check the number of concerent session present, it starts the
13993 * delack timer if only one session is present.
13994 * In the case of BT_COEX and TDLS mode it blindly stop delack functionality.
13995 *
13996 * Return: void.
13997 */
13998void hdd_manage_delack_timer(hdd_context_t *pHddCtx)
13999{
14000 uint8_t sessions;
14001
14002 if (!pHddCtx->cfg_ini->enable_delack) {
14003 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_DEBUG,
14004 "%s: TCP DELACK is not enabled", __func__);
14005 return;
14006 }
14007
14008 /* Blindly stop timer of BTCOEX and TDLS Session is up */
14009 if (pHddCtx->mode != 0) {
14010 hdd_set_default_stop_delack_timer(pHddCtx);
14011 return;
14012 }
14013
14014 sessions = hdd_get_total_sessions(pHddCtx);
14015 if (sessions == 1) {
14016 hdd_update_prev_rx_packet_count(pHddCtx);
14017 hdd_start_delack_timer(pHddCtx);
14018 } else {
14019 hdd_set_default_stop_delack_timer(pHddCtx);
14020 }
14021}
14022
Mihir Shetee1093ba2014-01-21 20:13:32 +053014023/**---------------------------------------------------------------------------
14024 *
14025 * \brief wlan_hdd_init_channels
14026 *
14027 * This function is used to initialize the channel list in CSR
14028 *
14029 * This function is called from hdd_wlan_startup
14030 *
14031 * \param - pHddCtx: HDD context
14032 *
14033 * \return - VOS_STATUS_SUCCESS: Success
14034 * VOS_STATUS_E_FAULT: Failure reported by SME
14035
14036 * --------------------------------------------------------------------------*/
14037static VOS_STATUS wlan_hdd_init_channels(hdd_context_t *pHddCtx)
14038{
14039 eHalStatus status;
14040
14041 status = sme_InitChannels(pHddCtx->hHal);
14042 if (HAL_STATUS_SUCCESS(status))
14043 {
14044 return VOS_STATUS_SUCCESS;
14045 }
14046 else
14047 {
14048 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Channel initialization failed(%d)",
14049 __func__, status);
14050 return VOS_STATUS_E_FAULT;
14051 }
14052}
14053
Mihir Shete04206452014-11-20 17:50:58 +053014054#ifdef CONFIG_ENABLE_LINUX_REG
Agarwal Ashish6db9d532014-09-30 18:19:10 +053014055VOS_STATUS wlan_hdd_init_channels_for_cc(hdd_context_t *pHddCtx, driver_load_type init )
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053014056{
14057 eHalStatus status;
14058
Agarwal Ashish6db9d532014-09-30 18:19:10 +053014059 status = sme_InitChannelsForCC(pHddCtx->hHal, init);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053014060 if (HAL_STATUS_SUCCESS(status))
14061 {
14062 return VOS_STATUS_SUCCESS;
14063 }
14064 else
14065 {
14066 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Issue reg hint failed(%d)",
14067 __func__, status);
14068 return VOS_STATUS_E_FAULT;
14069 }
14070}
Mihir Shete04206452014-11-20 17:50:58 +053014071#endif
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -070014072/*
14073 * API to find if there is any STA or P2P-Client is connected
14074 */
14075VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
14076{
14077 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
14078}
Jeff Johnsone7245742012-09-05 17:12:55 -070014079
Mihir Shetee2ae82a2015-03-16 14:08:49 +053014080
14081/*
14082 * API to find if the firmware will send logs using DXE channel
14083 */
14084v_U8_t hdd_is_fw_logging_enabled(void)
14085{
14086 hdd_context_t *pHddCtx;
14087
14088 pHddCtx = vos_get_context(VOS_MODULE_ID_HDD,
14089 vos_get_global_context(VOS_MODULE_ID_HDD, NULL));
14090
Sachin Ahuja084313e2015-05-21 17:57:10 +053014091 return (pHddCtx && pHddCtx->cfg_ini->enableMgmtLogging);
Mihir Shetee2ae82a2015-03-16 14:08:49 +053014092}
14093
Agarwal Ashish57e84372014-12-05 18:26:53 +053014094/*
Mihir Shetebe94ebb2015-05-26 12:07:14 +053014095 * API to find if the firmware will send trace logs using DXE channel
14096 */
14097v_U8_t hdd_is_fw_ev_logging_enabled(void)
14098{
14099 hdd_context_t *pHddCtx;
14100
14101 pHddCtx = vos_get_context(VOS_MODULE_ID_HDD,
14102 vos_get_global_context(VOS_MODULE_ID_HDD, NULL));
14103
14104 return (pHddCtx && pHddCtx->cfg_ini->enableFWLogging);
14105}
14106/*
Agarwal Ashish57e84372014-12-05 18:26:53 +053014107 * API to find if there is any session connected
14108 */
14109VOS_STATUS hdd_is_any_session_connected(hdd_context_t *pHddCtx)
14110{
14111 return sme_is_any_session_connected(pHddCtx->hHal);
14112}
14113
14114
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053014115int wlan_hdd_scan_abort(hdd_adapter_t *pAdapter)
14116{
14117 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14118 hdd_scaninfo_t *pScanInfo = NULL;
Girish Gowli4bf7a632014-06-12 13:42:11 +053014119 long status = 0;
c_hpothua3d45d52015-01-05 14:11:17 +053014120 tSirAbortScanStatus abortScanStatus;
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053014121
14122 pScanInfo = &pHddCtx->scan_info;
Ratnam Rachuric7681132015-06-30 10:35:13 +053014123 INIT_COMPLETION(pScanInfo->abortscan_event_var);
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053014124 if (pScanInfo->mScanPending)
14125 {
c_hpothua3d45d52015-01-05 14:11:17 +053014126 abortScanStatus = hdd_abort_mac_scan(pHddCtx, pScanInfo->sessionId,
14127 eCSR_SCAN_ABORT_DEFAULT);
14128 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
14129 FL("abortScanStatus: %d"), abortScanStatus);
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053014130
c_hpothua3d45d52015-01-05 14:11:17 +053014131 /* If there is active scan command lets wait for the completion else
14132 * there is no need to wait as scan command might be in the SME pending
14133 * command list.
14134 */
14135 if (abortScanStatus == eSIR_ABORT_ACTIVE_SCAN_LIST_NOT_EMPTY)
14136 {
c_hpothua3d45d52015-01-05 14:11:17 +053014137 status = wait_for_completion_interruptible_timeout(
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053014138 &pScanInfo->abortscan_event_var,
14139 msecs_to_jiffies(5000));
c_hpothua3d45d52015-01-05 14:11:17 +053014140 if (0 >= status)
14141 {
14142 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Girish Gowli4bf7a632014-06-12 13:42:11 +053014143 "%s: Timeout or Interrupt occurred while waiting for abort"
14144 "scan, status- %ld", __func__, status);
c_hpothua3d45d52015-01-05 14:11:17 +053014145 return -ETIMEDOUT;
14146 }
14147 }
14148 else if (abortScanStatus == eSIR_ABORT_SCAN_FAILURE)
14149 {
14150 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
14151 FL("hdd_abort_mac_scan failed"));
14152 return -VOS_STATUS_E_FAILURE;
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053014153 }
14154 }
Girish Gowli4bf7a632014-06-12 13:42:11 +053014155 return 0;
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053014156}
14157
Abhishek Singh7d624e12015-11-30 14:29:27 +053014158/**
14159 * hdd_indicate_mgmt_frame() - Wrapper to indicate management frame to
14160 * user space
14161 * @frame_ind: Management frame data to be informed.
14162 *
14163 * This function is used to indicate management frame to
14164 * user space
14165 *
14166 * Return: None
14167 *
14168 */
14169void hdd_indicate_mgmt_frame(tSirSmeMgmtFrameInd *frame_ind)
14170{
14171 hdd_context_t *hdd_ctx = NULL;
14172 hdd_adapter_t *adapter = NULL;
14173 v_CONTEXT_t vos_context = NULL;
14174
14175 /* Get the global VOSS context.*/
14176 vos_context = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
14177 if (!vos_context) {
14178 hddLog(LOGE, FL("Global VOS context is Null"));
14179 return;
14180 }
14181 /* Get the HDD context.*/
14182 hdd_ctx =
14183 (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, vos_context );
14184
14185 if (0 != wlan_hdd_validate_context(hdd_ctx))
14186 {
14187 return;
14188 }
14189 adapter = hdd_get_adapter_by_sme_session_id(hdd_ctx,
14190 frame_ind->sessionId);
14191
14192 if ((NULL != adapter) &&
14193 (WLAN_HDD_ADAPTER_MAGIC == adapter->magic))
14194 __hdd_indicate_mgmt_frame(adapter,
14195 frame_ind->frameLen,
14196 frame_ind->frameBuf,
14197 frame_ind->frameType,
14198 frame_ind->rxChan,
14199 frame_ind->rxRssi);
14200 return;
14201
14202}
14203
c_hpothu225aa7c2014-10-22 17:45:13 +053014204VOS_STATUS wlan_hdd_cancel_remain_on_channel(hdd_context_t *pHddCtx)
14205{
14206 hdd_adapter_t *pAdapter;
14207 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
14208 VOS_STATUS vosStatus;
14209
14210 vosStatus = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
14211 while (NULL != pAdapterNode && VOS_STATUS_E_EMPTY != vosStatus)
14212 {
14213 pAdapter = pAdapterNode->pAdapter;
14214 if (NULL != pAdapter)
14215 {
14216 if (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode ||
14217 WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ||
14218 WLAN_HDD_P2P_GO == pAdapter->device_mode)
14219 {
14220 hddLog(LOG1, FL("abort ROC deviceMode: %d"),
14221 pAdapter->device_mode);
14222 if (VOS_STATUS_SUCCESS !=
14223 wlan_hdd_cancel_existing_remain_on_channel(pAdapter))
14224 {
14225 hddLog(LOGE, FL("failed to abort ROC"));
14226 return VOS_STATUS_E_FAILURE;
14227 }
14228 }
14229 }
14230 vosStatus = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
14231 pAdapterNode = pNext;
14232 }
14233 return VOS_STATUS_SUCCESS;
14234}
Mahesh A Saptasagard477b092015-02-06 15:12:16 +053014235
Mihir Shete0be28772015-02-17 18:42:14 +053014236hdd_remain_on_chan_ctx_t *hdd_get_remain_on_channel_ctx(hdd_context_t *pHddCtx)
14237{
14238 hdd_adapter_t *pAdapter;
14239 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
14240 hdd_cfg80211_state_t *cfgState;
14241 hdd_remain_on_chan_ctx_t *pRemainChanCtx = NULL;
14242 VOS_STATUS vosStatus;
14243
14244 vosStatus = hdd_get_front_adapter (pHddCtx, &pAdapterNode);
14245 while (NULL != pAdapterNode && VOS_STATUS_E_EMPTY != vosStatus)
14246 {
14247 pAdapter = pAdapterNode->pAdapter;
14248 if (NULL != pAdapter)
14249 {
14250 cfgState = WLAN_HDD_GET_CFG_STATE_PTR(pAdapter);
14251 pRemainChanCtx = cfgState->remain_on_chan_ctx;
14252 if (pRemainChanCtx)
14253 break;
14254 }
14255 vosStatus = hdd_get_next_adapter (pHddCtx, pAdapterNode, &pNext);
14256 pAdapterNode = pNext;
14257 }
14258 return pRemainChanCtx;
14259}
14260
Padma, Santhosh Kumar778d8382015-03-04 17:41:22 +053014261/**
14262 * wlan_hdd_handle_dfs_chan_scan () - handles disable/enable DFS channels
14263 *
14264 * @pHddCtx: HDD context within host driver
14265 * @dfsScanMode: dfsScanMode passed from ioctl
14266 *
14267 */
14268
14269VOS_STATUS wlan_hdd_handle_dfs_chan_scan(hdd_context_t *pHddCtx,
14270 tANI_U8 dfsScanMode)
14271{
14272 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
14273 hdd_adapter_t *pAdapter;
14274 VOS_STATUS vosStatus;
14275 hdd_station_ctx_t *pHddStaCtx;
14276 eHalStatus status = eHAL_STATUS_SUCCESS;
14277
14278 if(!pHddCtx)
14279 {
14280 hddLog(LOGE, FL("HDD context is Null"));
14281 return eHAL_STATUS_FAILURE;
14282 }
14283
14284 if (pHddCtx->scan_info.mScanPending)
14285 {
14286 hddLog(LOG1, FL("Aborting scan for sessionId: %d"),
14287 pHddCtx->scan_info.sessionId);
14288 hdd_abort_mac_scan(pHddCtx,
14289 pHddCtx->scan_info.sessionId,
14290 eCSR_SCAN_ABORT_DEFAULT);
14291 }
14292
14293 if (!dfsScanMode)
14294 {
14295 vosStatus = hdd_get_front_adapter( pHddCtx, &pAdapterNode);
14296 while ((NULL != pAdapterNode) &&
14297 (VOS_STATUS_SUCCESS == vosStatus))
14298 {
14299 pAdapter = pAdapterNode->pAdapter;
14300
14301 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
14302 {
14303 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14304
14305 if(!pHddStaCtx)
14306 {
14307 hddLog(LOGE, FL("HDD STA context is Null"));
14308 return eHAL_STATUS_FAILURE;
14309 }
14310
14311 /* if STA is already connected on DFS channel,
14312 disconnect immediately*/
14313 if (hdd_connIsConnected(pHddStaCtx) &&
14314 (NV_CHANNEL_DFS ==
14315 vos_nv_getChannelEnabledState(
14316 pHddStaCtx->conn_info.operationChannel)))
14317 {
14318 status = sme_RoamDisconnect(pHddCtx->hHal,
14319 pAdapter->sessionId,
14320 eCSR_DISCONNECT_REASON_UNSPECIFIED);
14321 hddLog(LOG1, FL("Client connected on DFS channel %d,"
14322 "sme_RoamDisconnect returned with status: %d"
14323 "for sessionid: %d"), pHddStaCtx->conn_info.
14324 operationChannel, status, pAdapter->sessionId);
14325 }
14326 }
14327
14328 vosStatus = hdd_get_next_adapter(pHddCtx, pAdapterNode,
14329 &pNext);
14330 pAdapterNode = pNext;
14331 }
14332 }
14333
14334 sme_UpdateDFSScanMode(pHddCtx->hHal, dfsScanMode);
14335 sme_UpdateDFSRoamMode(pHddCtx->hHal,
14336 (dfsScanMode != DFS_CHNL_SCAN_DISABLED));
14337
14338 status = sme_HandleDFSChanScan(pHddCtx->hHal);
14339 if (!HAL_STATUS_SUCCESS(status))
14340 {
14341 hddLog(LOGE,
14342 FL("Failed in sme_HandleDFSChanScan (err=%d)"), status);
14343 return status;
14344 }
14345
14346 return status;
14347}
14348
Nirav Shah7e3c8132015-06-22 23:51:42 +053014349static int hdd_log2_ceil(unsigned value)
14350{
14351 /* need to switch to unsigned math so that negative values
14352 * will right-shift towards 0 instead of -1
14353 */
14354 unsigned tmp = value;
14355 int log2 = -1;
14356
14357 if (value == 0)
14358 return 0;
14359
14360 while (tmp) {
14361 log2++;
14362 tmp >>= 1;
14363 }
14364 if (1U << log2 != value)
14365 log2++;
14366
14367 return log2;
14368}
14369
14370/**
14371 * hdd_sta_id_hash_attach() - initialize sta id to macaddr hash
14372 * @pAdapter: adapter handle
14373 *
14374 * Return: vos status
14375 */
14376VOS_STATUS hdd_sta_id_hash_attach(hdd_adapter_t *pAdapter)
14377{
14378 int hash_elem, log2, i;
14379
14380 spin_lock_bh( &pAdapter->sta_hash_lock);
14381 if (pAdapter->is_sta_id_hash_initialized == VOS_TRUE) {
14382 spin_unlock_bh( &pAdapter->sta_hash_lock);
14383 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
14384 "%s: hash already attached for session id %d",
14385 __func__, pAdapter->sessionId);
14386 return VOS_STATUS_SUCCESS;
14387 }
14388 spin_unlock_bh( &pAdapter->sta_hash_lock);
14389
14390 hash_elem = WLAN_MAX_STA_COUNT;
14391 hash_elem *= HDD_STA_ID_HASH_MULTIPLIER;
14392 log2 = hdd_log2_ceil(hash_elem);
14393 hash_elem = 1 << log2;
14394
14395 pAdapter->sta_id_hash.mask = hash_elem - 1;
14396 pAdapter->sta_id_hash.idx_bits = log2;
14397 pAdapter->sta_id_hash.bins =
14398 vos_mem_malloc(hash_elem *sizeof(hdd_list_t));
14399 if (!pAdapter->sta_id_hash.bins) {
14400 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
14401 "%s: malloc failed for session %d",
14402 __func__, pAdapter->sessionId);
14403 return VOS_STATUS_E_NOMEM;
14404 }
14405
14406 for (i = 0; i < hash_elem; i++)
14407 hdd_list_init(&pAdapter->sta_id_hash.bins[i], WLAN_MAX_STA_COUNT);
14408
14409 spin_lock_bh( &pAdapter->sta_hash_lock);
14410 pAdapter->is_sta_id_hash_initialized = VOS_TRUE;
14411 spin_unlock_bh( &pAdapter->sta_hash_lock);
14412 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
14413 "%s: Station ID Hash attached for session id %d",
14414 __func__, pAdapter->sessionId);
14415
14416 return VOS_STATUS_SUCCESS;
14417}
14418
14419/**
14420 * hdd_sta_id_hash_detach() - deinit sta_id to macaddr hash
14421 * @pAdapter: adapter handle
14422 *
14423 * Return: vos status
14424 */
14425VOS_STATUS hdd_sta_id_hash_detach(hdd_adapter_t *pAdapter)
14426{
14427 int hash_elem, i;
14428 v_SIZE_t size;
14429
14430 spin_lock_bh( &pAdapter->sta_hash_lock);
14431 if (pAdapter->is_sta_id_hash_initialized != VOS_TRUE) {
14432 spin_unlock_bh( &pAdapter->sta_hash_lock);
14433 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
14434 "%s: hash not initialized for session id %d",
14435 __func__, pAdapter->sessionId);
14436 return VOS_STATUS_SUCCESS;
14437 }
14438
14439 pAdapter->is_sta_id_hash_initialized = VOS_FALSE;
14440 spin_unlock_bh( &pAdapter->sta_hash_lock);
14441
14442 hash_elem = 1 << pAdapter->sta_id_hash.idx_bits;
14443
14444 /* free all station info*/
14445 for (i = 0; i < hash_elem; i++) {
14446 hdd_list_size(&pAdapter->sta_id_hash.bins[i], &size);
14447 if (size != 0) {
14448 VOS_STATUS status;
14449 hdd_staid_hash_node_t *sta_info_node = NULL;
14450 hdd_staid_hash_node_t *next_node = NULL;
14451 status = hdd_list_peek_front ( &pAdapter->sta_id_hash.bins[i],
14452 (hdd_list_node_t**) &sta_info_node );
14453
14454 while ( NULL != sta_info_node && VOS_STATUS_SUCCESS == status )
14455 {
14456 status = hdd_list_remove_node( &pAdapter->sta_id_hash.bins[i],
14457 &sta_info_node->node);
14458 vos_mem_free(sta_info_node);
14459
14460 status = hdd_list_peek_next (&pAdapter->sta_id_hash.bins[i],
14461 (hdd_list_node_t*)sta_info_node,
14462 (hdd_list_node_t**)&next_node);
14463 sta_info_node = next_node;
14464 }
14465 }
14466 }
14467
14468 vos_mem_free(pAdapter->sta_id_hash.bins);
14469 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
14470 "%s: Station ID Hash detached for session id %d",
14471 __func__, pAdapter->sessionId);
14472 return VOS_STATUS_SUCCESS;
14473}
14474
14475/**
14476 * hdd_sta_id_hash_calculate_index() - derive index from macaddr
14477 * @pAdapter: adapter handle
14478 * @mac_addr_in: input mac address
14479 *
14480 * Return: index derived from mac address
14481 */
14482int hdd_sta_id_hash_calculate_index(hdd_adapter_t *pAdapter,
14483 v_MACADDR_t *mac_addr_in)
14484{
14485 uint16 index;
14486 struct hdd_align_mac_addr_t * mac_addr =
14487 (struct hdd_align_mac_addr_t *)mac_addr_in;
14488
14489 index = mac_addr->bytes_ab ^
14490 mac_addr->bytes_cd ^ mac_addr->bytes_ef;
14491 index ^= index >> pAdapter->sta_id_hash.idx_bits;
14492 index &= pAdapter->sta_id_hash.mask;
14493 return index;
14494}
14495
14496/**
14497 * hdd_sta_id_hash_add_entry() - add entry in hash
14498 * @pAdapter: adapter handle
14499 * @sta_id: station id
14500 * @mac_addr: mac address
14501 *
14502 * Return: vos status
14503 */
14504VOS_STATUS hdd_sta_id_hash_add_entry(hdd_adapter_t *pAdapter,
14505 v_U8_t sta_id, v_MACADDR_t *mac_addr)
14506{
14507 uint16 index;
14508 hdd_staid_hash_node_t *sta_info_node = NULL;
14509
Nirav Shah7e3c8132015-06-22 23:51:42 +053014510 index = hdd_sta_id_hash_calculate_index(pAdapter, mac_addr);
14511 sta_info_node = vos_mem_malloc(sizeof(hdd_staid_hash_node_t));
14512 if (!sta_info_node) {
Nirav Shah7e3c8132015-06-22 23:51:42 +053014513 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
14514 "%s: malloc failed", __func__);
14515 return VOS_STATUS_E_NOMEM;
14516 }
14517
14518 sta_info_node->sta_id = sta_id;
14519 vos_mem_copy(&sta_info_node->mac_addr, mac_addr, sizeof(v_MACADDR_t));
14520
Nirav Shah303ed5c2015-08-24 10:29:25 +053014521 spin_lock_bh( &pAdapter->sta_hash_lock);
14522 if (pAdapter->is_sta_id_hash_initialized != VOS_TRUE) {
14523 spin_unlock_bh( &pAdapter->sta_hash_lock);
14524 vos_mem_free(sta_info_node);
14525 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
14526 "%s: hash is not initialized for session id %d",
14527 __func__, pAdapter->sessionId);
14528 return VOS_STATUS_E_FAILURE;
14529 }
14530
Nirav Shah7e3c8132015-06-22 23:51:42 +053014531 hdd_list_insert_back ( &pAdapter->sta_id_hash.bins[index],
14532 (hdd_list_node_t*) sta_info_node );
14533 spin_unlock_bh( &pAdapter->sta_hash_lock);
14534 return VOS_STATUS_SUCCESS;
14535}
14536
14537/**
14538 * hdd_sta_id_hash_remove_entry() - remove entry from hash
14539 * @pAdapter: adapter handle
14540 * @sta_id: station id
14541 * @mac_addr: mac address
14542 *
14543 * Return: vos status
14544 */
14545VOS_STATUS hdd_sta_id_hash_remove_entry(hdd_adapter_t *pAdapter,
14546 v_U8_t sta_id, v_MACADDR_t *mac_addr)
14547{
14548 uint16 index;
14549 VOS_STATUS status;
14550 hdd_staid_hash_node_t *sta_info_node = NULL;
14551 hdd_staid_hash_node_t *next_node = NULL;
14552
14553 spin_lock_bh( &pAdapter->sta_hash_lock);
14554 if (pAdapter->is_sta_id_hash_initialized != VOS_TRUE) {
14555 spin_unlock_bh( &pAdapter->sta_hash_lock);
14556 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
14557 "%s: hash is not initialized for session id %d",
14558 __func__, pAdapter->sessionId);
14559 return VOS_STATUS_E_FAILURE;
14560 }
14561
14562 index = hdd_sta_id_hash_calculate_index(pAdapter, mac_addr);
14563 status = hdd_list_peek_front ( &pAdapter->sta_id_hash.bins[index],
14564 (hdd_list_node_t**) &sta_info_node );
14565
14566 while ( NULL != sta_info_node && VOS_STATUS_SUCCESS == status )
14567 {
14568 if (sta_info_node->sta_id == sta_id) {
14569 status = hdd_list_remove_node( &pAdapter->sta_id_hash.bins[index],
14570 &sta_info_node->node);
14571 vos_mem_free(sta_info_node);
14572 break;
14573 }
14574 status = hdd_list_peek_next (&pAdapter->sta_id_hash.bins[index],
14575 (hdd_list_node_t*)sta_info_node, (hdd_list_node_t**)&next_node);
14576 sta_info_node = next_node;
14577 }
14578 spin_unlock_bh( &pAdapter->sta_hash_lock);
14579 return status;
14580}
14581
14582/**
14583 * hdd_sta_id_find_from_mac_addr() - find sta id from mac address
14584 * @pAdapter: adapter handle
14585 * @mac_addr_in: mac address
14586 *
14587 * Return: station id
14588 */
14589int hdd_sta_id_find_from_mac_addr(hdd_adapter_t *pAdapter,
14590 v_MACADDR_t *mac_addr_in)
14591{
14592 uint8 is_found = 0;
14593 uint8 sta_id = HDD_WLAN_INVALID_STA_ID;
14594 uint16 index;
14595 VOS_STATUS status;
14596 hdd_staid_hash_node_t *sta_info_node = NULL;
14597 hdd_staid_hash_node_t *next_node = NULL;
14598
14599 spin_lock_bh( &pAdapter->sta_hash_lock);
14600 if (pAdapter->is_sta_id_hash_initialized != VOS_TRUE) {
14601 spin_unlock_bh( &pAdapter->sta_hash_lock);
Bhargav Shahce3b32c2015-08-10 12:29:24 +053014602 hddLog(VOS_TRACE_LEVEL_INFO,
Nirav Shah7e3c8132015-06-22 23:51:42 +053014603 FL("hash is not initialized for session id %d"),
14604 pAdapter->sessionId);
14605 return HDD_WLAN_INVALID_STA_ID;
14606 }
14607
14608 index = hdd_sta_id_hash_calculate_index(pAdapter, mac_addr_in);
14609 status = hdd_list_peek_front ( &pAdapter->sta_id_hash.bins[index],
14610 (hdd_list_node_t**) &sta_info_node );
14611
14612 while ( NULL != sta_info_node && VOS_STATUS_SUCCESS == status )
14613 {
14614 if (vos_mem_compare(&sta_info_node->mac_addr,
14615 mac_addr_in, sizeof(v_MACADDR_t))) {
14616 is_found = 1;
14617 sta_id = sta_info_node->sta_id;
14618 break;
14619 }
14620 status = hdd_list_peek_next (&pAdapter->sta_id_hash.bins[index],
14621 (hdd_list_node_t*)sta_info_node,
14622 (hdd_list_node_t**)&next_node);
14623 sta_info_node = next_node;
14624 }
14625 spin_unlock_bh( &pAdapter->sta_hash_lock);
14626 return sta_id;
14627}
14628
c_manjeecfd1efb2015-09-25 19:32:34 +053014629/*FW memory dump feature*/
14630/**
14631 * This structure hold information about the /proc file
14632 *
14633 */
14634static struct proc_dir_entry *proc_file, *proc_dir;
14635
14636/**
14637 * memdump_read() - perform read operation in memory dump proc file
14638 *
14639 * @file - handle for the proc file.
14640 * @buf - pointer to user space buffer.
14641 * @count - number of bytes to be read.
14642 * @pos - offset in the from buffer.
14643 *
14644 * This function performs read operation for the memory dump proc file.
14645 *
14646 * Return: number of bytes read on success, error code otherwise.
14647 */
14648static ssize_t memdump_read(struct file *file, char __user *buf,
14649 size_t count, loff_t *pos)
14650{
14651 int status;
14652 hdd_context_t *hdd_ctx = (hdd_context_t *)PDE_DATA(file_inode(file));
14653 size_t ret_count;
c_manjeef1495642015-10-13 18:35:01 +053014654 loff_t bytes_left;
c_manjeecfd1efb2015-09-25 19:32:34 +053014655 ENTER();
14656
14657 hddLog(LOG1, FL("Read req for size:%zu pos:%llu"), count, *pos);
14658 status = wlan_hdd_validate_context(hdd_ctx);
14659 if (0 != status) {
14660 return -EINVAL;
14661 }
14662
14663 if (!wlan_fwr_mem_dump_test_and_set_read_allowed_bit()) {
14664 hddLog(LOGE, FL("Current mem dump request timed out/failed"));
14665 return -EINVAL;
14666 }
14667
14668 /* run fs_read_handler in an atomic context*/
14669 vos_ssr_protect(__func__);
c_manjeef1495642015-10-13 18:35:01 +053014670 ret_count = wlan_fwr_mem_dump_fsread_handler( buf, count, pos, &bytes_left);
14671 if(bytes_left == 0)
c_manjeecfd1efb2015-09-25 19:32:34 +053014672 {
14673 /*Free the fwr mem dump buffer */
14674 wlan_free_fwr_mem_dump_buffer();
14675 wlan_set_fwr_mem_dump_state(FW_MEM_DUMP_IDLE);
c_manjeef1495642015-10-13 18:35:01 +053014676 ret_count=0;
c_manjeecfd1efb2015-09-25 19:32:34 +053014677 }
14678 /*if SSR/unload code is waiting for memdump_read to finish,signal it*/
14679 vos_ssr_unprotect(__func__);
14680 EXIT();
14681 return ret_count;
14682}
14683
14684/**
14685 * struct memdump_fops - file operations for memory dump feature
14686 * @read - read function for memory dump operation.
14687 *
14688 * This structure initialize the file operation handle for memory
14689 * dump feature
14690 */
14691static const struct file_operations memdump_fops = {
14692 read: memdump_read
14693};
14694
14695/*
14696* wlan_hdd_fw_mem_dump_cb : callback for Fw mem dump request
14697* To be passed by HDD to WDA and called upon receiving of response
14698* from firmware
14699* @fwMemDumpReqContext : memory dump request context
14700* @dump_rsp : dump response from HAL
14701* Returns none
14702*/
14703void wlan_hdd_fw_mem_dump_cb(void *fwMemDumpReqContext,
14704 tAniFwrDumpRsp *dump_rsp)
14705{
c_manjeef1495642015-10-13 18:35:01 +053014706 struct hdd_fw_mem_dump_req_ctx *pHddFwMemDumpCtx = (struct hdd_fw_mem_dump_req_ctx *)fwMemDumpReqContext;
c_manjeecfd1efb2015-09-25 19:32:34 +053014707
c_manjeef1495642015-10-13 18:35:01 +053014708 ENTER();
14709 spin_lock(&hdd_context_lock);
14710 if(!pHddFwMemDumpCtx || (FW_MEM_DUMP_MAGIC != pHddFwMemDumpCtx->magic)) {
14711 spin_unlock(&hdd_context_lock);
14712 return;
14713 }
14714 /* report the status to requesting function and free mem.*/
c_manjeecfd1efb2015-09-25 19:32:34 +053014715 if (dump_rsp->dump_status != eHAL_STATUS_SUCCESS) {
c_manjeef1495642015-10-13 18:35:01 +053014716 hddLog(LOGE, FL("fw dump request declined by fwr"));
14717 //set the request completion variable
14718 complete(&(pHddFwMemDumpCtx->req_completion));
c_manjeecfd1efb2015-09-25 19:32:34 +053014719 //Free the allocated fwr dump
14720 wlan_free_fwr_mem_dump_buffer();
14721 wlan_set_fwr_mem_dump_state(FW_MEM_DUMP_IDLE);
c_manjeecfd1efb2015-09-25 19:32:34 +053014722 }
c_manjeef1495642015-10-13 18:35:01 +053014723 else {
14724 hddLog(LOG1, FL("fw dump request accepted by fwr"));
14725 /* register the HDD callback which will be called by SVC */
14726 wlan_set_svc_fw_mem_dump_req_cb((void*)wlan_hdd_fw_mem_dump_req_cb,(void*)pHddFwMemDumpCtx);
14727 }
14728 spin_unlock(&hdd_context_lock);
c_manjeecfd1efb2015-09-25 19:32:34 +053014729 EXIT();
14730
14731}
14732
14733/**
14734 * memdump_procfs_remove() - Remove file/dir under procfs for memory dump
14735 *
14736 * This function removes file/dir under proc file system that was
14737 * processing firmware memory dump
14738 *
14739 * Return: None
14740 */
14741static void memdump_procfs_remove(void)
14742{
14743 remove_proc_entry(PROCFS_MEMDUMP_NAME, proc_dir);
14744 hddLog(LOG1 , FL("/proc/%s/%s removed\n"),
14745 PROCFS_MEMDUMP_DIR, PROCFS_MEMDUMP_NAME);
14746 remove_proc_entry(PROCFS_MEMDUMP_DIR, NULL);
14747 hddLog(LOG1 , FL("/proc/%s removed\n"), PROCFS_MEMDUMP_DIR);
14748}
14749
14750/**
14751 * memdump_procfs_init() - Initialize procfs for memory dump
14752 *
14753 * @vos_ctx - Global vos context.
14754 *
14755 * This function create file under proc file system to be used later for
14756 * processing firmware memory dump
14757 *
14758 * Return: 0 on success, error code otherwise.
14759 */
14760static int memdump_procfs_init(void *vos_ctx)
14761{
14762 hdd_context_t *hdd_ctx;
14763
14764 hdd_ctx = vos_get_context(VOS_MODULE_ID_HDD, vos_ctx);
14765 if (!hdd_ctx) {
14766 hddLog(LOGE , FL("Invalid HDD context"));
14767 return -EINVAL;
14768 }
14769
14770 proc_dir = proc_mkdir(PROCFS_MEMDUMP_DIR, NULL);
14771 if (proc_dir == NULL) {
14772 remove_proc_entry(PROCFS_MEMDUMP_DIR, NULL);
14773 hddLog(LOGE , FL("Error: Could not initialize /proc/%s"),
14774 PROCFS_MEMDUMP_DIR);
14775 return -ENOMEM;
14776 }
14777
14778 proc_file = proc_create_data(PROCFS_MEMDUMP_NAME,
14779 S_IRUSR | S_IWUSR, proc_dir,
14780 &memdump_fops, hdd_ctx);
14781 if (proc_file == NULL) {
14782 remove_proc_entry(PROCFS_MEMDUMP_NAME, proc_dir);
14783 hddLog(LOGE , FL("Error: Could not initialize /proc/%s"),
14784 PROCFS_MEMDUMP_NAME);
14785 return -ENOMEM;
14786 }
14787
14788 hddLog(LOG1 , FL("/proc/%s/%s created"),
14789 PROCFS_MEMDUMP_DIR, PROCFS_MEMDUMP_NAME);
14790
14791 return 0;
14792}
14793
14794/**
14795 * memdump_init() - Initialization function for memory dump feature
14796 *
14797 * This function creates proc file for memdump feature and registers
14798 * HDD callback function with SME.
14799 *
14800 * Return - 0 on success, error otherwise
14801 */
14802int memdump_init(void)
14803{
14804 hdd_context_t *hdd_ctx;
14805 void *vos_ctx;
14806 int status = 0;
14807
14808 vos_ctx = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
14809 if (!vos_ctx) {
14810 hddLog(LOGE, FL("Invalid VOS context"));
14811 return -EINVAL;
14812 }
14813
14814 hdd_ctx = vos_get_context(VOS_MODULE_ID_HDD, vos_ctx);
14815 if (!hdd_ctx) {
14816 hddLog(LOGE , FL("Invalid HDD context"));
14817 return -EINVAL;
14818 }
14819
14820 status = memdump_procfs_init(vos_ctx);
14821 if (status) {
14822 hddLog(LOGE , FL("Failed to create proc file"));
14823 return status;
14824 }
14825
14826 return 0;
14827}
14828
14829/**
14830 * memdump_deinit() - De initialize memdump feature
14831 *
14832 * This function removes proc file created for memdump feature.
14833 *
14834 * Return: None
14835 */
14836int memdump_deinit(void)
14837{
14838 hdd_context_t *hdd_ctx;
14839 void *vos_ctx;
14840
14841 vos_ctx = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
14842 if (!vos_ctx) {
14843 hddLog(LOGE, FL("Invalid VOS context"));
14844 return -EINVAL;
14845 }
14846
14847 hdd_ctx = vos_get_context(VOS_MODULE_ID_HDD, vos_ctx);
14848 if(!hdd_ctx) {
14849 hddLog(LOGE , FL("Invalid HDD context"));
14850 return -EINVAL;
14851 }
14852
14853 memdump_procfs_remove();
14854 return 0;
14855}
14856
14857/**
14858 * wlan_hdd_fw_mem_dump_req(pHddCtx) - common API(cfg80211/ioctl) for requesting fw mem dump to SME
14859 * Return: HAL status
14860 */
14861
14862int wlan_hdd_fw_mem_dump_req(hdd_context_t * pHddCtx)
14863{
14864 tAniFwrDumpReq fw_mem_dump_req={0};
c_manjeef1495642015-10-13 18:35:01 +053014865 struct hdd_fw_mem_dump_req_ctx fw_mem_dump_ctx;
c_manjeecfd1efb2015-09-25 19:32:34 +053014866 eHalStatus status = eHAL_STATUS_FAILURE;
Abhishek Singh4eca9822015-12-09 18:07:34 +053014867 int ret=0, result;
c_manjeecfd1efb2015-09-25 19:32:34 +053014868 ENTER();
c_manjeef1495642015-10-13 18:35:01 +053014869
c_manjeecfd1efb2015-09-25 19:32:34 +053014870 /*Check whether a dump request is already going on
14871 *Caution this function will free previously held memory if new dump request is allowed*/
14872 if (!wlan_fwr_mem_dump_test_and_set_write_allowed_bit()) {
14873 hddLog(LOGE, FL("Fw memdump already in progress"));
14874 return -EBUSY;
14875 }
14876 //Allocate memory for fw mem dump buffer
14877 ret = wlan_fwr_mem_dump_buffer_allocation();
14878 if(ret == -EFAULT)
14879 {
14880 hddLog(LOGE, FL("Fwr mem dump not supported by FW"));
14881 return ret;
14882 }
14883 if (0 != ret) {
14884 hddLog(LOGE, FL("Fwr mem Allocation failed"));
14885 return -ENOMEM;
14886 }
c_manjeef1495642015-10-13 18:35:01 +053014887 init_completion(&fw_mem_dump_ctx.req_completion);
14888 fw_mem_dump_ctx.magic = FW_MEM_DUMP_MAGIC;
14889 fw_mem_dump_ctx.status = false;
14890
c_manjeecfd1efb2015-09-25 19:32:34 +053014891 fw_mem_dump_req.fwMemDumpReqCallback = wlan_hdd_fw_mem_dump_cb;
c_manjeef1495642015-10-13 18:35:01 +053014892 fw_mem_dump_req.fwMemDumpReqContext = &fw_mem_dump_ctx;
c_manjeecfd1efb2015-09-25 19:32:34 +053014893 status = sme_FwMemDumpReq(pHddCtx->hHal, &fw_mem_dump_req);
14894 if(eHAL_STATUS_SUCCESS != status)
14895 {
14896 hddLog(VOS_TRACE_LEVEL_ERROR,
14897 "%s: fw_mem_dump_req failed ", __func__);
14898 wlan_free_fwr_mem_dump_buffer();
c_manjeef1495642015-10-13 18:35:01 +053014899 ret = -EFAULT;
14900 goto cleanup;
c_manjeecfd1efb2015-09-25 19:32:34 +053014901 }
c_manjeef1495642015-10-13 18:35:01 +053014902 /*wait for fw mem dump completion to send event to userspace*/
Abhishek Singh4eca9822015-12-09 18:07:34 +053014903 result =
14904 wait_for_completion_timeout(&fw_mem_dump_ctx.req_completion,
14905 msecs_to_jiffies(FW_MEM_DUMP_TIMEOUT_MS));
14906 if (0 >= result )
c_manjeef1495642015-10-13 18:35:01 +053014907 {
14908 hddLog(VOS_TRACE_LEVEL_ERROR,
Abhishek Singh4eca9822015-12-09 18:07:34 +053014909 "%s: fw_mem_dump_req timeout %d ", __func__,result);
14910 ret = -ETIMEDOUT;
c_manjeef1495642015-10-13 18:35:01 +053014911 }
14912cleanup:
14913 spin_lock(&hdd_context_lock);
14914 fw_mem_dump_ctx.magic = 0;
Abhishek Singh4eca9822015-12-09 18:07:34 +053014915 if(!ret && !fw_mem_dump_ctx.status)
14916 ret = -EFAULT;
c_manjeef1495642015-10-13 18:35:01 +053014917 spin_unlock(&hdd_context_lock);
c_manjeecfd1efb2015-09-25 19:32:34 +053014918
c_manjeef1495642015-10-13 18:35:01 +053014919 EXIT();
Abhishek Singh4eca9822015-12-09 18:07:34 +053014920 return ret;
c_manjeef1495642015-10-13 18:35:01 +053014921}
14922
14923/**
14924 * HDD callback which will be called by SVC to indicate mem dump completion.
14925 */
14926void wlan_hdd_fw_mem_dump_req_cb(struct hdd_fw_mem_dump_req_ctx* pHddFwMemDumpCtx)
14927{
14928 if (!pHddFwMemDumpCtx) {
14929 hddLog(VOS_TRACE_LEVEL_ERROR,
14930 "%s: HDD context not valid ", __func__);
14931 return;
14932 }
14933 spin_lock(&hdd_context_lock);
14934 /* check the req magic and set status */
14935 if (pHddFwMemDumpCtx->magic == FW_MEM_DUMP_MAGIC)
14936 {
14937 pHddFwMemDumpCtx->status = true;
14938 //signal the completion
14939 complete(&(pHddFwMemDumpCtx->req_completion));
14940 }
14941 else
14942 {
14943 hddLog(VOS_TRACE_LEVEL_ERROR,
14944 "%s: fw mem dump request possible timeout ", __func__);
14945 }
14946 spin_unlock(&hdd_context_lock);
c_manjeecfd1efb2015-09-25 19:32:34 +053014947}
14948
Mahesh A Saptasagar67ab9222015-10-21 15:38:41 +053014949void hdd_initialize_adapter_common(hdd_adapter_t *pAdapter)
14950{
14951 if (NULL == pAdapter)
14952 {
14953 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: pAdapter is NULL ", __func__);
14954 return;
14955 }
14956 init_completion(&pAdapter->session_open_comp_var);
14957 init_completion(&pAdapter->session_close_comp_var);
14958 init_completion(&pAdapter->disconnect_comp_var);
14959 init_completion(&pAdapter->linkup_event_var);
14960 init_completion(&pAdapter->cancel_rem_on_chan_var);
14961 init_completion(&pAdapter->rem_on_chan_ready_event);
14962 init_completion(&pAdapter->pno_comp_var);
14963#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
14964 init_completion(&pAdapter->offchannel_tx_event);
14965#endif
14966 init_completion(&pAdapter->tx_action_cnf_event);
14967#ifdef FEATURE_WLAN_TDLS
14968 init_completion(&pAdapter->tdls_add_station_comp);
14969 init_completion(&pAdapter->tdls_del_station_comp);
14970 init_completion(&pAdapter->tdls_mgmt_comp);
14971 init_completion(&pAdapter->tdls_link_establish_req_comp);
14972#endif
14973
14974#ifdef WLAN_FEATURE_RMC
14975 init_completion(&pAdapter->ibss_peer_info_comp);
14976#endif /* WLAN_FEATURE_RMC */
14977 init_completion(&pAdapter->ula_complete);
14978 init_completion(&pAdapter->change_country_code);
14979
14980#ifdef FEATURE_WLAN_BATCH_SCAN
14981 init_completion(&pAdapter->hdd_set_batch_scan_req_var);
14982 init_completion(&pAdapter->hdd_get_batch_scan_req_var);
14983#endif
Kapil Gupta2b44acb2016-12-30 16:49:51 +053014984 init_completion(&pAdapter->wlan_suspend_comp_var);
Mahesh A Saptasagar67ab9222015-10-21 15:38:41 +053014985
14986 return;
14987}
c_manjeecfd1efb2015-09-25 19:32:34 +053014988
Anurag Chouhan0b29de02016-12-16 13:18:40 +053014989#ifdef MDNS_OFFLOAD
14990
14991/**
14992 * hdd_mdns_enable_offload_done() - mdns enable offload response api
14993 * @padapter: holds adapter
14994 * @status: response status
14995 *
14996 * Return - None
14997 */
14998void hdd_mdns_enable_offload_done(void *padapter, VOS_STATUS status)
14999{
15000 hdd_adapter_t* adapter = (hdd_adapter_t*) padapter;
15001
15002 ENTER();
15003
15004 if (NULL == adapter)
15005 {
15006 hddLog(VOS_TRACE_LEVEL_ERROR,
15007 "%s: adapter is NULL",__func__);
15008 return;
15009 }
15010
15011 adapter->mdns_status.mdns_enable_status = status;
15012 vos_event_set(&adapter->mdns_status.vos_event);
15013 return;
15014}
15015
15016/**
15017 * hdd_mdns_fqdn_offload_done() - mdns fqdn offload response api
15018 * @padapter: holds adapter
15019 * @status: responce status
15020 *
15021 * Return - None
15022 */
15023void hdd_mdns_fqdn_offload_done(void *padapter, VOS_STATUS status)
15024{
15025 hdd_adapter_t* adapter = (hdd_adapter_t*) padapter;
15026
15027 ENTER();
15028
15029 if (NULL == adapter)
15030 {
15031 hddLog(VOS_TRACE_LEVEL_ERROR,
15032 "%s: adapter is NULL",__func__);
15033 return;
15034 }
15035
15036 adapter->mdns_status.mdns_fqdn_status = status;
15037 return;
15038}
15039
15040/**
15041 * hdd_mdns_resp_offload_done() - mdns resp offload response api
15042 * @padapter: holds adapter
15043 * @status: responce status
15044 *
15045 * Return - None
15046 */
15047void hdd_mdns_resp_offload_done(void *padapter, VOS_STATUS status)
15048{
15049 hdd_adapter_t* adapter = (hdd_adapter_t*) padapter;
15050
15051 ENTER();
15052
15053 if (NULL == adapter)
15054 {
15055 hddLog(VOS_TRACE_LEVEL_ERROR,
15056 "%s: adapter is NULL",__func__);
15057 return;
15058 }
15059
15060 adapter->mdns_status.mdns_resp_status = status;
15061 return;
15062}
15063
15064/**
15065 * wlan_hdd_mdns_process_response_dname() - Process mDNS domain name
15066 * @response: Pointer to a struct hdd_mdns_resp_info
15067 * @resp_info: Pointer to a struct tSirMDNSResponseInfo
15068 *
15069 * This function will pack the whole domain name without compression. It will
15070 * add the leading len for each field and add zero length octet to terminate
15071 * the domain name.
15072 *
15073 * Return: Return boolean. TRUE for success, FALSE for fail.
15074 */
15075static bool
15076wlan_hdd_mdns_process_response_dname(struct hdd_mdns_resp_info *response,
15077 sir_mdns_resp_info resp_info)
15078{
15079 uint8_t num;
15080 uint16_t idx;
15081 uint8_t len = 0;
15082
15083 if ((response == NULL) || (response->data == NULL) ||
15084 (response->offset == NULL)) {
15085 hddLog(LOGE, FL("Either data or offset in response is NULL!"));
15086 return FALSE;
15087 }
15088
15089 if ((resp_info == NULL) ||
15090 (resp_info->resp_len >= MAX_MDNS_RESP_LEN)) {
15091 hddLog(LOGE, FL("resp_len exceeds %d!"), MAX_MDNS_RESP_LEN);
15092 return FALSE;
15093 }
15094
15095 for (num = 0; num < response->num_entries; num++) {
15096 response->offset[num] =
15097 resp_info->resp_len + MDNS_HEADER_LEN;
15098 idx = num * MAX_LEN_DOMAINNAME_FIELD;
15099 len = strlen((char *)&response->data[idx]);
15100 if ((resp_info->resp_len + len + 1) >= MAX_MDNS_RESP_LEN) {
15101 hddLog(LOGE, FL("resp_len exceeds %d!"),
15102 MAX_MDNS_RESP_LEN);
15103 return FALSE;
15104 }
15105 resp_info->resp_data[resp_info->resp_len] = len;
15106 resp_info->resp_len++;
15107 vos_mem_copy(&resp_info->resp_data[resp_info->resp_len],
15108 &response->data[idx], len);
15109 resp_info->resp_len += len;
15110 }
15111
15112 /* The domain name terminates with the zero length octet */
15113 if (num == response->num_entries) {
15114 if (resp_info->resp_len >= MAX_MDNS_RESP_LEN) {
15115 hddLog(LOGE, FL("resp_len exceeds %d!"),
15116 MAX_MDNS_RESP_LEN);
15117 return FALSE;
15118 }
15119 resp_info->resp_data[resp_info->resp_len] = 0;
15120 resp_info->resp_len++;
15121 }
15122
15123 return TRUE;
15124}
15125
15126/**
15127 * wlan_hdd_mdns_format_response_u16() - Form uint16_t response data
15128 * @value: The uint16_t value is formed to the struct tSirMDNSResponseInfo
15129 * @resp_info: Pointer to a struct tSirMDNSResponseInfo
15130 *
15131 * Return: None
15132 */
15133static void wlan_hdd_mdns_format_response_u16(uint16_t value,
15134 sir_mdns_resp_info resp_info)
15135{
15136 uint8_t val_u8;
15137
15138 if ((resp_info == NULL) || (resp_info->resp_data == NULL))
15139 return;
15140 val_u8 = (value & 0xff00) >> 8;
15141 resp_info->resp_data[resp_info->resp_len++] = val_u8;
15142 val_u8 = value & 0xff;
15143 resp_info->resp_data[resp_info->resp_len++] = val_u8;
15144}
15145
15146/**
15147 * wlan_hdd_mdns_format_response_u32() - Form uint32_t response data
15148 * @value: The uint32_t value is formed to the struct tSirMDNSResponseInfo
15149 * @resp_info: Pointer to a struct tSirMDNSResponseInfo
15150 *
15151 * Return: None
15152 */
15153static void wlan_hdd_mdns_format_response_u32(uint32_t value,
15154 sir_mdns_resp_info resp_info)
15155{
15156 uint8_t val_u8;
15157
15158 if ((resp_info == NULL) || (resp_info->resp_data == NULL))
15159 return;
15160 val_u8 = (value & 0xff000000) >> 24;
15161 resp_info->resp_data[resp_info->resp_len++] = val_u8;
15162 val_u8 = (value & 0xff0000) >> 16;
15163 resp_info->resp_data[resp_info->resp_len++] = val_u8;
15164 val_u8 = (value & 0xff00) >> 8;
15165 resp_info->resp_data[resp_info->resp_len++] = val_u8;
15166 val_u8 = value & 0xff;
15167 resp_info->resp_data[resp_info->resp_len++] = val_u8;
15168}
15169
15170/**
15171 * wlan_hdd_mdns_process_response_misc() - Process misc info in mDNS response
15172 * @resp_type: Response type for mDNS
15173 * @resp_info: Pointer to a struct tSirMDNSResponseInfo
15174 *
15175 * This function will pack the response type, class and TTL (Time To Live).
15176 *
15177 * Return: Return boolean. TRUE for success, FALSE for fail.
15178 */
15179static bool wlan_hdd_mdns_process_response_misc(uint16_t resp_type,
15180 sir_mdns_resp_info resp_info)
15181{
15182 uint16_t len;
15183
15184 if (resp_info == NULL) {
15185 hddLog(LOGE, FL("resp_info is NULL!"));
15186 return FALSE;
15187 }
15188
15189 len = resp_info->resp_len + (2 * sizeof(uint16_t) + sizeof(uint32_t));
15190 if (len >= MAX_MDNS_RESP_LEN) {
15191 hddLog(LOGE, FL("resp_len exceeds %d!"), MAX_MDNS_RESP_LEN);
15192 return FALSE;
15193 }
15194
15195 /* Fill Type, Class, TTL */
15196 wlan_hdd_mdns_format_response_u16(resp_type, resp_info);
15197 wlan_hdd_mdns_format_response_u16(MDNS_CLASS, resp_info);
15198 wlan_hdd_mdns_format_response_u32(MDNS_TTL, resp_info);
15199
15200 return TRUE;
15201}
15202
15203/**
15204 * wlan_hdd_mdns_compress_data() - Compress the domain name in mDNS response
15205 * @resp_info: Pointer to a struct tSirMDNSResponseInfo
15206 * @response_dst: The response which domain name is compressed.
15207 * @response_src: The response which domain name is matched with response_dst.
15208 * Its offset is used for data compression.
15209 * @num_matched: The number of matched entries between response_dst and
15210 * response_src
15211 *
15212 * This function will form the different fields of domain name in response_dst
15213 * if any. Then use the offset of the matched domain name in response_src to
15214 * compress the matched domain name.
15215 *
15216 * Return: Return boolean. TRUE for success, FALSE for fail.
15217 */
15218static bool
15219wlan_hdd_mdns_compress_data(sir_mdns_resp_info resp_info,
15220 struct hdd_mdns_resp_info *response_dst,
15221 struct hdd_mdns_resp_info *response_src,
15222 uint8_t num_matched)
15223{
15224 uint8_t num, num_diff;
15225 uint16_t value, idx;
15226 uint8_t len = 0;
15227
15228 if ((response_src == NULL) || (response_dst == NULL) ||
15229 (resp_info == NULL)) {
15230 hddLog(LOGE, FL("response info is NULL!"));
15231 return FALSE;
15232 }
15233
15234 if (response_dst->num_entries < num_matched) {
15235 hddLog(LOGE, FL("num_entries is less than num_matched!"));
15236 return FALSE;
15237 }
15238
15239 if (resp_info->resp_len >= MAX_MDNS_RESP_LEN) {
15240 hddLog(LOGE, FL("resp_len exceeds %d!"), MAX_MDNS_RESP_LEN);
15241 return FALSE;
15242 }
15243
15244 num_diff = response_dst->num_entries - num_matched;
15245 if ((num_diff > 0) && (response_dst->data == NULL)) {
15246 hddLog(LOGE, FL("response_dst->data is NULL!"));
15247 return FALSE;
15248 }
15249
15250 /*
15251 * Handle the unmatched string at the beginning
15252 * Store the length of octets and the octets
15253 */
15254 for (num = 0; num < num_diff; num++) {
15255 response_dst->offset[num] =
15256 resp_info->resp_len + MDNS_HEADER_LEN;
15257 idx = num * MAX_LEN_DOMAINNAME_FIELD;
15258 len = strlen((char *)&response_dst->data[idx]);
15259 if ((resp_info->resp_len + len + 1) >= MAX_MDNS_RESP_LEN) {
15260 hddLog(LOGE, FL("resp_len exceeds %d!"),
15261 MAX_MDNS_RESP_LEN);
15262 return FALSE;
15263 }
15264 resp_info->resp_data[resp_info->resp_len] = len;
15265 resp_info->resp_len++;
15266 vos_mem_copy(&resp_info->resp_data[resp_info->resp_len],
15267 &response_dst->data[idx], len);
15268 resp_info->resp_len += len;
15269 }
15270 /*
15271 * Handle the matched string from the end
15272 * Just keep the offset and mask the leading two bit
15273 */
15274 if (response_src->num_entries >= num_matched) {
15275 num_diff = response_src->num_entries - num_matched;
15276 value = response_src->offset[num_diff];
15277 if (value > 0) {
15278 value |= 0xc000;
15279 if ((resp_info->resp_len + sizeof(uint16_t)) >=
15280 MAX_MDNS_RESP_LEN) {
15281 hddLog(LOGE, FL("resp_len exceeds %d!"),
15282 MAX_MDNS_RESP_LEN);
15283 return FALSE;
15284 }
15285 wlan_hdd_mdns_format_response_u16(value, resp_info);
15286 return TRUE;
15287 }
15288 }
15289 return FALSE;
15290}
15291
15292/**
15293 * wlan_hdd_mdns_reset_response() - Reset the response info
15294 * @response: The response which info is reset.
15295 *
15296 * Return: None
15297 */
15298static void wlan_hdd_mdns_reset_response(struct hdd_mdns_resp_info *response)
15299{
15300 if (response == NULL)
15301 return;
15302 response->num_entries = 0;
15303 response->data = NULL;
15304 response->offset = NULL;
15305}
15306
15307/**
15308 * wlan_hdd_mdns_init_response() - Initialize the response info
15309 * @response: The response which info is initiatized.
15310 * @resp_dname: The domain name string which might be tokenized.
15311 *
15312 * This function will allocate the memory for both response->data and
15313 * response->offset. Besides, it will also tokenize the domain name to some
15314 * entries and fill response->num_entries with the num of entries.
15315 *
15316 * Return: Return boolean. TRUE for success, FALSE for fail.
15317 */
15318static bool wlan_hdd_mdns_init_response(struct hdd_mdns_resp_info *response,
15319 uint8_t *resp_dname, char separator)
15320{
15321 uint16_t size;
15322
15323 if ((resp_dname == NULL) || (response == NULL)) {
15324 hddLog(LOGE, FL("resp_dname or response is NULL!"));
15325 return FALSE;
15326 }
15327
15328 size = MAX_NUM_FIELD_DOMAINNAME * MAX_LEN_DOMAINNAME_FIELD;
15329 response->data = vos_mem_malloc(size);
15330 if (response->data) {
15331 vos_mem_zero(response->data, size);
15332 if (VOS_STATUS_SUCCESS !=
15333 hdd_string_to_string_array((char *)resp_dname,
15334 response->data,
15335 separator,
15336 &response->num_entries,
15337 MAX_NUM_FIELD_DOMAINNAME,
15338 MAX_LEN_DOMAINNAME_FIELD)) {
15339 hddLog(LOGE, FL("hdd_string_to_string_array fail!"));
15340 goto err_init_resp;
15341 }
15342
15343 if ((response->num_entries > 0) &&
15344 (strlen((char *)&response->data[0]) > 0)) {
15345 size = sizeof(uint16_t) * response->num_entries;
15346 response->offset = vos_mem_malloc(size);
15347 if (response->offset) {
15348 vos_mem_zero(response->offset, size);
15349 return TRUE;
15350 }
15351 }
15352 }
15353
15354err_init_resp:
15355 if (response->data)
15356 vos_mem_free(response->data);
15357 wlan_hdd_mdns_reset_response(response);
15358 return FALSE;
15359}
15360
15361/**
15362 * wlan_hdd_mdns_find_entries_from_end() - Find the matched entries
15363 * @response1: The response info is used to be compared.
15364 * @response2: The response info is used to be compared.
15365 *
15366 * This function will find the matched entries from the end.
15367 *
15368 * Return: Return the number of the matched entries.
15369 */
15370static uint8_t
15371wlan_hdd_mdns_find_entries_from_end(struct hdd_mdns_resp_info *response1,
15372 struct hdd_mdns_resp_info *response2)
15373{
15374 uint8_t min, len1, i;
15375 uint16_t num1, num2;
15376 uint8_t num_matched = 0;
15377
15378 min = VOS_MIN(response1->num_entries, response2->num_entries);
15379
15380 for (i = 1; i <= min; i++) {
15381 num1 = (response1->num_entries - i);
15382 num1 *= MAX_LEN_DOMAINNAME_FIELD;
15383 num2 = (response2->num_entries - i);
15384 num2 *= MAX_LEN_DOMAINNAME_FIELD;
15385 len1 = strlen((char *)&response1->data[num1]);
15386
15387 if ((len1 == 0) ||
15388 (len1 != strlen((char *)&response2->data[num2])))
15389 break;
15390 if (memcmp(&response1->data[num1],
15391 &response2->data[num2], len1))
15392 break;
15393 else
15394 num_matched++;
15395 }
15396
15397 return num_matched;
15398}
15399
15400/**
15401 * wlan_hdd_mdns_find_max() - Find the maximum number of the matched entries
15402 * @matchedlist: Pointer to the array of struct hdd_mdns_resp_matched
15403 * @numlist: The number of the elements in the array matchedlist.
15404 *
15405 * Find the max number of the matched entries among the array matchedlist.
15406 *
15407 * Return: None
15408 */
15409static void wlan_hdd_mdns_find_max(struct hdd_mdns_resp_matched *matchedlist,
15410 uint8_t numlist)
15411{
15412 int j;
15413 struct hdd_mdns_resp_matched tmp;
15414
15415 /* At least two values are used for sorting */
15416 if ((numlist < 2) || (matchedlist == NULL)) {
15417 hddLog(LOGE, FL("At least two values are used for sorting!"));
15418 return;
15419 }
15420
15421 for (j = 0; j < numlist-1; j++) {
15422 if (matchedlist[j].num_matched >
15423 matchedlist[j+1].num_matched) {
15424 vos_mem_copy(&tmp, &matchedlist[j],
15425 sizeof(struct hdd_mdns_resp_matched));
15426 vos_mem_copy(&matchedlist[j], &matchedlist[j+1],
15427 sizeof(struct hdd_mdns_resp_matched));
15428 vos_mem_copy(&matchedlist[j+1], &tmp,
15429 sizeof(struct hdd_mdns_resp_matched));
15430 }
15431 }
15432}
15433
15434/**
15435 * wlan_hdd_mdns_pack_response_type_a() - Pack Type A response
15436 * @ini_config: Pointer to the struct hdd_config_t
15437 * @resp_info: Pointer to the struct tSirMDNSResponseInfo
15438 * @resptype_a: Pointer to the struct hdd_mdns_resp_info of Type A
15439 *
15440 * Type A response include QName, response type, class, TTL and Ipv4.
15441 *
15442 * Return: Return boolean. TRUE for success, FALSE for fail.
15443 */
15444static bool
15445wlan_hdd_mdns_pack_response_type_a(hdd_config_t *ini_config,
15446 sir_mdns_resp_info resp_info,
15447 struct hdd_mdns_resp_info *resptype_a)
15448{
15449 uint16_t value;
15450 uint32_t len;
15451
15452 ENTER();
15453 if ((ini_config == NULL) || (resp_info == NULL) ||
15454 (resptype_a == NULL)) {
15455 hddLog(LOGE, FL("ini_config or response info is NULL!"));
15456 return FALSE;
15457 }
15458
15459 /* No Type A response */
15460 if (strlen((char *)ini_config->mdns_resp_type_a) <= 0)
15461 return TRUE;
15462
15463 /* Wrong response is assigned, just ignore this response */
15464 if (!wlan_hdd_mdns_init_response(resptype_a,
15465 ini_config->mdns_resp_type_a, '.'))
15466 return TRUE;
15467
15468 /* Process response domain name */
15469 if (!wlan_hdd_mdns_process_response_dname(resptype_a, resp_info)) {
15470 hddLog(LOGE, FL("Fail to process mDNS response (%d)!"),
15471 MDNS_TYPE_A);
15472 return FALSE;
15473 }
15474
15475 /* Process response Type, Class, TTL */
15476 if (!wlan_hdd_mdns_process_response_misc(MDNS_TYPE_A, resp_info)) {
15477 hddLog(LOGE, FL("Fail to process mDNS misc response (%d)!"),
15478 MDNS_TYPE_A);
15479 return FALSE;
15480 }
15481
15482 /* Process response RDLength, RData */
15483 len = sizeof(uint16_t) + sizeof(uint32_t);
15484 len += resp_info->resp_len;
15485 if (len >= MAX_MDNS_RESP_LEN) {
15486 hddLog(LOGE, FL("resp_len exceeds %d!"), MAX_MDNS_RESP_LEN);
15487 return FALSE;
15488 }
15489 value = sizeof(uint32_t);
15490 wlan_hdd_mdns_format_response_u16(value, resp_info);
15491 wlan_hdd_mdns_format_response_u32(ini_config->mdns_resp_type_a_ipv4,
15492 resp_info);
15493
15494 EXIT();
15495 return TRUE;
15496}
15497
15498/**
15499 * wlan_hdd_mdns_pack_response_type_txt() - Pack Type Txt response
15500 * @ini_config: Pointer to the struct hdd_config_t
15501 * @resp_info: Pointer to the struct tSirMDNSResponseInfo
15502 * @resptype_txt: Pointer to the struct hdd_mdns_resp_info of Type txt
15503 * @resptype_a: Pointer to the struct hdd_mdns_resp_info of Type A
15504 *
15505 * Type Txt response include QName, response type, class, TTL and text content.
15506 * Also, it will find the matched QName from resptype_A and compress the data.
15507 *
15508 * Return: Return boolean. TRUE for success, FALSE for fail.
15509 */
15510static bool
15511wlan_hdd_mdns_pack_response_type_txt(hdd_config_t *ini_config,
15512 sir_mdns_resp_info resp_info,
15513 struct hdd_mdns_resp_info *resptype_txt,
15514 struct hdd_mdns_resp_info *resptype_a)
15515{
15516 uint8_t num_matched;
15517 uint8_t num;
15518 uint16_t idx;
15519 uint16_t value = 0;
15520 uint32_t len;
15521 uint32_t total_len;
15522 bool status;
15523 struct hdd_mdns_resp_info resptype_content;
15524
15525 ENTER();
15526
15527 if ((ini_config == NULL) || (resp_info == NULL) ||
15528 (resptype_txt == NULL)) {
15529 hddLog(LOGE, FL("ini_config or response info is NULL!"));
15530 return FALSE;
15531 }
15532
15533 /* No Type Txt response */
15534 if (strlen((char *)ini_config->mdns_resp_type_txt) <= 0)
15535 return TRUE;
15536
15537 /* Wrong response is assigned, just ignore this response */
15538 if (!wlan_hdd_mdns_init_response(resptype_txt,
15539 ini_config->mdns_resp_type_txt, '.'))
15540 return TRUE;
15541
15542 /*
15543 * For data compression
15544 * Check if any strings are matched with Type A response
15545 */
15546 if (resptype_a && (resptype_a->num_entries > 0)) {
15547 num_matched = wlan_hdd_mdns_find_entries_from_end(resptype_txt,
15548 resptype_a);
15549 if (num_matched > 0) {
15550 if (!wlan_hdd_mdns_compress_data(resp_info,
15551 resptype_txt, resptype_a, num_matched)) {
15552 hddLog(LOGE, FL("Fail to compress mDNS "
15553 "response (%d)!"), MDNS_TYPE_TXT);
15554 return FALSE;
15555 }
15556 } else {
15557 /*
15558 * num_matched is zero. Error!
15559 * At least ".local" is needed.
15560 */
15561 hddLog(LOGE, FL("No matched string! Fail to pack mDNS "
15562 "response (%d)!"), MDNS_TYPE_TXT);
15563 return FALSE;
15564 }
15565 } else {
15566 /* no TypeA response, so show the whole data */
15567 if (!wlan_hdd_mdns_process_response_dname(resptype_txt,
15568 resp_info)) {
15569 hddLog(LOGE, FL("Fail to process mDNS response (%d)!"),
15570 MDNS_TYPE_TXT);
15571 return FALSE;
15572 }
15573 }
15574
15575 /* Process response Type, Class, TTL */
15576 if (!wlan_hdd_mdns_process_response_misc(MDNS_TYPE_TXT, resp_info)) {
15577 hddLog(LOGE, FL("Fail to process mDNS misc response (%d)!"),
15578 MDNS_TYPE_TXT);
15579 return FALSE;
15580 }
15581
15582 /*
15583 * Process response RDLength, RData.
15584 * TypeTxt RData include len.
15585 */
15586 status = wlan_hdd_mdns_init_response(&resptype_content,
15587 ini_config->mdns_resp_type_txt_content,
15588 '/');
15589 if (status == FALSE) {
15590 hddLog(LOGE, FL("wlan_hdd_mdns_init_response FAIL"));
15591 return FALSE;
15592 }
15593
15594 for (num = 0; num < resptype_content.num_entries; num++) {
15595 idx = num * MAX_LEN_DOMAINNAME_FIELD;
15596 value += strlen((char *)&resptype_content.data[idx]);
15597 }
15598
15599 /* content len is uint16_t */
15600 total_len = sizeof(uint16_t);
15601 total_len += resp_info->resp_len + value +
15602 resptype_content.num_entries;
15603
15604 if (total_len >= MAX_MDNS_RESP_LEN) {
15605 hddLog(LOGE, FL("resp_len exceeds %d!"), MAX_MDNS_RESP_LEN);
15606 return FALSE;
15607 }
15608 wlan_hdd_mdns_format_response_u16(value + resptype_content.num_entries,
15609 resp_info);
15610
15611 for (num = 0; num < resptype_content.num_entries; num++) {
15612 idx = num * MAX_LEN_DOMAINNAME_FIELD;
15613 len = strlen((char *)&resptype_content.data[idx]);
15614 resp_info->resp_data[resp_info->resp_len] = len;
15615 resp_info->resp_len++;
15616
15617 vos_mem_copy(&resp_info->resp_data[resp_info->resp_len],
15618 &resptype_content.data[idx], len);
15619
15620 resp_info->resp_len += len;
15621 hddLog(LOG1, FL("index = %d, len = %d, str = %s"),
15622 num, len, &resptype_content.data[idx]);
15623 }
15624
15625 EXIT();
15626 return TRUE;
15627}
15628
15629/**
15630 * wlan_hdd_mdns_pack_response_type_ptr_dname() - Pack Type PTR domain name
15631 * @ini_config: Pointer to the struct hdd_config_t
15632 * @resp_info: Pointer to the struct tSirMDNSResponseInfo
15633 * @resptype_ptr_dn: Pointer to the struct hdd_mdns_resp_info of Type Ptr
15634 * domain name
15635 * @resptype_ptr: Pointer to the struct hdd_mdns_resp_info of Type Ptr
15636 * @resptype_txt: Pointer to the struct hdd_mdns_resp_info of Type Txt
15637 * @resptype_a: Pointer to the struct hdd_mdns_resp_info of Type A
15638 *
15639 * The Type Ptr response include Type PTR domain name in its data field.
15640 * Also, it will find the matched QName from the existing resptype_ptr,
15641 * resptype_txt, resptype_a and then compress the data.
15642 *
15643 * Return: Return boolean. TRUE for success, FALSE for fail.
15644 */
15645static bool
15646wlan_hdd_mdns_pack_response_type_ptr_dname(hdd_config_t *ini_config,
15647 sir_mdns_resp_info resp_info,
15648 struct hdd_mdns_resp_info *resptype_ptr_dn,
15649 struct hdd_mdns_resp_info *resptype_ptr,
15650 struct hdd_mdns_resp_info *resptype_txt,
15651 struct hdd_mdns_resp_info *resptype_a)
15652{
15653 uint8_t num_matched, numlist, size;
15654 struct hdd_mdns_resp_matched matchedlist[MAX_MDNS_RESP_TYPE-1];
15655 struct hdd_mdns_resp_info *resp;
15656
15657 if ((ini_config == NULL) || (resp_info == NULL) ||
15658 (resptype_ptr == NULL) || (resptype_ptr_dn == NULL)) {
15659 hddLog(LOGE, FL("ini_config or response info is NULL!"));
15660 return FALSE;
15661 }
15662
15663 /* No Type Ptr domain name response */
15664 if (strlen((char *)ini_config->mdns_resp_type_ptr_dname) <= 0)
15665 return TRUE;
15666
15667 /* Wrong response is assigned, just ignore this response */
15668 if (!wlan_hdd_mdns_init_response(resptype_ptr_dn,
15669 ini_config->mdns_resp_type_ptr_dname, '.'))
15670 return TRUE;
15671
15672 /*
15673 * For data compression
15674 * Check if any strings are matched with previous
15675 * response.
15676 */
15677 numlist = 0;
15678 size = (MAX_MDNS_RESP_TYPE-1);
15679 size *= sizeof(struct hdd_mdns_resp_matched);
15680 vos_mem_zero(matchedlist, size);
15681 num_matched = wlan_hdd_mdns_find_entries_from_end(resptype_ptr_dn,
15682 resptype_ptr);
15683 if (num_matched > 0) {
15684 matchedlist[numlist].num_matched = num_matched;
15685 matchedlist[numlist].type = MDNS_TYPE_PTR;
15686 numlist++;
15687 }
15688 if (resptype_txt && (resptype_txt->num_entries > 0)) {
15689 num_matched = wlan_hdd_mdns_find_entries_from_end(
15690 resptype_ptr_dn, resptype_txt);
15691 if (num_matched > 0) {
15692 matchedlist[numlist].num_matched = num_matched;
15693 matchedlist[numlist].type = MDNS_TYPE_TXT;
15694 numlist++;
15695 }
15696 }
15697 if (resptype_a && (resptype_a->num_entries > 0)) {
15698 num_matched = wlan_hdd_mdns_find_entries_from_end(
15699 resptype_ptr_dn,resptype_a);
15700 if (num_matched > 0) {
15701 matchedlist[numlist].num_matched = num_matched;
15702 matchedlist[numlist].type = MDNS_TYPE_A;
15703 numlist++;
15704 }
15705 }
15706 if (numlist > 0) {
15707 if (numlist > 1)
15708 wlan_hdd_mdns_find_max(matchedlist, numlist);
15709 resp = NULL;
15710 switch (matchedlist[numlist-1].type) {
15711 case MDNS_TYPE_A:
15712 resp = resptype_a;
15713 break;
15714 case MDNS_TYPE_TXT:
15715 resp = resptype_txt;
15716 break;
15717 case MDNS_TYPE_PTR:
15718 resp = resptype_ptr;
15719 break;
15720 default:
15721 hddLog(LOGE, FL("Fail to compress mDNS response "
15722 "(%d)!"), MDNS_TYPE_PTR_DNAME);
15723 return FALSE;
15724 }
15725 num_matched = matchedlist[numlist-1].num_matched;
15726 if (!wlan_hdd_mdns_compress_data(resp_info, resptype_ptr_dn,
15727 resp, num_matched)) {
15728 hddLog(LOGE, FL("Fail to compress mDNS response "
15729 "(%d)!"), MDNS_TYPE_PTR_DNAME);
15730 return FALSE;
15731 }
15732 } else {
15733 /* num = 0 -> no matched string */
15734 if (!wlan_hdd_mdns_process_response_dname(resptype_ptr_dn,
15735 resp_info)) {
15736 hddLog(LOGE, FL("Fail to process mDNS response (%d)!"),
15737 MDNS_TYPE_PTR_DNAME);
15738 return FALSE;
15739 }
15740 }
15741
15742 return TRUE;
15743}
15744
15745/**
15746 * wlan_hdd_mdns_pack_response_type_ptr() - Pack Type PTR response
15747 * @ini_config: Pointer to the struct hdd_config_t
15748 * @resp_info: Pointer to the struct tSirMDNSResponseInfo
15749 * @resptype_ptr: Pointer to the struct hdd_mdns_resp_info of Type Ptr
15750 * @resptype_ptr_dn: Pointer to the struct hdd_mdns_resp_info of Type Ptr
15751 * domain name
15752 * @resptype_txt: Pointer to the struct hdd_mdns_resp_info of Type Txt
15753 * @resptype_a: Pointer to the struct hdd_mdns_resp_info of Type A
15754 *
15755 * The Type Ptr response include QName, response type, class, TTL and
15756 * Type PTR domain name. Also, it will find the matched QName from the
15757 * existing resptype_txt, resptype_a and then compress the data.
15758 *
15759 * Return: Return boolean. TRUE for success, FALSE for fail.
15760 */
15761static bool
15762wlan_hdd_mdns_pack_response_type_ptr(hdd_config_t *ini_config,
15763 sir_mdns_resp_info resp_info,
15764 struct hdd_mdns_resp_info *resptype_ptr,
15765 struct hdd_mdns_resp_info *resptype_ptr_dn,
15766 struct hdd_mdns_resp_info *resptype_txt,
15767 struct hdd_mdns_resp_info *resptype_a)
15768{
15769 uint8_t num_matched, num_matched1;
15770 uint16_t value;
15771 uint8_t val_u8;
15772 uint32_t offset_data_len, len;
15773
15774 ENTER();
15775 if ((ini_config == NULL) || (resp_info == NULL) ||
15776 (resptype_ptr == NULL) || (resptype_ptr_dn == NULL)) {
15777 hddLog(LOGE, FL("ini_config or response info is NULL!"));
15778 return FALSE;
15779 }
15780
15781 /* No Type Ptr response */
15782 if (strlen((char *)ini_config->mdns_resp_type_ptr) <= 0)
15783 return TRUE;
15784
15785 /* Wrong response is assigned, just ignore this response */
15786 if (!wlan_hdd_mdns_init_response(resptype_ptr,
15787 ini_config->mdns_resp_type_ptr, '.'))
15788 return TRUE;
15789
15790 /*
15791 * For data compression
15792 * Check if any strings are matched with Type A response
15793 */
15794 num_matched = 0;
15795 num_matched1 = 0;
15796 if (resptype_a && (resptype_a->num_entries > 0)) {
15797 num_matched = wlan_hdd_mdns_find_entries_from_end(resptype_ptr,
15798 resptype_a);
15799 }
15800 if (resptype_txt && (resptype_txt->num_entries > 0)) {
15801 num_matched1 = wlan_hdd_mdns_find_entries_from_end(
15802 resptype_ptr, resptype_txt);
15803 }
15804 if ((num_matched != num_matched1) ||
15805 ((num_matched > 0) && (num_matched1 > 0))) {
15806 if (num_matched >= num_matched1) {
15807 if (!wlan_hdd_mdns_compress_data(resp_info,
15808 resptype_ptr, resptype_a, num_matched)) {
15809 hddLog(LOGE, FL("Fail to compress mDNS "
15810 "response (%d)!"), MDNS_TYPE_PTR);
15811 return FALSE;
15812 }
15813 } else {
15814 /* num_matched is less than num_matched1 */
15815 if (!wlan_hdd_mdns_compress_data(resp_info,
15816 resptype_ptr, resptype_txt, num_matched1)) {
15817 hddLog(LOGE, FL("Fail to compress mDNS "
15818 "response (%d)!"), MDNS_TYPE_PTR);
15819 return FALSE;
15820 }
15821 }
15822 } else {
15823 /*
15824 * Both num_matched and num_matched1 are zero.
15825 * no TypeA & TypeTxt
15826 */
15827 if (!wlan_hdd_mdns_process_response_dname(resptype_ptr,
15828 resp_info)) {
15829 hddLog(LOGE, FL("Fail to process mDNS response (%d)!"),
15830 MDNS_TYPE_PTR);
15831 return FALSE;
15832 }
15833 }
15834
15835 /* Process response Type, Class, TTL */
15836 if (!wlan_hdd_mdns_process_response_misc(MDNS_TYPE_PTR, resp_info)) {
15837 hddLog(LOGE, FL("Fail to process mDNS misc response (%d)!"),
15838 MDNS_TYPE_PTR);
15839 return FALSE;
15840 }
15841
15842 /*
15843 * Process response RDLength, RData (Ptr domain name)
15844 * Save the offset of RData length
15845 */
15846 offset_data_len = resp_info->resp_len;
15847 resp_info->resp_len += sizeof(uint16_t);
15848
15849 if (!wlan_hdd_mdns_pack_response_type_ptr_dname(ini_config, resp_info,
15850 resptype_ptr_dn, resptype_ptr,
15851 resptype_txt, resptype_a)) {
15852 return FALSE;
15853 }
15854 /* Set the RData length */
15855 len = offset_data_len + sizeof(uint16_t);
15856 if ((resptype_ptr_dn->num_entries > 0) &&
15857 (resp_info->resp_len > len)) {
15858 value = resp_info->resp_len - len;
15859 val_u8 = (value & 0xff00) >> 8;
15860 resp_info->resp_data[offset_data_len] = val_u8;
15861 val_u8 = value & 0xff;
15862 resp_info->resp_data[offset_data_len+1] = val_u8;
15863 } else {
15864 hddLog(LOGE, FL("Fail to process mDNS response (%d)!"),
15865 MDNS_TYPE_PTR);
15866 return FALSE;
15867 }
15868
15869 EXIT();
15870 return TRUE;
15871}
15872
15873/**
15874 * wlan_hdd_mdns_pack_response_type_srv_target()- Pack Type Service Target
15875 * @ini_config: Pointer to the struct hdd_config_t
15876 * @resp_info: Pointer to the struct tSirMDNSResponseInfo
15877 * @resptype_srv_tgt: Pointer to the struct hdd_mdns_resp_info of Type Srv
15878 * target
15879 * @resptype_srv: Pointer to the struct hdd_mdns_resp_info of Type Srv
15880 * @resptype_ptr: Pointer to the struct hdd_mdns_resp_info of Type Ptr
15881 * @resptype_ptr_dn: Pointer to the struct hdd_mdns_resp_info of Type Ptr
15882 * domain name
15883 * @resptype_txt: Pointer to the struct hdd_mdns_resp_info of Type Txt
15884 * @resptype_a: Pointer to the struct hdd_mdns_resp_info of Type A
15885 *
15886 * The Type service target is one of the data field in the Type SRV response.
15887 * Also, it will find the matched QName from the existing resptype_srv,
15888 * resptype_ptr, resptype_ptr_dn, resptype_txt, resptype_a and then compress
15889 * the data.
15890 *
15891 * Return: Return boolean. TRUE for success, FALSE for fail.
15892 */
15893static bool
15894wlan_hdd_mdns_pack_response_type_srv_target(hdd_config_t *ini_config,
15895 sir_mdns_resp_info resp_info,
15896 struct hdd_mdns_resp_info *resptype_srv_tgt,
15897 struct hdd_mdns_resp_info *resptype_srv,
15898 struct hdd_mdns_resp_info *resptype_ptr,
15899 struct hdd_mdns_resp_info *resptype_ptr_dn,
15900 struct hdd_mdns_resp_info *resptype_txt,
15901 struct hdd_mdns_resp_info *resptype_a)
15902{
15903 uint8_t num_matched, num, size;
15904 struct hdd_mdns_resp_matched matchedlist[MAX_MDNS_RESP_TYPE-1];
15905 struct hdd_mdns_resp_info *resp;
15906
15907 if ((ini_config == NULL) || (resp_info == NULL) ||
15908 (resptype_srv == NULL) || (resptype_srv_tgt == NULL)) {
15909 hddLog(LOGE, FL("ini_config or response info is NULL!"));
15910 return FALSE;
15911 }
15912
15913 /* No Type Srv Target response */
15914 if (strlen((char *)ini_config->mdns_resp_type_srv_target) <= 0)
15915 return TRUE;
15916
15917 /* Wrong response is assigned, just ignore this response */
15918 if (!wlan_hdd_mdns_init_response(resptype_srv_tgt,
15919 ini_config->mdns_resp_type_srv_target, '.'))
15920 return TRUE;
15921
15922 /*
15923 * For data compression
15924 * Check if any strings are matched with previous response.
15925 */
15926 num = 0;
15927 size = (MAX_MDNS_RESP_TYPE-1);
15928 size *= sizeof(struct hdd_mdns_resp_matched);
15929 vos_mem_zero(matchedlist, size);
15930 num_matched = wlan_hdd_mdns_find_entries_from_end(resptype_srv_tgt,
15931 resptype_srv);
15932 if (num_matched > 0) {
15933 matchedlist[num].num_matched = num_matched;
15934 matchedlist[num].type = MDNS_TYPE_SRV;
15935 num++;
15936 }
15937 if (resptype_ptr && (resptype_ptr->num_entries > 0)) {
15938 if (resptype_ptr_dn && (resptype_ptr_dn->num_entries > 0)) {
15939 num_matched = wlan_hdd_mdns_find_entries_from_end(
15940 resptype_srv_tgt, resptype_ptr_dn);
15941 if (num_matched > 0) {
15942 matchedlist[num].num_matched = num_matched;
15943 matchedlist[num].type = MDNS_TYPE_PTR_DNAME;
15944 num++;
15945 }
15946 }
15947 num_matched = wlan_hdd_mdns_find_entries_from_end(
15948 resptype_srv_tgt, resptype_ptr);
15949 if (num_matched > 0) {
15950 matchedlist[num].num_matched = num_matched;
15951 matchedlist[num].type = MDNS_TYPE_PTR;
15952 num++;
15953 }
15954 }
15955 if (resptype_txt && (resptype_txt->num_entries > 0)) {
15956 num_matched = wlan_hdd_mdns_find_entries_from_end(
15957 resptype_srv_tgt, resptype_txt);
15958 if (num_matched > 0) {
15959 matchedlist[num].num_matched = num_matched;
15960 matchedlist[num].type = MDNS_TYPE_TXT;
15961 num++;
15962 }
15963 }
15964 if (resptype_a && (resptype_a->num_entries > 0)) {
15965 num_matched = wlan_hdd_mdns_find_entries_from_end(
15966 resptype_srv_tgt, resptype_a);
15967 if (num_matched > 0) {
15968 matchedlist[num].num_matched = num_matched;
15969 matchedlist[num].type = MDNS_TYPE_A;
15970 num++;
15971 }
15972 }
15973 if (num > 0) {
15974 if (num > 1)
15975 wlan_hdd_mdns_find_max(matchedlist, num);
15976 resp = NULL;
15977 switch (matchedlist[num-1].type) {
15978 case MDNS_TYPE_A:
15979 resp = resptype_a;
15980 break;
15981 case MDNS_TYPE_TXT:
15982 resp = resptype_txt;
15983 break;
15984 case MDNS_TYPE_PTR:
15985 resp = resptype_ptr;
15986 break;
15987 case MDNS_TYPE_PTR_DNAME:
15988 resp = resptype_ptr_dn;
15989 break;
15990 case MDNS_TYPE_SRV:
15991 resp = resptype_srv;
15992 break;
15993 default:
15994 hddLog(LOGE, FL("Fail to compress mDNS response "
15995 "(%d)!"), MDNS_TYPE_SRV_TARGET);
15996 return FALSE;
15997 }
15998 num_matched = matchedlist[num-1].num_matched;
15999 if (!wlan_hdd_mdns_compress_data(resp_info, resptype_srv_tgt,
16000 resp, num_matched)) {
16001 hddLog(LOGE, FL("Fail to compress mDNS response "
16002 "(%d)!"), MDNS_TYPE_SRV_TARGET);
16003 return FALSE;
16004 }
16005 } else {
16006 /* num = 0 -> no matched string */
16007 if (!wlan_hdd_mdns_process_response_dname(resptype_srv_tgt,
16008 resp_info)) {
16009 hddLog(LOGE, FL("Fail to process mDNS response (%d)!"),
16010 MDNS_TYPE_SRV_TARGET);
16011 return FALSE;
16012 }
16013 }
16014
16015 return TRUE;
16016}
16017
16018/**
16019 * wlan_hdd_mdns_pack_response_type_srv()- Pack Type Service response
16020 * @ini_config: Pointer to the struct hdd_config_t
16021 * @resp_info: Pointer to the struct tSirMDNSResponseInfo
16022 * @resptype_srv: Pointer to the struct hdd_mdns_resp_info of Type Srv
16023 * @resptype_srv_tgt: Pointer to the struct hdd_mdns_resp_info of Type Srv
16024 * target
16025 * @resptype_ptr: Pointer to the struct hdd_mdns_resp_info of Type Ptr
16026 * @resptype_ptr_dn: Pointer to the struct hdd_mdns_resp_info of Type Ptr
16027 * domain name
16028 * @resptype_txt: Pointer to the struct hdd_mdns_resp_info of Type Txt
16029 * @resptype_a: Pointer to the struct hdd_mdns_resp_info of Type A
16030 *
16031 * The Type SRV (Service) response include QName, response type, class, TTL
16032 * and four kinds of data fields. Also, it will find the matched QName from
16033 * the existing resptype_ptr, resptype_ptr_dn, resptype_txt, resptype_a and
16034 * then compress the data.
16035 *
16036 * Return: Return boolean. TRUE for success, FALSE for fail.
16037 */
16038static bool
16039wlan_hdd_mdns_pack_response_type_srv(hdd_config_t *ini_config,
16040 sir_mdns_resp_info resp_info,
16041 struct hdd_mdns_resp_info *resptype_srv,
16042 struct hdd_mdns_resp_info *resptype_srv_tgt,
16043 struct hdd_mdns_resp_info *resptype_ptr,
16044 struct hdd_mdns_resp_info *resptype_ptr_dn,
16045 struct hdd_mdns_resp_info *resptype_txt,
16046 struct hdd_mdns_resp_info *resptype_a)
16047{
16048 uint8_t num_matched, num, size;
16049 uint16_t value;
16050 uint8_t val_u8;
16051 uint32_t offset_data_len, len;
16052 struct hdd_mdns_resp_info *resp;
16053 struct hdd_mdns_resp_matched matchedlist[MAX_MDNS_RESP_TYPE-1];
16054
16055 ENTER();
16056
16057 if ((ini_config == NULL) || (resp_info == NULL) ||
16058 (resptype_srv == NULL) || (resptype_srv_tgt == NULL)) {
16059 hddLog(LOGE, FL("ini_config or response info is NULL!"));
16060 return FALSE;
16061 }
16062
16063 /* No Type Srv response */
16064 if (strlen((char *)ini_config->mdns_resp_type_srv) <= 0)
16065 return TRUE;
16066
16067 /* Wrong response is assigned, just ignore this response */
16068 if (!wlan_hdd_mdns_init_response(resptype_srv,
16069 ini_config->mdns_resp_type_srv, '.'))
16070 return TRUE;
16071
16072 /*
16073 * For data compression
16074 * Check if any strings are matched with Type A response
16075 */
16076 num = 0;
16077 size = (MAX_MDNS_RESP_TYPE-1);
16078 size *= sizeof(struct hdd_mdns_resp_matched);
16079 vos_mem_zero(matchedlist, size);
16080 if (resptype_ptr && (resptype_ptr->num_entries > 0)) {
16081 if (resptype_ptr_dn && (resptype_ptr_dn->num_entries > 0)) {
16082 num_matched = wlan_hdd_mdns_find_entries_from_end(
16083 resptype_srv,
16084 resptype_ptr_dn);
16085 if (num_matched > 0) {
16086 matchedlist[num].num_matched = num_matched;
16087 matchedlist[num].type = MDNS_TYPE_PTR_DNAME;
16088 num++;
16089 }
16090 }
16091 num_matched = wlan_hdd_mdns_find_entries_from_end(resptype_srv,
16092 resptype_ptr);
16093 if (num_matched > 0) {
16094 matchedlist[num].num_matched = num_matched;
16095 matchedlist[num].type = MDNS_TYPE_PTR;
16096 num++;
16097 }
16098 }
16099 if (resptype_txt && (resptype_txt->num_entries > 0)) {
16100 num_matched = wlan_hdd_mdns_find_entries_from_end(resptype_srv,
16101 resptype_txt);
16102 if (num_matched > 0) {
16103 matchedlist[num].num_matched =num_matched;
16104 matchedlist[num].type = MDNS_TYPE_TXT;
16105 num++;
16106 }
16107 }
16108 if (resptype_a && (resptype_a->num_entries > 0)) {
16109 num_matched = wlan_hdd_mdns_find_entries_from_end(resptype_srv,
16110 resptype_a);
16111 if (num_matched > 0) {
16112 matchedlist[num].num_matched = num_matched;
16113 matchedlist[num].type = MDNS_TYPE_A;
16114 num++;
16115 }
16116 }
16117 if (num > 0) {
16118 if (num > 1)
16119 wlan_hdd_mdns_find_max(matchedlist, num);
16120 resp = NULL;
16121 switch (matchedlist[num-1].type) {
16122 case MDNS_TYPE_A:
16123 resp = resptype_a;
16124 break;
16125 case MDNS_TYPE_TXT:
16126 resp = resptype_txt;
16127 break;
16128 case MDNS_TYPE_PTR:
16129 resp = resptype_ptr;
16130 break;
16131 case MDNS_TYPE_PTR_DNAME:
16132 resp = resptype_ptr_dn;
16133 break;
16134 default:
16135 hddLog(LOGE, FL("Fail to compress mDNS response "
16136 "(%d)!"), MDNS_TYPE_SRV);
16137 return FALSE;
16138 }
16139 num_matched = matchedlist[num-1].num_matched;
16140 if (!wlan_hdd_mdns_compress_data(resp_info, resptype_srv,
16141 resp, num_matched)) {
16142 hddLog(LOGE, FL("Fail to compress mDNS response "
16143 "(%d)!"), MDNS_TYPE_SRV);
16144 return FALSE;
16145 }
16146 } else {
16147 /* num = 0 -> no matched string */
16148 if (!wlan_hdd_mdns_process_response_dname(resptype_srv,
16149 resp_info)) {
16150 hddLog(LOGE, FL("Fail to process mDNS response (%d)!"),
16151 MDNS_TYPE_SRV);
16152 return FALSE;
16153 }
16154 }
16155
16156 /* Process response Type, Class, TTL */
16157 if (!wlan_hdd_mdns_process_response_misc(MDNS_TYPE_SRV, resp_info)) {
16158 hddLog(LOGE, FL("Fail to process mDNS misc response (%d)!"),
16159 MDNS_TYPE_SRV);
16160 return FALSE;
16161 }
16162
16163 /*
16164 * Process response RDLength, RData (Srv target name)
16165 * Save the offset of RData length
16166 */
16167 offset_data_len = resp_info->resp_len;
16168 resp_info->resp_len += sizeof(uint16_t);
16169
16170 len = resp_info->resp_len + (3 * sizeof(uint16_t));
16171 if (len >= MAX_MDNS_RESP_LEN) {
16172 hddLog(LOGE, FL("resp_len exceeds %d!"), MAX_MDNS_RESP_LEN);
16173 return FALSE;
16174 }
16175
16176 /* set Srv Priority */
16177 value = ini_config->mdns_resp_type_srv_priority;
16178 wlan_hdd_mdns_format_response_u16(value, resp_info);
16179 /* set Srv Weight */
16180 value = ini_config->mdns_resp_type_srv_weight;
16181 wlan_hdd_mdns_format_response_u16(value, resp_info);
16182 /* set Srv Port */
16183 value = ini_config->mdns_resp_type_srv_port;
16184 wlan_hdd_mdns_format_response_u16(value, resp_info);
16185
16186 if (!wlan_hdd_mdns_pack_response_type_srv_target(ini_config, resp_info,
16187 resptype_srv_tgt, resptype_srv,
16188 resptype_ptr, resptype_ptr_dn,
16189 resptype_txt, resptype_a)) {
16190 return FALSE;
16191 }
16192 /* Set the RData length */
16193 len = offset_data_len + sizeof(uint16_t);
16194 if ((resptype_srv_tgt->num_entries > 0) &&
16195 (resp_info->resp_len > len)) {
16196 value = resp_info->resp_len - len;
16197 val_u8 = (value & 0xff00) >> 8;
16198 resp_info->resp_data[offset_data_len] = val_u8;
16199 val_u8 = value & 0xff;
16200 resp_info->resp_data[offset_data_len+1] = val_u8;
16201 } else {
16202 hddLog(LOGE, FL("Fail to process mDNS response (%d)!"),
16203 MDNS_TYPE_SRV);
16204 return FALSE;
16205 }
16206
16207 EXIT();
16208 return TRUE;
16209}
16210
16211/**
16212 * wlan_hdd_mdns_free_mem() - Free the allocated memory
16213 * @response: Pointer to the struct hdd_mdns_resp_info
16214 *
16215 * Return: None
16216 */
16217static void wlan_hdd_mdns_free_mem(struct hdd_mdns_resp_info *response)
16218{
16219 if (response && response->data)
16220 vos_mem_free(response->data);
16221 if (response && response->offset)
16222 vos_mem_free(response->offset);
16223}
16224
16225/**
16226 * wlan_hdd_mdns_pack_response() - Pack mDNS response
16227 * @ini_config: Pointer to the struct hdd_config_t
16228 * @resp_info: Pointer to the struct tSirMDNSResponseInfo
16229 *
16230 * This function will pack four types of responses (Type A, Type Txt, Type Ptr
16231 * and Type Service). Each response contains QName, response type, class, TTL
16232 * and data fields.
16233 *
16234 * Return: Return boolean. TRUE for success, FALSE for fail.
16235 */
16236static bool wlan_hdd_mdns_pack_response(hdd_config_t *ini_config,
16237 sir_mdns_resp_info resp_info)
16238{
16239 struct hdd_mdns_resp_info resptype_a, resptype_txt;
16240 struct hdd_mdns_resp_info resptype_ptr, resptype_ptr_dn;
16241 struct hdd_mdns_resp_info resptype_srv, resptype_srv_tgt;
16242 uint32_t num_res_records = 0;
16243 bool status = FALSE;
16244
16245 ENTER();
16246
16247 wlan_hdd_mdns_reset_response(&resptype_a);
16248 wlan_hdd_mdns_reset_response(&resptype_txt);
16249 wlan_hdd_mdns_reset_response(&resptype_ptr);
16250 wlan_hdd_mdns_reset_response(&resptype_ptr_dn);
16251 wlan_hdd_mdns_reset_response(&resptype_srv);
16252 wlan_hdd_mdns_reset_response(&resptype_srv_tgt);
16253
16254 resp_info->resp_len = 0;
16255
16256 /* Process Type A response */
16257 if (!wlan_hdd_mdns_pack_response_type_a(ini_config, resp_info,
16258 &resptype_a))
16259 goto err_resptype_a;
16260
16261 if ((resptype_a.num_entries > 0) &&
16262 (strlen((char *)&resptype_a.data[0]) > 0))
16263 num_res_records++;
16264
16265 /* Process Type TXT response */
16266 if (!wlan_hdd_mdns_pack_response_type_txt(ini_config, resp_info,
16267 &resptype_txt, &resptype_a))
16268 goto err_resptype_txt;
16269
16270 if ((resptype_txt.num_entries > 0) &&
16271 (strlen((char *)&resptype_txt.data[0]) > 0))
16272 num_res_records++;
16273
16274 /* Process Type PTR response */
16275 if (!wlan_hdd_mdns_pack_response_type_ptr(ini_config, resp_info,
16276 &resptype_ptr, &resptype_ptr_dn,
16277 &resptype_txt, &resptype_a))
16278 goto err_resptype_ptr;
16279
16280 if ((resptype_ptr.num_entries > 0) &&
16281 (strlen((char *)&resptype_ptr.data[0]) > 0))
16282 num_res_records++;
16283
16284 /* Process Type SRV response */
16285 if (!wlan_hdd_mdns_pack_response_type_srv(ini_config, resp_info,
16286 &resptype_srv, &resptype_srv_tgt,
16287 &resptype_ptr, &resptype_ptr_dn,
16288 &resptype_txt, &resptype_a))
16289 goto err_resptype_srv;
16290
16291 if ((resptype_srv.num_entries > 0) &&
16292 (strlen((char *)&resptype_srv.data[0]) > 0))
16293 num_res_records++;
16294
16295 resp_info->resourceRecord_count = num_res_records;
16296 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
16297 "%s: Pack mDNS response data successfully!", __func__);
16298 status = TRUE;
16299
16300err_resptype_srv:
16301 wlan_hdd_mdns_free_mem(&resptype_srv);
16302 wlan_hdd_mdns_free_mem(&resptype_srv_tgt);
16303
16304err_resptype_ptr:
16305 wlan_hdd_mdns_free_mem(&resptype_ptr);
16306 wlan_hdd_mdns_free_mem(&resptype_ptr_dn);
16307
16308err_resptype_txt:
16309 wlan_hdd_mdns_free_mem(&resptype_txt);
16310
16311err_resptype_a:
16312 wlan_hdd_mdns_free_mem(&resptype_a);
16313
16314 EXIT();
16315 return status;
16316}
16317
16318/**
16319 * wlan_hdd_set_mdns_offload() - Enable mDNS offload
16320 * @hostapd_adapter: Pointer to the struct hdd_adapter_t
16321 *
16322 * This function will set FQDN/unique FQDN (full qualified domain name)
16323 * and the mDNS response. Then send them to SME.
16324 *
16325 * Return: Return boolean. TRUE for success, FALSE for fail.
16326 */
16327bool wlan_hdd_set_mdns_offload(hdd_adapter_t *hostapd_adapter)
16328{
16329 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(hostapd_adapter);
16330 sir_mdns_offload_info mdns_offload_info;
16331 sir_mdns_fqdn_info mdns_fqdn_info;
16332 sir_mdns_resp_info mdns_resp_info;
16333 uint32_t fqdn_len, ufqdn_len;
16334
16335 ENTER();
16336
16337 /* 1. Prepare the MDNS fqdn request to send to SME */
16338 fqdn_len = strlen(hdd_ctx->cfg_ini->mdns_fqdn);
16339 ufqdn_len = strlen(hdd_ctx->cfg_ini->mdns_uniquefqdn);
16340 if ((fqdn_len == 0) && (ufqdn_len == 0)) {
16341 hddLog(LOGE, FL("No mDNS FQDN or UFQDN is assigned fqdn_len %d,"
16342 "ufqdn_len %d!"), fqdn_len, ufqdn_len);
16343 return FALSE;
16344 }
16345
16346 mdns_fqdn_info = vos_mem_malloc(sizeof(*mdns_fqdn_info));
16347 if (NULL == mdns_fqdn_info) {
16348 hddLog(LOGE, FL("could not allocate tSirMDNSFqdnInfo!"));
16349 return FALSE;
16350 }
16351 /* MDNS fqdn request */
16352 if (fqdn_len > 0) {
16353 vos_mem_zero(mdns_fqdn_info, sizeof(*mdns_fqdn_info));
16354 mdns_fqdn_info->bss_idx = hostapd_adapter->sessionId;
16355 mdns_fqdn_info->fqdn_type = MDNS_FQDN_TYPE_GENERAL;
16356 mdns_fqdn_info->fqdn_len = fqdn_len;
16357 mdns_fqdn_info->mdns_fqdn_callback = hdd_mdns_fqdn_offload_done;
16358 mdns_fqdn_info->mdns_fqdn_cb_context = hostapd_adapter;
16359 vos_mem_copy(mdns_fqdn_info->fqdn_data,
16360 hdd_ctx->cfg_ini->mdns_fqdn,
16361 mdns_fqdn_info->fqdn_len);
16362
16363 if (eHAL_STATUS_SUCCESS !=
16364 sme_set_mdns_fqdn(hdd_ctx->hHal, mdns_fqdn_info)) {
16365 hddLog(LOGE, FL("sme_set_mdns_fqdn fail!"));
16366 vos_mem_free(mdns_fqdn_info);
16367 return FALSE;
16368 }
16369 }
16370 /* MDNS unique fqdn request */
16371 if (ufqdn_len > 0) {
16372 vos_mem_zero(mdns_fqdn_info, sizeof(*mdns_fqdn_info));
16373 mdns_fqdn_info->bss_idx = hostapd_adapter->sessionId;
16374 mdns_fqdn_info->fqdn_type = MDNS_FQDN_TYPE_UNIQUE;
16375 mdns_fqdn_info->fqdn_len = ufqdn_len;
16376 mdns_fqdn_info->mdns_fqdn_callback = hdd_mdns_fqdn_offload_done;
16377 mdns_fqdn_info->mdns_fqdn_cb_context = hostapd_adapter;
16378 vos_mem_copy(mdns_fqdn_info->fqdn_data,
16379 hdd_ctx->cfg_ini->mdns_uniquefqdn,
16380 mdns_fqdn_info->fqdn_len);
16381 if (eHAL_STATUS_SUCCESS !=
16382 sme_set_mdns_fqdn(hdd_ctx->hHal, mdns_fqdn_info)) {
16383 hddLog(LOGE, FL("sme_set_mdns_fqdn fail!"));
16384 vos_mem_free(mdns_fqdn_info);
16385 return FALSE;
16386 }
16387 }
16388 vos_mem_free(mdns_fqdn_info);
16389
16390 /* 2. Prepare the MDNS response request to send to SME */
16391 mdns_resp_info = vos_mem_malloc(sizeof(*mdns_resp_info));
16392 if (NULL == mdns_resp_info) {
16393 hddLog(LOGE, FL("could not allocate tSirMDNSResponseInfo!"));
16394 return FALSE;
16395 }
16396
16397 vos_mem_zero(mdns_resp_info, sizeof(*mdns_resp_info));
16398 mdns_resp_info->bss_idx = hostapd_adapter->sessionId;
16399 mdns_resp_info->mdns_resp_callback = hdd_mdns_resp_offload_done;
16400 mdns_resp_info->mdns_resp_cb_context = hostapd_adapter;
16401 if (!wlan_hdd_mdns_pack_response(hdd_ctx->cfg_ini, mdns_resp_info)) {
16402 hddLog(LOGE, FL("wlan_hdd_pack_mdns_response fail!"));
16403 vos_mem_free(mdns_resp_info);
16404 return FALSE;
16405 }
16406 if (eHAL_STATUS_SUCCESS !=
16407 sme_set_mdns_resp(hdd_ctx->hHal, mdns_resp_info)) {
16408 hddLog(LOGE, FL("sme_set_mdns_resp fail!"));
16409 vos_mem_free(mdns_resp_info);
16410 return FALSE;
16411 }
16412 vos_mem_free(mdns_resp_info);
16413
16414 /* 3. Prepare the MDNS Enable request to send to SME */
16415 mdns_offload_info = vos_mem_malloc(sizeof(*mdns_offload_info));
16416 if (NULL == mdns_offload_info) {
16417 hddLog(LOGE, FL("could not allocate tSirMDNSOffloadInfo!"));
16418 return FALSE;
16419 }
16420
16421 vos_mem_zero(mdns_offload_info, sizeof(*mdns_offload_info));
16422
16423 mdns_offload_info->bss_idx = hostapd_adapter->sessionId;
16424 mdns_offload_info->enable = hdd_ctx->cfg_ini->enable_mdns_offload;
16425 mdns_offload_info->mdns_enable_callback = hdd_mdns_enable_offload_done;
16426 mdns_offload_info->mdns_enable_cb_context = hostapd_adapter;
16427 if (eHAL_STATUS_SUCCESS !=
16428 sme_set_mdns_offload(hdd_ctx->hHal, mdns_offload_info)) {
16429 hddLog(LOGE, FL("sme_set_mdns_offload fail!"));
16430 vos_mem_free(mdns_offload_info);
16431 return FALSE;
16432 }
16433
16434 vos_mem_free(mdns_offload_info);
16435 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
16436 "%s: enable mDNS offload successfully!", __func__);
16437 return TRUE;
16438}
Manjeet Singh3ed79242017-01-11 19:04:32 +053016439
16440
Anurag Chouhan0b29de02016-12-16 13:18:40 +053016441#endif /* MDNS_OFFLOAD */
c_manjeecfd1efb2015-09-25 19:32:34 +053016442
Hanumanth Reddy Pothulad864f312017-01-18 16:16:08 +053016443/**
16444 * wlan_hdd_start_sap() - This function starts bss of SAP.
16445 * @ap_adapter: SAP adapter
16446 *
16447 * This function will process the starting of sap adapter.
16448 *
16449 * Return: void.
16450 */
16451void wlan_hdd_start_sap(hdd_adapter_t *ap_adapter)
16452{
16453 hdd_ap_ctx_t *hdd_ap_ctx;
16454 hdd_hostapd_state_t *hostapd_state;
16455 VOS_STATUS vos_status;
16456 hdd_context_t *hdd_ctx;
16457 tsap_Config_t *pConfig;
16458
16459 if (NULL == ap_adapter) {
16460 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
16461 FL("ap_adapter is NULL here"));
16462 return;
16463 }
16464
16465 hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter);
16466 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
16467 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
16468 pConfig = &ap_adapter->sessionCtx.ap.sapConfig;
16469
16470 mutex_lock(&hdd_ctx->sap_lock);
16471 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags))
16472 goto end;
16473
16474 if (0 != wlan_hdd_cfg80211_update_apies(ap_adapter)) {
16475 hddLog(LOGE, FL("SAP Not able to set AP IEs"));
16476 goto end;
16477 }
16478
16479 vos_event_reset(&hostapd_state->vosEvent);
16480 if (WLANSAP_StartBss(hdd_ctx->pvosContext, hdd_hostapd_SAPEventCB,
16481 &hdd_ap_ctx->sapConfig, (v_PVOID_t)ap_adapter->dev)
16482 != VOS_STATUS_SUCCESS) {
16483 goto end;
16484 }
16485
16486 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
16487 FL("Waiting for SAP to start"));
16488 vos_status = vos_wait_single_event(&hostapd_state->vosEvent, 10000);
16489 if (!VOS_IS_STATUS_SUCCESS(vos_status)) {
16490 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
16491 FL("SAP Start failed"));
16492 goto end;
16493 }
16494 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
16495 FL("SAP Start Success"));
16496 set_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
16497
16498 wlan_hdd_incr_active_session(hdd_ctx, ap_adapter->device_mode);
16499 hostapd_state->bCommit = TRUE;
16500
16501end:
16502 mutex_unlock(&hdd_ctx->sap_lock);
16503 return;
16504}
16505
Manjeet Singh3ed79242017-01-11 19:04:32 +053016506#ifdef WLAN_FEATURE_TSF
16507
16508/**
16509 * hdd_tsf_cb() - handle tsf request callback
16510 *
16511 * @pcb_cxt: pointer to the hdd_contex
16512 * @ptsf: pointer to struct stsf
16513 *
16514 * Based on the request sent .
16515 *
16516 * Return: Describe the execute result of this routine
16517 */
16518static int hdd_tsf_cb(void *pcb_ctx, struct stsf *ptsf)
16519{
16520 hdd_context_t *hddctx;
16521 int status;
16522 hdd_adapter_t* adapter = (hdd_adapter_t*)pcb_ctx;
16523
16524 if (pcb_ctx == NULL || ptsf == NULL) {
16525 hddLog(VOS_TRACE_LEVEL_ERROR,
16526 FL("HDD context is not valid"));
16527 return -EINVAL;
16528 }
16529
16530 hddctx = (hdd_context_t *)pcb_ctx;
16531 status = wlan_hdd_validate_context(hddctx);
16532 if (0 != status)
16533 return -EINVAL;
16534
16535 if (NULL == adapter) {
16536 hddLog(VOS_TRACE_LEVEL_ERROR,
16537 FL("failed to find adapter"));
16538 return -EINVAL;
16539 }
16540
16541 hddLog(VOS_TRACE_LEVEL_INFO,
16542 FL("tsf cb handle event, device_mode is %d"),
16543 adapter->device_mode);
16544
16545 /* copy the return value to hdd_tsf_ctx in adapter*/
16546 if (ptsf->tsf_req_status) {
16547
16548 vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
16549 adapter->tsf_cap_ctx.tsf_get_state = TSF_NOT_RETURNED_BY_FW;
16550 adapter->tsf_cap_ctx.tsf_capture_state = TSF_IDLE;
16551 vos_event_set (&adapter->tsf_cap_ctx.tsf_capture_done_event);
16552 vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
16553
16554 hddLog(VOS_TRACE_LEVEL_ERROR, FL("tsf req failure :%d"),
16555 ptsf->tsf_req_status);
16556 return ptsf->tsf_req_status;
16557 }
16558 /* If this is a get request.Store the tsf values in adapter. */
16559 if (!ptsf->set_tsf_req) {
16560 vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
16561 adapter->tsf_cap_ctx.tsf_low = ptsf->tsf_low;
16562 adapter->tsf_cap_ctx.tsf_high = ptsf->tsf_high;
16563 adapter->tsf_cap_ctx.tsf_get_state = TSF_RETURN;
16564 adapter->tsf_cap_ctx.tsf_capture_state = TSF_IDLE;
16565 vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
16566
16567 hddLog(VOS_TRACE_LEVEL_INFO,
16568 FL("hdd_get_tsf_cb sta=%u, tsf_low=%u, tsf_high=%u"),
16569 adapter->sessionId, ptsf->tsf_low, ptsf->tsf_high);
16570 }
16571 else {
16572 vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
16573 adapter->tsf_cap_ctx.tsf_capture_state = TSF_CAP_STATE;
16574 adapter->tsf_cap_ctx.tsf_get_state = TSF_CURRENT_IN_CAP_STATE;
16575 vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
16576 }
16577 vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
16578 vos_event_set (&adapter->tsf_cap_ctx.tsf_capture_done_event);
16579 vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
16580
16581 /* free allocated mem */
16582 vos_mem_free(ptsf);
16583
16584 return 0;
16585}
16586
16587/**
16588 * hdd_capture_tsf() - capture tsf
16589 *
16590 * @adapter: pointer to adapter
16591 * @buf: pointer to upper layer buf
16592 * @len : the length of buf
16593 *
16594 * This function returns tsf value to uplayer.
16595 *
16596 * Return: Describe the execute result of this routine
16597 */
16598int hdd_capture_tsf(hdd_adapter_t *adapter, uint32_t *buf, int len)
16599{
16600 int ret = 0;
16601 hdd_station_ctx_t *hdd_sta_ctx;
16602 hdd_context_t *hdd_ctx;
16603 tSirCapTsfParams cap_tsf_params;
16604 VOS_STATUS status;
16605
16606 if (adapter == NULL || buf == NULL) {
16607 hddLog(VOS_TRACE_LEVEL_ERROR,
16608 FL("invalid pointer"));
16609 return -EINVAL;
16610 }
16611 if (len != 1)
16612 return -EINVAL;
16613
16614 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
16615
16616 if (wlan_hdd_validate_context(hdd_ctx)) {
16617 hddLog(VOS_TRACE_LEVEL_ERROR,
16618 FL("invalid hdd ctx"));
16619 return -EINVAL;
16620 }
16621 if (adapter->device_mode == WLAN_HDD_INFRA_STATION ||
16622 adapter->device_mode == WLAN_HDD_P2P_CLIENT) {
16623 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
16624 if (hdd_sta_ctx->conn_info.connState !=
16625 eConnectionState_Associated) {
16626
16627 hddLog(VOS_TRACE_LEVEL_INFO,
16628 FL("failed to cap tsf, not connect with ap"));
16629 buf[0] = TSF_STA_NOT_CONNECTED_NO_TSF;
16630 return ret;
16631 }
16632 }
16633 if ((adapter->device_mode == WLAN_HDD_SOFTAP ||
16634 adapter->device_mode == WLAN_HDD_P2P_GO) &&
16635 !(test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags))) {
16636 hddLog(VOS_TRACE_LEVEL_INFO,
16637 FL("Soft AP / P2p GO not beaconing"));
16638 buf[0] = TSF_SAP_NOT_STARTED_NO_TSF;
16639 return ret;
16640 }
16641 if (adapter->tsf_cap_ctx.tsf_capture_state == TSF_CAP_STATE) {
16642 hddLog(VOS_TRACE_LEVEL_INFO,
16643 FL("current in capture state, pls reset"));
16644 buf[0] = TSF_CURRENT_IN_CAP_STATE;
16645 } else {
16646 hddLog(VOS_TRACE_LEVEL_INFO, FL("ioctl issue cap tsf cmd"));
16647 buf[0] = TSF_RETURN;
16648 cap_tsf_params.session_id = adapter->sessionId;
16649 cap_tsf_params.tsf_rsp_cb_func = hdd_tsf_cb;
16650 cap_tsf_params.tsf_rsp_cb_ctx = adapter;
16651
16652 vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
16653 adapter->tsf_cap_ctx.tsf_capture_state = TSF_CAP_STATE;
16654 adapter->tsf_cap_ctx.tsf_get_state = TSF_CURRENT_IN_CAP_STATE;
16655 vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
16656
16657 ret = sme_capture_tsf_req(hdd_ctx->hHal, cap_tsf_params);
16658
16659 if (ret != VOS_STATUS_SUCCESS) {
16660 hddLog(VOS_TRACE_LEVEL_ERROR, FL("capture fail"));
16661 buf[0] = TSF_CAPTURE_FAIL;
16662 vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
16663 adapter->tsf_cap_ctx.tsf_capture_state = TSF_IDLE;
16664 vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
16665 return -EINVAL;
16666 }
16667 /* wait till we get a response from fw */
16668 status = vos_wait_single_event(&adapter->tsf_cap_ctx.
16669 tsf_capture_done_event,
16670 HDD_TSF_CAP_REQ_TIMEOUT);
16671
16672 if (!VOS_IS_STATUS_SUCCESS(status)) {
16673 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
16674 ("capture tsf vos wait for single_event failed!! %d"),
16675 adapter->tsf_cap_ctx.tsf_get_state);
16676
16677 vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
16678 adapter->tsf_cap_ctx.tsf_capture_state = TSF_IDLE;
16679 vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
16680
16681 return -EINVAL;
16682 }
16683 }
16684 buf[0] = TSF_RETURN;
16685 hddLog(VOS_TRACE_LEVEL_INFO,
16686 FL("ioctl return cap tsf cmd, ret = %d"), ret);
16687 return ret;
16688}
16689
16690/**
16691 * hdd_indicate_tsf() - return tsf to uplayer
16692 *
16693 * @adapter: pointer to adapter
16694 * @buf: pointer to uplayer buf
16695 * @len : the length of buf
16696 *
16697 * This function returns tsf value to uplayer.
16698 *
16699 * Return: Describe the execute result of this routine
16700 */
16701int hdd_indicate_tsf(hdd_adapter_t *adapter, uint32_t *buf, int len)
16702{
16703 int ret = 0;
16704 hdd_station_ctx_t *hdd_sta_ctx;
16705 hdd_context_t *hdd_ctx;
16706 tSirCapTsfParams cap_tsf_params;
16707 VOS_STATUS status;
16708
16709 if (adapter == NULL || buf == NULL) {
16710 hddLog(VOS_TRACE_LEVEL_ERROR,
16711 FL("invalid pointer"));
16712 return -EINVAL;
16713 }
16714 if (len != 3)
16715 return -EINVAL;
16716
16717 buf [1] = 0;
16718 buf [2] = 0;
16719 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
16720
16721 if (wlan_hdd_validate_context(hdd_ctx)) {
16722 hddLog(VOS_TRACE_LEVEL_ERROR,
16723 FL("invalid hdd ctx"));
16724 return -EINVAL;
16725 }
16726 if (adapter->device_mode == WLAN_HDD_INFRA_STATION ||
16727 adapter->device_mode == WLAN_HDD_P2P_CLIENT) {
16728 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
16729 if (hdd_sta_ctx->conn_info.connState !=
16730 eConnectionState_Associated) {
16731
16732 hddLog(VOS_TRACE_LEVEL_INFO,
16733 FL("failed to cap tsf, not connect with ap"));
16734 buf[0] = TSF_STA_NOT_CONNECTED_NO_TSF;
16735 return ret;
16736 }
16737 }
16738 if ((adapter->device_mode == WLAN_HDD_SOFTAP ||
16739 adapter->device_mode == WLAN_HDD_P2P_GO) &&
16740 !(test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags))) {
16741 hddLog(VOS_TRACE_LEVEL_INFO,
16742 FL("Soft AP / P2p GO not beaconing"));
16743 buf[0] = TSF_SAP_NOT_STARTED_NO_TSF;
16744 return ret;
16745 }
16746
16747 if (adapter->tsf_cap_ctx.tsf_capture_state != TSF_CAP_STATE ||
16748 adapter->tsf_cap_ctx.tsf_get_state != TSF_CURRENT_IN_CAP_STATE ) {
16749 hddLog(VOS_TRACE_LEVEL_INFO,
16750 FL("Not in capture state,Enter capture state first"));
16751 buf[0] = TSF_GET_FAIL;
16752 } else {
16753 hddLog(VOS_TRACE_LEVEL_INFO, FL("ioctl issue cap tsf cmd"));
16754 cap_tsf_params.session_id = adapter->sessionId;
16755 cap_tsf_params.tsf_rsp_cb_func = hdd_tsf_cb;
16756 cap_tsf_params.tsf_rsp_cb_ctx = adapter;
16757
16758 ret = sme_get_tsf_req(hdd_ctx->hHal, cap_tsf_params);
16759
16760 if (ret != VOS_STATUS_SUCCESS) {
16761 hddLog(VOS_TRACE_LEVEL_ERROR, FL("capture fail"));
16762 buf[0] = TSF_CAPTURE_FAIL;
16763 vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
16764 adapter->tsf_cap_ctx.tsf_capture_state = TSF_IDLE;
16765 vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
16766 return -EINVAL;
16767 }
16768 /* wait till we get a response from fw */
16769 status = vos_wait_single_event(&adapter->tsf_cap_ctx.
16770 tsf_capture_done_event,
16771 HDD_TSF_GET_REQ_TIMEOUT);
16772
16773 if (!VOS_IS_STATUS_SUCCESS(status)) {
16774 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
16775 ("capture tsf vos wait for single_event failed!! %d"),
16776 status);
16777
16778 vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
16779 adapter->tsf_cap_ctx.tsf_capture_state = TSF_IDLE;
16780 vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
16781 return status;
16782 }
16783 buf[1] = adapter->tsf_cap_ctx.tsf_low;
16784 buf[2] = adapter->tsf_cap_ctx.tsf_high;
16785
16786 hddLog(VOS_TRACE_LEVEL_INFO,
16787 FL("get tsf cmd,status=%u, tsf_low=%u, tsf_high=%u"),
16788 buf[0], buf[1], buf[2]);
16789 }
16790 hddLog(VOS_TRACE_LEVEL_INFO,
16791 FL("ioctl return cap tsf cmd, ret = %d"), ret);
16792 return ret;
16793}
16794
16795void wlan_hdd_tsf_init(hdd_adapter_t *adapter)
16796{
16797
16798 if (adapter == NULL) {
16799 hddLog(VOS_TRACE_LEVEL_ERROR,
16800 FL("TSF init on a null adapter!"));
16801 return;
16802 }
16803
16804 adapter->tsf_cap_ctx.tsf_get_state = TSF_RETURN;
16805 adapter->tsf_cap_ctx.tsf_capture_state = TSF_IDLE;
16806 vos_event_init(&adapter->tsf_cap_ctx.tsf_capture_done_event);
16807 vos_spin_lock_init(&adapter->tsf_cap_ctx.tsf_lock);
16808 adapter->tsf_cap_ctx.tsf_high = 0;
16809 adapter->tsf_cap_ctx.tsf_low = 0;
16810}
16811
16812#endif
16813
Jeff Johnson295189b2012-06-20 16:38:30 -070016814//Register the module init/exit functions
16815module_init(hdd_module_init);
16816module_exit(hdd_module_exit);
16817
16818MODULE_LICENSE("Dual BSD/GPL");
16819MODULE_AUTHOR("Qualcomm Atheros, Inc.");
16820MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
16821
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070016822module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
16823 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -070016824
Jeff Johnson76052702013-04-16 13:55:05 -070016825module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -070016826 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Arif Hussain66559122013-11-21 10:11:40 -080016827
16828module_param(enable_dfs_chan_scan, int,
16829 S_IRUSR | S_IRGRP | S_IROTH);
16830
16831module_param(enable_11d, int,
16832 S_IRUSR | S_IRGRP | S_IROTH);
16833
16834module_param(country_code, charp,
16835 S_IRUSR | S_IRGRP | S_IROTH);