blob: cf9cf6a54d2aed38d5518207b9959ce92fd01896 [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 }
761 else
762 {
763 /*New country Supports DFS as well resetting value back from .ini*/
764 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), cfg_param->enableDFSChnlScan);
765 }
766
767}
768
Abhishek Singh00b71972016-01-07 10:51:04 +0530769#ifdef WLAN_FEATURE_RMC
770static int hdd_parse_setrmcenable_command(tANI_U8 *pValue, tANI_U8 *pRmcEnable)
771{
772 tANI_U8 *inPtr = pValue;
773 int tempInt;
774 int v = 0;
775 char buf[32];
776 *pRmcEnable = 0;
777
778 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
779 /*no argument after the command*/
780 if (NULL == inPtr)
781 {
782 return 0;
783 }
784
785 /*no space after the command*/
786 else if (SPACE_ASCII_VALUE != *inPtr)
787 {
788 return 0;
789 }
790
791 /*removing empty spaces*/
792 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
793
794 /*no argument followed by spaces*/
795 if ('\0' == *inPtr)
796 {
797 return 0;
798 }
799
800 /* getting the first argument which enables or disables RMC
801 * for input IP v4 address*/
802 sscanf(inPtr, "%32s ", buf);
803 v = kstrtos32(buf, 10, &tempInt);
804 if ( v < 0)
805 {
806 return -EINVAL;
807 }
808
809 *pRmcEnable = tempInt;
810
811 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
812 "ucRmcEnable: %d", *pRmcEnable);
813
814 return 0;
815}
816
817/* Function header left blank Intentionally */
818static int hdd_parse_setrmcactionperiod_command(tANI_U8 *pValue,
819 tANI_U32 *pActionPeriod)
820{
821 tANI_U8 *inPtr = pValue;
822 int tempInt;
823 int v = 0;
824 char buf[32];
825 *pActionPeriod = 0;
826
827 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
828 /*no argument after the command*/
829 if (NULL == inPtr)
830 {
831 return -EINVAL;
832 }
833
834 /*no space after the command*/
835 else if (SPACE_ASCII_VALUE != *inPtr)
836 {
837 return -EINVAL;
838 }
839
840 /*removing empty spaces*/
841 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
842
843 /*no argument followed by spaces*/
844 if ('\0' == *inPtr)
845 {
846 return 0;
847 }
848
849 /* getting the first argument which enables or disables RMC
850 * for input IP v4 address*/
851 sscanf(inPtr, "%32s ", buf);
852 v = kstrtos32(buf, 10, &tempInt);
853 if ( v < 0)
854 {
855 return -EINVAL;
856 }
857
858 /* Range checking for passed paramter */
859 if (tempInt < WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY_STAMIN ||
860 tempInt > WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY_STAMAX)
861 {
862 return -EINVAL;
863 }
864
865 *pActionPeriod = tempInt;
866
867 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
868 "uActionPeriod: %d", *pActionPeriod);
869
870 return 0;
871}
872
873/* Function header left blank Intentionally */
874static int hdd_parse_setrmcrate_command(tANI_U8 *pValue,
875 tANI_U32 *pRate, tTxrateinfoflags *pTxFlags)
876{
877 tANI_U8 *inPtr = pValue;
878 int tempInt;
879 int v = 0;
880 char buf[32];
881 *pRate = 0;
882 *pTxFlags = 0;
883
884 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
885 /*no argument after the command*/
886 if (NULL == inPtr)
887 {
888 return -EINVAL;
889 }
890
891 /*no space after the command*/
892 else if (SPACE_ASCII_VALUE != *inPtr)
893 {
894 return -EINVAL;
895 }
896
897 /*removing empty spaces*/
898 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
899
900 /*no argument followed by spaces*/
901 if ('\0' == *inPtr)
902 {
903 return 0;
904 }
905
906 /*
907 * getting the first argument which sets multicast rate.
908 */
909 sscanf(inPtr, "%32s ", buf);
910 v = kstrtos32(buf, 10, &tempInt);
911 if ( v < 0)
912 {
913 return -EINVAL;
914 }
915
916 /*
917 * Validate the multicast rate.
918 */
919 switch (tempInt)
920 {
921 default:
922 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
923 "Unsupported rate: %d", tempInt);
924 return -EINVAL;
925 case 0:
926 case 6:
927 case 9:
928 case 12:
929 case 18:
930 case 24:
931 case 36:
932 case 48:
933 case 54:
934 *pTxFlags = eHAL_TX_RATE_LEGACY;
935 *pRate = tempInt * 10;
936 break;
937 case 65:
938 *pTxFlags = eHAL_TX_RATE_HT20;
939 *pRate = tempInt * 10;
940 break;
941 case 72:
942 *pTxFlags = eHAL_TX_RATE_HT20 | eHAL_TX_RATE_SGI;
943 *pRate = 722; /* fractional rate 72.2 Mbps */
944 break;
945 }
946
947 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
948 "Rate: %d", *pRate);
949
950 return 0;
951}
952
953/**---------------------------------------------------------------------------
954
955 \brief hdd_cfg80211_get_ibss_peer_info_cb() - Callback function for IBSS
956 Peer Info request
957
958 This is an asynchronous callback function from SME when the peer info
959 is received
960
961 \pUserData -> Adapter private data
962 \pPeerInfoRsp -> Peer info response
963
964 \return - 0 for success non-zero for failure
965 --------------------------------------------------------------------------*/
966static void
967hdd_cfg80211_get_ibss_peer_info_cb(v_VOID_t *pUserData, v_VOID_t *pPeerInfoRsp)
968{
969 hdd_adapter_t *pAdapter = (hdd_adapter_t *)pUserData;
970 tSirPeerInfoRspParams *pPeerInfo = (tSirPeerInfoRspParams *)pPeerInfoRsp;
971 hdd_station_ctx_t *pStaCtx;
972 v_U8_t i;
973
974 /*Sanity check*/
975 if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
976 {
977 hddLog(LOGE,
978 FL("invalid adapter or adapter has invalid magic"));
979 return;
980 }
981
982 pStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
983 if (NULL != pStaCtx && NULL != pPeerInfo &&
984 eHAL_STATUS_SUCCESS == pPeerInfo->status)
985 {
986 pStaCtx->ibss_peer_info.status = pPeerInfo->status;
987 pStaCtx->ibss_peer_info.numIBSSPeers = pPeerInfo->numPeers;
988
989 /* Paranoia check */
990 if (pPeerInfo->numPeers < HDD_MAX_NUM_IBSS_STA)
991 {
992 for (i = 0; i < pPeerInfo->numPeers; i++)
993 {
994 memcpy(&pStaCtx->ibss_peer_info.ibssPeerList[i],
995 &pPeerInfo->peerInfoParams[i],
996 sizeof(hdd_ibss_peer_info_params_t));
997 }
998 hddLog(LOG1,
999 FL("Peer Info copied in HDD"));
1000 }
1001 else
1002 {
1003 hddLog(LOGE,
1004 FL(" Number of peers %d returned is more than limit %d"),
1005 pPeerInfo->numPeers, HDD_MAX_NUM_IBSS_STA);
1006 }
1007 }
1008 else
1009 {
1010 hddLog(LOG1,
1011 FL("peerInfo returned is NULL"));
1012 }
1013
1014 complete(&pAdapter->ibss_peer_info_comp);
1015}
1016
1017/**---------------------------------------------------------------------------
1018
1019 \brief hdd_cfg80211_get_ibss_peer_info_all() -
1020
1021 Request function to get IBSS peer info from lower layers
1022
1023 \pAdapter -> Adapter context
1024
1025 \return - 0 for success non-zero for failure
1026 --------------------------------------------------------------------------*/
1027static
1028VOS_STATUS hdd_cfg80211_get_ibss_peer_info_all(hdd_adapter_t *pAdapter)
1029{
1030 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1031 long status;
1032 VOS_STATUS retStatus = VOS_STATUS_E_FAILURE;
1033
1034 INIT_COMPLETION(pAdapter->ibss_peer_info_comp);
1035
1036 retStatus = sme_RequestIBSSPeerInfo(hHal, pAdapter,
1037 hdd_cfg80211_get_ibss_peer_info_cb,
1038 VOS_TRUE, 0xFF);
1039
1040 if (VOS_STATUS_SUCCESS == retStatus)
1041 {
1042 status = wait_for_completion_interruptible_timeout
1043 (&pAdapter->ibss_peer_info_comp,
1044 msecs_to_jiffies(IBSS_PEER_INFO_REQ_TIMOEUT));
1045
1046 /* status will be 0 if timed out */
1047 if (status <= 0)
1048 {
1049 hddLog(VOS_TRACE_LEVEL_WARN, "%s: Warning: IBSS_PEER_INFO_TIMEOUT %ld",
1050 __func__, status);
1051 retStatus = VOS_STATUS_E_FAILURE;
1052 return retStatus;
1053 }
1054 }
1055 else
1056 {
1057 hddLog(VOS_TRACE_LEVEL_WARN,
1058 "%s: Warning: sme_RequestIBSSPeerInfo Request failed", __func__);
1059 }
1060
1061 return retStatus;
1062}
1063
1064/**---------------------------------------------------------------------------
1065
1066 \brief hdd_cfg80211_get_ibss_peer_info() -
1067
1068 Request function to get IBSS peer info from lower layers
1069
1070 \pAdapter -> Adapter context
1071 \staIdx -> Sta index for which the peer info is requested
1072
1073 \return - 0 for success non-zero for failure
1074 --------------------------------------------------------------------------*/
1075static VOS_STATUS
1076hdd_cfg80211_get_ibss_peer_info(hdd_adapter_t *pAdapter, v_U8_t staIdx)
1077{
1078 long status;
1079 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1080 VOS_STATUS retStatus = VOS_STATUS_E_FAILURE;
1081
1082 INIT_COMPLETION(pAdapter->ibss_peer_info_comp);
1083
1084 retStatus = sme_RequestIBSSPeerInfo(hHal, pAdapter,
1085 hdd_cfg80211_get_ibss_peer_info_cb,
1086 VOS_FALSE, staIdx);
1087
1088 if (VOS_STATUS_SUCCESS == retStatus)
1089 {
1090 status = wait_for_completion_interruptible_timeout
1091 (&pAdapter->ibss_peer_info_comp,
1092 msecs_to_jiffies(IBSS_PEER_INFO_REQ_TIMOEUT));
1093
1094 /* status = 0 on timeout */
1095 if (status <= 0)
1096 {
1097 hddLog(VOS_TRACE_LEVEL_WARN, "%s: Warning: IBSS_PEER_INFO_TIMEOUT %ld",
1098 __func__, status);
1099 retStatus = VOS_STATUS_E_FAILURE;
1100 return retStatus;
1101 }
1102 }
1103 else
1104 {
1105 hddLog(VOS_TRACE_LEVEL_WARN,
1106 "%s: Warning: sme_RequestIBSSPeerInfo Request failed", __func__);
1107 }
1108
1109 return retStatus;
1110}
1111
1112/* Function header left blank Intentionally */
1113VOS_STATUS
1114hdd_parse_get_ibss_peer_info(tANI_U8 *pValue, v_MACADDR_t *pPeerMacAddr)
1115{
1116 tANI_U8 *inPtr = pValue;
1117 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
1118
1119 /*no argument after the command*/
1120 if (NULL == inPtr)
1121 {
1122 return VOS_STATUS_E_FAILURE;;
1123 }
1124
1125 /*no space after the command*/
1126 else if (SPACE_ASCII_VALUE != *inPtr)
1127 {
1128 return VOS_STATUS_E_FAILURE;;
1129 }
1130
1131 /*removing empty spaces*/
1132 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
1133
1134 /*no argument followed by spaces*/
1135 if ('\0' == *inPtr)
1136 {
1137 return VOS_STATUS_E_FAILURE;;
1138 }
1139
1140 /*getting the first argument ie the peer mac address */
1141 if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' ||
1142 inPtr[11] != ':' || inPtr[14] != ':')
1143 {
1144 return VOS_STATUS_E_FAILURE;;
1145 }
1146 sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x",
1147 (unsigned int *)&pPeerMacAddr->bytes[0],
1148 (unsigned int *)&pPeerMacAddr->bytes[1],
1149 (unsigned int *)&pPeerMacAddr->bytes[2],
1150 (unsigned int *)&pPeerMacAddr->bytes[3],
1151 (unsigned int *)&pPeerMacAddr->bytes[4],
1152 (unsigned int *)&pPeerMacAddr->bytes[5]);
1153
1154 /* The command buffer seems to be fine */
1155 return VOS_STATUS_SUCCESS;
1156}
1157
1158/* Function header left blank Intentionally */
1159static int hdd_parse_set_ibss_oui_data_command(tANI_U8 *command, tANI_U8 *ie,
1160 tANI_U32 limit)
1161{
1162 tANI_U8 len;
1163 tANI_U8 data;
1164
1165 /* skip white space */
1166 while ((SPACE_ASCII_VALUE == *command) && ('\0' != *command))
1167 {
1168 command++;
1169 limit--;
1170 }
1171
1172 /* skip element id and element length */
1173 len = 2;
1174
1175 /* extract oui */
1176 while ((SPACE_ASCII_VALUE != *command) && ('\0' != *command) &&
1177 (limit > 1))
1178 {
1179 /* Convert ASCII to decimal */
1180 data = ((*command -'0') << 4) | (*(command + 1) - '0');
1181 ie[len++] = data;
1182 command += 2;
1183 limit -= 2;
1184 }
1185
1186 /* skip white space */
1187 while ((SPACE_ASCII_VALUE == *command) && ('\0' != *command))
1188 {
1189 command++;
1190 limit--;
1191 }
1192
1193 /* extract data */
1194 while ((SPACE_ASCII_VALUE != *command) && ('\0' != *command) &&
1195 (limit > 1))
1196 {
1197 /* Convert ASCII to decimal */
1198 data = ((*command -'0') << 4) | (*(command + 1) - '0');
1199 ie[len++] = data;
1200 command += 2;
1201 limit -= 2;
1202 }
1203
1204 /* fill element id and element length */
1205 ie[0] = IE_EID_VENDOR;
1206 ie[1] = len - 2;
1207
1208 return len;
1209}
1210
1211static tANI_U32 hdd_find_ibss_wpa_ie_pos(tANI_U8 *addIePtr, tANI_U32 addIeLen)
1212{
1213 tANI_U32 ieLenPresent = 0;
1214 int left = addIeLen;
1215 v_U8_t *ptr = addIePtr;
1216 v_U8_t elem_id,elem_len;
1217
1218 while(left >= 2)
1219 {
1220 elem_id = ptr[0];
1221 elem_len = ptr[1];
1222 left -= 2;
1223 if(elem_len > left)
1224 {
1225 hddLog(LOGE,
1226 FL("****Invalid elem_len=%d left=%d*****"),
1227 elem_len,left);
1228 return 0;
1229 }
1230 if ((elem_id == IE_EID_VENDOR) &&
1231 (left >= WPA_OUI_TYPE_SIZE))
1232 {
1233 if (!memcmp(&ptr[2], WPA_OUI_TYPE,
1234 WPA_OUI_TYPE_SIZE))
1235 {
1236 ieLenPresent += elem_len + 2;
1237 return ieLenPresent;
1238 }
1239 }
1240 ieLenPresent += (elem_len + 2);
1241 left -= elem_len;
1242 ptr += (elem_len + 2);
1243 }
1244 return 0;
1245}
1246
1247#endif /* WLAN_FEATURE_RMC */
1248
Rajeev79dbe4c2013-10-05 11:03:42 +05301249#ifdef FEATURE_WLAN_BATCH_SCAN
1250
1251/**---------------------------------------------------------------------------
1252
1253 \brief hdd_extract_assigned_int_from_str() - Extracts assigned integer from
1254 input string
1255
1256 This function extracts assigned integer from string in below format:
1257 "STRING=10" : extracts integer 10 from this string
1258
1259 \param - pInPtr Pointer to input string
1260 \param - base Base for string to int conversion(10 for decimal 16 for hex)
1261 \param - pOutPtr Pointer to variable in which extracted integer needs to be
1262 assigned
1263 \param - pLastArg to tell whether it is last arguement in input string or
1264 not
1265
1266 \return - NULL for failure cases
1267 pointer to next arguement in input string for success cases
1268 --------------------------------------------------------------------------*/
1269static tANI_U8 *
1270hdd_extract_assigned_int_from_str
1271(
1272 tANI_U8 *pInPtr,
1273 tANI_U8 base,
1274 tANI_U32 *pOutPtr,
1275 tANI_U8 *pLastArg
1276)
1277{
1278 int tempInt;
1279 int v = 0;
1280 char buf[32];
1281 int val = 0;
1282 *pLastArg = FALSE;
1283
1284 pInPtr = strnchr(pInPtr, strlen(pInPtr), EQUALS_TO_ASCII_VALUE);
1285 if (NULL == pInPtr)
1286 {
1287 return NULL;
1288 }
1289
1290 pInPtr++;
1291
1292 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
1293
1294 val = sscanf(pInPtr, "%32s ", buf);
1295 if (val < 0 && val > strlen(pInPtr))
1296 {
1297 return NULL;
1298 }
1299 pInPtr += val;
1300 v = kstrtos32(buf, base, &tempInt);
1301 if (v < 0)
1302 {
1303 return NULL;
1304 }
Rajeev Kumar4d93d842014-01-02 18:31:21 -08001305 if (tempInt < 0)
1306 {
1307 tempInt = 0;
1308 }
Rajeev79dbe4c2013-10-05 11:03:42 +05301309 *pOutPtr = tempInt;
1310
1311 pInPtr = strnchr(pInPtr, strlen(pInPtr), SPACE_ASCII_VALUE);
1312 if (NULL == pInPtr)
1313 {
1314 *pLastArg = TRUE;
1315 return NULL;
1316 }
1317 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
1318
1319 return pInPtr;
1320}
1321
1322/**---------------------------------------------------------------------------
1323
1324 \brief hdd_extract_assigned_char_from_str() - Extracts assigned char from
1325 input string
1326
1327 This function extracts assigned character from string in below format:
1328 "STRING=A" : extracts char 'A' from this string
1329
1330 \param - pInPtr Pointer to input string
1331 \param - pOutPtr Pointer to variable in which extracted char needs to be
1332 assigned
1333 \param - pLastArg to tell whether it is last arguement in input string or
1334 not
1335
1336 \return - NULL for failure cases
1337 pointer to next arguement in input string for success cases
1338 --------------------------------------------------------------------------*/
1339static tANI_U8 *
1340hdd_extract_assigned_char_from_str
1341(
1342 tANI_U8 *pInPtr,
1343 tANI_U8 *pOutPtr,
1344 tANI_U8 *pLastArg
1345)
1346{
1347 *pLastArg = FALSE;
1348
1349 pInPtr = strnchr(pInPtr, strlen(pInPtr), EQUALS_TO_ASCII_VALUE);
1350 if (NULL == pInPtr)
1351 {
1352 return NULL;
1353 }
1354
1355 pInPtr++;
1356
1357 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
1358
1359 *pOutPtr = *pInPtr;
1360
1361 pInPtr = strnchr(pInPtr, strlen(pInPtr), SPACE_ASCII_VALUE);
1362 if (NULL == pInPtr)
1363 {
1364 *pLastArg = TRUE;
1365 return NULL;
1366 }
1367 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
1368
1369 return pInPtr;
1370}
1371
1372
1373/**---------------------------------------------------------------------------
1374
1375 \brief hdd_parse_set_batchscan_command () - HDD parse set batch scan command
1376
1377 This function parses set batch scan command in below format:
1378 WLS_BATCHING_SET <space> followed by below arguements
1379 "SCANFREQ=XX" : Optional defaults to 30 sec
1380 "MSCAN=XX" : Required number of scans to attempt to batch
1381 "BESTN=XX" : Best Network (RSSI) defaults to 16
1382 "CHANNEL=<X,Y>" : optional defaults to all channels, can list 'A'or` B.
1383 A. implies only 5 GHz , B. implies only 2.4GHz
1384 "RTT=X" : optional defaults to 0
1385 returns the MIN of MSCAN or the max # of scans firmware can cache or -1 on
1386 error
1387
1388 For example input commands:
1389 1) WLS_BATCHING_SET SCANFREQ=60 MSCAN=10 BESTN=20 CHANNEL=A RTT=0 -> This is
1390 translated into set batch scan with following parameters:
1391 a) Frequence 60 seconds
1392 b) Batch 10 scans together
1393 c) Best RSSI to be 20
1394 d) 5GHz band only
1395 e) RTT is equal to 0
1396
1397 \param - pValue Pointer to input channel list
1398 \param - pHddSetBatchScanReq Pointer to HDD batch scan request structure
1399
1400 \return - 0 for success non-zero for failure
1401
1402 --------------------------------------------------------------------------*/
1403static int
1404hdd_parse_set_batchscan_command
1405(
1406 tANI_U8 *pValue,
1407 tSirSetBatchScanReq *pHddSetBatchScanReq
1408)
1409{
1410 tANI_U8 *inPtr = pValue;
1411 tANI_U8 val = 0;
1412 tANI_U8 lastArg = 0;
Abhishek Singh00b71972016-01-07 10:51:04 +05301413 tANI_U32 nScanFreq = HDD_SET_BATCH_SCAN_DEFAULT_FREQ;
Rajeev Kumar45e64a72013-11-18 19:48:15 -08001414 tANI_U32 nMscan;
Abhishek Singh00b71972016-01-07 10:51:04 +05301415 tANI_U32 nBestN = HDD_SET_BATCH_SCAN_BEST_NETWORK;
1416 tANI_U8 ucRfBand = HDD_SET_BATCH_SCAN_DEFAULT_BAND;
1417 tANI_U32 nRtt = 0;
Rajeev Kumarc933d982013-11-18 20:04:20 -08001418 tANI_U32 temp;
Rajeev79dbe4c2013-10-05 11:03:42 +05301419
Rajeev79dbe4c2013-10-05 11:03:42 +05301420 /*go to space after WLS_BATCHING_SET command*/
1421 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
1422 /*no argument after the command*/
1423 if (NULL == inPtr)
1424 {
1425 return -EINVAL;
1426 }
1427
1428 /*no space after the command*/
1429 else if (SPACE_ASCII_VALUE != *inPtr)
1430 {
1431 return -EINVAL;
1432 }
1433
1434 /*removing empty spaces*/
1435 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
1436
1437 /*no argument followed by spaces*/
1438 if ('\0' == *inPtr)
1439 {
1440 return -EINVAL;
1441 }
1442
1443 /*check and parse SCANFREQ*/
1444 if ((strncmp(inPtr, "SCANFREQ", 8) == 0))
1445 {
1446 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumarc933d982013-11-18 20:04:20 -08001447 &temp, &lastArg);
Rajeev Kumar45e64a72013-11-18 19:48:15 -08001448
Rajeev Kumarc933d982013-11-18 20:04:20 -08001449 if (0 != temp)
Rajeev Kumar45e64a72013-11-18 19:48:15 -08001450 {
Rajeev Kumarc933d982013-11-18 20:04:20 -08001451 nScanFreq = temp;
Rajeev Kumar45e64a72013-11-18 19:48:15 -08001452 }
1453
Rajeev79dbe4c2013-10-05 11:03:42 +05301454 if ( (NULL == inPtr) || (TRUE == lastArg))
1455 {
1456 return -EINVAL;
1457 }
1458 }
1459
1460 /*check and parse MSCAN*/
1461 if ((strncmp(inPtr, "MSCAN", 5) == 0))
1462 {
1463 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumar45e64a72013-11-18 19:48:15 -08001464 &nMscan, &lastArg);
1465
1466 if (0 == nMscan)
1467 {
1468 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1469 "invalid MSCAN=%d", nMscan);
1470 return -EINVAL;
1471 }
1472
Rajeev79dbe4c2013-10-05 11:03:42 +05301473 if (TRUE == lastArg)
1474 {
1475 goto done;
1476 }
1477 else if (NULL == inPtr)
1478 {
1479 return -EINVAL;
1480 }
1481 }
1482 else
1483 {
1484 return -EINVAL;
1485 }
1486
1487 /*check and parse BESTN*/
1488 if ((strncmp(inPtr, "BESTN", 5) == 0))
1489 {
1490 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumarc933d982013-11-18 20:04:20 -08001491 &temp, &lastArg);
Rajeev Kumar45e64a72013-11-18 19:48:15 -08001492
Rajeev Kumarc933d982013-11-18 20:04:20 -08001493 if (0 != temp)
Rajeev Kumar45e64a72013-11-18 19:48:15 -08001494 {
Rajeev Kumarc933d982013-11-18 20:04:20 -08001495 nBestN = temp;
Rajeev Kumar45e64a72013-11-18 19:48:15 -08001496 }
1497
Rajeev79dbe4c2013-10-05 11:03:42 +05301498 if (TRUE == lastArg)
1499 {
1500 goto done;
1501 }
1502 else if (NULL == inPtr)
1503 {
1504 return -EINVAL;
1505 }
1506 }
1507
1508 /*check and parse CHANNEL*/
1509 if ((strncmp(inPtr, "CHANNEL", 7) == 0))
1510 {
1511 inPtr = hdd_extract_assigned_char_from_str(inPtr, &val, &lastArg);
Rajeev Kumarc933d982013-11-18 20:04:20 -08001512
Rajeev79dbe4c2013-10-05 11:03:42 +05301513 if (('A' == val) || ('a' == val))
1514 {
c_hpothuebf89732014-02-25 13:00:24 +05301515 ucRfBand = HDD_SET_BATCH_SCAN_5GHz_BAND_ONLY;
Rajeev79dbe4c2013-10-05 11:03:42 +05301516 }
1517 else if (('B' == val) || ('b' == val))
1518 {
c_hpothuebf89732014-02-25 13:00:24 +05301519 ucRfBand = HDD_SET_BATCH_SCAN_24GHz_BAND_ONLY;
Rajeev79dbe4c2013-10-05 11:03:42 +05301520 }
1521 else
1522 {
Rajeev Kumarc933d982013-11-18 20:04:20 -08001523 ucRfBand = HDD_SET_BATCH_SCAN_DEFAULT_BAND;
1524 }
1525
1526 if (TRUE == lastArg)
1527 {
1528 goto done;
1529 }
1530 else if (NULL == inPtr)
1531 {
Rajeev79dbe4c2013-10-05 11:03:42 +05301532 return -EINVAL;
1533 }
1534 }
1535
1536 /*check and parse RTT*/
1537 if ((strncmp(inPtr, "RTT", 3) == 0))
1538 {
1539 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumar45e64a72013-11-18 19:48:15 -08001540 &nRtt, &lastArg);
Rajeev79dbe4c2013-10-05 11:03:42 +05301541 if (TRUE == lastArg)
1542 {
1543 goto done;
1544 }
1545 if (NULL == inPtr)
1546 {
1547 return -EINVAL;
1548 }
1549 }
1550
1551
1552done:
1553
Rajeev Kumar45e64a72013-11-18 19:48:15 -08001554 pHddSetBatchScanReq->scanFrequency = nScanFreq;
1555 pHddSetBatchScanReq->numberOfScansToBatch = nMscan;
1556 pHddSetBatchScanReq->bestNetwork = nBestN;
1557 pHddSetBatchScanReq->rfBand = ucRfBand;
1558 pHddSetBatchScanReq->rtt = nRtt;
1559
Rajeev79dbe4c2013-10-05 11:03:42 +05301560 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1561 "Received WLS_BATCHING_SET with SCANFREQ=%d "
1562 "MSCAN=%d BESTN=%d CHANNEL=%d RTT=%d",
1563 pHddSetBatchScanReq->scanFrequency,
1564 pHddSetBatchScanReq->numberOfScansToBatch,
1565 pHddSetBatchScanReq->bestNetwork,
1566 pHddSetBatchScanReq->rfBand,
1567 pHddSetBatchScanReq->rtt);
1568
1569 return 0;
1570}/*End of hdd_parse_set_batchscan_command*/
1571
1572/**---------------------------------------------------------------------------
1573
1574 \brief hdd_set_batch_scan_req_callback () - This function is called after
1575 receiving set batch scan response from FW and it saves set batch scan
1576 response data FW to HDD context and sets the completion event on
1577 which hdd_ioctl is waiting
1578
1579 \param - callbackContext Pointer to HDD adapter
1580 \param - pRsp Pointer to set batch scan response data received from FW
1581
1582 \return - nothing
1583
1584 --------------------------------------------------------------------------*/
1585static void hdd_set_batch_scan_req_callback
1586(
1587 void *callbackContext,
1588 tSirSetBatchScanRsp *pRsp
1589)
1590{
1591 hdd_adapter_t* pAdapter = (hdd_adapter_t*)callbackContext;
1592 tSirSetBatchScanRsp *pHddSetBatchScanRsp;
1593
1594 /*sanity check*/
1595 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
1596 {
1597 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1598 "%s: Invalid pAdapter magic", __func__);
1599 VOS_ASSERT(0);
1600 return;
1601 }
1602 pHddSetBatchScanRsp = &pAdapter->hddSetBatchScanRsp;
1603
1604 /*save set batch scan response*/
1605 pHddSetBatchScanRsp->nScansToBatch = pRsp->nScansToBatch;
1606
1607 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1608 "Received set batch scan rsp from FW with nScansToBatch=%d",
1609 pHddSetBatchScanRsp->nScansToBatch);
1610
1611 pAdapter->hdd_wait_for_set_batch_scan_rsp = FALSE;
1612 complete(&pAdapter->hdd_set_batch_scan_req_var);
1613
1614 return;
1615}/*End of hdd_set_batch_scan_req_callback*/
1616
1617
1618/**---------------------------------------------------------------------------
1619
1620 \brief hdd_populate_batch_scan_rsp_queue () - This function stores AP meta
1621 info in hdd batch scan response queue
1622
1623 \param - pAdapter Pointer to hdd adapter
1624 \param - pAPMetaInfo Pointer to access point meta info
1625 \param - scanId scan ID of batch scan response
1626 \param - isLastAp tells whether AP is last AP in batch scan response or not
1627
1628 \return - nothing
1629
1630 --------------------------------------------------------------------------*/
1631static void hdd_populate_batch_scan_rsp_queue( hdd_adapter_t* pAdapter,
1632 tpSirBatchScanNetworkInfo pApMetaInfo, tANI_U32 scanId, v_BOOL_t isLastAp)
1633{
1634 tHddBatchScanRsp *pHead;
1635 tHddBatchScanRsp *pNode;
1636 tHddBatchScanRsp *pPrev;
1637 tHddBatchScanRsp *pTemp;
1638 tANI_U8 ssidLen;
1639
1640 /*head of hdd batch scan response queue*/
1641 pHead = pAdapter->pBatchScanRsp;
1642
1643 pNode = (tHddBatchScanRsp *)vos_mem_malloc(sizeof(tHddBatchScanRsp));
1644 if (NULL == pNode)
1645 {
1646 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1647 "%s: Could not allocate memory", __func__);
1648 VOS_ASSERT(0);
1649 return;
1650 }
1651
1652 vos_mem_copy(pNode->ApInfo.bssid, pApMetaInfo->bssid,
1653 sizeof(pNode->ApInfo.bssid));
1654 ssidLen = strlen(pApMetaInfo->ssid);
1655 if (SIR_MAX_SSID_SIZE < ssidLen)
1656 {
1657 /*invalid scan result*/
1658 vos_mem_free(pNode);
1659 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1660 "%s: Invalid AP meta info ssidlen %d", __func__, ssidLen);
1661 return;
1662 }
1663 vos_mem_copy(pNode->ApInfo.ssid, pApMetaInfo->ssid, ssidLen);
1664 /*null terminate ssid*/
1665 pNode->ApInfo.ssid[ssidLen] = '\0';
1666 pNode->ApInfo.ch = pApMetaInfo->ch;
1667 pNode->ApInfo.rssi = pApMetaInfo->rssi;
1668 pNode->ApInfo.age = pApMetaInfo->timestamp;
1669 pNode->ApInfo.batchId = scanId;
1670 pNode->ApInfo.isLastAp = isLastAp;
1671
1672 pNode->pNext = NULL;
1673 if (NULL == pHead)
1674 {
1675 pAdapter->pBatchScanRsp = pNode;
1676 }
1677 else
1678 {
1679 pTemp = pHead;
1680 while (NULL != pTemp)
1681 {
1682 pPrev = pTemp;
1683 pTemp = pTemp->pNext;
1684 }
1685 pPrev->pNext = pNode;
1686 }
1687
1688 return;
1689}/*End of hdd_populate_batch_scan_rsp_queue*/
1690
1691/**---------------------------------------------------------------------------
1692
1693 \brief hdd_batch_scan_result_ind_callback () - This function is called after
1694 receiving batch scan response indication from FW. It saves get batch scan
1695 response data in HDD batch scan response queue. This callback sets the
1696 completion event on which hdd_ioctl is waiting only after getting complete
1697 batch scan response data from FW
1698
1699 \param - callbackContext Pointer to HDD adapter
1700 \param - pRsp Pointer to get batch scan response data received from FW
1701
1702 \return - nothing
1703
1704 --------------------------------------------------------------------------*/
1705static void hdd_batch_scan_result_ind_callback
1706(
1707 void *callbackContext,
1708 void *pRsp
1709)
1710{
1711 v_BOOL_t isLastAp;
1712 tANI_U32 numApMetaInfo;
Rajeev Kumarce651e42013-10-21 18:57:15 -07001713 tANI_U32 numNetworkInScanList;
Rajeev79dbe4c2013-10-05 11:03:42 +05301714 tANI_U32 numberScanList;
1715 tANI_U32 nextScanListOffset;
1716 tANI_U32 nextApMetaInfoOffset;
1717 hdd_adapter_t* pAdapter;
1718 tpSirBatchScanList pScanList;
1719 tpSirBatchScanNetworkInfo pApMetaInfo;
1720 tpSirBatchScanResultIndParam pBatchScanRsp;/*batch scan rsp data from FW*/
1721 tSirSetBatchScanReq *pReq;
1722
1723 pAdapter = (hdd_adapter_t *)callbackContext;
1724 /*sanity check*/
Rajeev Kumar5286bb92013-12-05 11:52:10 -08001725 if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
Rajeev79dbe4c2013-10-05 11:03:42 +05301726 {
1727 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1728 "%s: Invalid pAdapter magic", __func__);
1729 VOS_ASSERT(0);
1730 return;
1731 }
1732
1733 /*initialize locals*/
1734 pReq = &pAdapter->hddSetBatchScanReq;
1735 pBatchScanRsp = (tpSirBatchScanResultIndParam)pRsp;
1736 isLastAp = FALSE;
1737 numApMetaInfo = 0;
Rajeev Kumarce651e42013-10-21 18:57:15 -07001738 numNetworkInScanList = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05301739 numberScanList = 0;
1740 nextScanListOffset = 0;
1741 nextApMetaInfoOffset = 0;
1742 pScanList = NULL;
1743 pApMetaInfo = NULL;
1744
1745 if ((NULL == pBatchScanRsp) || (NULL == pReq))
1746 {
1747 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1748 "%s: pBatchScanRsp is %p pReq %p", __func__, pBatchScanRsp, pReq);
1749 isLastAp = TRUE;
1750 goto done;
1751 }
1752
1753 pAdapter->numScanList = numberScanList = pBatchScanRsp->numScanLists;
1754 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1755 "Batch scan rsp: numberScalList %d", numberScanList);
1756
1757 if ((!numberScanList) || (numberScanList > pReq->numberOfScansToBatch))
1758 {
1759 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1760 "%s: numberScanList %d", __func__, numberScanList);
1761 isLastAp = TRUE;
1762 goto done;
1763 }
1764
1765 while (numberScanList)
1766 {
Rajeev Kumarce651e42013-10-21 18:57:15 -07001767 pScanList = (tpSirBatchScanList)((tANI_U8 *)pBatchScanRsp->scanResults +
Rajeev79dbe4c2013-10-05 11:03:42 +05301768 nextScanListOffset);
1769 if (NULL == pScanList)
1770 {
1771 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1772 "%s: pScanList is %p", __func__, pScanList);
1773 isLastAp = TRUE;
1774 goto done;
1775 }
Rajeev Kumarce651e42013-10-21 18:57:15 -07001776 numNetworkInScanList = numApMetaInfo = pScanList->numNetworksInScanList;
Rajeev79dbe4c2013-10-05 11:03:42 +05301777 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumarce651e42013-10-21 18:57:15 -07001778 "Batch scan rsp: numApMetaInfo %d scanId %d",
1779 numApMetaInfo, pScanList->scanId);
Rajeev79dbe4c2013-10-05 11:03:42 +05301780
1781 if ((!numApMetaInfo) || (numApMetaInfo > pReq->bestNetwork))
1782 {
1783 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1784 "%s: numApMetaInfo %d", __func__, numApMetaInfo);
1785 isLastAp = TRUE;
1786 goto done;
1787 }
1788
Rajeev Kumarce651e42013-10-21 18:57:15 -07001789 /*Initialize next AP meta info offset for next scan list*/
1790 nextApMetaInfoOffset = 0;
1791
Rajeev79dbe4c2013-10-05 11:03:42 +05301792 while (numApMetaInfo)
1793 {
1794 pApMetaInfo = (tpSirBatchScanNetworkInfo)(pScanList->scanList +
1795 nextApMetaInfoOffset);
1796 if (NULL == pApMetaInfo)
1797 {
1798 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1799 "%s: pApMetaInfo is %p", __func__, pApMetaInfo);
1800 isLastAp = TRUE;
1801 goto done;
1802 }
1803 /*calculate AP age*/
1804 pApMetaInfo->timestamp =
1805 pBatchScanRsp->timestamp - pApMetaInfo->timestamp;
1806
1807 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
Arif Hussaina7c8e412013-11-20 11:06:42 -08001808 "%s: bssId "MAC_ADDRESS_STR
1809 " ch %d rssi %d timestamp %d", __func__,
1810 MAC_ADDR_ARRAY(pApMetaInfo->bssid),
1811 pApMetaInfo->ch, pApMetaInfo->rssi,
1812 pApMetaInfo->timestamp);
Rajeev79dbe4c2013-10-05 11:03:42 +05301813
1814 /*mark last AP in batch scan response*/
1815 if ((TRUE == pBatchScanRsp->isLastResult) &&
1816 (1 == numberScanList) && (1 == numApMetaInfo))
1817 {
1818 isLastAp = TRUE;
1819 }
1820
1821 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1822 /*store batch scan repsonse in hdd queue*/
1823 hdd_populate_batch_scan_rsp_queue(pAdapter, pApMetaInfo,
1824 pScanList->scanId, isLastAp);
1825 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1826
1827 nextApMetaInfoOffset += sizeof(tSirBatchScanNetworkInfo);
1828 numApMetaInfo--;
1829 }
1830
Rajeev Kumarce651e42013-10-21 18:57:15 -07001831 nextScanListOffset += ((sizeof(tSirBatchScanList) - sizeof(tANI_U8))
1832 + (sizeof(tSirBatchScanNetworkInfo)
1833 * numNetworkInScanList));
Rajeev79dbe4c2013-10-05 11:03:42 +05301834 numberScanList--;
1835 }
1836
1837done:
1838
1839 /*notify hdd_ioctl only if complete batch scan rsp is received and it was
1840 requested from hdd_ioctl*/
1841 if ((TRUE == pAdapter->hdd_wait_for_get_batch_scan_rsp) &&
1842 (TRUE == isLastAp))
1843 {
1844 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
1845 complete(&pAdapter->hdd_get_batch_scan_req_var);
1846 }
1847
1848 return;
1849}/*End of hdd_batch_scan_result_ind_callback*/
1850
1851/**---------------------------------------------------------------------------
1852
1853 \brief hdd_format_batch_scan_rsp () - This function formats batch scan
1854 response as per batch scan FR request format by putting proper markers
1855
1856 \param - pDest pointer to destination buffer
1857 \param - cur_len current length
1858 \param - tot_len total remaining size which can be written to user space
1859 \param - pApMetaInfo Pointer to get batch scan response AP meta info
1860 \param - pAdapter Pointer to HDD adapter
1861
1862 \return - ret no of characters written
1863
1864 --------------------------------------------------------------------------*/
1865static tANI_U32
1866hdd_format_batch_scan_rsp
1867(
1868 tANI_U8 *pDest,
1869 tANI_U32 cur_len,
1870 tANI_U32 tot_len,
1871 tHddBatchScanRsp *pApMetaInfo,
1872 hdd_adapter_t* pAdapter
1873)
1874{
1875 tANI_U32 ret = 0;
1876 tANI_U32 rem_len = 0;
1877 tANI_U8 temp_len = 0;
1878 tANI_U8 temp_total_len = 0;
1879 tANI_U8 temp[HDD_BATCH_SCAN_AP_META_INFO_SIZE];
1880 tANI_U8 *pTemp = temp;
1881
1882 /*Batch scan reponse needs to be returned to user space in
1883 following format:
1884 "scancount=X\n" where X is the number of scans in current batch
1885 batch
1886 "trunc\n" optional present if current scan truncated
1887 "bssid=XX:XX:XX:XX:XX:XX\n"
1888 "ssid=XXXX\n"
1889 "freq=X\n" frequency in Mhz
1890 "level=XX\n"
1891 "age=X\n" ms
1892 "dist=X\n" cm (-1 if not available)
1893 "errror=X\n" (-1if not available)
1894 "====\n" (end of ap marker)
1895 "####\n" (end of scan marker)
1896 "----\n" (end of results)*/
1897 /*send scan result in above format to user space based on
1898 available length*/
1899 /*The GET response may have more data than the driver can return in its
1900 buffer. In that case the buffer should be filled to the nearest complete
1901 scan, ending with "%%%%".Subsequent callsshould return the remaining data
1902 starting with the next scan (optional .trunc\n., .apcount=X\n., etc).
1903 The final buffer should end with "----\n"*/
1904
1905 /*sanity*/
1906 if (cur_len > tot_len)
1907 {
1908 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1909 "%s: invaid cur_len %d tot_len %d", __func__, cur_len, tot_len);
1910 return 0;
1911 }
1912 else
1913 {
1914 rem_len = (tot_len - cur_len);
1915 }
1916
1917 /*end scan marker*/
1918 if (pApMetaInfo->ApInfo.batchId != pAdapter->prev_batch_id)
1919 {
1920 temp_len = snprintf(pTemp, sizeof(temp), "####\n");
1921 pTemp += temp_len;
1922 temp_total_len += temp_len;
1923 }
1924
1925 /*bssid*/
1926 temp_len = snprintf(pTemp, sizeof(temp),
1927 "bssid=0x%x:0x%x:0x%x:0x%x:0x%x:0x%x\n",
1928 pApMetaInfo->ApInfo.bssid[0], pApMetaInfo->ApInfo.bssid[1],
1929 pApMetaInfo->ApInfo.bssid[2], pApMetaInfo->ApInfo.bssid[3],
1930 pApMetaInfo->ApInfo.bssid[4], pApMetaInfo->ApInfo.bssid[5]);
1931 pTemp += temp_len;
1932 temp_total_len += temp_len;
1933
1934 /*ssid*/
1935 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "ssid=%s\n",
1936 pApMetaInfo->ApInfo.ssid);
1937 pTemp += temp_len;
1938 temp_total_len += temp_len;
1939
1940 /*freq*/
1941 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "freq=%d\n",
Rajeev Kumarc40f7512013-11-04 14:13:23 -08001942 sme_ChnToFreq(pApMetaInfo->ApInfo.ch));
Rajeev79dbe4c2013-10-05 11:03:42 +05301943 pTemp += temp_len;
1944 temp_total_len += temp_len;
1945
1946 /*level*/
1947 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "level=%d\n",
1948 pApMetaInfo->ApInfo.rssi);
1949 pTemp += temp_len;
1950 temp_total_len += temp_len;
1951
1952 /*age*/
Jeff Johnson02797792013-10-26 19:17:13 -07001953 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "age=%d\n",
Rajeev79dbe4c2013-10-05 11:03:42 +05301954 pApMetaInfo->ApInfo.age);
1955 pTemp += temp_len;
1956 temp_total_len += temp_len;
1957
1958 /*dist*/
1959 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "dist=-1\n");
1960 pTemp += temp_len;
1961 temp_total_len += temp_len;
1962
1963 /*error*/
1964 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "error=-1\n");
1965 pTemp += temp_len;
1966 temp_total_len += temp_len;
1967
1968 /*end AP marker*/
1969 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "====\n");
1970 pTemp += temp_len;
1971 temp_total_len += temp_len;
1972
1973 /*last AP in batch scan response*/
1974 if(TRUE == pApMetaInfo->ApInfo.isLastAp)
1975 {
1976 /*end scan marker*/
1977 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "####\n");
1978 pTemp += temp_len;
1979 temp_total_len += temp_len;
1980
1981 /*end batch scan result marker*/
1982 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "----\n");
1983 pTemp += temp_len;
1984 temp_total_len += temp_len;
Kiet Lamaa8e15a2014-02-11 23:30:06 -08001985
Rajeev79dbe4c2013-10-05 11:03:42 +05301986 }
1987
1988 if (temp_total_len < rem_len)
1989 {
1990 ret = temp_total_len + 1;
1991 strlcpy(pDest, temp, ret);
1992 pAdapter->isTruncated = FALSE;
1993 }
1994 else
1995 {
1996 pAdapter->isTruncated = TRUE;
1997 if (rem_len >= strlen("%%%%"))
1998 {
Rajeev Kumarc933d982013-11-18 20:04:20 -08001999 ret = snprintf(pDest, sizeof(temp), "%%%%");
Rajeev79dbe4c2013-10-05 11:03:42 +05302000 }
Rajeev Kumarc933d982013-11-18 20:04:20 -08002001 else
Rajeev79dbe4c2013-10-05 11:03:42 +05302002 {
2003 ret = 0;
2004 }
2005 }
2006
2007 return ret;
2008
2009}/*End of hdd_format_batch_scan_rsp*/
2010
2011/**---------------------------------------------------------------------------
2012
2013 \brief hdd_populate_user_batch_scan_rsp() - This function populates user data
2014 buffer starting with head of hdd batch scan response queue
2015
2016 \param - pAdapter Pointer to HDD adapter
2017 \param - pDest Pointer to user data buffer
2018 \param - cur_len current offset in user buffer
2019 \param - rem_len remaining no of bytes in user buffer
2020
2021 \return - number of bytes written in user buffer
2022
2023 --------------------------------------------------------------------------*/
2024
2025tANI_U32 hdd_populate_user_batch_scan_rsp
2026(
2027 hdd_adapter_t* pAdapter,
2028 tANI_U8 *pDest,
2029 tANI_U32 cur_len,
2030 tANI_U32 rem_len
2031)
2032{
2033 tHddBatchScanRsp *pHead;
2034 tHddBatchScanRsp *pPrev;
2035 tANI_U32 len;
2036
Rajeev79dbe4c2013-10-05 11:03:42 +05302037 pAdapter->isTruncated = FALSE;
2038
2039 /*head of hdd batch scan response queue*/
2040 pHead = pAdapter->pBatchScanRsp;
2041 while (pHead)
2042 {
2043 len = hdd_format_batch_scan_rsp(pDest, cur_len, rem_len, pHead,
2044 pAdapter);
2045 pDest += len;
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07002046 pDest--;
Rajeev79dbe4c2013-10-05 11:03:42 +05302047 cur_len += len;
2048 if(TRUE == pAdapter->isTruncated)
2049 {
2050 /*result is truncated return rest of scan rsp in next req*/
2051 cur_len = rem_len;
2052 break;
2053 }
2054 pPrev = pHead;
2055 pHead = pHead->pNext;
2056 pAdapter->pBatchScanRsp = pHead;
Rajeev Kumarbe17d8b2014-01-10 15:39:45 -08002057 if (TRUE == pPrev->ApInfo.isLastAp)
2058 {
2059 pAdapter->prev_batch_id = 0;
2060 }
2061 else
2062 {
2063 pAdapter->prev_batch_id = pPrev->ApInfo.batchId;
2064 }
Rajeev79dbe4c2013-10-05 11:03:42 +05302065 vos_mem_free(pPrev);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002066 pPrev = NULL;
Rajeev79dbe4c2013-10-05 11:03:42 +05302067 }
2068
2069 return cur_len;
2070}/*End of hdd_populate_user_batch_scan_rsp*/
2071
2072/**---------------------------------------------------------------------------
2073
2074 \brief hdd_return_batch_scan_rsp_to_user () - This function returns batch
2075 scan response data from HDD queue to user space
2076 It does following in detail:
2077 a) if HDD has enough data in its queue then it 1st copies data to user
2078 space and then send get batch scan indication message to FW. In this
2079 case it does not wait on any event and batch scan response data will
2080 be populated in HDD response queue in MC thread context after receiving
2081 indication from FW
2082 b) else send get batch scan indication message to FW and wait on an event
2083 which will be set once HDD receives complete batch scan response from
2084 FW and then this function returns batch scan response to user space
2085
2086 \param - pAdapter Pointer to HDD adapter
2087 \param - pPrivData Pointer to priv_data
2088
2089 \return - 0 for success -EFAULT for failure
2090
2091 --------------------------------------------------------------------------*/
2092
2093int hdd_return_batch_scan_rsp_to_user
2094(
2095 hdd_adapter_t* pAdapter,
2096 hdd_priv_data_t *pPrivData,
2097 tANI_U8 *command
2098)
2099{
2100 tANI_U8 *pDest;
2101 tANI_U32 count = 0;
2102 tANI_U32 len = 0;
2103 tANI_U32 cur_len = 0;
2104 tANI_U32 rem_len = 0;
2105 eHalStatus halStatus;
2106 unsigned long rc;
2107 tSirTriggerBatchScanResultInd *pReq;
2108
2109 pReq = &pAdapter->hddTriggerBatchScanResultInd;
2110 pReq->param = 0;/*batch scan client*/
2111 pDest = (tANI_U8 *)(command + pPrivData->used_len);
2112 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
2113
2114 cur_len = pPrivData->used_len;
2115 if (pPrivData->total_len > pPrivData->used_len)
2116 {
2117 rem_len = pPrivData->total_len - pPrivData->used_len;
2118 }
2119 else
2120 {
2121 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2122 "%s: Invalid user data buffer total_len %d used_len %d",
2123 __func__, pPrivData->total_len, pPrivData->used_len);
2124 return -EFAULT;
2125 }
2126
2127 mutex_lock(&pAdapter->hdd_batch_scan_lock);
2128 len = hdd_populate_user_batch_scan_rsp(pAdapter, pDest,
2129 cur_len, rem_len);
2130 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
2131
2132 /*enough scan result available in cache to return to user space or
2133 scan result needs to be fetched 1st from fw and then return*/
Rajeev Kumar99db6262013-11-11 15:23:36 -08002134 if (len == cur_len)
Rajeev79dbe4c2013-10-05 11:03:42 +05302135 {
2136 pAdapter->hdd_wait_for_get_batch_scan_rsp = TRUE;
2137 halStatus = sme_TriggerBatchScanResultInd(
2138 WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
2139 pAdapter->sessionId, hdd_batch_scan_result_ind_callback,
2140 pAdapter);
2141 if ( eHAL_STATUS_SUCCESS == halStatus )
2142 {
2143 if (TRUE == pAdapter->hdd_wait_for_get_batch_scan_rsp)
2144 {
2145 INIT_COMPLETION(pAdapter->hdd_get_batch_scan_req_var);
2146 rc = wait_for_completion_timeout(
2147 &pAdapter->hdd_get_batch_scan_req_var,
2148 msecs_to_jiffies(HDD_GET_BATCH_SCAN_RSP_TIME_OUT));
Abhishek Singh00b71972016-01-07 10:51:04 +05302149 if (0 >= rc)
Rajeev79dbe4c2013-10-05 11:03:42 +05302150 {
2151 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Abhishek Singh00b71972016-01-07 10:51:04 +05302152 "%s: wait on hdd_get_batch_scan_req_var failed %ld",
2153 __func__, rc);
Rajeev79dbe4c2013-10-05 11:03:42 +05302154 return -EFAULT;
2155 }
2156 }
2157
2158 len = snprintf(pDest, HDD_BATCH_SCAN_AP_META_INFO_SIZE,
Jeff Johnson02797792013-10-26 19:17:13 -07002159 "scancount=%u\n", pAdapter->numScanList);
Rajeev79dbe4c2013-10-05 11:03:42 +05302160 pDest += len;
2161 cur_len += len;
2162
2163 mutex_lock(&pAdapter->hdd_batch_scan_lock);
2164 len = hdd_populate_user_batch_scan_rsp(pAdapter, pDest,
2165 cur_len, rem_len);
2166 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
2167
2168 count = 0;
2169 len = (len - pPrivData->used_len);
2170 pDest = (command + pPrivData->used_len);
2171 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar99db6262013-11-11 15:23:36 -08002172 "NEW BATCH SCAN RESULT:");
Rajeev79dbe4c2013-10-05 11:03:42 +05302173 while(count < len)
2174 {
2175 printk("%c", *(pDest + count));
2176 count++;
2177 }
2178 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2179 "%s: copy %d data to user buffer", __func__, len);
2180 if (copy_to_user(pPrivData->buf, pDest, len))
2181 {
2182 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2183 "%s: failed to copy data to user buffer", __func__);
2184 return -EFAULT;
2185 }
2186 }
2187 else
2188 {
2189 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2190 "sme_GetBatchScanScan returned failure halStatus %d",
2191 halStatus);
2192 return -EINVAL;
2193 }
2194 }
2195 else
2196 {
Rajeev79dbe4c2013-10-05 11:03:42 +05302197 count = 0;
2198 len = (len - pPrivData->used_len);
2199 pDest = (command + pPrivData->used_len);
2200 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar99db6262013-11-11 15:23:36 -08002201 "REMAINING TRUNCATED BATCH SCAN RESULT:");
Rajeev79dbe4c2013-10-05 11:03:42 +05302202 while(count < len)
2203 {
2204 printk("%c", *(pDest + count));
2205 count++;
2206 }
Rajeev Kumar99db6262013-11-11 15:23:36 -08002207 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2208 "%s: copy %d data to user buffer", __func__, len);
Rajeev79dbe4c2013-10-05 11:03:42 +05302209 if (copy_to_user(pPrivData->buf, pDest, len))
2210 {
2211 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2212 "%s: failed to copy data to user buffer", __func__);
2213 return -EFAULT;
2214 }
Rajeev79dbe4c2013-10-05 11:03:42 +05302215 }
2216
2217 return 0;
2218} /*End of hdd_return_batch_scan_rsp_to_user*/
2219
Rajeev Kumar8b373292014-01-08 20:36:55 -08002220/**---------------------------------------------------------------------------
2221
2222 \brief hdd_handle_batch_scan_ioctl () - This function handles WLS_BATCHING
2223 IOCTLs from user space. Following BATCH SCAN DEV IOCTs are handled:
2224 WLS_BATCHING VERSION
2225 WLS_BATCHING SET
2226 WLS_BATCHING GET
2227 WLS_BATCHING STOP
2228
2229 \param - pAdapter Pointer to HDD adapter
2230 \param - pPrivdata Pointer to priv_data
2231 \param - command Pointer to command
2232
2233 \return - 0 for success -EFAULT for failure
2234
2235 --------------------------------------------------------------------------*/
2236
2237int hdd_handle_batch_scan_ioctl
2238(
2239 hdd_adapter_t *pAdapter,
2240 hdd_priv_data_t *pPrivdata,
2241 tANI_U8 *command
2242)
2243{
2244 int ret = 0;
Yue Mae36e3552014-03-05 17:06:20 -08002245 hdd_context_t *pHddCtx;
2246
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05302247 ENTER();
2248
Yue Mae36e3552014-03-05 17:06:20 -08002249 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2250 ret = wlan_hdd_validate_context(pHddCtx);
2251 if (ret)
2252 {
Yue Mae36e3552014-03-05 17:06:20 -08002253 goto exit;
2254 }
Rajeev Kumar8b373292014-01-08 20:36:55 -08002255
2256 if (strncmp(command, "WLS_BATCHING VERSION", 20) == 0)
2257 {
2258 char extra[32];
2259 tANI_U8 len = 0;
2260 tANI_U8 version = HDD_BATCH_SCAN_VERSION;
2261
2262 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
2263 {
2264 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2265 "%s: Batch scan feature is not supported by FW", __func__);
2266 ret = -EINVAL;
2267 goto exit;
2268 }
2269
2270 len = scnprintf(extra, sizeof(extra), "WLS_BATCHING_VERSION %d",
2271 version);
2272 if (copy_to_user(pPrivdata->buf, &extra, len + 1))
2273 {
2274 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2275 "%s: failed to copy data to user buffer", __func__);
2276 ret = -EFAULT;
2277 goto exit;
2278 }
2279 ret = HDD_BATCH_SCAN_VERSION;
2280 }
2281 else if (strncmp(command, "WLS_BATCHING SET", 16) == 0)
2282 {
2283 int status;
2284 tANI_U8 *value = (command + 16);
2285 eHalStatus halStatus;
2286 unsigned long rc;
2287 tSirSetBatchScanReq *pReq = &pAdapter->hddSetBatchScanReq;
2288 tSirSetBatchScanRsp *pRsp = &pAdapter->hddSetBatchScanRsp;
2289
2290 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
2291 {
2292 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2293 "%s: Batch scan feature is not supported by FW", __func__);
2294 ret = -EINVAL;
2295 goto exit;
2296 }
2297
2298 if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) &&
2299 (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) &&
2300 (WLAN_HDD_P2P_GO != pAdapter->device_mode) &&
2301 (WLAN_HDD_P2P_DEVICE != pAdapter->device_mode))
2302 {
2303 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Sushant Kaushik8bc7df22014-04-09 17:55:29 +05302304 "Received WLS_BATCHING SET command in invalid mode %s (%d) "
Rajeev Kumar8b373292014-01-08 20:36:55 -08002305 "WLS_BATCHING_SET is only allowed in infra STA/P2P client mode",
Sushant Kaushik8bc7df22014-04-09 17:55:29 +05302306 hdd_device_modetoString(pAdapter->device_mode),
2307 pAdapter->device_mode);
Rajeev Kumar8b373292014-01-08 20:36:55 -08002308 ret = -EINVAL;
2309 goto exit;
2310 }
2311
2312 status = hdd_parse_set_batchscan_command(value, pReq);
2313 if (status)
2314 {
2315 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2316 "Invalid WLS_BATCHING SET command");
2317 ret = -EINVAL;
2318 goto exit;
2319 }
2320
2321
2322 pAdapter->hdd_wait_for_set_batch_scan_rsp = TRUE;
2323 halStatus = sme_SetBatchScanReq(WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
2324 pAdapter->sessionId, hdd_set_batch_scan_req_callback,
2325 pAdapter);
2326
2327 if ( eHAL_STATUS_SUCCESS == halStatus )
2328 {
Mahesh A Saptasagar5f568172014-05-14 17:02:33 +05302329 char extra[32];
2330 tANI_U8 len = 0;
2331 tANI_U8 mScan = 0;
2332
Rajeev Kumar8b373292014-01-08 20:36:55 -08002333 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2334 "sme_SetBatchScanReq returned success halStatus %d",
2335 halStatus);
2336 if (TRUE == pAdapter->hdd_wait_for_set_batch_scan_rsp)
2337 {
2338 INIT_COMPLETION(pAdapter->hdd_set_batch_scan_req_var);
2339 rc = wait_for_completion_timeout(
2340 &pAdapter->hdd_set_batch_scan_req_var,
2341 msecs_to_jiffies(HDD_SET_BATCH_SCAN_REQ_TIME_OUT));
2342 if (0 == rc)
2343 {
2344 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2345 "%s: Timeout waiting for set batch scan to complete",
2346 __func__);
2347 ret = -EINVAL;
2348 goto exit;
2349 }
2350 }
2351 if ( !pRsp->nScansToBatch )
2352 {
2353 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2354 "%s: Received set batch scan failure response from FW",
2355 __func__);
2356 ret = -EINVAL;
2357 goto exit;
2358 }
2359 /*As per the Batch Scan Framework API we should return the MIN of
2360 either MSCAN or the max # of scans firmware can cache*/
Mahesh A Saptasagar5f568172014-05-14 17:02:33 +05302361 mScan = MIN(pReq->numberOfScansToBatch , pRsp->nScansToBatch);
Rajeev Kumar8b373292014-01-08 20:36:55 -08002362
2363 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STARTED;
2364
2365 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2366 "%s: request MSCAN %d response MSCAN %d ret %d",
Mahesh A Saptasagar5f568172014-05-14 17:02:33 +05302367 __func__, pReq->numberOfScansToBatch, pRsp->nScansToBatch, mScan);
2368 len = scnprintf(extra, sizeof(extra), "%d", mScan);
2369 if (copy_to_user(pPrivdata->buf, &extra, len + 1))
2370 {
2371 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2372 "%s: failed to copy MSCAN value to user buffer", __func__);
2373 ret = -EFAULT;
2374 goto exit;
2375 }
Rajeev Kumar8b373292014-01-08 20:36:55 -08002376 }
2377 else
2378 {
2379 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2380 "sme_SetBatchScanReq returned failure halStatus %d",
2381 halStatus);
2382 ret = -EINVAL;
2383 goto exit;
2384 }
2385 }
2386 else if (strncmp(command, "WLS_BATCHING STOP", 17) == 0)
2387 {
2388 eHalStatus halStatus;
2389 tSirStopBatchScanInd *pInd = &pAdapter->hddStopBatchScanInd;
2390 pInd->param = 0;
2391
2392 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
2393 {
2394 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2395 "%s: Batch scan feature is not supported by FW", __func__);
2396 ret = -EINVAL;
2397 goto exit;
2398 }
2399
2400 if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState)
2401 {
Deepthi Gowribfd17132014-11-14 17:59:04 +05302402 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Rajeev Kumar8b373292014-01-08 20:36:55 -08002403 "Batch scan is not yet enabled batch scan state %d",
2404 pAdapter->batchScanState);
2405 ret = -EINVAL;
2406 goto exit;
2407 }
2408
Kiet Lamaa8e15a2014-02-11 23:30:06 -08002409 mutex_lock(&pAdapter->hdd_batch_scan_lock);
2410 hdd_deinit_batch_scan(pAdapter);
2411 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
2412
Rajeev Kumar8b373292014-01-08 20:36:55 -08002413 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
2414
2415 halStatus = sme_StopBatchScanInd(WLAN_HDD_GET_HAL_CTX(pAdapter), pInd,
2416 pAdapter->sessionId);
2417 if ( eHAL_STATUS_SUCCESS == halStatus )
2418 {
2419 ret = 0;
2420 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2421 "sme_StopBatchScanInd returned success halStatus %d",
2422 halStatus);
2423 }
2424 else
2425 {
2426 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2427 "sme_StopBatchScanInd returned failure halStatus %d",
2428 halStatus);
2429 ret = -EINVAL;
2430 goto exit;
2431 }
2432 }
2433 else if (strncmp(command, "WLS_BATCHING GET", 16) == 0)
2434 {
2435 tANI_U32 remain_len;
2436
2437 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
2438 {
2439 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2440 "%s: Batch scan feature is not supported by FW", __func__);
2441 ret = -EINVAL;
2442 goto exit;
2443 }
2444
2445 if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState)
2446 {
Deepthi Gowribfd17132014-11-14 17:59:04 +05302447 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Rajeev Kumar8b373292014-01-08 20:36:55 -08002448 "Batch scan is not yet enabled could not return results"
2449 "Batch Scan state %d",
2450 pAdapter->batchScanState);
2451 ret = -EINVAL;
2452 goto exit;
2453 }
2454
2455 pPrivdata->used_len = 16;
2456 remain_len = pPrivdata->total_len - pPrivdata->used_len;
2457 if (remain_len < pPrivdata->total_len)
2458 {
2459 /*Clear previous batch scan response data if any*/
2460 vos_mem_zero((tANI_U8 *)(command + pPrivdata->used_len), remain_len);
2461 }
2462 else
2463 {
2464 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2465 "Invalid total length from user space can't fetch batch"
2466 " scan response total_len %d used_len %d remain len %d",
2467 pPrivdata->total_len, pPrivdata->used_len, remain_len);
2468 ret = -EINVAL;
2469 goto exit;
2470 }
2471 ret = hdd_return_batch_scan_rsp_to_user(pAdapter, pPrivdata, command);
2472 }
2473
2474exit:
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05302475 EXIT();
Rajeev Kumar8b373292014-01-08 20:36:55 -08002476 return ret;
2477}
2478
2479
Rajeev79dbe4c2013-10-05 11:03:42 +05302480#endif/*End of FEATURE_WLAN_BATCH_SCAN*/
2481
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05302482#if defined(WLAN_FEATURE_VOWIFI_11R) || defined(FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
2483/**
2484 * hdd_assign_handoff_src_reassoc - Set handoff source as REASSOC
2485 * to Handoff request
2486 * @handoffInfo: Pointer to Handoff request
2487 * @src: enum of handoff_src
2488 * Return: None
2489 */
2490#ifndef QCA_WIFI_ISOC
2491static inline void hdd_assign_handoff_src_reassoc(tCsrHandoffRequest
2492 *handoffInfo, handoff_src src)
2493{
2494 handoffInfo->src = src;
2495}
2496#else
2497static inline void hdd_assign_handoff_src_reassoc(tCsrHandoffRequest
2498 *handoffInfo, handoff_src src)
2499{
2500}
2501#endif
2502
2503/**
Selvaraj, Sridhar4fa15232016-06-18 12:27:25 +05302504 * hdd_reassoc() - perform a user space-directed reassoc
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05302505 *
2506 * @pAdapter: Adapter upon which the command was received
2507 * @bssid: BSSID with which to reassociate
2508 * @channel: channel upon which to reassociate
Selvaraj, Sridhar4fa15232016-06-18 12:27:25 +05302509 * @src: The source for the trigger of this action
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05302510 *
2511 * Return: 0 for success non-zero for failure
2512 */
2513#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
Selvaraj, Sridhar8ecb4192016-06-23 17:50:49 +05302514int hdd_reassoc(hdd_adapter_t *pAdapter, const tANI_U8 *bssid,
Selvaraj, Sridhar4fa15232016-06-18 12:27:25 +05302515 const tANI_U8 channel, const handoff_src src)
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05302516{
2517 hdd_station_ctx_t *pHddStaCtx;
2518 tCsrHandoffRequest handoffInfo;
2519 hdd_context_t *pHddCtx = NULL;
2520 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2521
2522 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2523
2524 /* if not associated, no need to proceed with reassoc */
2525 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
2526 hddLog(LOG1, FL("Not associated"));
2527 return -EINVAL;
2528 }
2529
2530 /* if the target bssid is same as currently associated AP,
2531 then no need to proceed with reassoc */
2532 if (!memcmp(bssid, pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr))) {
2533 hddLog(LOG1, FL("Reassoc BSSID is same as currently associated AP bssid"));
2534 return -EINVAL;
2535 }
2536
2537 /* Check channel number is a valid channel number */
2538 if (VOS_STATUS_SUCCESS !=
2539 wlan_hdd_validate_operation_channel(pAdapter, channel)) {
2540 hddLog(LOGE, FL("Invalid Channel %d"), channel);
2541 return -EINVAL;
2542 }
2543
2544 /* Proceed with reassoc */
2545 handoffInfo.channel = channel;
Selvaraj, Sridhar4fa15232016-06-18 12:27:25 +05302546 hdd_assign_handoff_src_reassoc(&handoffInfo, src);
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05302547 memcpy(handoffInfo.bssid, bssid, sizeof(tSirMacAddr));
2548 sme_HandoffRequest(pHddCtx->hHal, &handoffInfo);
2549 return 0;
2550}
2551#else
Selvaraj, Sridhar8ecb4192016-06-23 17:50:49 +05302552int hdd_reassoc(hdd_adapter_t *pAdapter, const tANI_U8 *bssid,
Selvaraj, Sridhar4fa15232016-06-18 12:27:25 +05302553 const tANI_U8 channel, const handoff_src src)
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05302554{
2555 return -EPERM;
2556}
2557#endif
2558
2559/**
2560 * hdd_parse_reassoc_v1() - parse version 1 of the REASSOC command
2561 * This function parses the v1 REASSOC command with the format
2562 * REASSOC xx:xx:xx:xx:xx:xx CH where "xx:xx:xx:xx:xx:xx" is the
2563 * Hex-ASCII representation of the BSSID and CH is the ASCII
2564 * representation of the channel. For example
2565 * REASSOC 00:0a:0b:11:22:33 48
2566 *
2567 * @pAdapter: Adapter upon which the command was received
2568 * @command: ASCII text command that was received
2569 *
2570 * Return: 0 for success non-zero for failure
2571 */
2572static int
2573hdd_parse_reassoc_v1(hdd_adapter_t *pAdapter, const char *command)
2574{
2575 tANI_U8 channel = 0;
2576 tSirMacAddr bssid;
2577 int ret;
2578
2579 ret = hdd_parse_reassoc_command_v1_data(command, bssid, &channel);
2580 if (ret)
2581 hddLog(LOGE, FL("Failed to parse reassoc command data"));
2582 else
Selvaraj, Sridhar4fa15232016-06-18 12:27:25 +05302583 ret = hdd_reassoc(pAdapter, bssid, channel, REASSOC);
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05302584
2585 return ret;
2586}
2587
2588/**
2589 * hdd_parse_reassoc_v2() - parse version 2 of the REASSOC command
2590 * This function parses the v2 REASSOC command with the format
2591 * REASSOC <android_wifi_reassoc_params>
2592 *
2593 * @pAdapter: Adapter upon which the command was received
2594 * @command: command that was received, ASCII command followed
2595 * by binary data
2596 *
2597 * Return: 0 for success non-zero for failure
2598 */
2599static int
2600hdd_parse_reassoc_v2(hdd_adapter_t *pAdapter, const char *command)
2601{
2602 struct android_wifi_reassoc_params params;
2603 tSirMacAddr bssid;
2604 int ret;
2605
2606 /* The params are located after "REASSOC " */
2607 memcpy(&params, command + 8, sizeof(params));
2608
2609 if (!mac_pton(params.bssid, (u8 *)&bssid)) {
2610 hddLog(LOGE, FL("MAC address parsing failed"));
2611 ret = -EINVAL;
2612 } else {
Selvaraj, Sridhar4fa15232016-06-18 12:27:25 +05302613 ret = hdd_reassoc(pAdapter, bssid, params.channel, REASSOC);
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05302614 }
2615 return ret;
2616}
2617
2618/**
2619 * hdd_parse_reassoc() - parse the REASSOC command
2620 * There are two different versions of the REASSOC command.Version 1
2621 * of the command contains a parameter list that is ASCII characters
2622 * whereas version 2 contains a combination of ASCII and binary
2623 * payload. Determine if a version 1 or a version 2 command is being
2624 * parsed by examining the parameters, and then dispatch the parser
2625 * that is appropriate for the command.
2626 *
2627 * @pAdapter: Adapter upon which the command was received
2628 * @command: command that was received
2629 *
2630 * Return: 0 for success non-zero for failure
2631 */
2632static int
2633hdd_parse_reassoc(hdd_adapter_t *pAdapter, const char *command)
2634{
2635 int ret;
2636
2637 /*
2638 * both versions start with "REASSOC"
2639 * v1 has a bssid and channel # as an ASCII string
2640 * REASSOC xx:xx:xx:xx:xx:xx CH
2641 * v2 has a C struct
2642 * REASSOC <binary c struct>
2643 *
2644 * The first field in the v2 struct is also the bssid in ASCII.
2645 * But in the case of a v2 message the BSSID is NUL-terminated.
2646 * Hence we can peek at that offset to see if this is V1 or V2
2647 * REASSOC xx:xx:xx:xx:xx:xx*
2648 * 1111111111222222
2649 * 01234567890123456789012345
2650 */
2651 if (command[25])
2652 ret = hdd_parse_reassoc_v1(pAdapter, command);
2653 else
2654 ret = hdd_parse_reassoc_v2(pAdapter, command);
2655
2656 return ret;
2657}
2658#endif /* WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_ESE FEATURE_WLAN_LFR */
2659
c_hpothu92367912014-05-01 15:18:17 +05302660static void getBcnMissRateCB(VOS_STATUS status, int bcnMissRate, void *data)
2661{
c_hpothu39eb1e32014-06-26 16:31:50 +05302662 bcnMissRateContext_t *pCBCtx;
2663
2664 if (NULL == data)
2665 {
2666 hddLog(VOS_TRACE_LEVEL_ERROR, FL("argument data is NULL"));
2667 return;
2668 }
c_hpothu92367912014-05-01 15:18:17 +05302669
2670 /* there is a race condition that exists between this callback
2671 function and the caller since the caller could time out either
2672 before or while this code is executing. we use a spinlock to
2673 serialize these actions */
2674 spin_lock(&hdd_context_lock);
2675
c_hpothu39eb1e32014-06-26 16:31:50 +05302676 pCBCtx = (bcnMissRateContext_t *)data;
c_hpothu92367912014-05-01 15:18:17 +05302677 gbcnMissRate = -1;
2678
c_hpothu39eb1e32014-06-26 16:31:50 +05302679 if (pCBCtx->magic != BCN_MISS_RATE_CONTEXT_MAGIC)
c_hpothu92367912014-05-01 15:18:17 +05302680 {
2681 hddLog(VOS_TRACE_LEVEL_ERROR,
c_hpothu39eb1e32014-06-26 16:31:50 +05302682 FL("invalid context magic: %08x"), pCBCtx->magic);
c_hpothu92367912014-05-01 15:18:17 +05302683 spin_unlock(&hdd_context_lock);
2684 return ;
2685 }
2686
2687 if (VOS_STATUS_SUCCESS == status)
2688 {
c_hpothu39eb1e32014-06-26 16:31:50 +05302689 gbcnMissRate = bcnMissRate;
c_hpothu92367912014-05-01 15:18:17 +05302690 }
c_hpothu39eb1e32014-06-26 16:31:50 +05302691 else
2692 {
2693 hddLog(VOS_TRACE_LEVEL_ERROR, FL("failed to get bcnMissRate"));
2694 }
2695
c_hpothu92367912014-05-01 15:18:17 +05302696 complete(&(pCBCtx->completion));
2697 spin_unlock(&hdd_context_lock);
2698
2699 return;
2700}
2701
Abhishek Singh08aa7762014-12-16 13:59:03 +05302702void hdd_FWStatisCB( VOS_STATUS status,
2703 tSirFwStatsResult *fwStatsResult, void *pContext )
Satyanarayana Dash72806012014-12-02 14:30:08 +05302704{
2705 fwStatsContext_t *fwStatsCtx;
Satyanarayana Dash72806012014-12-02 14:30:08 +05302706 hdd_adapter_t *pAdapter;
2707
2708 hddLog(VOS_TRACE_LEVEL_INFO, FL(" with status = %d"),status);
2709
Abhishek Singh08aa7762014-12-16 13:59:03 +05302710 if (NULL == pContext)
Satyanarayana Dash72806012014-12-02 14:30:08 +05302711 {
2712 hddLog(VOS_TRACE_LEVEL_ERROR, FL("argument data is NULL"));
2713 return;
2714 }
2715 /* there is a race condition that exists between this callback
2716 function and the caller since the caller could time out either
2717 before or while this code is executing. we use a spinlock to
2718 serialize these actions */
2719 spin_lock(&hdd_context_lock);
Abhishek Singh08aa7762014-12-16 13:59:03 +05302720 fwStatsCtx = (fwStatsContext_t *) pContext;
Satyanarayana Dash72806012014-12-02 14:30:08 +05302721 if (fwStatsCtx->magic != FW_STATS_CONTEXT_MAGIC)
2722 {
2723 hddLog(VOS_TRACE_LEVEL_ERROR,
2724 FL("invalid context magic: %08x"), fwStatsCtx->magic);
2725 spin_unlock(&hdd_context_lock);
2726 return;
2727 }
2728 pAdapter = fwStatsCtx->pAdapter;
2729 if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
2730 {
2731 hddLog(VOS_TRACE_LEVEL_ERROR,
2732 FL("pAdapter returned is NULL or invalid"));
2733 spin_unlock(&hdd_context_lock);
2734 return;
2735 }
2736 pAdapter->fwStatsRsp.type = 0;
Abhishek Singh08aa7762014-12-16 13:59:03 +05302737 if ((VOS_STATUS_SUCCESS == status) && (NULL != fwStatsResult))
Satyanarayana Dash72806012014-12-02 14:30:08 +05302738 {
Satyanarayana Dash72806012014-12-02 14:30:08 +05302739 switch( fwStatsResult->type )
2740 {
2741 case FW_UBSP_STATS:
2742 {
Abhishek Singh08aa7762014-12-16 13:59:03 +05302743 memcpy(&pAdapter->fwStatsRsp,fwStatsResult,sizeof(tSirFwStatsResult));
Satyanarayana Dash72806012014-12-02 14:30:08 +05302744 hddLog(VOS_TRACE_LEVEL_INFO,
2745 FL("ubsp_enter_cnt = %d ubsp_jump_ddr_cnt = %d"),
Abhishek Singh08aa7762014-12-16 13:59:03 +05302746 pAdapter->fwStatsRsp.fwStatsData.ubspStats.ubsp_enter_cnt,
2747 pAdapter->fwStatsRsp.fwStatsData.ubspStats.ubsp_jump_ddr_cnt);
Satyanarayana Dash72806012014-12-02 14:30:08 +05302748 }
2749 break;
2750 default:
2751 {
2752 hddLog(VOS_TRACE_LEVEL_ERROR,
2753 FL(" No handling for stats type %d"),fwStatsResult->type);
2754 }
2755 }
2756 }
2757 complete(&(fwStatsCtx->completion));
2758 spin_unlock(&hdd_context_lock);
2759 return;
2760}
2761
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302762static int hdd_get_dwell_time(hdd_config_t *pCfg, tANI_U8 *command, char *extra, tANI_U8 n, tANI_U8 *len)
2763{
2764 int ret = 0;
2765
2766 if (!pCfg || !command || !extra || !len)
2767 {
2768 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2769 "%s: argument passsed for GETDWELLTIME is incorrect", __func__);
2770 ret = -EINVAL;
2771 return ret;
2772 }
2773
2774 if (strncmp(command, "GETDWELLTIME ACTIVE MAX", 23) == 0)
2775 {
2776 *len = scnprintf(extra, n, "GETDWELLTIME ACTIVE MAX %u\n",
2777 (int)pCfg->nActiveMaxChnTime);
2778 return ret;
2779 }
2780 else if (strncmp(command, "GETDWELLTIME ACTIVE MIN", 23) == 0)
2781 {
2782 *len = scnprintf(extra, n, "GETDWELLTIME ACTIVE MIN %u\n",
2783 (int)pCfg->nActiveMinChnTime);
2784 return ret;
2785 }
2786 else if (strncmp(command, "GETDWELLTIME PASSIVE MAX", 24) == 0)
2787 {
2788 *len = scnprintf(extra, n, "GETDWELLTIME PASSIVE MAX %u\n",
2789 (int)pCfg->nPassiveMaxChnTime);
2790 return ret;
2791 }
2792 else if (strncmp(command, "GETDWELLTIME PASSIVE MIN", 24) == 0)
2793 {
2794 *len = scnprintf(extra, n, "GETDWELLTIME PASSIVE MIN %u\n",
2795 (int)pCfg->nPassiveMinChnTime);
2796 return ret;
2797 }
Rajesh Babu Prathipati0fd227e2014-07-05 12:50:00 +05302798 else if (strncmp(command, "GETDWELLTIME", 12) == 0)
2799 {
2800 *len = scnprintf(extra, n, "GETDWELLTIME %u \n",
2801 (int)pCfg->nActiveMaxChnTime);
2802 return ret;
2803 }
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302804 else
2805 {
2806 ret = -EINVAL;
2807 }
2808
2809 return ret;
2810}
2811
2812static int hdd_set_dwell_time(hdd_adapter_t *pAdapter, tANI_U8 *command)
2813{
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302814 tHalHandle hHal;
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302815 hdd_config_t *pCfg;
2816 tANI_U8 *value = command;
2817 int val = 0, ret = 0, temp = 0;
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302818 tSmeConfigParams smeConfig;
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302819
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302820 if (!pAdapter || !command || !(pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini)
2821 || !(hHal = (WLAN_HDD_GET_HAL_CTX(pAdapter))))
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302822 {
2823 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2824 "%s: argument passed for SETDWELLTIME is incorrect", __func__);
2825 ret = -EINVAL;
2826 return ret;
2827 }
2828
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302829 vos_mem_zero(&smeConfig, sizeof(smeConfig));
2830 sme_GetConfigParam(hHal, &smeConfig);
2831
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302832 if (strncmp(command, "SETDWELLTIME ACTIVE MAX", 23) == 0 )
2833 {
2834 value = value + 24;
2835 temp = kstrtou32(value, 10, &val);
2836 if (temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_MIN ||
2837 val > CFG_ACTIVE_MAX_CHANNEL_TIME_MAX )
2838 {
2839 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2840 "%s: argument passed for SETDWELLTIME ACTIVE MAX is incorrect", __func__);
2841 ret = -EFAULT;
2842 return ret;
2843 }
2844 pCfg->nActiveMaxChnTime = val;
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302845 smeConfig.csrConfig.nActiveMaxChnTime = val;
2846 sme_UpdateConfig(hHal, &smeConfig);
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302847 }
2848 else if (strncmp(command, "SETDWELLTIME ACTIVE MIN", 23) == 0)
2849 {
2850 value = value + 24;
2851 temp = kstrtou32(value, 10, &val);
2852 if (temp !=0 || val < CFG_ACTIVE_MIN_CHANNEL_TIME_MIN ||
2853 val > CFG_ACTIVE_MIN_CHANNEL_TIME_MAX )
2854 {
2855 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2856 "%s: argument passsed for SETDWELLTIME ACTIVE MIN is incorrect", __func__);
2857 ret = -EFAULT;
2858 return ret;
2859 }
2860 pCfg->nActiveMinChnTime = val;
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302861 smeConfig.csrConfig.nActiveMinChnTime = val;
2862 sme_UpdateConfig(hHal, &smeConfig);
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302863 }
2864 else if (strncmp(command, "SETDWELLTIME PASSIVE MAX", 24) == 0)
2865 {
2866 value = value + 25;
2867 temp = kstrtou32(value, 10, &val);
2868 if (temp != 0 || val < CFG_PASSIVE_MAX_CHANNEL_TIME_MIN ||
2869 val > CFG_PASSIVE_MAX_CHANNEL_TIME_MAX )
2870 {
2871 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2872 "%s: argument passed for SETDWELLTIME PASSIVE MAX is incorrect", __func__);
2873 ret = -EFAULT;
2874 return ret;
2875 }
2876 pCfg->nPassiveMaxChnTime = val;
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302877 smeConfig.csrConfig.nPassiveMaxChnTime = val;
2878 sme_UpdateConfig(hHal, &smeConfig);
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302879 }
2880 else if (strncmp(command, "SETDWELLTIME PASSIVE MIN", 24) == 0)
2881 {
2882 value = value + 25;
2883 temp = kstrtou32(value, 10, &val);
2884 if (temp != 0 || val < CFG_PASSIVE_MIN_CHANNEL_TIME_MIN ||
2885 val > CFG_PASSIVE_MIN_CHANNEL_TIME_MAX )
2886 {
2887 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2888 "%s: argument passed for SETDWELLTIME PASSIVE MIN is incorrect", __func__);
2889 ret = -EFAULT;
2890 return ret;
2891 }
2892 pCfg->nPassiveMinChnTime = val;
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302893 smeConfig.csrConfig.nPassiveMinChnTime = val;
2894 sme_UpdateConfig(hHal, &smeConfig);
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302895 }
Rajesh Babu Prathipati0fd227e2014-07-05 12:50:00 +05302896 else if (strncmp(command, "SETDWELLTIME", 12) == 0)
2897 {
2898 value = value + 13;
2899 temp = kstrtou32(value, 10, &val);
2900 if (temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_MIN ||
2901 val > CFG_ACTIVE_MAX_CHANNEL_TIME_MAX )
2902 {
2903 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2904 "%s: argument passed for SETDWELLTIME is incorrect", __func__);
2905 ret = -EFAULT;
2906 return ret;
2907 }
2908 pCfg->nActiveMaxChnTime = val;
2909 smeConfig.csrConfig.nActiveMaxChnTime = val;
2910 sme_UpdateConfig(hHal, &smeConfig);
2911 }
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302912 else
2913 {
2914 ret = -EINVAL;
2915 }
2916
2917 return ret;
2918}
Agarwal Ashish8bd53ae2015-06-12 18:03:45 +05302919static int hdd_cmd_setFccChannel(hdd_context_t *pHddCtx, tANI_U8 *cmd,
2920 tANI_U8 cmd_len)
2921{
2922 tANI_U8 *value;
2923 tANI_U8 fcc_constraint;
2924
2925 eHalStatus status;
2926 int ret = 0;
2927 value = cmd + cmd_len + 1;
2928
2929 ret = kstrtou8(value, 10, &fcc_constraint);
2930 if ((ret < 0) || (fcc_constraint > 1)) {
2931 /*
2932 * If the input value is greater than max value of datatype,
2933 * then also it is a failure
2934 */
2935 hddLog(VOS_TRACE_LEVEL_ERROR,
2936 "%s: value out of range", __func__);
2937 return -EINVAL;
2938 }
2939
Agrawal Ashish842eea82016-02-04 17:56:16 +05302940 status = sme_handleSetFccChannel(pHddCtx->hHal, fcc_constraint,
2941 pHddCtx->scan_info.mScanPending);
Agarwal Ashish8bd53ae2015-06-12 18:03:45 +05302942 if (status != eHAL_STATUS_SUCCESS)
2943 ret = -EPERM;
2944
2945 return ret;
2946}
2947
Mahesh A Saptasagarbeca12c2015-09-07 16:21:06 +05302948/**---------------------------------------------------------------------------
Agarwal Ashish8bd53ae2015-06-12 18:03:45 +05302949
Mahesh A Saptasagarbeca12c2015-09-07 16:21:06 +05302950 \brief hdd_enable_disable_ca_event() - When Host sends IOCTL (enabled),
2951 FW will send *ONE* CA ind to Host(even though it is duplicate).
2952 When Host send IOCTL (disable), FW doesn't perform any action.
2953 Whenever any change in CA *and* WLAN is in SAP/P2P-GO mode, FW
2954 sends CA ind to host. (regard less of IOCTL status)
2955 \param - pHddCtx - HDD context
2956 \param - command - command received from framework
2957 \param - cmd_len - len of the command
2958
2959 \return - 0 on success, appropriate error values on failure.
2960
2961 --------------------------------------------------------------------------*/
2962int hdd_enable_disable_ca_event(hdd_context_t *pHddCtx, tANI_U8* command, tANI_U8 cmd_len)
2963{
2964 tANI_U8 set_value;
2965 int ret = 0;
2966 eHalStatus status;
2967
2968 ret = wlan_hdd_validate_context(pHddCtx);
2969 if (0 != ret)
2970 {
2971 ret = -EINVAL;
2972 goto exit;
2973 }
2974
2975 if (pHddCtx->cfg_ini->gOptimizeCAevent == 0)
2976 {
2977 hddLog(VOS_TRACE_LEVEL_ERROR, "Enable gOptimizeCAevent"
2978 " ini param to control channel avooidance indication");
2979 ret = 0;
2980 goto exit;
2981 }
2982
2983 set_value = command[cmd_len + 1] - '0';
2984 status = sme_enableDisableChanAvoidIndEvent(pHddCtx->hHal, set_value);
2985 if (status != eHAL_STATUS_SUCCESS)
2986 {
2987 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to send"
2988 " enableDisableChanAoidance command to SME\n", __func__);
2989 ret = -EINVAL;
2990 }
2991
2992exit:
2993 return ret;
2994}
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302995
Selvaraj, Sridhar3714c4d2016-06-22 15:19:12 +05302996/**
2997 * wlan_hdd_fastreassoc_handoff_request() - Post Handoff request to SME
2998 * @pHddCtx: Pointer to the HDD context
2999 * @channel: channel to reassociate
3000 * @targetApBssid: Target AP/BSSID to reassociate
3001 *
3002 * Return: None
3003 */
3004#if defined(WLAN_FEATURE_ROAM_SCAN_OFFLOAD) && !defined(QCA_WIFI_ISOC)
3005static void wlan_hdd_fastreassoc_handoff_request(hdd_context_t *pHddCtx,
3006 uint8_t channel, tSirMacAddr targetApBssid)
3007{
3008 tCsrHandoffRequest handoffInfo;
3009 handoffInfo.channel = channel;
3010 handoffInfo.src = FASTREASSOC;
3011 vos_mem_copy(handoffInfo.bssid, targetApBssid, sizeof(tSirMacAddr));
3012 sme_HandoffRequest(pHddCtx->hHal, &handoffInfo);
3013}
3014#else
3015static void wlan_hdd_fastreassoc_handoff_request(hdd_context_t *pHddCtx,
3016 uint8_t channel, tSirMacAddr targetApBssid)
3017{
3018}
3019#endif
3020
3021/**
3022 * csr_fastroam_neighbor_ap_event() - Function to trigger scan/roam
3023 * @pAdapter: Pointer to HDD adapter
3024 * @channel: Channel to scan/roam
3025 * @targetApBssid: BSSID to roam
3026 *
3027 * Return: None
3028 */
3029#ifdef QCA_WIFI_ISOC
3030static void csr_fastroam_neighbor_ap_event(hdd_adapter_t *pAdapter,
3031 uint8_t channel, tSirMacAddr targetApBssid)
3032{
3033 smeIssueFastRoamNeighborAPEvent(WLAN_HDD_GET_HAL_CTX(pAdapter),
3034 &targetApBssid[0], eSME_ROAM_TRIGGER_SCAN, channel);
3035}
3036#else
3037static void csr_fastroam_neighbor_ap_event(hdd_adapter_t *pAdapter,
3038 uint8_t channel, tSirMacAddr targetApBssid)
3039{
3040}
3041#endif
3042
3043/**
3044 * wlan_hdd_handle_fastreassoc() - Handle fastreassoc command
3045 * @pAdapter: pointer to hdd adapter
3046 * @command: pointer to the command received
3047 *
3048 * Return: VOS_STATUS enum
3049 */
3050static VOS_STATUS wlan_hdd_handle_fastreassoc(hdd_adapter_t *pAdapter,
3051 uint8_t *command)
3052{
3053 tANI_U8 *value = command;
3054 tANI_U8 channel = 0;
3055 tSirMacAddr targetApBssid;
Selvaraj, Sridhar3714c4d2016-06-22 15:19:12 +05303056 hdd_station_ctx_t *pHddStaCtx = NULL;
3057 hdd_context_t *pHddCtx = NULL;
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05303058 int ret;
Selvaraj, Sridhar349b8fe2017-01-18 13:11:25 +05303059 tCsrRoamModifyProfileFields mod_profile_fields;
3060 uint32_t roam_id = 0;
Selvaraj, Sridhar3714c4d2016-06-22 15:19:12 +05303061 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3062 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3063
3064 /* if not associated, no need to proceed with reassoc */
3065 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
3066 hddLog(LOG1, FL("Not associated!"));
3067 return eHAL_STATUS_FAILURE;
3068 }
3069
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05303070 ret = hdd_parse_reassoc_command_v1_data(value, targetApBssid, &channel);
3071 if (ret) {
Selvaraj, Sridhar3714c4d2016-06-22 15:19:12 +05303072 hddLog(LOGE, FL("Failed to parse reassoc command data"));
3073 return eHAL_STATUS_FAILURE;
3074 }
3075
3076 /* if the target bssid is same as currently associated AP,
3077 then no need to proceed with reassoc */
3078 if (vos_mem_compare(targetApBssid,
3079 pHddStaCtx->conn_info.bssId,
3080 sizeof(tSirMacAddr))) {
Selvaraj, Sridhar349b8fe2017-01-18 13:11:25 +05303081 sme_GetModifyProfileFields(pHddCtx->hHal, pAdapter->sessionId,
3082 &mod_profile_fields);
3083 sme_RoamReassoc(pHddCtx->hHal, pAdapter->sessionId, NULL,
3084 mod_profile_fields, &roam_id, 1);
Selvaraj, Sridhar3714c4d2016-06-22 15:19:12 +05303085 hddLog(LOG1, FL("Reassoc BSSID is same as currently associated AP bssid"));
Selvaraj, Sridhar349b8fe2017-01-18 13:11:25 +05303086 return eHAL_STATUS_SUCCESS;
Selvaraj, Sridhar3714c4d2016-06-22 15:19:12 +05303087 }
3088
3089 /* Check channel number is a valid channel number */
3090 if (VOS_STATUS_SUCCESS !=
3091 wlan_hdd_validate_operation_channel(pAdapter, channel)) {
3092 hddLog(LOGE, FL("Invalid Channel [%d]"), channel);
3093 return eHAL_STATUS_FAILURE;
3094 }
3095
3096 /* Proceed with reassoc */
3097 wlan_hdd_fastreassoc_handoff_request(pHddCtx, channel, targetApBssid);
3098
3099 /* Proceed with scan/roam */
3100 csr_fastroam_neighbor_ap_event(pAdapter, channel, targetApBssid);
3101
3102 return eHAL_STATUS_SUCCESS;
3103}
3104
3105/**
3106 * hdd_assign_reassoc_handoff - Set handoff source as REASSOC
3107 * @handoffInfo: Pointer to the csr Handoff Request.
3108 *
3109 * Return: None
3110 */
3111#ifndef QCA_WIFI_ISOC
3112static inline void hdd_assign_reassoc_handoff(tCsrHandoffRequest *handoffInfo)
3113{
3114 handoffInfo->src = REASSOC;
3115}
3116#else
3117static inline void hdd_assign_reassoc_handoff(tCsrHandoffRequest *handoffInfo)
3118{
3119}
3120#endif
3121
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003122static int hdd_driver_command(hdd_adapter_t *pAdapter,
3123 hdd_priv_data_t *ppriv_data)
Jeff Johnson295189b2012-06-20 16:38:30 -07003124{
Jeff Johnson295189b2012-06-20 16:38:30 -07003125 hdd_priv_data_t priv_data;
3126 tANI_U8 *command = NULL;
Kaushik, Sushant96122442014-10-21 16:40:18 +05303127 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3128 hdd_scaninfo_t *pScanInfo = NULL;
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003129 int ret = 0;
Kaushik, Sushant96122442014-10-21 16:40:18 +05303130 int status;
Anand N Sunkade9adb1b2015-07-29 09:56:45 +05303131#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0))
3132 struct cfg80211_mgmt_tx_params params;
3133#endif
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05303134
3135 ENTER();
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003136 /*
3137 * Note that valid pointers are provided by caller
3138 */
Jeff Johnson295189b2012-06-20 16:38:30 -07003139
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003140 /* copy to local struct to avoid numerous changes to legacy code */
3141 priv_data = *ppriv_data;
Jeff Johnson295189b2012-06-20 16:38:30 -07003142
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003143 if (priv_data.total_len <= 0 ||
3144 priv_data.total_len > WLAN_PRIV_DATA_MAX_LEN)
Sameer Thalappil8ef3a0e2013-04-05 14:36:04 -07003145 {
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003146 hddLog(VOS_TRACE_LEVEL_WARN,
3147 "%s:invalid priv_data.total_len(%d)!!!", __func__,
3148 priv_data.total_len);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003149 ret = -EINVAL;
3150 goto exit;
3151 }
Kaushik, Sushant96122442014-10-21 16:40:18 +05303152 status = wlan_hdd_validate_context(pHddCtx);
3153 if (0 != status)
3154 {
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05303155 ret = -EINVAL;
3156 goto exit;
Kaushik, Sushant96122442014-10-21 16:40:18 +05303157 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003158 /* Allocate +1 for '\0' */
3159 command = kmalloc(priv_data.total_len + 1, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07003160 if (!command)
3161 {
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003162 hddLog(VOS_TRACE_LEVEL_ERROR,
3163 "%s: failed to allocate memory", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003164 ret = -ENOMEM;
3165 goto exit;
3166 }
3167
3168 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
3169 {
3170 ret = -EFAULT;
3171 goto exit;
3172 }
3173
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003174 /* Make sure the command is NUL-terminated */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003175 command[priv_data.total_len] = '\0';
3176
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003177 /* at one time the following block of code was conditional. braces
3178 * have been retained to avoid re-indenting the legacy code
3179 */
Jeff Johnson295189b2012-06-20 16:38:30 -07003180 {
3181 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
3182
3183 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07003184 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -07003185
3186 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
3187 {
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303188 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3189 TRACE_CODE_HDD_P2P_DEV_ADDR_IOCTL,
3190 pAdapter->sessionId, (unsigned)
3191 (*(pHddCtx->p2pDeviceAddress.bytes+2)<<24 |
3192 *(pHddCtx->p2pDeviceAddress.bytes+3)<<16 |
3193 *(pHddCtx->p2pDeviceAddress.bytes+4)<<8 |
3194 *(pHddCtx->p2pDeviceAddress.bytes+5))));
Jeff Johnson295189b2012-06-20 16:38:30 -07003195 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
3196 sizeof(tSirMacAddr)))
3197 {
3198 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Arif Hussain6d2a3322013-11-17 19:50:10 -08003199 "%s: failed to copy data to user buffer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003200 ret = -EFAULT;
3201 }
3202 }
Amar Singhal0974e402013-02-12 14:27:46 -08003203 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07003204 {
Amar Singhal0974e402013-02-12 14:27:46 -08003205 tANI_U8 *ptr = command ;
Srinivas Girigowdade697412013-02-14 16:31:48 -08003206
Jeff Johnson295189b2012-06-20 16:38:30 -07003207 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -08003208
3209 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -07003210 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07003211 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -08003212 "%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 +05303213 if(VOS_FTM_MODE != hdd_get_conparam())
3214 {
3215 /* Change band request received */
3216 ret = hdd_setBand_helper(pAdapter->dev, ptr);
3217 if(ret < 0)
3218 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
3219 "%s: failed to set band ret=%d", __func__, ret);
3220 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08003221 }
Kiet Lamf040f472013-11-20 21:15:23 +05303222 else if(strncmp(command, "SETWMMPS", 8) == 0)
3223 {
3224 tANI_U8 *ptr = command;
3225 ret = hdd_wmmps_helper(pAdapter, ptr);
3226 }
Agarwal Ashishef54a182014-12-16 15:07:31 +05303227
3228 else if(strncmp(command, "TDLSSCAN", 8) == 0)
3229 {
3230 tANI_U8 *ptr = command;
3231 ret = hdd_set_tdls_scan_type(pAdapter, ptr);
3232 }
3233
Jeff Johnson32d95a32012-09-10 13:15:23 -07003234 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
3235 {
3236 char *country_code;
3237
3238 country_code = command + 8;
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07003239
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07003240 INIT_COMPLETION(pAdapter->change_country_code);
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07003241 hdd_checkandupdate_dfssetting(pAdapter, country_code);
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -07003242#ifndef CONFIG_ENABLE_LINUX_REG
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +05303243 hdd_checkandupdate_phymode(pAdapter, country_code);
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -07003244#endif
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07003245 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal,
3246 (void *)(tSmeChangeCountryCallback)
3247 wlan_hdd_change_country_code_callback,
Abhishek Singha306a442013-11-07 18:39:01 +05303248 country_code, pAdapter, pHddCtx->pvosContext, eSIR_TRUE, eSIR_TRUE);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07003249 if (eHAL_STATUS_SUCCESS == ret)
3250 {
3251 ret = wait_for_completion_interruptible_timeout(
3252 &pAdapter->change_country_code,
3253 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
3254 if (0 >= ret)
3255 {
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003256 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: SME while setting country code timed out %d",
c_hpothu6ff1c3c2013-10-01 19:01:57 +05303257 __func__, ret);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07003258 }
3259 }
3260 else
Jeff Johnson32d95a32012-09-10 13:15:23 -07003261 {
3262 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003263 "%s: SME Change Country code fail ret=%d", __func__, ret);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07003264 ret = -EINVAL;
Jeff Johnson32d95a32012-09-10 13:15:23 -07003265 }
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07003266
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07003267 }
3268 /*
3269 command should be a string having format
3270 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
3271 */
Amar Singhal0974e402013-02-12 14:27:46 -08003272 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07003273 {
Amar Singhal0974e402013-02-12 14:27:46 -08003274 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07003275
3276 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003277 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07003278
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -08003279 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -07003280 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -08003281 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
3282 {
3283 int suspend = 0;
3284 tANI_U8 *ptr = (tANI_U8*)command + 15;
3285
3286 suspend = *ptr - '0';
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303287 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3288 TRACE_CODE_HDD_SETSUSPENDMODE_IOCTL,
3289 pAdapter->sessionId, suspend));
Sameer Thalappil45931fb2013-02-01 11:18:05 -08003290 hdd_set_wlan_suspend_mode(suspend);
3291 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08003292#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
3293 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
3294 {
3295 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003296 tANI_S8 rssi = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08003297 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
3298 eHalStatus status = eHAL_STATUS_SUCCESS;
3299
3300 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
3301 value = value + 15;
3302
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003303 /* Convert the value from ascii to integer */
3304 ret = kstrtos8(value, 10, &rssi);
3305 if (ret < 0)
3306 {
3307 /* If the input value is greater than max value of datatype, then also
3308 kstrtou8 fails */
3309 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3310 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdafa7157d2013-10-31 10:14:22 -07003311 __func__,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003312 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
3313 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
3314 ret = -EINVAL;
3315 goto exit;
3316 }
3317
Srinivas Girigowdade697412013-02-14 16:31:48 -08003318 lookUpThreshold = abs(rssi);
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003319
Srinivas Girigowdade697412013-02-14 16:31:48 -08003320 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
3321 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
3322 {
3323 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3324 "Neighbor lookup threshold value %d is out of range"
3325 " (Min: %d Max: %d)", lookUpThreshold,
3326 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
3327 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
3328 ret = -EINVAL;
3329 goto exit;
3330 }
3331
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303332 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3333 TRACE_CODE_HDD_SETROAMTRIGGER_IOCTL,
3334 pAdapter->sessionId, lookUpThreshold));
Srinivas Girigowdade697412013-02-14 16:31:48 -08003335 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3336 "%s: Received Command to Set Roam trigger"
3337 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
3338
3339 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
3340 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
3341 if (eHAL_STATUS_SUCCESS != status)
3342 {
3343 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3344 "%s: Failed to set roam trigger, try again", __func__);
3345 ret = -EPERM;
3346 goto exit;
3347 }
3348
3349 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
mukul sharmad6e1fdd2014-06-23 19:19:09 +05303350 pHddCtx->cfg_ini->nNeighborReassocRssiThreshold = lookUpThreshold + 5;
Srinivas Girigowdade697412013-02-14 16:31:48 -08003351 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
3352 }
3353 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
3354 {
3355 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
3356 int rssi = (-1) * lookUpThreshold;
3357 char extra[32];
3358 tANI_U8 len = 0;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303359 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3360 TRACE_CODE_HDD_GETROAMTRIGGER_IOCTL,
3361 pAdapter->sessionId, lookUpThreshold));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003362 len = scnprintf(extra, sizeof(extra), "%s %d", command, rssi);
Srinivas Girigowda91719232015-07-13 15:10:10 +05303363 len = VOS_MIN(priv_data.total_len, len + 1);
3364 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdade697412013-02-14 16:31:48 -08003365 {
3366 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3367 "%s: failed to copy data to user buffer", __func__);
3368 ret = -EFAULT;
3369 goto exit;
3370 }
3371 }
3372 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
3373 {
3374 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003375 tANI_U8 roamScanPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003376 tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003377
Srinivas Girigowdade697412013-02-14 16:31:48 -08003378 /* input refresh period is in terms of seconds */
3379 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
3380 value = value + 18;
3381 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003382 ret = kstrtou8(value, 10, &roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08003383 if (ret < 0)
3384 {
3385 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003386 kstrtou8 fails */
Srinivas Girigowdade697412013-02-14 16:31:48 -08003387 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003388 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdade697412013-02-14 16:31:48 -08003389 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07003390 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
3391 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08003392 ret = -EINVAL;
3393 goto exit;
3394 }
3395
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003396 if ((roamScanPeriod < (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000)) ||
3397 (roamScanPeriod > (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000)))
Srinivas Girigowdade697412013-02-14 16:31:48 -08003398 {
3399 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003400 "Roam scan period value %d is out of range"
3401 " (Min: %d Max: %d)", roamScanPeriod,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07003402 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
3403 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08003404 ret = -EINVAL;
3405 goto exit;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303406 }
3407 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3408 TRACE_CODE_HDD_SETROAMSCANPERIOD_IOCTL,
3409 pAdapter->sessionId, roamScanPeriod));
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003410 neighborEmptyScanRefreshPeriod = roamScanPeriod * 1000;
Srinivas Girigowdade697412013-02-14 16:31:48 -08003411
3412 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3413 "%s: Received Command to Set roam scan period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003414 " (Empty Scan refresh period) = %d", __func__, roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08003415
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003416 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod;
3417 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08003418 }
3419 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
3420 {
3421 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
3422 char extra[32];
3423 tANI_U8 len = 0;
3424
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303425 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3426 TRACE_CODE_HDD_GETROAMSCANPERIOD_IOCTL,
3427 pAdapter->sessionId, nEmptyScanRefreshPeriod));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003428 len = scnprintf(extra, sizeof(extra), "%s %d",
3429 "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08003430 /* Returned value is in units of seconds */
Ratnam Rachuria72ba112015-07-17 13:27:03 +05303431 len = VOS_MIN(priv_data.total_len, len + 1);
3432 if (copy_to_user(priv_data.buf, &extra, len)) {
Srinivas Girigowdade697412013-02-14 16:31:48 -08003433 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3434 "%s: failed to copy data to user buffer", __func__);
3435 ret = -EFAULT;
3436 goto exit;
3437 }
3438 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003439 else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0)
3440 {
3441 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003442 tANI_U8 roamScanRefreshPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003443 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003444
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003445 /* input refresh period is in terms of seconds */
3446 /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */
3447 value = value + 25;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003448
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003449 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003450 ret = kstrtou8(value, 10, &roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003451 if (ret < 0)
3452 {
3453 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003454 kstrtou8 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003455 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003456 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003457 __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003458 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
3459 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
3460 ret = -EINVAL;
3461 goto exit;
3462 }
3463
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003464 if ((roamScanRefreshPeriod < (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000)) ||
3465 (roamScanRefreshPeriod > (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000)))
3466 {
3467 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3468 "Neighbor scan results refresh period value %d is out of range"
3469 " (Min: %d Max: %d)", roamScanRefreshPeriod,
3470 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
3471 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
3472 ret = -EINVAL;
3473 goto exit;
3474 }
3475 neighborScanRefreshPeriod = roamScanRefreshPeriod * 1000;
3476
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003477 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3478 "%s: Received Command to Set roam scan refresh period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003479 " (Scan refresh period) = %d", __func__, roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003480
3481 pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod;
3482 sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
3483 }
3484 else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0)
3485 {
3486 tANI_U16 value = sme_getNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
3487 char extra[32];
3488 tANI_U8 len = 0;
3489
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003490 len = scnprintf(extra, sizeof(extra), "%s %d",
3491 "GETROAMSCANREFRESHPERIOD", (value/1000));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003492 /* Returned value is in units of seconds */
Ratnam Rachuri2c9d6702015-07-17 13:25:16 +05303493 len = VOS_MIN(priv_data.total_len, len + 1);
3494 if (copy_to_user(priv_data.buf, &extra, len)) {
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003495 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3496 "%s: failed to copy data to user buffer", __func__);
3497 ret = -EFAULT;
3498 goto exit;
3499 }
3500 }
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07003501#ifdef FEATURE_WLAN_LFR
3502 /* SETROAMMODE */
3503 else if (strncmp(command, "SETROAMMODE", SIZE_OF_SETROAMMODE) == 0)
3504 {
3505 tANI_U8 *value = command;
3506 tANI_BOOLEAN roamMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
3507
3508 /* Move pointer to ahead of SETROAMMODE<delimiter> */
3509 value = value + SIZE_OF_SETROAMMODE + 1;
3510
3511 /* Convert the value from ascii to integer */
3512 ret = kstrtou8(value, SIZE_OF_SETROAMMODE, &roamMode);
3513 if (ret < 0)
3514 {
3515 /* If the input value is greater than max value of datatype, then also
3516 kstrtou8 fails */
3517 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3518 "%s: kstrtou8 failed range [%d - %d]", __func__,
3519 CFG_LFR_FEATURE_ENABLED_MIN,
3520 CFG_LFR_FEATURE_ENABLED_MAX);
3521 ret = -EINVAL;
3522 goto exit;
3523 }
3524 if ((roamMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
3525 (roamMode > CFG_LFR_FEATURE_ENABLED_MAX))
3526 {
3527 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3528 "Roam Mode value %d is out of range"
3529 " (Min: %d Max: %d)", roamMode,
3530 CFG_LFR_FEATURE_ENABLED_MIN,
3531 CFG_LFR_FEATURE_ENABLED_MAX);
3532 ret = -EINVAL;
3533 goto exit;
3534 }
3535
3536 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3537 "%s: Received Command to Set Roam Mode = %d", __func__, roamMode);
3538 /*
3539 * Note that
3540 * SETROAMMODE 0 is to enable LFR while
3541 * SETROAMMODE 1 is to disable LFR, but
3542 * NotifyIsFastRoamIniFeatureEnabled 0/1 is to enable/disable.
3543 * So, we have to invert the value to call sme_UpdateIsFastRoamIniFeatureEnabled.
3544 */
3545 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
3546 roamMode = CFG_LFR_FEATURE_ENABLED_MAX; /* Roam enable */
3547 else
3548 roamMode = CFG_LFR_FEATURE_ENABLED_MIN; /* Roam disable */
3549
3550 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = roamMode;
3551 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), roamMode);
3552 }
3553 /* GETROAMMODE */
Mahesh A Saptasagarec7d1092015-04-02 13:41:34 +05303554 else if (strncmp(command, "GETROAMMODE", SIZE_OF_GETROAMMODE) == 0)
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07003555 {
3556 tANI_BOOLEAN roamMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
3557 char extra[32];
3558 tANI_U8 len = 0;
3559
3560 /*
3561 * roamMode value shall be inverted because the sementics is different.
3562 */
3563 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
3564 roamMode = CFG_LFR_FEATURE_ENABLED_MAX;
3565 else
3566 roamMode = CFG_LFR_FEATURE_ENABLED_MIN;
3567
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003568 len = scnprintf(extra, sizeof(extra), "%s %d", command, roamMode);
Ratnam Rachuri28693eb2015-07-17 13:23:42 +05303569 len = VOS_MIN(priv_data.total_len, len + 1);
3570 if (copy_to_user(priv_data.buf, &extra, len)) {
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07003571 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3572 "%s: failed to copy data to user buffer", __func__);
3573 ret = -EFAULT;
3574 goto exit;
3575 }
3576 }
3577#endif
Srinivas Girigowdade697412013-02-14 16:31:48 -08003578#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003579#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -08003580 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
3581 {
3582 tANI_U8 *value = command;
3583 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
3584
3585 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
3586 value = value + 13;
3587 /* Convert the value from ascii to integer */
3588 ret = kstrtou8(value, 10, &roamRssiDiff);
3589 if (ret < 0)
3590 {
3591 /* If the input value is greater than max value of datatype, then also
3592 kstrtou8 fails */
3593 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3594 "%s: kstrtou8 failed range [%d - %d]", __func__,
3595 CFG_ROAM_RSSI_DIFF_MIN,
3596 CFG_ROAM_RSSI_DIFF_MAX);
3597 ret = -EINVAL;
3598 goto exit;
3599 }
3600
3601 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
3602 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
3603 {
3604 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3605 "Roam rssi diff value %d is out of range"
3606 " (Min: %d Max: %d)", roamRssiDiff,
3607 CFG_ROAM_RSSI_DIFF_MIN,
3608 CFG_ROAM_RSSI_DIFF_MAX);
3609 ret = -EINVAL;
3610 goto exit;
3611 }
3612
3613 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3614 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
3615
3616 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
3617 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
3618 }
Mahesh A Saptasagarec7d1092015-04-02 13:41:34 +05303619 else if (strncmp(command, "GETROAMDELTA", 12) == 0)
Srinivas Girigowdade697412013-02-14 16:31:48 -08003620 {
3621 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
3622 char extra[32];
3623 tANI_U8 len = 0;
3624
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303625 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3626 TRACE_CODE_HDD_GETROAMDELTA_IOCTL,
3627 pAdapter->sessionId, roamRssiDiff));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003628 len = scnprintf(extra, sizeof(extra), "%s %d",
3629 command, roamRssiDiff);
Ratnam Rachuri22a3b402015-07-17 13:21:49 +05303630 len = VOS_MIN(priv_data.total_len, len + 1);
3631 if (copy_to_user(priv_data.buf, &extra, len)) {
Srinivas Girigowdade697412013-02-14 16:31:48 -08003632 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3633 "%s: failed to copy data to user buffer", __func__);
3634 ret = -EFAULT;
3635 goto exit;
3636 }
3637 }
3638#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003639#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -08003640 else if (strncmp(command, "GETBAND", 7) == 0)
3641 {
3642 int band = -1;
3643 char extra[32];
3644 tANI_U8 len = 0;
3645 hdd_getBand_helper(pHddCtx, &band);
3646
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303647 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3648 TRACE_CODE_HDD_GETBAND_IOCTL,
3649 pAdapter->sessionId, band));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003650 len = scnprintf(extra, sizeof(extra), "%s %d", command, band);
Ratnam Rachuri52139592015-07-17 13:17:29 +05303651 len = VOS_MIN(priv_data.total_len, len + 1);
3652 if (copy_to_user(priv_data.buf, &extra, len)) {
Srinivas Girigowdade697412013-02-14 16:31:48 -08003653 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3654 "%s: failed to copy data to user buffer", __func__);
3655 ret = -EFAULT;
3656 goto exit;
3657 }
3658 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08003659 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
3660 {
3661 tANI_U8 *value = command;
3662 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
3663 tANI_U8 numChannels = 0;
3664 eHalStatus status = eHAL_STATUS_SUCCESS;
3665
3666 status = hdd_parse_channellist(value, ChannelList, &numChannels);
3667 if (eHAL_STATUS_SUCCESS != status)
3668 {
3669 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3670 "%s: Failed to parse channel list information", __func__);
3671 ret = -EINVAL;
3672 goto exit;
3673 }
3674
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303675 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3676 TRACE_CODE_HDD_SETROAMSCANCHANNELS_IOCTL,
3677 pAdapter->sessionId, numChannels));
Srinivas Girigowdade697412013-02-14 16:31:48 -08003678 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
3679 {
3680 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3681 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
3682 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
3683 ret = -EINVAL;
3684 goto exit;
3685 }
3686 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
3687 numChannels);
3688 if (eHAL_STATUS_SUCCESS != status)
3689 {
3690 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3691 "%s: Failed to update channel list information", __func__);
3692 ret = -EINVAL;
3693 goto exit;
3694 }
3695 }
3696 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
3697 {
3698 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
3699 tANI_U8 numChannels = 0;
Jeff Johnson51b67782013-04-05 12:35:41 -07003700 tANI_U8 j = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08003701 char extra[128] = {0};
Jeff Johnson51b67782013-04-05 12:35:41 -07003702 int len;
Srinivas Girigowdade697412013-02-14 16:31:48 -08003703
3704 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
3705 ChannelList, &numChannels ))
3706 {
3707 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3708 "%s: failed to get roam scan channel list", __func__);
3709 ret = -EFAULT;
3710 goto exit;
3711 }
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303712 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3713 TRACE_CODE_HDD_GETROAMSCANCHANNELS_IOCTL,
3714 pAdapter->sessionId, numChannels));
Srinivas Girigowdade697412013-02-14 16:31:48 -08003715 /* output channel list is of the format
3716 [Number of roam scan channels][Channel1][Channel2]... */
3717 /* copy the number of channels in the 0th index */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003718 len = scnprintf(extra, sizeof(extra), "%s %d", command, numChannels);
Sushant Kaushika08ca192015-09-16 15:52:04 +05303719 for (j = 0; (j < numChannels) && len <= sizeof(extra); j++)
Srinivas Girigowdade697412013-02-14 16:31:48 -08003720 {
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003721 len += scnprintf(extra + len, sizeof(extra) - len, " %d",
3722 ChannelList[j]);
Srinivas Girigowdade697412013-02-14 16:31:48 -08003723 }
3724
Sushant Kaushikc9b8be52015-07-15 16:41:27 +05303725 len = VOS_MIN(priv_data.total_len, len + 1);
3726 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdade697412013-02-14 16:31:48 -08003727 {
3728 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3729 "%s: failed to copy data to user buffer", __func__);
3730 ret = -EFAULT;
3731 goto exit;
3732 }
3733 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003734 else if (strncmp(command, "GETCCXMODE", 10) == 0)
3735 {
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003736 tANI_BOOLEAN eseMode = sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003737 char extra[32];
3738 tANI_U8 len = 0;
3739
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003740 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003741 then this operation is not permitted (return FAILURE) */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003742 if (eseMode &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003743 hdd_is_okc_mode_enabled(pHddCtx) &&
3744 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
3745 {
3746 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003747 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003748 " hence this operation is not permitted!", __func__);
3749 ret = -EPERM;
3750 goto exit;
3751 }
3752
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003753 len = scnprintf(extra, sizeof(extra), "%s %d",
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003754 "GETCCXMODE", eseMode);
Sushant Kaushikf8abd352015-07-15 16:37:49 +05303755 len = VOS_MIN(priv_data.total_len, len + 1);
3756 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003757 {
3758 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3759 "%s: failed to copy data to user buffer", __func__);
3760 ret = -EFAULT;
3761 goto exit;
3762 }
3763 }
3764 else if (strncmp(command, "GETOKCMODE", 10) == 0)
3765 {
3766 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
3767 char extra[32];
3768 tANI_U8 len = 0;
3769
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003770 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003771 then this operation is not permitted (return FAILURE) */
3772 if (okcMode &&
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003773 sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003774 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
3775 {
3776 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003777 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003778 " hence this operation is not permitted!", __func__);
3779 ret = -EPERM;
3780 goto exit;
3781 }
3782
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003783 len = scnprintf(extra, sizeof(extra), "%s %d",
3784 "GETOKCMODE", okcMode);
Sushant Kaushikbc2fb5c2015-07-15 16:43:16 +05303785 len = VOS_MIN(priv_data.total_len, len + 1);
3786 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003787 {
3788 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3789 "%s: failed to copy data to user buffer", __func__);
3790 ret = -EFAULT;
3791 goto exit;
3792 }
3793 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003794 else if (strncmp(command, "GETFASTROAM", 11) == 0)
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003795 {
3796 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
3797 char extra[32];
3798 tANI_U8 len = 0;
3799
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003800 len = scnprintf(extra, sizeof(extra), "%s %d",
3801 "GETFASTROAM", lfrMode);
Sushant Kaushik4da7ec92015-07-15 16:39:32 +05303802 len = VOS_MIN(priv_data.total_len, len + 1);
3803 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003804 {
3805 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3806 "%s: failed to copy data to user buffer", __func__);
3807 ret = -EFAULT;
3808 goto exit;
3809 }
3810 }
3811 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
3812 {
3813 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
3814 char extra[32];
3815 tANI_U8 len = 0;
3816
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003817 len = scnprintf(extra, sizeof(extra), "%s %d",
3818 "GETFASTTRANSITION", ft);
Sushant Kaushik231a4452015-07-15 16:23:56 +05303819 len = VOS_MIN(priv_data.total_len, len + 1);
3820 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003821 {
3822 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3823 "%s: failed to copy data to user buffer", __func__);
3824 ret = -EFAULT;
3825 goto exit;
3826 }
3827 }
3828 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
3829 {
3830 tANI_U8 *value = command;
3831 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
3832
3833 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
3834 value = value + 26;
3835 /* Convert the value from ascii to integer */
3836 ret = kstrtou8(value, 10, &minTime);
3837 if (ret < 0)
3838 {
3839 /* If the input value is greater than max value of datatype, then also
3840 kstrtou8 fails */
3841 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3842 "%s: kstrtou8 failed range [%d - %d]", __func__,
3843 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
3844 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
3845 ret = -EINVAL;
3846 goto exit;
3847 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003848 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
3849 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
3850 {
3851 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3852 "scan min channel time value %d is out of range"
3853 " (Min: %d Max: %d)", minTime,
3854 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
3855 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
3856 ret = -EINVAL;
3857 goto exit;
3858 }
3859
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303860 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3861 TRACE_CODE_HDD_SETROAMSCANCHANNELMINTIME_IOCTL,
3862 pAdapter->sessionId, minTime));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003863 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3864 "%s: Received Command to change channel min time = %d", __func__, minTime);
3865
3866 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
3867 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
3868 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003869 else if (strncmp(command, "SENDACTIONFRAME", 15) == 0)
3870 {
3871 tANI_U8 *value = command;
3872 tANI_U8 channel = 0;
3873 tANI_U8 dwellTime = 0;
3874 tANI_U8 bufLen = 0;
3875 tANI_U8 *buf = NULL;
3876 tSirMacAddr targetApBssid;
3877 eHalStatus status = eHAL_STATUS_SUCCESS;
3878 struct ieee80211_channel chan;
3879 tANI_U8 finalLen = 0;
3880 tANI_U8 *finalBuf = NULL;
3881 tANI_U8 temp = 0;
3882 u64 cookie;
3883 hdd_station_ctx_t *pHddStaCtx = NULL;
3884 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3885
3886 /* if not associated, no need to send action frame */
3887 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3888 {
3889 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
3890 ret = -EINVAL;
3891 goto exit;
3892 }
3893
3894 status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel,
3895 &dwellTime, &buf, &bufLen);
3896 if (eHAL_STATUS_SUCCESS != status)
3897 {
3898 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3899 "%s: Failed to parse send action frame data", __func__);
3900 ret = -EINVAL;
3901 goto exit;
3902 }
3903
3904 /* if the target bssid is different from currently associated AP,
3905 then no need to send action frame */
3906 if (VOS_TRUE != vos_mem_compare(targetApBssid,
3907 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
3908 {
3909 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__);
3910 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07003911 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08003912 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003913 goto exit;
3914 }
3915
3916 /* if the channel number is different from operating channel then
3917 no need to send action frame */
3918 if (channel != pHddStaCtx->conn_info.operationChannel)
3919 {
3920 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3921 "%s: channel(%d) is different from operating channel(%d)",
3922 __func__, channel, pHddStaCtx->conn_info.operationChannel);
3923 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07003924 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08003925 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003926 goto exit;
3927 }
3928 chan.center_freq = sme_ChnToFreq(channel);
3929
3930 finalLen = bufLen + 24;
3931 finalBuf = vos_mem_malloc(finalLen);
3932 if (NULL == finalBuf)
3933 {
3934 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__);
3935 ret = -ENOMEM;
Jeff Johnson11c33152013-04-16 17:52:40 -07003936 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08003937 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003938 goto exit;
3939 }
3940 vos_mem_zero(finalBuf, finalLen);
3941
3942 /* Fill subtype */
3943 temp = SIR_MAC_MGMT_ACTION << 4;
3944 vos_mem_copy(finalBuf + 0, &temp, sizeof(temp));
3945
3946 /* Fill type */
3947 temp = SIR_MAC_MGMT_FRAME;
3948 vos_mem_copy(finalBuf + 2, &temp, sizeof(temp));
3949
3950 /* Fill destination address (bssid of the AP) */
3951 vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid));
3952
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07003953 /* Fill source address (STA mac address) */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003954 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
3955
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07003956 /* Fill BSSID (AP mac address) */
3957 vos_mem_copy(finalBuf + 16, targetApBssid, sizeof(targetApBssid));
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003958
3959 /* Fill received buffer from 24th address */
3960 vos_mem_copy(finalBuf + 24, buf, bufLen);
3961
Jeff Johnson11c33152013-04-16 17:52:40 -07003962 /* done with the parsed buffer */
3963 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08003964 buf = NULL;
Jeff Johnson11c33152013-04-16 17:52:40 -07003965
Anand N Sunkade9adb1b2015-07-29 09:56:45 +05303966#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0))
3967 params.chan = &chan;
3968 params.offchan = 0;
3969 params.wait = dwellTime;
3970 params.buf = finalBuf;
3971 params.len = finalLen;
3972 params.no_cck = 1;
3973 params.dont_wait_for_ack = 1;
3974 ret = wlan_hdd_mgmt_tx(NULL, &pAdapter->wdev, &params, &cookie);
3975#else
DARAM SUDHA39eede62014-02-12 11:16:40 +05303976 wlan_hdd_mgmt_tx( NULL,
Yue Maf49ba872013-08-19 12:04:25 -07003977#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
3978 &(pAdapter->wdev),
3979#else
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003980 pAdapter->dev,
Yue Maf49ba872013-08-19 12:04:25 -07003981#endif
3982 &chan, 0,
3983#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
3984 NL80211_CHAN_HT20, 1,
3985#endif
3986 dwellTime, finalBuf, finalLen, 1,
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003987 1, &cookie );
Anand N Sunkade9adb1b2015-07-29 09:56:45 +05303988#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0)*/
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003989 vos_mem_free(finalBuf);
3990 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003991 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
3992 {
3993 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
3994 char extra[32];
3995 tANI_U8 len = 0;
3996
3997 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003998 len = scnprintf(extra, sizeof(extra), "%s %d",
3999 "GETROAMSCANCHANNELMINTIME", val);
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05304000 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
4001 TRACE_CODE_HDD_GETROAMSCANCHANNELMINTIME_IOCTL,
4002 pAdapter->sessionId, val));
Sushant Kaushikbb8c52c2015-07-15 16:36:23 +05304003 len = VOS_MIN(priv_data.total_len, len + 1);
4004 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004005 {
4006 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4007 "%s: failed to copy data to user buffer", __func__);
4008 ret = -EFAULT;
4009 goto exit;
4010 }
4011 }
4012 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
4013 {
4014 tANI_U8 *value = command;
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07004015 tANI_U16 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004016
4017 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
4018 value = value + 19;
4019 /* Convert the value from ascii to integer */
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07004020 ret = kstrtou16(value, 10, &maxTime);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004021 if (ret < 0)
4022 {
4023 /* If the input value is greater than max value of datatype, then also
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07004024 kstrtou16 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004025 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07004026 "%s: kstrtou16 failed range [%d - %d]", __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004027 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
4028 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
4029 ret = -EINVAL;
4030 goto exit;
4031 }
4032
4033 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
4034 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
4035 {
4036 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4037 "lfr mode value %d is out of range"
4038 " (Min: %d Max: %d)", maxTime,
4039 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
4040 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
4041 ret = -EINVAL;
4042 goto exit;
4043 }
4044
4045 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4046 "%s: Received Command to change channel max time = %d", __func__, maxTime);
4047
4048 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
4049 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
4050 }
4051 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
4052 {
4053 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
4054 char extra[32];
4055 tANI_U8 len = 0;
4056
4057 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004058 len = scnprintf(extra, sizeof(extra), "%s %d",
4059 "GETSCANCHANNELTIME", val);
Ratheesh S Pacbfa932015-07-16 15:27:18 +05304060 len = VOS_MIN(priv_data.total_len, len + 1);
4061 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004062 {
4063 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4064 "%s: failed to copy data to user buffer", __func__);
4065 ret = -EFAULT;
4066 goto exit;
4067 }
4068 }
4069 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
4070 {
4071 tANI_U8 *value = command;
4072 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
4073
4074 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
4075 value = value + 16;
4076 /* Convert the value from ascii to integer */
4077 ret = kstrtou16(value, 10, &val);
4078 if (ret < 0)
4079 {
4080 /* If the input value is greater than max value of datatype, then also
4081 kstrtou16 fails */
4082 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4083 "%s: kstrtou16 failed range [%d - %d]", __func__,
4084 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
4085 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
4086 ret = -EINVAL;
4087 goto exit;
4088 }
4089
4090 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
4091 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
4092 {
4093 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4094 "scan home time value %d is out of range"
4095 " (Min: %d Max: %d)", val,
4096 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
4097 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
4098 ret = -EINVAL;
4099 goto exit;
4100 }
4101
4102 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4103 "%s: Received Command to change scan home time = %d", __func__, val);
4104
4105 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
4106 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
4107 }
4108 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
4109 {
4110 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
4111 char extra[32];
4112 tANI_U8 len = 0;
4113
4114 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004115 len = scnprintf(extra, sizeof(extra), "%s %d",
4116 "GETSCANHOMETIME", val);
Ratheesh S P728d7c62015-07-16 15:38:58 +05304117 len = VOS_MIN(priv_data.total_len, len + 1);
4118 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004119 {
4120 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4121 "%s: failed to copy data to user buffer", __func__);
4122 ret = -EFAULT;
4123 goto exit;
4124 }
4125 }
4126 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
4127 {
4128 tANI_U8 *value = command;
4129 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
4130
4131 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
4132 value = value + 17;
4133 /* Convert the value from ascii to integer */
4134 ret = kstrtou8(value, 10, &val);
4135 if (ret < 0)
4136 {
4137 /* If the input value is greater than max value of datatype, then also
4138 kstrtou8 fails */
4139 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4140 "%s: kstrtou8 failed range [%d - %d]", __func__,
4141 CFG_ROAM_INTRA_BAND_MIN,
4142 CFG_ROAM_INTRA_BAND_MAX);
4143 ret = -EINVAL;
4144 goto exit;
4145 }
4146
4147 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
4148 (val > CFG_ROAM_INTRA_BAND_MAX))
4149 {
4150 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4151 "intra band mode value %d is out of range"
4152 " (Min: %d Max: %d)", val,
4153 CFG_ROAM_INTRA_BAND_MIN,
4154 CFG_ROAM_INTRA_BAND_MAX);
4155 ret = -EINVAL;
4156 goto exit;
4157 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004158 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4159 "%s: Received Command to change intra band = %d", __func__, val);
4160
4161 pHddCtx->cfg_ini->nRoamIntraBand = val;
4162 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
4163 }
4164 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
4165 {
4166 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
4167 char extra[32];
4168 tANI_U8 len = 0;
4169
4170 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004171 len = scnprintf(extra, sizeof(extra), "%s %d",
4172 "GETROAMINTRABAND", val);
Ratheesh S P2dd2a3e2015-07-16 15:34:23 +05304173 len = VOS_MIN(priv_data.total_len, len + 1);
4174 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004175 {
4176 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4177 "%s: failed to copy data to user buffer", __func__);
4178 ret = -EFAULT;
4179 goto exit;
4180 }
4181 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004182 else if (strncmp(command, "SETSCANNPROBES", 14) == 0)
4183 {
4184 tANI_U8 *value = command;
4185 tANI_U8 nProbes = CFG_ROAM_SCAN_N_PROBES_DEFAULT;
4186
4187 /* Move pointer to ahead of SETSCANNPROBES<delimiter> */
4188 value = value + 15;
4189 /* Convert the value from ascii to integer */
4190 ret = kstrtou8(value, 10, &nProbes);
4191 if (ret < 0)
4192 {
4193 /* If the input value is greater than max value of datatype, then also
4194 kstrtou8 fails */
4195 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4196 "%s: kstrtou8 failed range [%d - %d]", __func__,
4197 CFG_ROAM_SCAN_N_PROBES_MIN,
4198 CFG_ROAM_SCAN_N_PROBES_MAX);
4199 ret = -EINVAL;
4200 goto exit;
4201 }
4202
4203 if ((nProbes < CFG_ROAM_SCAN_N_PROBES_MIN) ||
4204 (nProbes > CFG_ROAM_SCAN_N_PROBES_MAX))
4205 {
4206 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4207 "NProbes value %d is out of range"
4208 " (Min: %d Max: %d)", nProbes,
4209 CFG_ROAM_SCAN_N_PROBES_MIN,
4210 CFG_ROAM_SCAN_N_PROBES_MAX);
4211 ret = -EINVAL;
4212 goto exit;
4213 }
4214
4215 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4216 "%s: Received Command to Set nProbes = %d", __func__, nProbes);
4217
4218 pHddCtx->cfg_ini->nProbes = nProbes;
4219 sme_UpdateRoamScanNProbes((tHalHandle)(pHddCtx->hHal), nProbes);
4220 }
Mahesh A Saptasagarec7d1092015-04-02 13:41:34 +05304221 else if (strncmp(command, "GETSCANNPROBES", 14) == 0)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004222 {
4223 tANI_U8 val = sme_getRoamScanNProbes((tHalHandle)(pHddCtx->hHal));
4224 char extra[32];
4225 tANI_U8 len = 0;
4226
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004227 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Ratnam Rachuri6da525d2015-08-07 13:55:54 +05304228 len = VOS_MIN(priv_data.total_len, len + 1);
4229 if (copy_to_user(priv_data.buf, &extra, len)) {
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004230 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4231 "%s: failed to copy data to user buffer", __func__);
4232 ret = -EFAULT;
4233 goto exit;
4234 }
4235 }
4236 else if (strncmp(command, "SETSCANHOMEAWAYTIME", 19) == 0)
4237 {
4238 tANI_U8 *value = command;
4239 tANI_U16 homeAwayTime = CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT;
4240
4241 /* Move pointer to ahead of SETSCANHOMEAWAYTIME<delimiter> */
4242 /* input value is in units of msec */
4243 value = value + 20;
4244 /* Convert the value from ascii to integer */
4245 ret = kstrtou16(value, 10, &homeAwayTime);
4246 if (ret < 0)
4247 {
4248 /* If the input value is greater than max value of datatype, then also
4249 kstrtou8 fails */
4250 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4251 "%s: kstrtou8 failed range [%d - %d]", __func__,
4252 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
4253 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
4254 ret = -EINVAL;
4255 goto exit;
4256 }
4257
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004258 if ((homeAwayTime < CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN) ||
4259 (homeAwayTime > CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX))
4260 {
4261 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4262 "homeAwayTime value %d is out of range"
4263 " (Min: %d Max: %d)", homeAwayTime,
4264 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
4265 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
4266 ret = -EINVAL;
4267 goto exit;
4268 }
4269
4270 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4271 "%s: Received Command to Set scan away time = %d", __func__, homeAwayTime);
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07004272 if (pHddCtx->cfg_ini->nRoamScanHomeAwayTime != homeAwayTime)
4273 {
4274 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
4275 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_TRUE);
4276 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004277 }
Mahesh A Saptasagarec7d1092015-04-02 13:41:34 +05304278 else if (strncmp(command, "GETSCANHOMEAWAYTIME", 19) == 0)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004279 {
4280 tANI_U16 val = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
4281 char extra[32];
4282 tANI_U8 len = 0;
4283
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004284 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Ratnam Rachuri51a5ad12015-08-07 14:06:37 +05304285 len = VOS_MIN(priv_data.total_len, len + 1);
4286 if (copy_to_user(priv_data.buf, &extra, len)) {
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004287 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4288 "%s: failed to copy data to user buffer", __func__);
4289 ret = -EFAULT;
4290 goto exit;
4291 }
4292 }
4293 else if (strncmp(command, "REASSOC", 7) == 0)
4294 {
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05304295 ret = hdd_parse_reassoc(pAdapter, command);
4296 if (!ret)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004297 goto exit;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004298 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07004299 else if (strncmp(command, "SETWESMODE", 10) == 0)
4300 {
4301 tANI_U8 *value = command;
4302 tANI_BOOLEAN wesMode = CFG_ENABLE_WES_MODE_NAME_DEFAULT;
4303
4304 /* Move pointer to ahead of SETWESMODE<delimiter> */
4305 value = value + 11;
4306 /* Convert the value from ascii to integer */
4307 ret = kstrtou8(value, 10, &wesMode);
4308 if (ret < 0)
4309 {
4310 /* If the input value is greater than max value of datatype, then also
4311 kstrtou8 fails */
4312 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4313 "%s: kstrtou8 failed range [%d - %d]", __func__,
4314 CFG_ENABLE_WES_MODE_NAME_MIN,
4315 CFG_ENABLE_WES_MODE_NAME_MAX);
4316 ret = -EINVAL;
4317 goto exit;
4318 }
4319
4320 if ((wesMode < CFG_ENABLE_WES_MODE_NAME_MIN) ||
4321 (wesMode > CFG_ENABLE_WES_MODE_NAME_MAX))
4322 {
4323 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4324 "WES Mode value %d is out of range"
4325 " (Min: %d Max: %d)", wesMode,
4326 CFG_ENABLE_WES_MODE_NAME_MIN,
4327 CFG_ENABLE_WES_MODE_NAME_MAX);
4328 ret = -EINVAL;
4329 goto exit;
4330 }
4331 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4332 "%s: Received Command to Set WES Mode rssi diff = %d", __func__, wesMode);
4333
4334 pHddCtx->cfg_ini->isWESModeEnabled = wesMode;
4335 sme_UpdateWESMode((tHalHandle)(pHddCtx->hHal), wesMode);
4336 }
Mahesh A Saptasagarec7d1092015-04-02 13:41:34 +05304337 else if (strncmp(command, "GETWESMODE", 10) == 0)
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07004338 {
4339 tANI_BOOLEAN wesMode = sme_GetWESMode((tHalHandle)(pHddCtx->hHal));
4340 char extra[32];
4341 tANI_U8 len = 0;
4342
Arif Hussain826d9412013-11-12 16:44:54 -08004343 len = scnprintf(extra, sizeof(extra), "%s %d", command, wesMode);
Ratnam Rachuri8fe90c62015-08-07 14:03:26 +05304344 len = VOS_MIN(priv_data.total_len, len + 1);
4345 if (copy_to_user(priv_data.buf, &extra, len)) {
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07004346 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4347 "%s: failed to copy data to user buffer", __func__);
4348 ret = -EFAULT;
4349 goto exit;
4350 }
4351 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004352#endif /* WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_ESE || FEATURE_WLAN_LFR */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004353#ifdef FEATURE_WLAN_LFR
4354 else if (strncmp(command, "SETFASTROAM", 11) == 0)
4355 {
4356 tANI_U8 *value = command;
4357 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
4358
4359 /* Move pointer to ahead of SETFASTROAM<delimiter> */
4360 value = value + 12;
4361 /* Convert the value from ascii to integer */
4362 ret = kstrtou8(value, 10, &lfrMode);
4363 if (ret < 0)
4364 {
4365 /* If the input value is greater than max value of datatype, then also
4366 kstrtou8 fails */
4367 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4368 "%s: kstrtou8 failed range [%d - %d]", __func__,
4369 CFG_LFR_FEATURE_ENABLED_MIN,
4370 CFG_LFR_FEATURE_ENABLED_MAX);
4371 ret = -EINVAL;
4372 goto exit;
4373 }
4374
4375 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
4376 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
4377 {
4378 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4379 "lfr mode value %d is out of range"
4380 " (Min: %d Max: %d)", lfrMode,
4381 CFG_LFR_FEATURE_ENABLED_MIN,
4382 CFG_LFR_FEATURE_ENABLED_MAX);
4383 ret = -EINVAL;
4384 goto exit;
4385 }
4386
4387 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4388 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
4389
4390 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
4391 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
4392 }
4393#endif
4394#ifdef WLAN_FEATURE_VOWIFI_11R
4395 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
4396 {
4397 tANI_U8 *value = command;
4398 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
4399
4400 /* Move pointer to ahead of SETFASTROAM<delimiter> */
4401 value = value + 18;
4402 /* Convert the value from ascii to integer */
4403 ret = kstrtou8(value, 10, &ft);
4404 if (ret < 0)
4405 {
4406 /* If the input value is greater than max value of datatype, then also
4407 kstrtou8 fails */
4408 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4409 "%s: kstrtou8 failed range [%d - %d]", __func__,
4410 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
4411 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
4412 ret = -EINVAL;
4413 goto exit;
4414 }
4415
4416 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
4417 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
4418 {
4419 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4420 "ft mode value %d is out of range"
4421 " (Min: %d Max: %d)", ft,
4422 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
4423 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
4424 ret = -EINVAL;
4425 goto exit;
4426 }
4427
4428 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4429 "%s: Received Command to change ft mode = %d", __func__, ft);
4430
4431 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
4432 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
4433 }
Padma, Santhosh Kumar778d8382015-03-04 17:41:22 +05304434 else if (strncmp(command, "SETDFSSCANMODE", 14) == 0)
4435 {
4436 tANI_U8 *value = command;
4437 tANI_U8 dfsScanMode = DFS_CHNL_SCAN_ENABLED_NORMAL;
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05304438
Padma, Santhosh Kumar778d8382015-03-04 17:41:22 +05304439 /* Move pointer to ahead of SETDFSSCANMODE<delimiter> */
4440 value = value + 15;
4441 /* Convert the value from ascii to integer */
4442 ret = kstrtou8(value, 10, &dfsScanMode);
4443 if (ret < 0)
4444 {
4445 /* If the input value is greater than max value of
4446 datatype, then also kstrtou8 fails
4447 */
4448 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4449 "%s: kstrtou8 failed range [%d - %d]", __func__,
4450 CFG_ENABLE_DFS_CHNL_SCAN_MIN,
4451 CFG_ENABLE_DFS_CHNL_SCAN_MAX);
4452 ret = -EINVAL;
4453 goto exit;
4454 }
4455
4456 if ((dfsScanMode < CFG_ENABLE_DFS_CHNL_SCAN_MIN) ||
4457 (dfsScanMode > CFG_ENABLE_DFS_CHNL_SCAN_MAX))
4458 {
4459 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4460 "dfsScanMode value %d is out of range"
4461 " (Min: %d Max: %d)", dfsScanMode,
4462 CFG_ENABLE_DFS_CHNL_SCAN_MIN,
4463 CFG_ENABLE_DFS_CHNL_SCAN_MAX);
4464 ret = -EINVAL;
4465 goto exit;
4466 }
4467 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4468 "%s: Received Command to Set DFS Scan Mode = %d",
4469 __func__, dfsScanMode);
4470
4471 ret = wlan_hdd_handle_dfs_chan_scan(pHddCtx, dfsScanMode);
4472 }
4473 else if (strncmp(command, "GETDFSSCANMODE", 14) == 0)
4474 {
4475 tANI_U8 dfsScanMode = sme_GetDFSScanMode(pHddCtx->hHal);
4476 char extra[32];
4477 tANI_U8 len = 0;
4478
4479 len = scnprintf(extra, sizeof(extra), "%s %d", command, dfsScanMode);
Ratheesh S P767224e2015-07-16 15:35:51 +05304480 len = VOS_MIN(priv_data.total_len, len + 1);
4481 if (copy_to_user(priv_data.buf, &extra, len))
Padma, Santhosh Kumar778d8382015-03-04 17:41:22 +05304482 {
4483 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4484 "%s: failed to copy data to user buffer", __func__);
4485 ret = -EFAULT;
4486 goto exit;
4487 }
4488 }
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05304489 else if (strncmp(command, "FASTREASSOC", 11) == 0)
4490 {
Selvaraj, Sridhar3714c4d2016-06-22 15:19:12 +05304491 ret = wlan_hdd_handle_fastreassoc(pAdapter, command);
4492 if (!ret)
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05304493 goto exit;
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05304494 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004495#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004496#ifdef FEATURE_WLAN_ESE
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004497 else if (strncmp(command, "SETCCXMODE", 10) == 0)
4498 {
4499 tANI_U8 *value = command;
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004500 tANI_U8 eseMode = CFG_ESE_FEATURE_ENABLED_DEFAULT;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004501
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004502 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07004503 then this operation is not permitted (return FAILURE) */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004504 if (sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07004505 hdd_is_okc_mode_enabled(pHddCtx) &&
4506 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
4507 {
4508 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004509 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07004510 " hence this operation is not permitted!", __func__);
4511 ret = -EPERM;
4512 goto exit;
4513 }
4514
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004515 /* Move pointer to ahead of SETCCXMODE<delimiter> */
4516 value = value + 11;
4517 /* Convert the value from ascii to integer */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004518 ret = kstrtou8(value, 10, &eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004519 if (ret < 0)
4520 {
4521 /* If the input value is greater than max value of datatype, then also
4522 kstrtou8 fails */
4523 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4524 "%s: kstrtou8 failed range [%d - %d]", __func__,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004525 CFG_ESE_FEATURE_ENABLED_MIN,
4526 CFG_ESE_FEATURE_ENABLED_MAX);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004527 ret = -EINVAL;
4528 goto exit;
4529 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004530 if ((eseMode < CFG_ESE_FEATURE_ENABLED_MIN) ||
4531 (eseMode > CFG_ESE_FEATURE_ENABLED_MAX))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004532 {
4533 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004534 "Ese mode value %d is out of range"
4535 " (Min: %d Max: %d)", eseMode,
4536 CFG_ESE_FEATURE_ENABLED_MIN,
4537 CFG_ESE_FEATURE_ENABLED_MAX);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004538 ret = -EINVAL;
4539 goto exit;
4540 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004541 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004542 "%s: Received Command to change ese mode = %d", __func__, eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004543
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004544 pHddCtx->cfg_ini->isEseIniFeatureEnabled = eseMode;
4545 sme_UpdateIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal), eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004546 }
4547#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004548 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
4549 {
4550 tANI_U8 *value = command;
4551 tANI_BOOLEAN roamScanControl = 0;
4552
4553 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
4554 value = value + 19;
4555 /* Convert the value from ascii to integer */
4556 ret = kstrtou8(value, 10, &roamScanControl);
4557 if (ret < 0)
4558 {
4559 /* If the input value is greater than max value of datatype, then also
4560 kstrtou8 fails */
4561 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4562 "%s: kstrtou8 failed ", __func__);
4563 ret = -EINVAL;
4564 goto exit;
4565 }
4566
4567 if (0 != roamScanControl)
4568 {
4569 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4570 "roam scan control invalid value = %d",
4571 roamScanControl);
4572 ret = -EINVAL;
4573 goto exit;
4574 }
4575 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4576 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
4577
4578 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
4579 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004580#ifdef FEATURE_WLAN_OKC
4581 else if (strncmp(command, "SETOKCMODE", 10) == 0)
4582 {
4583 tANI_U8 *value = command;
4584 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
4585
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004586 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07004587 then this operation is not permitted (return FAILURE) */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004588 if (sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07004589 hdd_is_okc_mode_enabled(pHddCtx) &&
4590 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
4591 {
4592 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004593 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07004594 " hence this operation is not permitted!", __func__);
4595 ret = -EPERM;
4596 goto exit;
4597 }
4598
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004599 /* Move pointer to ahead of SETOKCMODE<delimiter> */
4600 value = value + 11;
4601 /* Convert the value from ascii to integer */
4602 ret = kstrtou8(value, 10, &okcMode);
4603 if (ret < 0)
4604 {
4605 /* If the input value is greater than max value of datatype, then also
4606 kstrtou8 fails */
4607 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4608 "%s: kstrtou8 failed range [%d - %d]", __func__,
4609 CFG_OKC_FEATURE_ENABLED_MIN,
4610 CFG_OKC_FEATURE_ENABLED_MAX);
4611 ret = -EINVAL;
4612 goto exit;
4613 }
4614
4615 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
4616 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
4617 {
4618 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4619 "Okc mode value %d is out of range"
4620 " (Min: %d Max: %d)", okcMode,
4621 CFG_OKC_FEATURE_ENABLED_MIN,
4622 CFG_OKC_FEATURE_ENABLED_MAX);
4623 ret = -EINVAL;
4624 goto exit;
4625 }
4626
4627 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4628 "%s: Received Command to change okc mode = %d", __func__, okcMode);
4629
4630 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
4631 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07004632#endif /* FEATURE_WLAN_OKC */
Mahesh A Saptasagarec7d1092015-04-02 13:41:34 +05304633 else if (strncmp(command, "GETROAMSCANCONTROL", 18) == 0)
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004634 {
4635 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
4636 char extra[32];
4637 tANI_U8 len = 0;
4638
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004639 len = scnprintf(extra, sizeof(extra), "%s %d",
4640 command, roamScanControl);
Ratnam Rachuri083ada82015-08-07 14:01:05 +05304641 len = VOS_MIN(priv_data.total_len, len + 1);
4642 if (copy_to_user(priv_data.buf, &extra, len)) {
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004643 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4644 "%s: failed to copy data to user buffer", __func__);
4645 ret = -EFAULT;
4646 goto exit;
4647 }
4648 }
Gopichand Nakkala227c7f32013-06-26 22:44:57 +05304649#ifdef WLAN_FEATURE_PACKET_FILTERING
4650 else if (strncmp(command, "ENABLE_PKTFILTER_IPV6", 21) == 0)
4651 {
4652 tANI_U8 filterType = 0;
4653 tANI_U8 *value = command;
4654
4655 /* Move pointer to ahead of ENABLE_PKTFILTER_IPV6<delimiter> */
4656 value = value + 22;
4657
4658 /* Convert the value from ascii to integer */
4659 ret = kstrtou8(value, 10, &filterType);
4660 if (ret < 0)
4661 {
4662 /* If the input value is greater than max value of datatype,
4663 * then also kstrtou8 fails
4664 */
4665 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4666 "%s: kstrtou8 failed range ", __func__);
4667 ret = -EINVAL;
4668 goto exit;
4669 }
4670
4671 if (filterType != 0 && filterType != 1)
4672 {
4673 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4674 "%s: Accepted Values are 0 and 1 ", __func__);
4675 ret = -EINVAL;
4676 goto exit;
4677 }
4678 wlan_hdd_setIPv6Filter(WLAN_HDD_GET_CTX(pAdapter), filterType,
4679 pAdapter->sessionId);
4680 }
4681#endif
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05304682 else if (strncmp(command, "BTCOEXMODE", 10) == 0 )
4683 {
Kiet Lamad161252014-07-22 11:23:32 -07004684 char *dhcpPhase;
Satyanarayana Dash1faea4f2014-09-22 16:21:04 +05304685 int ret;
4686
Kiet Lamad161252014-07-22 11:23:32 -07004687 dhcpPhase = command + 11;
4688 if ('1' == *dhcpPhase)
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05304689 {
Deepthi Gowribfd17132014-11-14 17:59:04 +05304690 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Kiet Lamad161252014-07-22 11:23:32 -07004691 FL("send DHCP START indication"));
c_hpothu9b781ba2013-12-30 20:57:45 +05304692
4693 pHddCtx->btCoexModeSet = TRUE;
Kiet Lamad161252014-07-22 11:23:32 -07004694
Satyanarayana Dash1faea4f2014-09-22 16:21:04 +05304695 ret = wlan_hdd_scan_abort(pAdapter);
4696 if (ret < 0)
4697 {
4698 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4699 FL("failed to abort existing scan %d"), ret);
4700 }
4701
Kiet Lamad161252014-07-22 11:23:32 -07004702 sme_DHCPStartInd(pHddCtx->hHal, pAdapter->device_mode,
4703 pAdapter->sessionId);
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05304704 }
Kiet Lamad161252014-07-22 11:23:32 -07004705 else if ('2' == *dhcpPhase)
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05304706 {
Deepthi Gowribfd17132014-11-14 17:59:04 +05304707 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Kiet Lamad161252014-07-22 11:23:32 -07004708 FL("send DHCP STOP indication"));
c_hpothu9b781ba2013-12-30 20:57:45 +05304709
4710 pHddCtx->btCoexModeSet = FALSE;
Kiet Lamad161252014-07-22 11:23:32 -07004711
4712 sme_DHCPStopInd(pHddCtx->hHal, pAdapter->device_mode,
4713 pAdapter->sessionId);
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05304714 }
4715 }
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07004716 else if (strncmp(command, "SCAN-ACTIVE", 11) == 0)
4717 {
Abhishek Singh58749d62016-02-03 15:27:20 +05304718 hddLog(LOG1,
4719 FL("making default scan to ACTIVE"));
c_hpothudbefd3e2014-04-28 15:59:47 +05304720 pHddCtx->scan_info.scan_mode = eSIR_ACTIVE_SCAN;
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07004721 }
4722 else if (strncmp(command, "SCAN-PASSIVE", 12) == 0)
4723 {
Abhishek Singh58749d62016-02-03 15:27:20 +05304724 hddLog(LOG1,
4725 FL("making default scan to PASSIVE"));
c_hpothudbefd3e2014-04-28 15:59:47 +05304726 pHddCtx->scan_info.scan_mode = eSIR_PASSIVE_SCAN;
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07004727 }
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05304728 else if (strncmp(command, "GETDWELLTIME", 12) == 0)
4729 {
4730 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
4731 char extra[32];
4732 tANI_U8 len = 0;
4733
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05304734 memset(extra, 0, sizeof(extra));
4735 ret = hdd_get_dwell_time(pCfg, command, extra, sizeof(extra), &len);
Ratnam Rachuri12d5d462015-08-07 14:10:23 +05304736 len = VOS_MIN(priv_data.total_len, len + 1);
4737 if (ret != 0 || copy_to_user(priv_data.buf, &extra, len)) {
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05304738 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4739 "%s: failed to copy data to user buffer", __func__);
4740 ret = -EFAULT;
4741 goto exit;
4742 }
4743 ret = len;
4744 }
4745 else if (strncmp(command, "SETDWELLTIME", 12) == 0)
4746 {
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05304747 ret = hdd_set_dwell_time(pAdapter, command);
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05304748 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07004749 else if ( strncasecmp(command, "MIRACAST", 8) == 0 )
4750 {
4751 tANI_U8 filterType = 0;
4752 tANI_U8 *value;
4753 value = command + 9;
4754
4755 /* Convert the value from ascii to integer */
4756 ret = kstrtou8(value, 10, &filterType);
4757 if (ret < 0)
4758 {
4759 /* If the input value is greater than max value of datatype,
4760 * then also kstrtou8 fails
4761 */
4762 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4763 "%s: kstrtou8 failed range ", __func__);
4764 ret = -EINVAL;
4765 goto exit;
4766 }
4767 if ((filterType < WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL ) ||
4768 (filterType > WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL))
4769 {
4770 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4771 "%s: Accepted Values are 0 to 2. 0-Disabled, 1-Source,"
4772 " 2-Sink ", __func__);
4773 ret = -EINVAL;
4774 goto exit;
4775 }
4776 //Filtertype value should be either 0-Disabled, 1-Source, 2-sink
4777 pHddCtx->drvr_miracast = filterType;
Kaushik, Sushant96122442014-10-21 16:40:18 +05304778 pScanInfo = &pHddCtx->scan_info;
4779 if (filterType && pScanInfo != NULL &&
4780 pHddCtx->scan_info.mScanPending)
4781 {
4782 /*Miracast Session started. Abort Scan */
4783 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4784 "%s, Aborting Scan For Miracast",__func__);
4785 hdd_abort_mac_scan(pHddCtx, pScanInfo->sessionId,
4786 eCSR_SCAN_ABORT_DEFAULT);
4787 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07004788 hdd_tx_rx_pkt_cnt_stat_timer_handler(pHddCtx);
Ganesh Kondabattini8f6e3b32014-08-25 16:07:54 +05304789 sme_SetMiracastMode(pHddCtx->hHal, pHddCtx->drvr_miracast);
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07004790 }
Leo Chang614d2072013-08-22 14:59:44 -07004791 else if (strncmp(command, "SETMCRATE", 9) == 0)
4792 {
Leo Chang614d2072013-08-22 14:59:44 -07004793 tANI_U8 *value = command;
4794 int targetRate;
Leo Chang1f98cbd2013-10-17 15:03:52 -07004795 tSirRateUpdateInd *rateUpdate;
4796 eHalStatus status;
Leo Chang614d2072013-08-22 14:59:44 -07004797
4798 /* Only valid for SAP mode */
4799 if (WLAN_HDD_SOFTAP != pAdapter->device_mode)
4800 {
4801 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4802 "%s: SAP mode is not running", __func__);
4803 ret = -EFAULT;
4804 goto exit;
4805 }
4806
4807 /* Move pointer to ahead of SETMCRATE<delimiter> */
4808 /* input value is in units of hundred kbps */
4809 value = value + 10;
4810 /* Convert the value from ascii to integer, decimal base */
4811 ret = kstrtouint(value, 10, &targetRate);
4812
Leo Chang1f98cbd2013-10-17 15:03:52 -07004813 rateUpdate = (tSirRateUpdateInd *)vos_mem_malloc(sizeof(tSirRateUpdateInd));
4814 if (NULL == rateUpdate)
Leo Chang614d2072013-08-22 14:59:44 -07004815 {
Leo Chang1f98cbd2013-10-17 15:03:52 -07004816 hddLog(VOS_TRACE_LEVEL_ERROR,
4817 "%s: SETMCRATE indication alloc fail", __func__);
4818 ret = -EFAULT;
4819 goto exit;
4820 }
4821 vos_mem_zero(rateUpdate, sizeof(tSirRateUpdateInd ));
4822
4823 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4824 "MC Target rate %d", targetRate);
4825 /* Ignore unicast */
4826 rateUpdate->ucastDataRate = -1;
4827 rateUpdate->mcastDataRate24GHz = targetRate;
4828 rateUpdate->mcastDataRate5GHz = targetRate;
4829 rateUpdate->mcastDataRate24GHzTxFlag = 0;
4830 rateUpdate->mcastDataRate5GHzTxFlag = 0;
4831 status = sme_SendRateUpdateInd(pHddCtx->hHal, rateUpdate);
4832 if (eHAL_STATUS_SUCCESS != status)
4833 {
4834 hddLog(VOS_TRACE_LEVEL_ERROR,
4835 "%s: SET_MC_RATE failed", __func__);
4836 vos_mem_free(rateUpdate);
4837 ret = -EFAULT;
4838 goto exit;
Leo Chang614d2072013-08-22 14:59:44 -07004839 }
4840 }
Rajeev79dbe4c2013-10-05 11:03:42 +05304841#ifdef FEATURE_WLAN_BATCH_SCAN
Rajeev Kumar8b373292014-01-08 20:36:55 -08004842 else if (strncmp(command, "WLS_BATCHING", 12) == 0)
Rajeev79dbe4c2013-10-05 11:03:42 +05304843 {
Rajeev Kumar8b373292014-01-08 20:36:55 -08004844 ret = hdd_handle_batch_scan_ioctl(pAdapter, &priv_data, command);
Rajeev79dbe4c2013-10-05 11:03:42 +05304845 }
4846#endif
Abhishek Singh00b71972016-01-07 10:51:04 +05304847#ifdef WLAN_FEATURE_RMC
4848 else if ((strncasecmp(command, "SETIBSSBEACONOUIDATA", 20) == 0) &&
4849 (WLAN_HDD_IBSS == pAdapter->device_mode))
4850 {
4851 int i = 0;
4852 tANI_U8 *ibss_ie;
4853 tANI_U32 command_len;
4854 tANI_U8 *value = command;
4855 tHalHandle hHal = pHddCtx->hHal;
4856 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
4857 tANI_U32 ibss_ie_length;
4858 tANI_U32 len, present;
4859 tANI_U8 *addIE;
4860 tANI_U8 *addIEData;
4861
4862 hddLog(LOG1,
4863 FL(" received command %s"),((char *) value));
4864 /* validate argument of command */
4865 if (strlen(value) <= 21)
4866 {
4867 hddLog(LOGE,
4868 FL("No arguements in command length %zu"), strlen(value));
4869 ret = -EFAULT;
4870 goto exit;
4871 }
4872
4873 /* moving to arguments of commands */
4874 value = value + 21;
4875 command_len = strlen(value);
4876
4877 /* oui_data can't be less than 3 bytes */
4878 if (command_len <= (2 * WLAN_HDD_IBSS_MIN_OUI_DATA_LENGTH))
4879 {
4880 hddLog(LOGE,
4881 FL("Invalid SETIBSSBEACONOUIDATA command length %d"),
4882 command_len);
4883 ret = -EFAULT;
4884 goto exit;
4885 }
4886 ibss_ie = vos_mem_malloc(command_len);
4887 if (!ibss_ie) {
4888 hddLog(LOGE,
4889 FL("Could not allocate memory for command length %d"),
4890 command_len);
4891 ret = -ENOMEM;
4892 goto exit;
4893 }
4894 vos_mem_zero(ibss_ie, command_len);
4895
4896 ibss_ie_length = hdd_parse_set_ibss_oui_data_command(value, ibss_ie,
4897 command_len);
4898 if (ibss_ie_length < (2 * WLAN_HDD_IBSS_MIN_OUI_DATA_LENGTH)) {
4899 hddLog(LOGE, FL("Could not parse command %s return length %d"),
4900 value, ibss_ie_length);
4901 ret = -EFAULT;
4902 vos_mem_free(ibss_ie);
4903 goto exit;
4904 }
4905
4906 hddLog(LOG1, FL("ibss_ie length %d ibss_ie:"), ibss_ie_length);
4907 while (i < ibss_ie_length)
4908 hddLog(LOG1, FL("0x%x"), ibss_ie[i++]);
4909
4910 /* Populate Vendor IE in Beacon */
4911 if ((ccmCfgGetInt(hHal,
4912 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
4913 &present)) != eHAL_STATUS_SUCCESS)
4914 {
4915 hddLog(LOGE,
4916 FL("unable to ftch WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG"));
4917 ret = -EFAULT;
4918 vos_mem_free(ibss_ie);
4919 goto exit;
4920 }
4921
4922 addIE = vos_mem_malloc(WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN);
4923 if (!addIE) {
4924 hddLog(LOGE,
4925 FL("Could not allocate memory for command length %d"),
4926 command_len);
4927 vos_mem_free(ibss_ie);
4928 ret = -ENOMEM;
4929 goto exit;
4930 }
4931 vos_mem_zero(addIE, WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN);
4932
4933 if (present)
4934 {
4935 if ((wlan_cfgGetStrLen(pMac,
4936 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, &len)) != eSIR_SUCCESS)
4937 {
4938 hddLog(LOGE,
4939 FL("unable to fetch WNI_CFG_PROBE_RSP_BCN_ADDNIE_LEN"));
4940 ret = -EFAULT;
4941 vos_mem_free(ibss_ie);
4942 vos_mem_free(addIE);
4943 goto exit;
4944 }
4945
4946 if (len <= WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN && len &&
4947 ((len + ibss_ie_length) <=
4948 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN))
4949 {
4950 if ((ccmCfgGetStr(hHal,
4951 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, addIE, &len))
4952 != eHAL_STATUS_SUCCESS)
4953 {
4954 hddLog(LOGE,
4955 FL("unable to fetch WNI_PROBE_RSP_BCN_ADDNIE_DATA"));
4956 ret = -EFAULT;
4957 vos_mem_free(ibss_ie);
4958 vos_mem_free(addIE);
4959 goto exit;
4960 }
4961 else
4962 {
4963 /* Curruntly only WPA IE is added before Vendor IE
4964 * so we can blindly place the Vendor IE after WPA
4965 * IE. If no WPA IE found replace all with Vendor IE.
4966 */
4967 len = hdd_find_ibss_wpa_ie_pos(addIE, len);
4968 }
4969 }
4970 else
4971 {
4972 hddLog(LOGE,
4973 FL("IE len exceed limit len %d,ibss_ie_length %d "),
4974 len, ibss_ie_length);
4975 ret = -EFAULT;
4976 vos_mem_free(addIE);
4977 vos_mem_free(ibss_ie);
4978 goto exit;
4979 }
4980 }
4981 else {
4982 len = 0;
4983 }
4984
4985 vos_mem_copy (addIE + len , ibss_ie, ibss_ie_length);
4986 len += ibss_ie_length;
4987
4988 if (ccmCfgSetStr(hHal,
4989 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, addIE, len, NULL,
4990 eANI_BOOLEAN_FALSE) != eHAL_STATUS_SUCCESS)
4991 {
4992 hddLog(LOGE,
4993 FL("unable to set WNI_CFG_PRBE_RSP_BCN_ADDNIE_DATA"));
4994 ret = -EFAULT;
4995 vos_mem_free(ibss_ie);
4996 vos_mem_free(addIE);
4997 goto exit;
4998 }
4999 vos_mem_free(addIE);
5000 if (ccmCfgSetInt(hHal,
5001 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 1,NULL,
5002 eANI_BOOLEAN_FALSE) != eHAL_STATUS_SUCCESS)
5003 {
5004 hddLog(LOGE,
5005 FL("unble to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG"));
5006 ret = -EFAULT;
5007 vos_mem_free(ibss_ie);
5008 goto exit;
5009 }
5010
5011 /* Populate Vendor IE in probe resp */
5012 if ((ccmCfgGetInt(hHal,
5013 WNI_CFG_PROBE_RSP_ADDNIE_FLAG,
5014 &present)) != eHAL_STATUS_SUCCESS)
5015 {
5016 hddLog(LOGE,
5017 FL("unable to fetch WNI_CFG_PROBE_RSP_ADDNIE_FLAG"));
5018 ret = -EFAULT;
5019 vos_mem_free(ibss_ie);
5020 goto exit;
5021 }
5022
5023 addIEData = vos_mem_malloc(WNI_CFG_PROBE_RSP_ADDNIE_DATA1_LEN);
5024 if (!addIEData) {
5025 hddLog(LOGE,
5026 FL("Could not allocate memory for command length %d"),
5027 command_len);
5028 vos_mem_free(ibss_ie);
5029 ret = -ENOMEM;
5030 goto exit;
5031 }
5032 vos_mem_zero(addIEData, WNI_CFG_PROBE_RSP_ADDNIE_DATA1_LEN);
5033
5034 if (present) {
5035 if (eSIR_SUCCESS != wlan_cfgGetStrLen(pMac,
5036 WNI_CFG_PROBE_RSP_ADDNIE_DATA1, &len)) {
5037 hddLog(LOGE,
5038 FL("unable to fetch WNI_CFG_PROBE_RSP_ADDNIE_DATA1"));
5039 ret = -EFAULT;
5040 vos_mem_free(ibss_ie);
5041 vos_mem_free(addIEData);
5042 goto exit;
5043 }
5044 if (len < WNI_CFG_PROBE_RSP_ADDNIE_DATA1_LEN && len &&
5045 (ibss_ie_length + len) <=
5046 WNI_CFG_PROBE_RSP_ADDNIE_DATA1_LEN) {
5047
5048 if ((ccmCfgGetStr(hHal,
5049 WNI_CFG_PROBE_RSP_ADDNIE_DATA1, addIEData, &len))
5050 != eHAL_STATUS_SUCCESS) {
5051 hddLog(LOGE,
5052 FL("unable fetch WNI_CFG_PROBE_RSP_ADDNIE_DATA1"));
5053 ret = -EFAULT;
5054 vos_mem_free(ibss_ie);
5055 vos_mem_free(addIEData);
5056 goto exit;
5057 }
5058 else {
5059 /* Curruntly only WPA IE is added before Vendor IE
5060 * so we can blindly place the Vendor IE after WPA
5061 * IE. If no WPA IE found replace all with Vendor IE.
5062 */
5063 len = hdd_find_ibss_wpa_ie_pos(addIEData, len);
5064 }
5065 }
5066 else
5067 {
5068 hddLog(LOGE,
5069 FL("IE len exceed limit len %d,ibss_ie_length %d "),
5070 len, ibss_ie_length);
5071 ret = -EFAULT;
5072 vos_mem_free(addIEData);
5073 vos_mem_free(ibss_ie);
5074 goto exit;
5075 }
5076 } /* probe rsp ADD IE present */
5077 else {
5078 /* probe rsp add IE is not present */
5079 len = 0;
5080 }
5081
5082 vos_mem_copy(addIEData +len , ibss_ie, ibss_ie_length);
5083 len += ibss_ie_length;
5084
5085 vos_mem_free(ibss_ie);
5086
5087 if (ccmCfgSetStr(hHal,
5088 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,
5089 (tANI_U8*)(addIEData),
5090 len, NULL,
5091 eANI_BOOLEAN_FALSE)
5092 == eHAL_STATUS_FAILURE) {
5093 hddLog(LOGE,
5094 FL("unable to copy to WNI_CFG_PROBE_RSP_ADDNIE_DATA1"));
5095 ret = -EFAULT;
5096 vos_mem_free(addIEData);
5097 goto exit;
5098 }
5099 vos_mem_free(addIEData);
5100 if (ccmCfgSetInt(WLAN_HDD_GET_HAL_CTX(pAdapter),
5101 WNI_CFG_PROBE_RSP_ADDNIE_FLAG, 1,NULL,
5102 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
5103 {
5104 hddLog(LOGE,
5105 FL("unable to copy WNI_CFG_PROBE_RSP_ADDNIE_FLAG"));
5106 ret = -EFAULT;
5107 goto exit;
5108 }
5109 }
5110 else if (strncasecmp(command, "SETRMCENABLE", 12) == 0)
5111 {
5112 tANI_U8 *value = command;
5113 tANI_U8 ucRmcEnable = 0;
5114 int status;
5115
5116 if ((WLAN_HDD_IBSS != pAdapter->device_mode) &&
5117 (WLAN_HDD_SOFTAP != pAdapter->device_mode))
5118 {
5119 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5120 "Received SETRMCENABLE command in invalid mode %d "
5121 "SETRMCENABLE command is only allowed in IBSS or SOFTAP mode",
5122 pAdapter->device_mode);
5123 ret = -EINVAL;
5124 goto exit;
5125 }
5126
5127 status = hdd_parse_setrmcenable_command(value, &ucRmcEnable);
5128 if (status)
5129 {
5130 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5131 "Invalid SETRMCENABLE command ");
5132 ret = -EINVAL;
5133 goto exit;
5134 }
5135
5136 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5137 "%s: ucRmcEnable %d ", __func__, ucRmcEnable);
5138
5139 if (TRUE == ucRmcEnable)
5140 {
5141 status = sme_EnableRMC( (tHalHandle)(pHddCtx->hHal),
5142 pAdapter->sessionId );
5143 }
5144 else if(FALSE == ucRmcEnable)
5145 {
5146 status = sme_DisableRMC( (tHalHandle)(pHddCtx->hHal),
5147 pAdapter->sessionId );
5148 }
5149 else
5150 {
5151 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5152 "Invalid SETRMCENABLE command %d", ucRmcEnable);
5153 ret = -EINVAL;
5154 goto exit;
5155 }
5156
5157 if (VOS_STATUS_SUCCESS != status)
5158 {
5159 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5160 "%s: SETRMC %d failed status %d", __func__, ucRmcEnable,
5161 status);
5162 ret = -EINVAL;
5163 goto exit;
5164 }
5165 }
5166 else if (strncasecmp(command, "SETRMCACTIONPERIOD", 18) == 0)
5167 {
5168 tANI_U8 *value = command;
5169 tANI_U32 uActionPeriod = 0;
5170 int status;
5171
5172 if ((WLAN_HDD_IBSS != pAdapter->device_mode) &&
5173 (WLAN_HDD_SOFTAP != pAdapter->device_mode))
5174 {
5175 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5176 "Received SETRMC command in invalid mode %d "
5177 "SETRMC command is only allowed in IBSS or SOFTAP mode",
5178 pAdapter->device_mode);
5179 ret = -EINVAL;
5180 goto exit;
5181 }
5182
5183 status = hdd_parse_setrmcactionperiod_command(value, &uActionPeriod);
5184 if (status)
5185 {
5186 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5187 "Invalid SETRMCACTIONPERIOD command ");
5188 ret = -EINVAL;
5189 goto exit;
5190 }
5191
5192 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5193 "%s: uActionPeriod %d ", __func__, uActionPeriod);
5194
5195 if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY,
5196 uActionPeriod, NULL, eANI_BOOLEAN_FALSE))
5197 {
5198 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5199 "%s: Could not set SETRMCACTIONPERIOD %d", __func__, uActionPeriod);
5200 ret = -EINVAL;
5201 goto exit;
5202 }
5203
5204 }
5205 else if (strncasecmp(command, "GETIBSSPEERINFOALL", 18) == 0)
5206 {
5207 /* Peer Info All Command */
5208 int status = eHAL_STATUS_SUCCESS;
5209 hdd_station_ctx_t *pHddStaCtx = NULL;
5210 char *extra = NULL;
5211 int idx = 0, length = 0;
5212 v_MACADDR_t *macAddr;
5213 v_U32_t txRateMbps = 0, numOfBytestoPrint = 0;
5214
5215 if (WLAN_HDD_IBSS == pAdapter->device_mode)
5216 {
5217 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5218 }
5219 else
5220 {
5221 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5222 "%s: pAdapter is not valid for this device mode",
5223 __func__);
5224 ret = -EINVAL;
5225 goto exit;
5226 }
5227
5228 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5229 "%s: Received GETIBSSPEERINFOALL Command", __func__);
5230
5231
5232 /* Handle the command */
5233 status = hdd_cfg80211_get_ibss_peer_info_all(pAdapter);
5234 if (VOS_STATUS_SUCCESS == status)
5235 {
5236 /* The variable extra needed to be allocated on the heap since
5237 * amount of memory required to copy the data for 32 devices
5238 * exceeds the size of 1024 bytes of default stack size. On
5239 * 64 bit devices, the default max stack size of 2048 bytes
5240 */
5241 extra = kmalloc(WLAN_MAX_BUF_SIZE, GFP_KERNEL);
5242
5243 if (NULL == extra)
5244 {
5245 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5246 "%s:kmalloc failed", __func__);
5247 ret = -EINVAL;
5248 goto exit;
5249 }
5250
5251 /* Copy number of stations */
5252 length = scnprintf( extra, WLAN_MAX_BUF_SIZE, "%d ",
5253 pHddStaCtx->ibss_peer_info.numIBSSPeers);
5254 numOfBytestoPrint = length;
5255 for (idx = 0; idx < pHddStaCtx->ibss_peer_info.numIBSSPeers; idx++)
5256 {
5257 macAddr =
5258 hdd_wlan_get_ibss_mac_addr_from_staid(pAdapter,
5259 pHddStaCtx->ibss_peer_info.ibssPeerList[idx].staIdx);
5260 if (NULL != macAddr)
5261 {
5262 txRateMbps =
5263 ((pHddStaCtx->ibss_peer_info.ibssPeerList[idx].txRate)*500*1000)/1000000;
5264
5265 length += scnprintf( (extra + length), WLAN_MAX_BUF_SIZE - length,
5266 "%02x:%02x:%02x:%02x:%02x:%02x %d %d ",
5267 macAddr->bytes[0], macAddr->bytes[1], macAddr->bytes[2],
5268 macAddr->bytes[3], macAddr->bytes[4], macAddr->bytes[5],
5269 (int)txRateMbps,
5270 (int)pHddStaCtx->ibss_peer_info.ibssPeerList[idx].rssi);
5271 }
5272 else
5273 {
5274 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5275 "%s: MAC ADDR is NULL for staIdx: %d", __func__,
5276 pHddStaCtx->ibss_peer_info.ibssPeerList[idx].staIdx);
5277 }
5278
5279 /*
5280 * VOS_TRACE() macro has limitation of 512 bytes for the print
5281 * buffer. Hence printing the data in two chunks. The first chunk
5282 * will have the data for 16 devices and the second chunk will
5283 * have the rest.
5284 */
5285 if (idx < NUM_OF_STA_DATA_TO_PRINT)
5286 {
5287 numOfBytestoPrint = length;
5288 }
5289 }
5290
5291 /*
5292 * Copy the data back into buffer, if the data to copy is
5293 * morethan 512 bytes than we will split the data and do
5294 * it in two shots
5295 */
5296 if (copy_to_user(priv_data.buf, extra, numOfBytestoPrint))
5297 {
5298 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5299 "%s: Copy into user data buffer failed ", __func__);
5300 ret = -EFAULT;
5301 kfree(extra);
5302 goto exit;
5303 }
5304 priv_data.buf[numOfBytestoPrint] = '\0';
5305 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED,
5306 "%s", priv_data.buf);
5307
5308 if (length > numOfBytestoPrint)
5309 {
5310 if (copy_to_user(priv_data.buf + numOfBytestoPrint,
5311 extra + numOfBytestoPrint,
5312 length - numOfBytestoPrint + 1))
5313 {
5314 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5315 "%s: Copy into user data buffer failed ", __func__);
5316 ret = -EFAULT;
5317 kfree(extra);
5318 goto exit;
5319 }
5320 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED,
5321 "%s", &priv_data.buf[numOfBytestoPrint]);
5322 }
5323
5324 /* Free temporary buffer */
5325 kfree(extra);
5326 }
5327
5328 else
5329 {
5330 /* Command failed, log error */
5331 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5332 "%s: GETIBSSPEERINFOALL command failed with status code %d",
5333 __func__, status);
5334 ret = -EINVAL;
5335 goto exit;
5336 }
5337 ret = 0;
5338 }
5339 else if(strncasecmp(command, "GETIBSSPEERINFO", 15) == 0)
5340 {
5341 /* Peer Info <Peer Addr> command */
5342 tANI_U8 *value = command;
5343 VOS_STATUS status;
5344 hdd_station_ctx_t *pHddStaCtx = NULL;
5345 char extra[128] = { 0 };
5346 v_U32_t length = 0;
5347 v_U8_t staIdx = 0;
5348 v_U32_t txRateMbps = 0;
5349 v_MACADDR_t peerMacAddr;
5350
5351 if (WLAN_HDD_IBSS == pAdapter->device_mode)
5352 {
5353 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5354 }
5355 else
5356 {
5357 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5358 "%s: pAdapter is not valid for this device mode",
5359 __func__);
5360 ret = -EINVAL;
5361 goto exit;
5362 }
5363
5364 /* if there are no peers, no need to continue with the command */
5365 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5366 "%s: Received GETIBSSPEERINFO Command", __func__);
5367
5368 if (eConnectionState_IbssConnected != pHddStaCtx->conn_info.connState)
5369 {
5370 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5371 "%s:No IBSS Peers coalesced", __func__);
5372 ret = -EINVAL;
5373 goto exit;
5374 }
5375
5376 /* Parse the incoming command buffer */
5377 status = hdd_parse_get_ibss_peer_info(value, &peerMacAddr);
5378 if (VOS_STATUS_SUCCESS != status)
5379 {
5380 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5381 "%s: Invalid GETIBSSPEERINFO command", __func__);
5382 ret = -EINVAL;
5383 goto exit;
5384 }
5385
5386 /* Get station index for the peer mac address */
5387 hdd_Ibss_GetStaId(pHddStaCtx, &peerMacAddr, &staIdx);
5388
5389 if (staIdx > HDD_MAX_NUM_IBSS_STA)
5390 {
5391 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5392 "%s: Invalid StaIdx %d returned", __func__, staIdx);
5393 ret = -EINVAL;
5394 goto exit;
5395 }
5396
5397 /* Handle the command */
5398 status = hdd_cfg80211_get_ibss_peer_info(pAdapter, staIdx);
5399 if (VOS_STATUS_SUCCESS == status)
5400 {
5401 v_U32_t txRate = pHddStaCtx->ibss_peer_info.ibssPeerList[0].txRate;
5402 txRateMbps = (txRate * 500 * 1000)/1000000;
5403
5404 length = scnprintf( extra, sizeof(extra), "%d %d", (int)txRateMbps,
5405 (int)pHddStaCtx->ibss_peer_info.ibssPeerList[0].rssi);
5406
5407 /* Copy the data back into buffer */
5408 if (copy_to_user(priv_data.buf, &extra, length+ 1))
5409 {
5410 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5411 "%s: copy data to user buffer failed GETIBSSPEERINFO command",
5412 __func__);
5413 ret = -EFAULT;
5414 goto exit;
5415 }
5416 }
5417 else
5418 {
5419 /* Command failed, log error */
5420 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5421 "%s: GETIBSSPEERINFO command failed with status code %d",
5422 __func__, status);
5423 ret = -EINVAL;
5424 goto exit;
5425 }
5426
5427 /* Success ! */
5428 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED,
5429 "%s", priv_data.buf);
5430 ret = 0;
5431 }
5432 else if (strncasecmp(command, "SETRMCTXRATE", 12) == 0)
5433 {
5434 tANI_U8 *value = command;
5435 tANI_U32 uRate = 0;
5436 tTxrateinfoflags txFlags = 0;
5437 tSirRateUpdateInd *rateUpdateParams;
5438 int status;
5439
5440 if ((WLAN_HDD_IBSS != pAdapter->device_mode) &&
5441 (WLAN_HDD_SOFTAP != pAdapter->device_mode))
5442 {
5443 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5444 "Received SETRMCTXRATE command in invalid mode %d "
5445 "SETRMC command is only allowed in IBSS or SOFTAP mode",
5446 pAdapter->device_mode);
5447 ret = -EINVAL;
5448 goto exit;
5449 }
5450
5451 status = hdd_parse_setrmcrate_command(value, &uRate, &txFlags);
5452 if (status)
5453 {
5454 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5455 "Invalid SETRMCTXRATE command ");
5456 ret = -EINVAL;
5457 goto exit;
5458 }
5459
5460 rateUpdateParams = vos_mem_malloc(sizeof(tSirRateUpdateInd));
5461 if (NULL == rateUpdateParams)
5462 {
5463 ret = -EINVAL;
5464 goto exit;
5465 }
5466
5467 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5468 "%s: uRate %d ", __func__, uRate);
5469
5470 vos_mem_zero(rateUpdateParams, sizeof(tSirRateUpdateInd ));
5471
5472 /* -1 implies ignore this param */
5473 rateUpdateParams->ucastDataRate = -1;
5474
5475 /*
5476 * Fill the user specifieed RMC rate param
5477 * and the derived tx flags.
5478 */
5479 rateUpdateParams->rmcDataRate = uRate;
5480 rateUpdateParams->rmcDataRateTxFlag = txFlags;
5481
5482 status = sme_SendRateUpdateInd((tHalHandle)(pHddCtx->hHal), rateUpdateParams);
5483 }
5484 else if (strncasecmp(command, "SETIBSSTXFAILEVENT", 18) == 0 )
5485 {
5486 char *value;
5487 tANI_U8 tx_fail_count = 0;
5488 tANI_U16 pid = 0;
5489
5490 value = command;
5491
5492 ret = hdd_ParseIBSSTXFailEventParams(value, &tx_fail_count, &pid);
5493
5494 if (0 != ret)
5495 {
5496 hddLog(VOS_TRACE_LEVEL_INFO,
5497 "%s: Failed to parse SETIBSSTXFAILEVENT arguments",
5498 __func__);
5499 goto exit;
5500 }
5501
5502 hddLog(VOS_TRACE_LEVEL_INFO, "%s: tx_fail_cnt=%hhu, pid=%hu",
5503 __func__, tx_fail_count, pid);
5504
5505 if (0 == tx_fail_count)
5506 {
5507 // Disable TX Fail Indication
5508 if (eHAL_STATUS_SUCCESS ==
5509 sme_TXFailMonitorStartStopInd(pHddCtx->hHal,
5510 tx_fail_count,
5511 NULL))
5512 {
5513 cesium_pid = 0;
5514 }
5515 else
5516 {
5517 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5518 "%s: failed to disable TX Fail Event ", __func__);
5519 ret = -EINVAL;
5520 }
5521 }
5522 else
5523 {
5524 if (eHAL_STATUS_SUCCESS ==
5525 sme_TXFailMonitorStartStopInd(pHddCtx->hHal,
5526 tx_fail_count,
5527 (void*)hdd_tx_fail_ind_callback))
5528 {
5529 cesium_pid = pid;
5530 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5531 "%s: Registered Cesium pid %u", __func__,
5532 cesium_pid);
5533 }
5534 else
5535 {
5536 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5537 "%s: Failed to enable TX Fail Monitoring", __func__);
5538 ret = -EINVAL;
5539 }
5540 }
5541 }
5542
5543#endif /* WLAN_FEATURE_RMC */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08005544#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07005545 else if (strncmp(command, "SETCCXROAMSCANCHANNELS", 22) == 0)
5546 {
5547 tANI_U8 *value = command;
5548 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
5549 tANI_U8 numChannels = 0;
5550 eHalStatus status = eHAL_STATUS_SUCCESS;
5551
5552 status = hdd_parse_channellist(value, ChannelList, &numChannels);
5553 if (eHAL_STATUS_SUCCESS != status)
5554 {
5555 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5556 "%s: Failed to parse channel list information", __func__);
5557 ret = -EINVAL;
5558 goto exit;
5559 }
5560
5561 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
5562 {
5563 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5564 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
5565 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
5566 ret = -EINVAL;
5567 goto exit;
5568 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08005569 status = sme_SetEseRoamScanChannelList((tHalHandle)(pHddCtx->hHal),
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07005570 ChannelList,
5571 numChannels);
5572 if (eHAL_STATUS_SUCCESS != status)
5573 {
5574 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5575 "%s: Failed to update channel list information", __func__);
5576 ret = -EINVAL;
5577 goto exit;
5578 }
5579 }
5580 else if (strncmp(command, "GETTSMSTATS", 11) == 0)
5581 {
5582 tANI_U8 *value = command;
5583 char extra[128] = {0};
5584 int len = 0;
5585 tANI_U8 tid = 0;
5586 hdd_station_ctx_t *pHddStaCtx = NULL;
5587 tAniTrafStrmMetrics tsmMetrics;
5588 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5589
5590 /* if not associated, return error */
5591 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
5592 {
5593 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:Not associated!",__func__);
5594 ret = -EINVAL;
5595 goto exit;
5596 }
5597
5598 /* Move pointer to ahead of GETTSMSTATS<delimiter> */
5599 value = value + 12;
5600 /* Convert the value from ascii to integer */
5601 ret = kstrtou8(value, 10, &tid);
5602 if (ret < 0)
5603 {
5604 /* If the input value is greater than max value of datatype, then also
5605 kstrtou8 fails */
5606 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5607 "%s: kstrtou8 failed range [%d - %d]", __func__,
5608 TID_MIN_VALUE,
5609 TID_MAX_VALUE);
5610 ret = -EINVAL;
5611 goto exit;
5612 }
5613
5614 if ((tid < TID_MIN_VALUE) || (tid > TID_MAX_VALUE))
5615 {
5616 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5617 "tid value %d is out of range"
5618 " (Min: %d Max: %d)", tid,
5619 TID_MIN_VALUE,
5620 TID_MAX_VALUE);
5621 ret = -EINVAL;
5622 goto exit;
5623 }
5624
5625 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5626 "%s: Received Command to get tsm stats tid = %d", __func__, tid);
5627
5628 if (VOS_STATUS_SUCCESS != hdd_get_tsm_stats(pAdapter, tid, &tsmMetrics))
5629 {
5630 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5631 "%s: failed to get tsm stats", __func__);
5632 ret = -EFAULT;
5633 goto exit;
5634 }
5635
5636 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5637 "UplinkPktQueueDly(%d)\n"
5638 "UplinkPktQueueDlyHist[0](%d)\n"
5639 "UplinkPktQueueDlyHist[1](%d)\n"
5640 "UplinkPktQueueDlyHist[2](%d)\n"
5641 "UplinkPktQueueDlyHist[3](%d)\n"
Arun Kumar Khandavallie8768212014-02-17 16:43:34 +05305642 "UplinkPktTxDly(%u)\n"
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07005643 "UplinkPktLoss(%d)\n"
5644 "UplinkPktCount(%d)\n"
5645 "RoamingCount(%d)\n"
5646 "RoamingDly(%d)", tsmMetrics.UplinkPktQueueDly,
5647 tsmMetrics.UplinkPktQueueDlyHist[0],
5648 tsmMetrics.UplinkPktQueueDlyHist[1],
5649 tsmMetrics.UplinkPktQueueDlyHist[2],
5650 tsmMetrics.UplinkPktQueueDlyHist[3],
5651 tsmMetrics.UplinkPktTxDly, tsmMetrics.UplinkPktLoss,
5652 tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount, tsmMetrics.RoamingDly);
5653
5654 /* Output TSM stats is of the format
5655 GETTSMSTATS [PktQueueDly] [PktQueueDlyHist[0]]:[PktQueueDlyHist[1]] ...[RoamingDly]
5656 eg., GETTSMSTATS 10 1:0:0:161 20 1 17 8 39800 */
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08005657 len = scnprintf(extra, sizeof(extra), "%s %d %d:%d:%d:%d %u %d %d %d %d", command,
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07005658 tsmMetrics.UplinkPktQueueDly, tsmMetrics.UplinkPktQueueDlyHist[0],
5659 tsmMetrics.UplinkPktQueueDlyHist[1], tsmMetrics.UplinkPktQueueDlyHist[2],
5660 tsmMetrics.UplinkPktQueueDlyHist[3], tsmMetrics.UplinkPktTxDly,
5661 tsmMetrics.UplinkPktLoss, tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount,
5662 tsmMetrics.RoamingDly);
5663
Ratnam Rachurid53009c2015-08-07 13:59:00 +05305664 len = VOS_MIN(priv_data.total_len, len + 1);
5665 if (copy_to_user(priv_data.buf, &extra, len)) {
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07005666 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5667 "%s: failed to copy data to user buffer", __func__);
5668 ret = -EFAULT;
5669 goto exit;
5670 }
5671 }
5672 else if (strncmp(command, "SETCCKMIE", 9) == 0)
5673 {
5674 tANI_U8 *value = command;
5675 tANI_U8 *cckmIe = NULL;
5676 tANI_U8 cckmIeLen = 0;
5677 eHalStatus status = eHAL_STATUS_SUCCESS;
5678
5679 status = hdd_parse_get_cckm_ie(value, &cckmIe, &cckmIeLen);
5680 if (eHAL_STATUS_SUCCESS != status)
5681 {
5682 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5683 "%s: Failed to parse cckm ie data", __func__);
5684 ret = -EINVAL;
5685 goto exit;
5686 }
5687
5688 if (cckmIeLen > DOT11F_IE_RSN_MAX_LEN)
5689 {
5690 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5691 "%s: CCKM Ie input length is more than max[%d]", __func__,
5692 DOT11F_IE_RSN_MAX_LEN);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08005693 vos_mem_free(cckmIe);
5694 cckmIe = NULL;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07005695 ret = -EINVAL;
5696 goto exit;
5697 }
5698 sme_SetCCKMIe((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, cckmIe, cckmIeLen);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08005699 vos_mem_free(cckmIe);
5700 cckmIe = NULL;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07005701 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08005702 else if (strncmp(command, "CCXBEACONREQ", 12) == 0)
5703 {
5704 tANI_U8 *value = command;
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08005705 tCsrEseBeaconReq eseBcnReq;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08005706 eHalStatus status = eHAL_STATUS_SUCCESS;
Srinivas Girigowda0c6d7fe2014-05-28 18:18:10 -07005707
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08005708 status = hdd_parse_ese_beacon_req(value, &eseBcnReq);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08005709 if (eHAL_STATUS_SUCCESS != status)
5710 {
5711 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08005712 "%s: Failed to parse ese beacon req", __func__);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08005713 ret = -EINVAL;
5714 goto exit;
5715 }
Srinivas Girigowda0c6d7fe2014-05-28 18:18:10 -07005716 if (!hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))) {
5717 hddLog(VOS_TRACE_LEVEL_INFO, FL("Not associated"));
5718 hdd_indicateEseBcnReportNoResults (pAdapter,
5719 eseBcnReq.bcnReq[0].measurementToken,
5720 0x02, //BIT(1) set for measurement done
5721 0); // no BSS
5722 goto exit;
5723 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08005724
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08005725 status = sme_SetEseBeaconRequest((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, &eseBcnReq);
5726 if (eHAL_STATUS_SUCCESS != status)
5727 {
5728 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5729 "%s: sme_SetEseBeaconRequest failed (%d)", __func__, status);
5730 ret = -EINVAL;
5731 goto exit;
5732 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08005733 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08005734#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
c_hpothu92367912014-05-01 15:18:17 +05305735 else if (strncmp(command, "GETBCNMISSRATE", 14) == 0)
5736 {
5737 eHalStatus status;
5738 char buf[32], len;
5739 long waitRet;
5740 bcnMissRateContext_t getBcnMissRateCtx;
5741
5742 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5743
5744 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
5745 {
5746 hddLog(VOS_TRACE_LEVEL_WARN,
5747 FL("GETBCNMISSRATE: STA is not in connected state"));
5748 ret = -1;
5749 goto exit;
5750 }
5751
5752 init_completion(&(getBcnMissRateCtx.completion));
5753 getBcnMissRateCtx.magic = BCN_MISS_RATE_CONTEXT_MAGIC;
5754
5755 status = sme_getBcnMissRate((tHalHandle)(pHddCtx->hHal),
5756 pAdapter->sessionId,
5757 (void *)getBcnMissRateCB,
5758 (void *)(&getBcnMissRateCtx));
5759 if( eHAL_STATUS_SUCCESS != status)
5760 {
5761 hddLog(VOS_TRACE_LEVEL_INFO,
5762 FL("GETBCNMISSRATE: fail to post WDA cmd"));
5763 ret = -EINVAL;
5764 goto exit;
5765 }
5766
5767 waitRet = wait_for_completion_interruptible_timeout
5768 (&getBcnMissRateCtx.completion, BCN_MISS_RATE_TIME);
5769 if(waitRet <= 0)
5770 {
5771 hddLog(VOS_TRACE_LEVEL_ERROR,
5772 FL("failed to wait on bcnMissRateComp %d"), ret);
5773
5774 //Make magic number to zero so that callback is not called.
5775 spin_lock(&hdd_context_lock);
5776 getBcnMissRateCtx.magic = 0x0;
5777 spin_unlock(&hdd_context_lock);
5778 ret = -EINVAL;
5779 goto exit;
5780 }
5781
5782 hddLog(VOS_TRACE_LEVEL_INFO,
5783 FL("GETBCNMISSRATE: bcnMissRate: %d"), gbcnMissRate);
5784
5785 len = snprintf(buf, sizeof(buf), "GETBCNMISSRATE %d", gbcnMissRate);
5786 if (copy_to_user(priv_data.buf, &buf, len + 1))
5787 {
5788 hddLog(VOS_TRACE_LEVEL_ERROR,
5789 "%s: failed to copy data to user buffer", __func__);
5790 ret = -EFAULT;
5791 goto exit;
5792 }
5793 ret = len;
5794 }
Atul Mittal87ec2422014-09-24 13:12:50 +05305795#ifdef FEATURE_WLAN_TDLS
5796 else if (strncmp(command, "TDLSSECONDARYCHANNELOFFSET", 26) == 0) {
5797 tANI_U8 *value = command;
5798 int set_value;
5799 /* Move pointer to ahead of TDLSOFFCH*/
5800 value += 26;
c_manjeebbc40212015-12-08 13:52:59 +05305801 if (!(sscanf(value, "%d", &set_value))) {
5802 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5803 FL("No input identified"));
5804 ret = -EINVAL;
5805 goto exit;
5806 }
5807
Atul Mittal87ec2422014-09-24 13:12:50 +05305808 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5809 "%s: Tdls offchannel offset:%d",
5810 __func__, set_value);
5811 ret = iw_set_tdlssecoffchanneloffset(pHddCtx, set_value);
5812 if (ret < 0)
5813 {
5814 ret = -EINVAL;
5815 goto exit;
5816 }
5817
5818 } else if (strncmp(command, "TDLSOFFCHANNELMODE", 18) == 0) {
5819 tANI_U8 *value = command;
5820 int set_value;
5821 /* Move pointer to ahead of tdlsoffchnmode*/
5822 value += 18;
c_manjee82323892015-12-08 12:40:34 +05305823 ret = sscanf(value, "%d", &set_value);
5824 if (ret != 1) {
5825 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5826 FL("No input identified"));
5827 ret = -EINVAL;
5828 goto exit;
5829 }
Atul Mittal87ec2422014-09-24 13:12:50 +05305830 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5831 "%s: Tdls offchannel mode:%d",
5832 __func__, set_value);
5833 ret = iw_set_tdlsoffchannelmode(pAdapter, set_value);
5834 if (ret < 0)
5835 {
5836 ret = -EINVAL;
5837 goto exit;
5838 }
5839 } else if (strncmp(command, "TDLSOFFCHANNEL", 14) == 0) {
5840 tANI_U8 *value = command;
5841 int set_value;
5842 /* Move pointer to ahead of TDLSOFFCH*/
5843 value += 14;
c_manjeef6ccaf52015-12-08 11:52:11 +05305844 ret = sscanf(value, "%d", &set_value);
5845 if (ret != 1) {
5846 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5847 "Wrong value is given for hdd_set_tdls_offchannel");
5848 ret = -EINVAL;
5849 goto exit;
5850 }
5851
Atul Mittal87ec2422014-09-24 13:12:50 +05305852 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5853 "%s: Tdls offchannel num: %d",
5854 __func__, set_value);
5855 ret = iw_set_tdlsoffchannel(pHddCtx, set_value);
5856 if (ret < 0)
5857 {
5858 ret = -EINVAL;
5859 goto exit;
5860 }
5861 }
5862#endif
Satyanarayana Dash72806012014-12-02 14:30:08 +05305863 else if (strncmp(command, "GETFWSTATS", 10) == 0)
5864 {
5865 eHalStatus status;
5866 char *buf = NULL;
5867 char len;
5868 long waitRet;
5869 fwStatsContext_t fwStatsCtx;
Abhishek Singh08aa7762014-12-16 13:59:03 +05305870 tSirFwStatsResult *fwStatsRsp = &(pAdapter->fwStatsRsp);
Satyanarayana Dash72806012014-12-02 14:30:08 +05305871 tANI_U8 *ptr = command;
5872 int stats = *(ptr + 11) - '0';
5873
5874 hddLog(VOS_TRACE_LEVEL_INFO, FL("stats = %d "),stats);
5875 if (!IS_FEATURE_FW_STATS_ENABLE)
5876 {
5877 hddLog(VOS_TRACE_LEVEL_INFO,
5878 FL("Get Firmware stats feature not supported"));
5879 ret = -EINVAL;
5880 goto exit;
5881 }
5882
5883 if (FW_STATS_MAX <= stats || 0 >= stats)
5884 {
5885 hddLog(VOS_TRACE_LEVEL_INFO,
5886 FL(" stats %d not supported"),stats);
5887 ret = -EINVAL;
5888 goto exit;
5889 }
5890
5891 init_completion(&(fwStatsCtx.completion));
5892 fwStatsCtx.magic = FW_STATS_CONTEXT_MAGIC;
5893 fwStatsCtx.pAdapter = pAdapter;
5894 fwStatsRsp->type = 0;
5895 status = sme_GetFwStats( (tHalHandle)pHddCtx->hHal, stats,
Abhishek Singh08aa7762014-12-16 13:59:03 +05305896 &fwStatsCtx, hdd_FWStatisCB);
Satyanarayana Dash72806012014-12-02 14:30:08 +05305897 if (eHAL_STATUS_SUCCESS != status)
5898 {
5899 hddLog(VOS_TRACE_LEVEL_ERROR,
5900 FL(" fail to post WDA cmd status = %d"), status);
5901 ret = -EINVAL;
5902 goto exit;
5903 }
5904 waitRet = wait_for_completion_timeout
5905 (&(fwStatsCtx.completion), FW_STATE_WAIT_TIME);
5906 if (waitRet <= 0)
5907 {
5908 hddLog(VOS_TRACE_LEVEL_ERROR,
5909 FL("failed to wait on GwtFwstats"));
5910 //Make magic number to zero so that callback is not executed.
5911 spin_lock(&hdd_context_lock);
5912 fwStatsCtx.magic = 0x0;
5913 spin_unlock(&hdd_context_lock);
5914 ret = -EINVAL;
5915 goto exit;
5916 }
5917 if (fwStatsRsp->type)
5918 {
5919 buf = kmalloc(FW_STATE_RSP_LEN, GFP_KERNEL);
5920 if (!buf)
5921 {
5922 hddLog(VOS_TRACE_LEVEL_ERROR,
5923 FL(" failed to allocate memory"));
5924 ret = -ENOMEM;
5925 goto exit;
5926 }
5927 switch( fwStatsRsp->type )
5928 {
5929 case FW_UBSP_STATS:
5930 {
5931 len = snprintf(buf, FW_STATE_RSP_LEN,
5932 "GETFWSTATS: ubsp_enter_cnt %d ubsp_jump_ddr_cnt %d",
Abhishek Singh08aa7762014-12-16 13:59:03 +05305933 fwStatsRsp->fwStatsData.ubspStats.ubsp_enter_cnt,
5934 fwStatsRsp->fwStatsData.ubspStats.ubsp_jump_ddr_cnt);
Satyanarayana Dash72806012014-12-02 14:30:08 +05305935 }
5936 break;
5937 default:
5938 {
5939 hddLog(VOS_TRACE_LEVEL_ERROR, FL( "No handling for stats type %d"),fwStatsRsp->type);
5940 ret = -EFAULT;
5941 kfree(buf);
5942 goto exit;
5943 }
5944 }
5945 if (copy_to_user(priv_data.buf, buf, len + 1))
5946 {
5947 hddLog(VOS_TRACE_LEVEL_ERROR,
5948 FL(" failed to copy data to user buffer"));
5949 ret = -EFAULT;
5950 kfree(buf);
5951 goto exit;
5952 }
5953 ret = len;
5954 kfree(buf);
5955 }
5956 else
5957 {
5958 hddLog(VOS_TRACE_LEVEL_ERROR,
5959 FL("failed to fetch the stats"));
5960 ret = -EFAULT;
5961 goto exit;
5962 }
5963
5964 }
Agarwal Ashish8bd53ae2015-06-12 18:03:45 +05305965 else if (strncasecmp(command, "SET_FCC_CHANNEL", 15) == 0)
5966 {
5967 /*
5968 * this command wld be called by user-space when it detects WLAN
5969 * ON after airplane mode is set. When APM is set, WLAN turns off.
5970 * But it can be turned back on. Otherwise; when APM is turned back
5971 * off, WLAN wld turn back on. So at that point the command is
5972 * expected to come down. 0 means disable, 1 means enable. The
5973 * constraint is removed when parameter 1 is set or different
5974 * country code is set
5975 */
5976 ret = hdd_cmd_setFccChannel(pHddCtx, command, 15);
5977 }
Mahesh A Saptasagarbeca12c2015-09-07 16:21:06 +05305978 else if (strncasecmp(command, "DISABLE_CA_EVENT", 16) == 0)
5979 {
5980 ret = hdd_enable_disable_ca_event(pHddCtx, command, 16);
5981 }
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07005982 else {
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05305983 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
5984 TRACE_CODE_HDD_UNSUPPORTED_IOCTL,
5985 pAdapter->sessionId, 0));
Satyanarayana Dash72806012014-12-02 14:30:08 +05305986 hddLog( VOS_TRACE_LEVEL_WARN, FL("Unsupported GUI command %s"),
5987 command);
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07005988 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005989 }
5990exit:
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05305991 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07005992 if (command)
5993 {
5994 kfree(command);
5995 }
5996 return ret;
5997}
5998
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07005999#ifdef CONFIG_COMPAT
6000static int hdd_driver_compat_ioctl(hdd_adapter_t *pAdapter, struct ifreq *ifr)
6001{
6002 struct {
6003 compat_uptr_t buf;
6004 int used_len;
6005 int total_len;
6006 } compat_priv_data;
6007 hdd_priv_data_t priv_data;
6008 int ret = 0;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006009
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07006010 /*
6011 * Note that pAdapter and ifr have already been verified by caller,
6012 * and HDD context has also been validated
6013 */
6014 if (copy_from_user(&compat_priv_data, ifr->ifr_data,
6015 sizeof(compat_priv_data))) {
6016 ret = -EFAULT;
6017 goto exit;
6018 }
6019 priv_data.buf = compat_ptr(compat_priv_data.buf);
6020 priv_data.used_len = compat_priv_data.used_len;
6021 priv_data.total_len = compat_priv_data.total_len;
6022 ret = hdd_driver_command(pAdapter, &priv_data);
6023 exit:
6024 return ret;
6025}
6026#else /* CONFIG_COMPAT */
6027static int hdd_driver_compat_ioctl(hdd_adapter_t *pAdapter, struct ifreq *ifr)
6028{
6029 /* will never be invoked */
6030 return 0;
6031}
6032#endif /* CONFIG_COMPAT */
6033
6034static int hdd_driver_ioctl(hdd_adapter_t *pAdapter, struct ifreq *ifr)
6035{
6036 hdd_priv_data_t priv_data;
6037 int ret = 0;
6038
6039 /*
6040 * Note that pAdapter and ifr have already been verified by caller,
6041 * and HDD context has also been validated
6042 */
6043 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(priv_data))) {
6044 ret = -EFAULT;
6045 } else {
6046 ret = hdd_driver_command(pAdapter, &priv_data);
6047 }
6048 return ret;
6049}
6050
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05306051int __hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07006052{
6053 hdd_adapter_t *pAdapter;
6054 hdd_context_t *pHddCtx;
6055 int ret;
6056
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05306057 ENTER();
6058
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07006059 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6060 if (NULL == pAdapter) {
6061 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6062 "%s: HDD adapter context is Null", __func__);
6063 ret = -ENODEV;
6064 goto exit;
6065 }
6066 if (dev != pAdapter->dev) {
6067 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6068 "%s: HDD adapter/dev inconsistency", __func__);
6069 ret = -ENODEV;
6070 goto exit;
6071 }
6072
6073 if ((!ifr) || (!ifr->ifr_data)) {
6074 ret = -EINVAL;
6075 goto exit;
6076 }
6077
6078 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6079 ret = wlan_hdd_validate_context(pHddCtx);
6080 if (ret) {
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07006081 ret = -EBUSY;
6082 goto exit;
6083 }
6084
6085 switch (cmd) {
6086 case (SIOCDEVPRIVATE + 1):
6087 if (is_compat_task())
6088 ret = hdd_driver_compat_ioctl(pAdapter, ifr);
6089 else
6090 ret = hdd_driver_ioctl(pAdapter, ifr);
6091 break;
6092 default:
6093 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unknown ioctl %d",
6094 __func__, cmd);
6095 ret = -EINVAL;
6096 break;
6097 }
6098 exit:
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05306099 EXIT();
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07006100 return ret;
6101}
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006102
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05306103int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
6104{
6105 int ret;
6106
6107 vos_ssr_protect(__func__);
6108 ret = __hdd_ioctl(dev, ifr, cmd);
6109 vos_ssr_unprotect(__func__);
6110
6111 return ret;
6112}
6113
Katya Nigame7b69a82015-04-28 15:24:06 +05306114int hdd_mon_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
6115{
6116 return 0;
6117}
6118
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006119#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006120/**---------------------------------------------------------------------------
6121
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006122 \brief hdd_parse_ese_beacon_req() - Parse ese beacon request
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006123
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006124 This function parses the ese beacon request passed in the format
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006125 CCXBEACONREQ<space><Number of fields><space><Measurement token>
6126 <space>Channel 1<space>Scan Mode <space>Meas Duration<space>Channel N
6127 <space>Scan Mode N<space>Meas Duration N
6128 if the Number of bcn req fields (N) does not match with the actual number of fields passed
6129 then take N.
6130 <Meas Token><Channel><Scan Mode> and <Meas Duration> are treated as one pair
6131 For example, CCXBEACONREQ 2 1 1 1 30 2 44 0 40.
6132 This function does not take care of removing duplicate channels from the list
6133
6134 \param - pValue Pointer to data
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006135 \param - pEseBcnReq output pointer to store parsed ie information
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006136
6137 \return - 0 for success non-zero for failure
6138
6139 --------------------------------------------------------------------------*/
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006140static VOS_STATUS hdd_parse_ese_beacon_req(tANI_U8 *pValue,
6141 tCsrEseBeaconReq *pEseBcnReq)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006142{
6143 tANI_U8 *inPtr = pValue;
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306144 uint8_t input = 0;
6145 uint32_t tempInt = 0;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006146 int j = 0, i = 0, v = 0;
6147 char buf[32];
6148
6149 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
6150 /*no argument after the command*/
6151 if (NULL == inPtr)
6152 {
6153 return -EINVAL;
6154 }
6155 /*no space after the command*/
6156 else if (SPACE_ASCII_VALUE != *inPtr)
6157 {
6158 return -EINVAL;
6159 }
6160
6161 /*removing empty spaces*/
6162 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
6163
6164 /*no argument followed by spaces*/
6165 if ('\0' == *inPtr) return -EINVAL;
6166
6167 /*getting the first argument ie measurement token*/
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08006168 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006169 if (1 != v) return -EINVAL;
6170
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306171 v = kstrtos8(buf, 10, &input);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006172 if ( v < 0) return -EINVAL;
6173
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306174 input = VOS_MIN(input, SIR_ESE_MAX_MEAS_IE_REQS);
6175 pEseBcnReq->numBcnReqIe = input;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006176
Srinivas Girigowda725a88e2016-03-31 19:24:25 +05306177 hddLog(LOG1, "Number of Bcn Req Ie fields: %d", pEseBcnReq->numBcnReqIe);
6178
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006179
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006180 for (j = 0; j < (pEseBcnReq->numBcnReqIe); j++)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006181 {
6182 for (i = 0; i < 4; i++)
6183 {
6184 /*inPtr pointing to the beginning of first space after number of ie fields*/
6185 inPtr = strpbrk( inPtr, " " );
6186 /*no ie data after the number of ie fields argument*/
6187 if (NULL == inPtr) return -EINVAL;
6188
6189 /*removing empty space*/
6190 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
6191
6192 /*no ie data after the number of ie fields argument and spaces*/
6193 if ( '\0' == *inPtr ) return -EINVAL;
6194
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08006195 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006196 if (1 != v) return -EINVAL;
6197
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306198 v = kstrtou32(buf, 10, &tempInt);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006199 if (v < 0) return -EINVAL;
6200
6201 switch (i)
6202 {
6203 case 0: /* Measurement token */
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306204 if (!tempInt)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006205 {
6206 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306207 "Invalid Measurement Token: %u", tempInt);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006208 return -EINVAL;
6209 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006210 pEseBcnReq->bcnReq[j].measurementToken = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006211 break;
6212
6213 case 1: /* Channel number */
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306214 if ((!tempInt) ||
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006215 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
6216 {
6217 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306218 "Invalid Channel Number: %u", tempInt);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006219 return -EINVAL;
6220 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006221 pEseBcnReq->bcnReq[j].channel = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006222 break;
6223
6224 case 2: /* Scan mode */
Varun Reddy Yeturu0b18d5a2013-12-04 11:42:23 -08006225 if ((tempInt < eSIR_PASSIVE_SCAN) || (tempInt > eSIR_BEACON_TABLE))
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006226 {
6227 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306228 "Invalid Scan Mode(%u) Expected{0|1|2}", tempInt);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006229 return -EINVAL;
6230 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006231 pEseBcnReq->bcnReq[j].scanMode= tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006232 break;
6233
6234 case 3: /* Measurement duration */
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306235 if (((!tempInt) && (pEseBcnReq->bcnReq[j].scanMode != eSIR_BEACON_TABLE)) ||
6236 ((pEseBcnReq->bcnReq[j].scanMode == eSIR_BEACON_TABLE)))
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006237 {
6238 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306239 "Invalid Measurement Duration: %u", tempInt);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006240 return -EINVAL;
6241 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006242 pEseBcnReq->bcnReq[j].measurementDuration = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006243 break;
6244 }
6245 }
6246 }
6247
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006248 for (j = 0; j < pEseBcnReq->numBcnReqIe; j++)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006249 {
6250 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arun Kumar Khandavallie8768212014-02-17 16:43:34 +05306251 "Index(%d) Measurement Token(%u)Channel(%u) Scan Mode(%u) Measurement Duration(%u)\n",
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006252 j,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006253 pEseBcnReq->bcnReq[j].measurementToken,
6254 pEseBcnReq->bcnReq[j].channel,
6255 pEseBcnReq->bcnReq[j].scanMode,
6256 pEseBcnReq->bcnReq[j].measurementDuration);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006257 }
6258
6259 return VOS_STATUS_SUCCESS;
6260}
6261
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006262static void hdd_GetTsmStatsCB( tAniTrafStrmMetrics tsmMetrics, const tANI_U32 staId, void *pContext )
6263{
6264 struct statsContext *pStatsContext = NULL;
6265 hdd_adapter_t *pAdapter = NULL;
6266
6267 if (NULL == pContext)
6268 {
6269 hddLog(VOS_TRACE_LEVEL_ERROR,
6270 "%s: Bad param, pContext [%p]",
6271 __func__, pContext);
6272 return;
6273 }
6274
Jeff Johnson72a40512013-12-19 10:14:15 -08006275 /* there is a race condition that exists between this callback
6276 function and the caller since the caller could time out either
6277 before or while this code is executing. we use a spinlock to
6278 serialize these actions */
6279 spin_lock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006280
6281 pStatsContext = pContext;
6282 pAdapter = pStatsContext->pAdapter;
6283 if ((NULL == pAdapter) || (STATS_CONTEXT_MAGIC != pStatsContext->magic))
6284 {
6285 /* the caller presumably timed out so there is nothing we can do */
Jeff Johnson72a40512013-12-19 10:14:15 -08006286 spin_unlock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006287 hddLog(VOS_TRACE_LEVEL_WARN,
6288 "%s: Invalid context, pAdapter [%p] magic [%08x]",
6289 __func__, pAdapter, pStatsContext->magic);
6290 return;
6291 }
6292
Jeff Johnson72a40512013-12-19 10:14:15 -08006293 /* context is valid so caller is still waiting */
6294
6295 /* paranoia: invalidate the magic */
6296 pStatsContext->magic = 0;
6297
6298 /* copy over the tsm stats */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006299 pAdapter->tsmStats.UplinkPktQueueDly = tsmMetrics.UplinkPktQueueDly;
6300 vos_mem_copy(pAdapter->tsmStats.UplinkPktQueueDlyHist,
6301 tsmMetrics.UplinkPktQueueDlyHist,
6302 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
6303 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
6304 pAdapter->tsmStats.UplinkPktTxDly = tsmMetrics.UplinkPktTxDly;
6305 pAdapter->tsmStats.UplinkPktLoss = tsmMetrics.UplinkPktLoss;
6306 pAdapter->tsmStats.UplinkPktCount = tsmMetrics.UplinkPktCount;
6307 pAdapter->tsmStats.RoamingCount = tsmMetrics.RoamingCount;
6308 pAdapter->tsmStats.RoamingDly = tsmMetrics.RoamingDly;
6309
Jeff Johnson72a40512013-12-19 10:14:15 -08006310 /* notify the caller */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006311 complete(&pStatsContext->completion);
Jeff Johnson72a40512013-12-19 10:14:15 -08006312
6313 /* serialization is complete */
6314 spin_unlock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006315}
6316
6317
6318
6319static VOS_STATUS hdd_get_tsm_stats(hdd_adapter_t *pAdapter, const tANI_U8 tid,
6320 tAniTrafStrmMetrics* pTsmMetrics)
6321{
6322 hdd_station_ctx_t *pHddStaCtx = NULL;
6323 eHalStatus hstatus;
Jeff Johnson72a40512013-12-19 10:14:15 -08006324 VOS_STATUS vstatus = VOS_STATUS_SUCCESS;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006325 long lrc;
6326 struct statsContext context;
6327 hdd_context_t *pHddCtx = NULL;
6328
6329 if (NULL == pAdapter)
6330 {
6331 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: pAdapter is NULL", __func__);
6332 return VOS_STATUS_E_FAULT;
6333 }
6334
6335 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6336 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6337
6338 /* we are connected prepare our callback context */
6339 init_completion(&context.completion);
6340 context.pAdapter = pAdapter;
6341 context.magic = STATS_CONTEXT_MAGIC;
6342
6343 /* query tsm stats */
6344 hstatus = sme_GetTsmStats(pHddCtx->hHal, hdd_GetTsmStatsCB,
6345 pHddStaCtx->conn_info.staId[ 0 ],
6346 pHddStaCtx->conn_info.bssId,
6347 &context, pHddCtx->pvosContext, tid);
6348
6349 if (eHAL_STATUS_SUCCESS != hstatus)
6350 {
Jeff Johnson72a40512013-12-19 10:14:15 -08006351 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unable to retrieve statistics",
6352 __func__);
6353 vstatus = VOS_STATUS_E_FAULT;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006354 }
6355 else
6356 {
6357 /* request was sent -- wait for the response */
6358 lrc = wait_for_completion_interruptible_timeout(&context.completion,
6359 msecs_to_jiffies(WLAN_WAIT_TIME_STATS));
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006360 if (lrc <= 0)
6361 {
6362 hddLog(VOS_TRACE_LEVEL_ERROR,
6363 "%s: SME %s while retrieving statistics",
6364 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson72a40512013-12-19 10:14:15 -08006365 vstatus = VOS_STATUS_E_TIMEOUT;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006366 }
6367 }
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006368
Jeff Johnson72a40512013-12-19 10:14:15 -08006369 /* either we never sent a request, we sent a request and received a
6370 response or we sent a request and timed out. if we never sent a
6371 request or if we sent a request and got a response, we want to
6372 clear the magic out of paranoia. if we timed out there is a
6373 race condition such that the callback function could be
6374 executing at the same time we are. of primary concern is if the
6375 callback function had already verified the "magic" but had not
6376 yet set the completion variable when a timeout occurred. we
6377 serialize these activities by invalidating the magic while
6378 holding a shared spinlock which will cause us to block if the
6379 callback is currently executing */
6380 spin_lock(&hdd_context_lock);
6381 context.magic = 0;
6382 spin_unlock(&hdd_context_lock);
6383
6384 if (VOS_STATUS_SUCCESS == vstatus)
6385 {
6386 pTsmMetrics->UplinkPktQueueDly = pAdapter->tsmStats.UplinkPktQueueDly;
6387 vos_mem_copy(pTsmMetrics->UplinkPktQueueDlyHist,
6388 pAdapter->tsmStats.UplinkPktQueueDlyHist,
6389 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
6390 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
6391 pTsmMetrics->UplinkPktTxDly = pAdapter->tsmStats.UplinkPktTxDly;
6392 pTsmMetrics->UplinkPktLoss = pAdapter->tsmStats.UplinkPktLoss;
6393 pTsmMetrics->UplinkPktCount = pAdapter->tsmStats.UplinkPktCount;
6394 pTsmMetrics->RoamingCount = pAdapter->tsmStats.RoamingCount;
6395 pTsmMetrics->RoamingDly = pAdapter->tsmStats.RoamingDly;
6396 }
6397 return vstatus;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006398}
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006399#endif /*FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006400
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006401#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -08006402void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
6403{
6404 eCsrBand band = -1;
6405 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
6406 switch (band)
6407 {
6408 case eCSR_BAND_ALL:
6409 *pBand = WLAN_HDD_UI_BAND_AUTO;
6410 break;
6411
6412 case eCSR_BAND_24:
6413 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
6414 break;
6415
6416 case eCSR_BAND_5G:
6417 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
6418 break;
6419
6420 default:
6421 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
6422 *pBand = -1;
6423 break;
6424 }
6425}
6426
6427/**---------------------------------------------------------------------------
6428
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006429 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
6430
6431 This function parses the send action frame data passed in the format
6432 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
6433
Srinivas Girigowda56076852013-08-20 14:00:50 -07006434 \param - pValue Pointer to input data
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006435 \param - pTargetApBssid Pointer to target Ap bssid
6436 \param - pChannel Pointer to the Target AP channel
6437 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
6438 \param - pBuf Pointer to data
6439 \param - pBufLen Pointer to data length
6440
6441 \return - 0 for success non-zero for failure
6442
6443 --------------------------------------------------------------------------*/
6444VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
6445 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
6446{
6447 tANI_U8 *inPtr = pValue;
6448 tANI_U8 *dataEnd;
6449 int tempInt;
6450 int j = 0;
6451 int i = 0;
6452 int v = 0;
6453 tANI_U8 tempBuf[32];
6454 tANI_U8 tempByte = 0;
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08006455 /* 12 hexa decimal digits, 5 ':' and '\0' */
6456 tANI_U8 macAddress[18];
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006457
6458 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
6459 /*no argument after the command*/
6460 if (NULL == inPtr)
6461 {
6462 return -EINVAL;
6463 }
6464
6465 /*no space after the command*/
6466 else if (SPACE_ASCII_VALUE != *inPtr)
6467 {
6468 return -EINVAL;
6469 }
6470
6471 /*removing empty spaces*/
6472 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
6473
6474 /*no argument followed by spaces*/
6475 if ('\0' == *inPtr)
6476 {
6477 return -EINVAL;
6478 }
6479
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07006480 v = sscanf(inPtr, "%17s", macAddress);
6481 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006482 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07006483 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6484 "Invalid MAC address or All hex inputs are not read (%d)", v);
6485 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006486 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07006487
6488 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
6489 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
6490 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
6491 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
6492 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
6493 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006494
6495 /* point to the next argument */
6496 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
6497 /*no argument after the command*/
6498 if (NULL == inPtr) return -EINVAL;
6499
6500 /*removing empty spaces*/
6501 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
6502
6503 /*no argument followed by spaces*/
6504 if ('\0' == *inPtr)
6505 {
6506 return -EINVAL;
6507 }
6508
6509 /*getting the next argument ie the channel number */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08006510 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07006511 if (1 != v) return -EINVAL;
6512
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006513 v = kstrtos32(tempBuf, 10, &tempInt);
Agarwal Ashish353b3a82014-04-08 14:55:11 +05306514 if ( v < 0 || tempInt <= 0 || tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX )
Kiet Lambe150c22013-11-21 16:30:32 +05306515 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006516
6517 *pChannel = tempInt;
6518
6519 /* point to the next argument */
6520 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
6521 /*no argument after the command*/
6522 if (NULL == inPtr) return -EINVAL;
6523 /*removing empty spaces*/
6524 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
6525
6526 /*no argument followed by spaces*/
6527 if ('\0' == *inPtr)
6528 {
6529 return -EINVAL;
6530 }
6531
6532 /*getting the next argument ie the dwell time */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08006533 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07006534 if (1 != v) return -EINVAL;
6535
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006536 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda5a6e0672014-01-09 14:42:57 -08006537 if ( v < 0 || tempInt < 0) return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006538
6539 *pDwellTime = tempInt;
6540
6541 /* point to the next argument */
6542 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
6543 /*no argument after the command*/
6544 if (NULL == inPtr) return -EINVAL;
6545 /*removing empty spaces*/
6546 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
6547
6548 /*no argument followed by spaces*/
6549 if ('\0' == *inPtr)
6550 {
6551 return -EINVAL;
6552 }
6553
6554 /* find the length of data */
6555 dataEnd = inPtr;
6556 while(('\0' != *dataEnd) )
6557 {
6558 dataEnd++;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006559 }
Kiet Lambe150c22013-11-21 16:30:32 +05306560 *pBufLen = dataEnd - inPtr ;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006561 if ( *pBufLen <= 0) return -EINVAL;
6562
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07006563 /* Allocate the number of bytes based on the number of input characters
6564 whether it is even or odd.
6565 if the number of input characters are even, then we need N/2 byte.
6566 if the number of input characters are odd, then we need do (N+1)/2 to
6567 compensate rounding off.
6568 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
6569 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
6570 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006571 if (NULL == *pBuf)
6572 {
6573 hddLog(VOS_TRACE_LEVEL_FATAL,
6574 "%s: vos_mem_alloc failed ", __func__);
6575 return -EINVAL;
6576 }
6577
6578 /* the buffer received from the upper layer is character buffer,
6579 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
6580 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
6581 and f0 in 3rd location */
6582 for (i = 0, j = 0; j < *pBufLen; j += 2)
6583 {
Kiet Lambe150c22013-11-21 16:30:32 +05306584 if( j+1 == *pBufLen)
6585 {
6586 tempByte = hdd_parse_hex(inPtr[j]);
6587 }
6588 else
6589 {
6590 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
6591 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006592 (*pBuf)[i++] = tempByte;
6593 }
6594 *pBufLen = i;
6595 return VOS_STATUS_SUCCESS;
6596}
6597
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006598/**---------------------------------------------------------------------------
6599
Srinivas Girigowdade697412013-02-14 16:31:48 -08006600 \brief hdd_parse_channellist() - HDD Parse channel list
6601
6602 This function parses the channel list passed in the format
6603 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07006604 if the Number of channels (N) does not match with the actual number of channels passed
6605 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
6606 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
6607 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
6608 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08006609
6610 \param - pValue Pointer to input channel list
6611 \param - ChannelList Pointer to local output array to record channel list
6612 \param - pNumChannels Pointer to number of roam scan channels
6613
6614 \return - 0 for success non-zero for failure
6615
6616 --------------------------------------------------------------------------*/
6617VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
6618{
6619 tANI_U8 *inPtr = pValue;
6620 int tempInt;
6621 int j = 0;
6622 int v = 0;
6623 char buf[32];
6624
6625 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
6626 /*no argument after the command*/
6627 if (NULL == inPtr)
6628 {
6629 return -EINVAL;
6630 }
6631
6632 /*no space after the command*/
6633 else if (SPACE_ASCII_VALUE != *inPtr)
6634 {
6635 return -EINVAL;
6636 }
6637
6638 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07006639 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08006640
6641 /*no argument followed by spaces*/
6642 if ('\0' == *inPtr)
6643 {
6644 return -EINVAL;
6645 }
6646
6647 /*getting the first argument ie the number of channels*/
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08006648 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07006649 if (1 != v) return -EINVAL;
6650
Srinivas Girigowdade697412013-02-14 16:31:48 -08006651 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07006652 if ((v < 0) ||
6653 (tempInt <= 0) ||
6654 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
6655 {
6656 return -EINVAL;
6657 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08006658
6659 *pNumChannels = tempInt;
6660
6661 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
6662 "Number of channels are: %d", *pNumChannels);
6663
6664 for (j = 0; j < (*pNumChannels); j++)
6665 {
6666 /*inPtr pointing to the beginning of first space after number of channels*/
6667 inPtr = strpbrk( inPtr, " " );
6668 /*no channel list after the number of channels argument*/
6669 if (NULL == inPtr)
6670 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07006671 if (0 != j)
6672 {
6673 *pNumChannels = j;
6674 return VOS_STATUS_SUCCESS;
6675 }
6676 else
6677 {
6678 return -EINVAL;
6679 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08006680 }
6681
6682 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07006683 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08006684
6685 /*no channel list after the number of channels argument and spaces*/
6686 if ( '\0' == *inPtr )
6687 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07006688 if (0 != j)
6689 {
6690 *pNumChannels = j;
6691 return VOS_STATUS_SUCCESS;
6692 }
6693 else
6694 {
6695 return -EINVAL;
6696 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08006697 }
6698
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08006699 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07006700 if (1 != v) return -EINVAL;
6701
Srinivas Girigowdade697412013-02-14 16:31:48 -08006702 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07006703 if ((v < 0) ||
6704 (tempInt <= 0) ||
6705 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
6706 {
6707 return -EINVAL;
6708 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08006709 pChannelList[j] = tempInt;
6710
6711 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
6712 "Channel %d added to preferred channel list",
6713 pChannelList[j] );
6714 }
6715
Srinivas Girigowdade697412013-02-14 16:31:48 -08006716 return VOS_STATUS_SUCCESS;
6717}
6718
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07006719
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05306720/**
6721 * hdd_parse_reassoc_command_v1_data() - HDD Parse reassoc command data
6722 * This function parses the reasoc command data passed in the format
6723 * REASSOC<space><bssid><space><channel>
6724 *
6725 * @pValue: Pointer to input data (its a NUL terminated string)
6726 * @pTargetApBssid: Pointer to target Ap bssid
6727 * @pChannel: Pointer to the Target AP channel
6728 *
6729 * Return: 0 for success non-zero for failure
6730 */
6731static int hdd_parse_reassoc_command_v1_data(const tANI_U8 *pValue,
6732 tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07006733{
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05306734 const tANI_U8 *inPtr = pValue;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07006735 int tempInt;
6736 int v = 0;
6737 tANI_U8 tempBuf[32];
Kiet Lamaa8e15a2014-02-11 23:30:06 -08006738 /* 12 hexa decimal digits, 5 ':' and '\0' */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08006739 tANI_U8 macAddress[18];
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07006740
6741 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
6742 /*no argument after the command*/
6743 if (NULL == inPtr)
6744 {
6745 return -EINVAL;
6746 }
6747
6748 /*no space after the command*/
6749 else if (SPACE_ASCII_VALUE != *inPtr)
6750 {
6751 return -EINVAL;
6752 }
6753
6754 /*removing empty spaces*/
6755 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
6756
6757 /*no argument followed by spaces*/
6758 if ('\0' == *inPtr)
6759 {
6760 return -EINVAL;
6761 }
6762
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07006763 v = sscanf(inPtr, "%17s", macAddress);
6764 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07006765 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07006766 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6767 "Invalid MAC address or All hex inputs are not read (%d)", v);
6768 return -EINVAL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07006769 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07006770
6771 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
6772 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
6773 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
6774 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
6775 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
6776 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07006777
6778 /* point to the next argument */
6779 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
6780 /*no argument after the command*/
6781 if (NULL == inPtr) return -EINVAL;
6782
6783 /*removing empty spaces*/
6784 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
6785
6786 /*no argument followed by spaces*/
6787 if ('\0' == *inPtr)
6788 {
6789 return -EINVAL;
6790 }
6791
6792 /*getting the next argument ie the channel number */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08006793 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07006794 if (1 != v) return -EINVAL;
6795
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07006796 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07006797 if ((v < 0) ||
Padma, Santhosh Kumar0fa809b2014-11-13 14:56:56 +05306798 (tempInt < 0) ||
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07006799 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
6800 {
6801 return -EINVAL;
6802 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07006803
6804 *pChannel = tempInt;
6805 return VOS_STATUS_SUCCESS;
6806}
6807
6808#endif
6809
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006810#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006811/**---------------------------------------------------------------------------
6812
6813 \brief hdd_parse_get_cckm_ie() - HDD Parse and fetch the CCKM IE
6814
6815 This function parses the SETCCKM IE command
6816 SETCCKMIE<space><ie data>
6817
6818 \param - pValue Pointer to input data
6819 \param - pCckmIe Pointer to output cckm Ie
6820 \param - pCckmIeLen Pointer to output cckm ie length
6821
6822 \return - 0 for success non-zero for failure
6823
6824 --------------------------------------------------------------------------*/
6825VOS_STATUS hdd_parse_get_cckm_ie(tANI_U8 *pValue, tANI_U8 **pCckmIe,
6826 tANI_U8 *pCckmIeLen)
6827{
6828 tANI_U8 *inPtr = pValue;
6829 tANI_U8 *dataEnd;
6830 int j = 0;
6831 int i = 0;
6832 tANI_U8 tempByte = 0;
6833
6834 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
6835 /*no argument after the command*/
6836 if (NULL == inPtr)
6837 {
6838 return -EINVAL;
6839 }
6840
6841 /*no space after the command*/
6842 else if (SPACE_ASCII_VALUE != *inPtr)
6843 {
6844 return -EINVAL;
6845 }
6846
6847 /*removing empty spaces*/
6848 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
6849
6850 /*no argument followed by spaces*/
6851 if ('\0' == *inPtr)
6852 {
6853 return -EINVAL;
6854 }
6855
6856 /* find the length of data */
6857 dataEnd = inPtr;
6858 while(('\0' != *dataEnd) )
6859 {
6860 dataEnd++;
6861 ++(*pCckmIeLen);
6862 }
6863 if ( *pCckmIeLen <= 0) return -EINVAL;
6864
6865 /* Allocate the number of bytes based on the number of input characters
6866 whether it is even or odd.
6867 if the number of input characters are even, then we need N/2 byte.
6868 if the number of input characters are odd, then we need do (N+1)/2 to
6869 compensate rounding off.
6870 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
6871 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
6872 *pCckmIe = vos_mem_malloc((*pCckmIeLen + 1)/2);
6873 if (NULL == *pCckmIe)
6874 {
6875 hddLog(VOS_TRACE_LEVEL_FATAL,
6876 "%s: vos_mem_alloc failed ", __func__);
6877 return -EINVAL;
6878 }
6879 vos_mem_zero(*pCckmIe, (*pCckmIeLen + 1)/2);
6880 /* the buffer received from the upper layer is character buffer,
6881 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
6882 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
6883 and f0 in 3rd location */
6884 for (i = 0, j = 0; j < *pCckmIeLen; j += 2)
6885 {
6886 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
6887 (*pCckmIe)[i++] = tempByte;
6888 }
6889 *pCckmIeLen = i;
6890
6891 return VOS_STATUS_SUCCESS;
6892}
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006893#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006894
Jeff Johnson295189b2012-06-20 16:38:30 -07006895/**---------------------------------------------------------------------------
6896
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07006897 \brief hdd_is_valid_mac_address() - Validate MAC address
6898
6899 This function validates whether the given MAC address is valid or not
6900 Expected MAC address is of the format XX:XX:XX:XX:XX:XX
6901 where X is the hexa decimal digit character and separated by ':'
6902 This algorithm works even if MAC address is not separated by ':'
6903
6904 This code checks given input string mac contains exactly 12 hexadecimal digits.
6905 and a separator colon : appears in the input string only after
6906 an even number of hex digits.
6907
6908 \param - pMacAddr pointer to the input MAC address
6909 \return - 1 for valid and 0 for invalid
6910
6911 --------------------------------------------------------------------------*/
6912
6913v_BOOL_t hdd_is_valid_mac_address(const tANI_U8 *pMacAddr)
6914{
6915 int xdigit = 0;
6916 int separator = 0;
6917 while (*pMacAddr)
6918 {
6919 if (isxdigit(*pMacAddr))
6920 {
6921 xdigit++;
6922 }
6923 else if (':' == *pMacAddr)
6924 {
6925 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
6926 break;
6927
6928 ++separator;
6929 }
6930 else
6931 {
6932 separator = -1;
6933 /* Invalid MAC found */
6934 return 0;
6935 }
6936 ++pMacAddr;
6937 }
6938 return (xdigit == 12 && (separator == 5 || separator == 0));
6939}
6940
6941/**---------------------------------------------------------------------------
6942
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05306943 \brief __hdd_open() - HDD Open function
Jeff Johnson295189b2012-06-20 16:38:30 -07006944
6945 \param - dev Pointer to net_device structure
6946
6947 \return - 0 for success non-zero for failure
6948
6949 --------------------------------------------------------------------------*/
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05306950int __hdd_open(struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07006951{
6952 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6953 hdd_context_t *pHddCtx;
6954 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6955 VOS_STATUS status;
6956 v_BOOL_t in_standby = TRUE;
6957
6958 if (NULL == pAdapter)
6959 {
6960 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Agarwal Ashish971c2882013-10-30 20:11:12 +05306961 "%s: pAdapter is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006962 return -ENODEV;
6963 }
6964
6965 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05306966 MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_OPEN_REQUEST,
6967 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson295189b2012-06-20 16:38:30 -07006968 if (NULL == pHddCtx)
6969 {
6970 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006971 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006972 return -ENODEV;
6973 }
6974
6975 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6976 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
6977 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07006978 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
6979 {
6980 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306981 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07006982 in_standby = FALSE;
6983 break;
6984 }
6985 else
6986 {
6987 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6988 pAdapterNode = pNext;
6989 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006990 }
6991
6992 if (TRUE == in_standby)
6993 {
6994 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
6995 {
6996 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
6997 "wlan out of power save", __func__);
6998 return -EINVAL;
6999 }
7000 }
7001
Jeff Johnson6a81ca42013-04-05 10:37:08 -07007002 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07007003 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
7004 {
7005 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007006 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007007 /* Enable TX queues only when we are connected */
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05307008 hddLog(VOS_TRACE_LEVEL_INFO, FL("Enabling queues"));
Jeff Johnson295189b2012-06-20 16:38:30 -07007009 netif_tx_start_all_queues(dev);
7010 }
7011
7012 return 0;
7013}
7014
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307015/**---------------------------------------------------------------------------
7016
7017 \brief hdd_open() - Wrapper function for __hdd_open to protect it from SSR
7018
7019 This is called in response to ifconfig up
7020
7021 \param - dev Pointer to net_device structure
7022
7023 \return - 0 for success non-zero for failure
7024
7025 --------------------------------------------------------------------------*/
7026int hdd_open(struct net_device *dev)
7027{
7028 int ret;
7029
7030 vos_ssr_protect(__func__);
7031 ret = __hdd_open(dev);
7032 vos_ssr_unprotect(__func__);
7033
7034 return ret;
7035}
7036
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +05307037int __hdd_mon_open (struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07007038{
7039 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7040
7041 if(pAdapter == NULL) {
7042 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007043 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007044 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007045 }
7046
Jeff Johnson295189b2012-06-20 16:38:30 -07007047 return 0;
7048}
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +05307049
7050int hdd_mon_open (struct net_device *dev)
7051{
7052 int ret;
7053
7054 vos_ssr_protect(__func__);
7055 ret = __hdd_mon_open(dev);
7056 vos_ssr_unprotect(__func__);
7057
7058 return ret;
7059}
7060
Katya Nigame7b69a82015-04-28 15:24:06 +05307061int hdd_mon_stop(struct net_device *dev)
7062{
7063 return 0;
7064}
7065
Jeff Johnson295189b2012-06-20 16:38:30 -07007066/**---------------------------------------------------------------------------
7067
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307068 \brief __hdd_stop() - HDD stop function
Jeff Johnson295189b2012-06-20 16:38:30 -07007069
7070 \param - dev Pointer to net_device structure
7071
7072 \return - 0 for success non-zero for failure
7073
7074 --------------------------------------------------------------------------*/
7075
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307076int __hdd_stop (struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07007077{
Vinay Krishna Eranna90f43532014-10-27 16:45:54 +05307078 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07007079 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7080 hdd_context_t *pHddCtx;
7081 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7082 VOS_STATUS status;
7083 v_BOOL_t enter_standby = TRUE;
7084
7085 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07007086 if (NULL == pAdapter)
7087 {
7088 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Agarwal Ashish971c2882013-10-30 20:11:12 +05307089 "%s: pAdapter is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007090 return -ENODEV;
7091 }
Sachin Ahuja9b4958f2015-01-15 21:37:00 +05307092 MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_STOP_REQUEST,
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05307093 pAdapter->sessionId, pAdapter->device_mode));
Vinay Krishna Eranna90f43532014-10-27 16:45:54 +05307094
7095 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7096 ret = wlan_hdd_validate_context(pHddCtx);
7097 if (ret)
Jeff Johnson295189b2012-06-20 16:38:30 -07007098 {
Vinay Krishna Eranna90f43532014-10-27 16:45:54 +05307099 return ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07007100 }
7101
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307102 /* Nothing to be done if the interface is not opened */
7103 if (VOS_FALSE == test_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags))
7104 {
7105 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7106 "%s: NETDEV Interface is not OPENED", __func__);
7107 return -ENODEV;
7108 }
7109
7110 /* Make sure the interface is marked as closed */
Jeff Johnson6a81ca42013-04-05 10:37:08 -07007111 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07007112 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307113
7114 /* Disable TX on the interface, after this hard_start_xmit() will not
7115 * be called on that interface
7116 */
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05307117 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
Jeff Johnson295189b2012-06-20 16:38:30 -07007118 netif_tx_disable(pAdapter->dev);
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307119
7120 /* Mark the interface status as "down" for outside world */
Jeff Johnson295189b2012-06-20 16:38:30 -07007121 netif_carrier_off(pAdapter->dev);
7122
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307123 /* The interface is marked as down for outside world (aka kernel)
7124 * But the driver is pretty much alive inside. The driver needs to
7125 * tear down the existing connection on the netdev (session)
7126 * cleanup the data pipes and wait until the control plane is stabilized
7127 * for this interface. The call also needs to wait until the above
7128 * mentioned actions are completed before returning to the caller.
7129 * Notice that the hdd_stop_adapter is requested not to close the session
7130 * That is intentional to be able to scan if it is a STA/P2P interface
7131 */
7132 hdd_stop_adapter(pHddCtx, pAdapter, VOS_FALSE);
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05307133#ifdef FEATURE_WLAN_TDLS
7134 mutex_lock(&pHddCtx->tdls_lock);
7135#endif
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307136 /* DeInit the adapter. This ensures datapath cleanup as well */
c_hpothu002231a2015-02-05 14:58:51 +05307137 hdd_deinit_adapter(pHddCtx, pAdapter, TRUE);
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05307138#ifdef FEATURE_WLAN_TDLS
7139 mutex_unlock(&pHddCtx->tdls_lock);
7140#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007141 /* SoftAP ifaces should never go in power save mode
7142 making sure same here. */
7143 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
7144 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07007145 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07007146 )
7147 {
7148 /* SoftAP mode, so return from here */
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307149 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
7150 "%s: In SAP MODE", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007151 EXIT();
7152 return 0;
7153 }
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307154 /* Find if any iface is up. If any iface is up then can't put device to
7155 * sleep/power save mode
7156 */
Jeff Johnson295189b2012-06-20 16:38:30 -07007157 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7158 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
7159 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07007160 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
7161 {
7162 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307163 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07007164 enter_standby = FALSE;
7165 break;
7166 }
7167 else
7168 {
7169 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7170 pAdapterNode = pNext;
7171 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007172 }
7173
7174 if (TRUE == enter_standby)
7175 {
7176 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
7177 "entering standby", __func__);
7178 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
7179 {
7180 /*log and return success*/
7181 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
7182 "wlan in power save", __func__);
7183 }
7184 }
7185
7186 EXIT();
7187 return 0;
7188}
7189
7190/**---------------------------------------------------------------------------
7191
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307192 \brief hdd_stop() - wrapper_function for __hdd_stop to protect it from SSR
Jeff Johnson295189b2012-06-20 16:38:30 -07007193
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307194 This is called in response to ifconfig down
7195
7196 \param - dev Pointer to net_device structure
7197
7198 \return - 0 for success non-zero for failure
7199-----------------------------------------------------------------------------*/
7200int hdd_stop (struct net_device *dev)
7201{
7202 int ret;
7203
7204 vos_ssr_protect(__func__);
7205 ret = __hdd_stop(dev);
7206 vos_ssr_unprotect(__func__);
7207
7208 return ret;
7209}
7210
7211/**---------------------------------------------------------------------------
7212
7213 \brief __hdd_uninit() - HDD uninit function
Jeff Johnson295189b2012-06-20 16:38:30 -07007214
7215 \param - dev Pointer to net_device structure
7216
7217 \return - void
7218
7219 --------------------------------------------------------------------------*/
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307220static void __hdd_uninit (struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07007221{
7222 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05307223 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07007224 ENTER();
7225
7226 do
7227 {
7228 if (NULL == pAdapter)
7229 {
7230 hddLog(VOS_TRACE_LEVEL_FATAL,
7231 "%s: NULL pAdapter", __func__);
7232 break;
7233 }
7234
7235 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
7236 {
7237 hddLog(VOS_TRACE_LEVEL_FATAL,
7238 "%s: Invalid magic", __func__);
7239 break;
7240 }
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05307241 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7242 if (NULL == pHddCtx)
Jeff Johnson295189b2012-06-20 16:38:30 -07007243 {
7244 hddLog(VOS_TRACE_LEVEL_FATAL,
7245 "%s: NULL pHddCtx", __func__);
7246 break;
7247 }
7248
7249 if (dev != pAdapter->dev)
7250 {
7251 hddLog(VOS_TRACE_LEVEL_FATAL,
7252 "%s: Invalid device reference", __func__);
7253 /* we haven't validated all cases so let this go for now */
7254 }
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05307255#ifdef FEATURE_WLAN_TDLS
7256 mutex_lock(&pHddCtx->tdls_lock);
7257#endif
c_hpothu002231a2015-02-05 14:58:51 +05307258 hdd_deinit_adapter(pHddCtx, pAdapter, TRUE);
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05307259#ifdef FEATURE_WLAN_TDLS
7260 mutex_unlock(&pHddCtx->tdls_lock);
7261#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007262
7263 /* after uninit our adapter structure will no longer be valid */
7264 pAdapter->dev = NULL;
7265 pAdapter->magic = 0;
Manjeet Singh47ee8472016-04-11 11:57:18 +05307266 pAdapter->pHddCtx = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007267 } while (0);
7268
7269 EXIT();
7270}
7271
7272/**---------------------------------------------------------------------------
7273
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307274 \brief hdd_uninit() - Wrapper function to protect __hdd_uninit from SSR
7275
7276 This is called during the netdev unregister to uninitialize all data
7277associated with the device
7278
7279 \param - dev Pointer to net_device structure
7280
7281 \return - void
7282
7283 --------------------------------------------------------------------------*/
7284static void hdd_uninit (struct net_device *dev)
7285{
7286 vos_ssr_protect(__func__);
7287 __hdd_uninit(dev);
7288 vos_ssr_unprotect(__func__);
7289}
7290
7291/**---------------------------------------------------------------------------
7292
Jeff Johnson295189b2012-06-20 16:38:30 -07007293 \brief hdd_release_firmware() -
7294
7295 This function calls the release firmware API to free the firmware buffer.
7296
7297 \param - pFileName Pointer to the File Name.
7298 pCtx - Pointer to the adapter .
7299
7300
7301 \return - 0 for success, non zero for failure
7302
7303 --------------------------------------------------------------------------*/
7304
7305VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
7306{
7307 VOS_STATUS status = VOS_STATUS_SUCCESS;
7308 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
7309 ENTER();
7310
7311
7312 if (!strcmp(WLAN_FW_FILE, pFileName)) {
7313
7314 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
7315
7316 if(pHddCtx->fw) {
7317 release_firmware(pHddCtx->fw);
7318 pHddCtx->fw = NULL;
7319 }
7320 else
7321 status = VOS_STATUS_E_FAILURE;
7322 }
7323 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
7324 if(pHddCtx->nv) {
7325 release_firmware(pHddCtx->nv);
7326 pHddCtx->nv = NULL;
7327 }
7328 else
7329 status = VOS_STATUS_E_FAILURE;
7330
7331 }
7332
7333 EXIT();
7334 return status;
7335}
7336
7337/**---------------------------------------------------------------------------
7338
7339 \brief hdd_request_firmware() -
7340
7341 This function reads the firmware file using the request firmware
7342 API and returns the the firmware data and the firmware file size.
7343
7344 \param - pfileName - Pointer to the file name.
7345 - pCtx - Pointer to the adapter .
7346 - ppfw_data - Pointer to the pointer of the firmware data.
7347 - pSize - Pointer to the file size.
7348
7349 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
7350
7351 --------------------------------------------------------------------------*/
7352
7353
7354VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
7355{
7356 int status;
7357 VOS_STATUS retval = VOS_STATUS_SUCCESS;
7358 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
7359 ENTER();
7360
7361 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
7362
7363 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
7364
7365 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
7366 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
7367 __func__, pfileName);
7368 retval = VOS_STATUS_E_FAILURE;
7369 }
7370
7371 else {
7372 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
7373 *pSize = pHddCtx->fw->size;
7374 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
7375 __func__, *pSize);
7376 }
7377 }
7378 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
7379
7380 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
7381
7382 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
7383 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
7384 __func__, pfileName);
7385 retval = VOS_STATUS_E_FAILURE;
7386 }
7387
7388 else {
7389 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
7390 *pSize = pHddCtx->nv->size;
7391 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
7392 __func__, *pSize);
7393 }
7394 }
7395
7396 EXIT();
7397 return retval;
7398}
7399/**---------------------------------------------------------------------------
7400 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
7401
7402 This is the function invoked by SME to inform the result of a full power
7403 request issued by HDD
7404
7405 \param - callbackcontext - Pointer to cookie
7406 status - result of request
7407
7408 \return - None
7409
7410--------------------------------------------------------------------------*/
7411void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
7412{
7413 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
7414
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07007415 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07007416 if(&pHddCtx->full_pwr_comp_var)
7417 {
7418 complete(&pHddCtx->full_pwr_comp_var);
7419 }
7420}
7421
Abhishek Singh00b71972016-01-07 10:51:04 +05307422#ifdef WLAN_FEATURE_RMC
7423static void hdd_tx_fail_ind_callback(v_U8_t *MacAddr, v_U8_t seqNo)
7424{
7425 int payload_len;
7426 struct sk_buff *skb;
7427 struct nlmsghdr *nlh;
7428 v_U8_t *data;
7429
7430 payload_len = ETH_ALEN;
7431
7432 if (0 == cesium_pid)
7433 {
7434 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: cesium process not registered",
7435 __func__);
7436 return;
7437 }
7438
7439 if ((skb = nlmsg_new(payload_len,GFP_ATOMIC)) == NULL)
7440 {
7441 hddLog(VOS_TRACE_LEVEL_ERROR,
7442 "%s: nlmsg_new() failed for msg size[%d]",
7443 __func__, NLMSG_SPACE(payload_len));
7444 return;
7445 }
7446
7447 nlh = nlmsg_put(skb, cesium_pid, seqNo, 0, payload_len, NLM_F_REQUEST);
7448
7449 if (NULL == nlh)
7450 {
7451 hddLog(VOS_TRACE_LEVEL_ERROR,
7452 "%s: nlmsg_put() failed for msg size[%d]",
7453 __func__, NLMSG_SPACE(payload_len));
7454
7455 kfree_skb(skb);
7456 return;
7457 }
7458
7459 data = nlmsg_data(nlh);
7460 memcpy(data, MacAddr, ETH_ALEN);
7461
7462 if (nlmsg_unicast(cesium_nl_srv_sock, skb, cesium_pid) < 0)
7463 {
7464 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: nlmsg_unicast() failed for msg size[%d]",
7465 __func__, NLMSG_SPACE(payload_len));
7466 }
7467
7468 return;
7469}
7470
7471/**---------------------------------------------------------------------------
7472 \brief hdd_ParseuserParams - return a pointer to the next argument
7473
7474 \return - status
7475
7476--------------------------------------------------------------------------*/
7477static int hdd_ParseUserParams(tANI_U8 *pValue, tANI_U8 **ppArg)
7478{
7479 tANI_U8 *pVal;
7480
7481 pVal = strchr(pValue, ' ');
7482
7483 if (NULL == pVal)
7484 {
7485 /* no argument remains */
7486 return -EINVAL;
7487 }
7488 else if (SPACE_ASCII_VALUE != *pVal)
7489 {
7490 /* no space after the current argument */
7491 return -EINVAL;
7492 }
7493
7494 pVal++;
7495
7496 /* remove empty spaces */
7497 while ((SPACE_ASCII_VALUE == *pVal) && ('\0' != *pVal))
7498 {
7499 pVal++;
7500 }
7501
7502 /* no argument followed by spaces */
7503 if ('\0' == *pVal)
7504 {
7505 return -EINVAL;
7506 }
7507
7508 *ppArg = pVal;
7509
7510 return 0;
7511}
7512
7513/**----------------------------------------------------------------------------
7514 \brief hdd_ParseIBSSTXFailEventParams - Parse params for SETIBSSTXFAILEVENT
7515
7516 \return - status
7517
7518------------------------------------------------------------------------------*/
7519static int hdd_ParseIBSSTXFailEventParams(tANI_U8 *pValue,
7520 tANI_U8 *tx_fail_count,
7521 tANI_U16 *pid)
7522{
7523 tANI_U8 *param = NULL;
7524 int ret;
7525
7526 ret = hdd_ParseUserParams(pValue, &param);
7527
7528 if (0 == ret && NULL != param)
7529 {
7530 if (1 != sscanf(param, "%hhu", tx_fail_count))
7531 {
7532 ret = -EINVAL;
7533 goto done;
7534 }
7535 }
7536 else
7537 {
7538 goto done;
7539 }
7540
7541 if (0 == *tx_fail_count)
7542 {
7543 *pid = 0;
7544 goto done;
7545 }
7546
7547 pValue = param;
7548 pValue++;
7549
7550 ret = hdd_ParseUserParams(pValue, &param);
7551
7552 if (0 == ret)
7553 {
7554 if (1 != sscanf(param, "%hu", pid))
7555 {
7556 ret = -EINVAL;
7557 goto done;
7558 }
7559 }
7560 else
7561 {
7562 goto done;
7563 }
7564
7565done:
7566 return ret;
7567}
7568
7569static int hdd_open_cesium_nl_sock()
7570{
7571#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
7572 struct netlink_kernel_cfg cfg = {
7573 .groups = WLAN_NLINK_MCAST_GRP_ID,
7574 .input = NULL
7575 };
7576#endif
7577 int ret = 0;
7578
7579#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
7580 cesium_nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_CESIUM,
7581#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0))
7582 THIS_MODULE,
7583#endif
7584 &cfg);
7585#else
7586 cesium_nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_CESIUM,
7587 WLAN_NLINK_MCAST_GRP_ID, NULL, NULL, THIS_MODULE);
7588#endif
7589
7590 if (cesium_nl_srv_sock == NULL)
7591 {
7592 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7593 "NLINK: cesium netlink_kernel_create failed");
7594 ret = -ECONNREFUSED;
7595 }
7596
7597 return ret;
7598}
7599
7600static void hdd_close_cesium_nl_sock()
7601{
7602 if (NULL != cesium_nl_srv_sock)
7603 {
7604 netlink_kernel_release(cesium_nl_srv_sock);
7605 cesium_nl_srv_sock = NULL;
7606 }
7607}
7608#endif /* WLAN_FEATURE_RMC */
Jeff Johnson295189b2012-06-20 16:38:30 -07007609/**---------------------------------------------------------------------------
7610
7611 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
7612
7613 This is the function invoked by SME to inform the result of BMPS
7614 request issued by HDD
7615
7616 \param - callbackcontext - Pointer to cookie
7617 status - result of request
7618
7619 \return - None
7620
7621--------------------------------------------------------------------------*/
7622void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
7623{
7624
7625 struct completion *completion_var = (struct completion*) callbackContext;
7626
Arif Hussain6d2a3322013-11-17 19:50:10 -08007627 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07007628 if(completion_var != NULL)
7629 {
7630 complete(completion_var);
7631 }
7632}
7633
7634/**---------------------------------------------------------------------------
7635
7636 \brief hdd_get_cfg_file_size() -
7637
7638 This function reads the configuration file using the request firmware
7639 API and returns the configuration file size.
7640
7641 \param - pCtx - Pointer to the adapter .
7642 - pFileName - Pointer to the file name.
7643 - pBufSize - Pointer to the buffer size.
7644
7645 \return - 0 for success, non zero for failure
7646
7647 --------------------------------------------------------------------------*/
7648
7649VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
7650{
7651 int status;
7652 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
7653
7654 ENTER();
7655
7656 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
7657
7658 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
7659 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
7660 status = VOS_STATUS_E_FAILURE;
7661 }
7662 else {
7663 *pBufSize = pHddCtx->fw->size;
7664 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
7665 release_firmware(pHddCtx->fw);
7666 pHddCtx->fw = NULL;
7667 }
7668
7669 EXIT();
7670 return VOS_STATUS_SUCCESS;
7671}
7672
7673/**---------------------------------------------------------------------------
7674
7675 \brief hdd_read_cfg_file() -
7676
7677 This function reads the configuration file using the request firmware
7678 API and returns the cfg data and the buffer size of the configuration file.
7679
7680 \param - pCtx - Pointer to the adapter .
7681 - pFileName - Pointer to the file name.
7682 - pBuffer - Pointer to the data buffer.
7683 - pBufSize - Pointer to the buffer size.
7684
7685 \return - 0 for success, non zero for failure
7686
7687 --------------------------------------------------------------------------*/
7688
7689VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
7690 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
7691{
7692 int status;
7693 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
7694
7695 ENTER();
7696
7697 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
7698
7699 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
7700 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
7701 return VOS_STATUS_E_FAILURE;
7702 }
7703 else {
7704 if(*pBufSize != pHddCtx->fw->size) {
7705 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
7706 "file size", __func__);
7707 release_firmware(pHddCtx->fw);
7708 pHddCtx->fw = NULL;
7709 return VOS_STATUS_E_FAILURE;
7710 }
7711 else {
7712 if(pBuffer) {
7713 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
7714 }
7715 release_firmware(pHddCtx->fw);
7716 pHddCtx->fw = NULL;
7717 }
7718 }
7719
7720 EXIT();
7721
7722 return VOS_STATUS_SUCCESS;
7723}
7724
7725/**---------------------------------------------------------------------------
7726
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307727 \brief __hdd_set_mac_address() -
Jeff Johnson295189b2012-06-20 16:38:30 -07007728
7729 This function sets the user specified mac address using
7730 the command ifconfig wlanX hw ether <mac adress>.
7731
7732 \param - dev - Pointer to the net device.
7733 - addr - Pointer to the sockaddr.
7734 \return - 0 for success, non zero for failure
7735
7736 --------------------------------------------------------------------------*/
7737
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307738static int __hdd_set_mac_address(struct net_device *dev, void *addr)
Jeff Johnson295189b2012-06-20 16:38:30 -07007739{
Mahesh A Saptasagar74088392015-02-05 17:22:09 +05307740 hdd_adapter_t *pAdapter;
7741 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07007742 struct sockaddr *psta_mac_addr = addr;
7743 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
Mahesh A Saptasagar74088392015-02-05 17:22:09 +05307744 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07007745
7746 ENTER();
Mahesh A Saptasagar74088392015-02-05 17:22:09 +05307747 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7748 if (NULL == pAdapter)
7749 {
7750 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7751 "%s: Adapter is NULL",__func__);
7752 return -EINVAL;
7753 }
7754 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7755 ret = wlan_hdd_validate_context(pHddCtx);
7756 if (0 != ret)
7757 {
Mahesh A Saptasagar74088392015-02-05 17:22:09 +05307758 return ret;
7759 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007760
7761 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
Jeff Johnson295189b2012-06-20 16:38:30 -07007762 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
7763
7764 EXIT();
7765 return halStatus;
7766}
7767
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307768/**---------------------------------------------------------------------------
7769
7770 \brief hdd_set_mac_address() -
7771
7772 Wrapper function to protect __hdd_set_mac_address() function from ssr
7773
7774 \param - dev - Pointer to the net device.
7775 - addr - Pointer to the sockaddr.
7776 \return - 0 for success, non zero for failure
7777
7778 --------------------------------------------------------------------------*/
7779static int hdd_set_mac_address(struct net_device *dev, void *addr)
7780{
7781 int ret;
7782
7783 vos_ssr_protect(__func__);
7784 ret = __hdd_set_mac_address(dev, addr);
7785 vos_ssr_unprotect(__func__);
7786
7787 return ret;
7788}
7789
Jeff Johnson295189b2012-06-20 16:38:30 -07007790tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
7791{
7792 int i;
7793 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
7794 {
Abhishek Singheb183782014-02-06 13:37:21 +05307795 if( 0 == ((pHddCtx->cfg_ini->intfAddrMask) & (1 << i)) )
Jeff Johnson295189b2012-06-20 16:38:30 -07007796 break;
7797 }
7798
7799 if( VOS_MAX_CONCURRENCY_PERSONA == i)
7800 return NULL;
7801
7802 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
7803 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
7804}
7805
7806void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
7807{
7808 int i;
7809 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
7810 {
7811 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
7812 {
7813 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
7814 break;
7815 }
7816 }
7817 return;
7818}
7819
7820#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
7821 static struct net_device_ops wlan_drv_ops = {
7822 .ndo_open = hdd_open,
7823 .ndo_stop = hdd_stop,
7824 .ndo_uninit = hdd_uninit,
7825 .ndo_start_xmit = hdd_hard_start_xmit,
7826 .ndo_tx_timeout = hdd_tx_timeout,
7827 .ndo_get_stats = hdd_stats,
7828 .ndo_do_ioctl = hdd_ioctl,
7829 .ndo_set_mac_address = hdd_set_mac_address,
7830 .ndo_select_queue = hdd_select_queue,
7831#ifdef WLAN_FEATURE_PACKET_FILTERING
7832#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
7833 .ndo_set_rx_mode = hdd_set_multicast_list,
7834#else
7835 .ndo_set_multicast_list = hdd_set_multicast_list,
7836#endif //LINUX_VERSION_CODE
7837#endif
7838 };
Jeff Johnson295189b2012-06-20 16:38:30 -07007839 static struct net_device_ops wlan_mon_drv_ops = {
7840 .ndo_open = hdd_mon_open,
Katya Nigame7b69a82015-04-28 15:24:06 +05307841 .ndo_stop = hdd_mon_stop,
Jeff Johnson295189b2012-06-20 16:38:30 -07007842 .ndo_uninit = hdd_uninit,
7843 .ndo_start_xmit = hdd_mon_hard_start_xmit,
7844 .ndo_tx_timeout = hdd_tx_timeout,
7845 .ndo_get_stats = hdd_stats,
Katya Nigame7b69a82015-04-28 15:24:06 +05307846 .ndo_do_ioctl = hdd_mon_ioctl,
Jeff Johnson295189b2012-06-20 16:38:30 -07007847 .ndo_set_mac_address = hdd_set_mac_address,
7848 };
Mahesh A Saptasagar305e2632015-03-04 12:57:33 +05307849
Jeff Johnson295189b2012-06-20 16:38:30 -07007850#endif
7851
7852void hdd_set_station_ops( struct net_device *pWlanDev )
7853{
7854#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
Jeff Johnson295189b2012-06-20 16:38:30 -07007855 pWlanDev->netdev_ops = &wlan_drv_ops;
7856#else
7857 pWlanDev->open = hdd_open;
7858 pWlanDev->stop = hdd_stop;
7859 pWlanDev->uninit = hdd_uninit;
7860 pWlanDev->hard_start_xmit = NULL;
7861 pWlanDev->tx_timeout = hdd_tx_timeout;
7862 pWlanDev->get_stats = hdd_stats;
7863 pWlanDev->do_ioctl = hdd_ioctl;
Jeff Johnson295189b2012-06-20 16:38:30 -07007864 pWlanDev->set_mac_address = hdd_set_mac_address;
7865#endif
7866}
7867
Katya Nigam1fd24402015-02-16 14:52:19 +05307868void hdd_set_ibss_ops( hdd_adapter_t *pAdapter )
7869{
7870 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
7871 wlan_drv_ops.ndo_start_xmit = hdd_ibss_hard_start_xmit;
7872 #else
7873 pAdapter->dev->hard_start_xmit = hdd_ibss_hard_start_xmit;
7874 #endif
7875}
7876
Jeff Johnsoneed415b2013-01-18 16:11:20 -08007877static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07007878{
7879 struct net_device *pWlanDev = NULL;
7880 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007881 /*
7882 * cfg80211 initialization and registration....
7883 */
Anand N Sunkadc34abbd2015-07-29 09:52:59 +05307884 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name,
7885#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0))
7886 NET_NAME_UNKNOWN,
7887#endif
7888 ether_setup, NUM_TX_QUEUES);
Jeff Johnson295189b2012-06-20 16:38:30 -07007889 if(pWlanDev != NULL)
7890 {
7891
7892 //Save the pointer to the net_device in the HDD adapter
7893 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
7894
Jeff Johnson295189b2012-06-20 16:38:30 -07007895 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
7896
7897 pAdapter->dev = pWlanDev;
7898 pAdapter->pHddCtx = pHddCtx;
7899 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
Agarwal Ashish47d18112014-08-04 19:55:07 +05307900 spin_lock_init(&pAdapter->lock_for_active_session);
Jeff Johnson295189b2012-06-20 16:38:30 -07007901
Rajeev79dbe4c2013-10-05 11:03:42 +05307902#ifdef FEATURE_WLAN_BATCH_SCAN
Rajeev79dbe4c2013-10-05 11:03:42 +05307903 pAdapter->pBatchScanRsp = NULL;
7904 pAdapter->numScanList = 0;
Rajeev Kumar20140c12013-10-21 19:39:02 -07007905 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
Kiet Lamaa8e15a2014-02-11 23:30:06 -08007906 pAdapter->prev_batch_id = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05307907 mutex_init(&pAdapter->hdd_batch_scan_lock);
7908#endif
7909
Jeff Johnson295189b2012-06-20 16:38:30 -07007910 pAdapter->isLinkUpSvcNeeded = FALSE;
7911 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
7912 //Init the net_device structure
7913 strlcpy(pWlanDev->name, name, IFNAMSIZ);
7914
7915 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
7916 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
7917 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
7918 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
7919
7920 hdd_set_station_ops( pAdapter->dev );
7921
7922 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07007923 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
7924 pAdapter->wdev.wiphy = pHddCtx->wiphy;
7925 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07007926 /* set pWlanDev's parent to underlying device */
7927 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
Kumar Anand82c009f2014-05-29 00:29:42 -07007928
7929 hdd_wmm_init( pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07007930 }
7931
7932 return pAdapter;
7933}
7934
7935VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
7936{
7937 struct net_device *pWlanDev = pAdapter->dev;
7938 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
7939 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
7940 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
7941
7942 if( rtnl_lock_held )
7943 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08007944 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07007945 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
7946 {
7947 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
7948 return VOS_STATUS_E_FAILURE;
7949 }
7950 }
7951 if (register_netdevice(pWlanDev))
7952 {
7953 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
7954 return VOS_STATUS_E_FAILURE;
7955 }
7956 }
7957 else
7958 {
7959 if(register_netdev(pWlanDev))
7960 {
7961 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
7962 return VOS_STATUS_E_FAILURE;
7963 }
7964 }
7965 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
7966
7967 return VOS_STATUS_SUCCESS;
7968}
7969
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07007970static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07007971{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07007972 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07007973
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07007974 if (NULL == pAdapter)
7975 {
7976 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
7977 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07007978 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07007979
7980 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
7981 {
7982 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
7983 return eHAL_STATUS_NOT_INITIALIZED;
7984 }
7985
7986 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
7987
Sameer Thalappilbee426e2013-10-30 10:30:30 -07007988#ifndef WLAN_OPEN_SOURCE
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07007989 /* need to make sure all of our scheduled work has completed.
7990 * This callback is called from MC thread context, so it is safe to
7991 * to call below flush workqueue API from here.
Sameer Thalappilbee426e2013-10-30 10:30:30 -07007992 *
7993 * Even though this is called from MC thread context, if there is a faulty
7994 * work item in the system, that can hang this call forever. So flushing
7995 * this global work queue is not safe; and now we make sure that
7996 * individual work queues are stopped correctly. But the cancel work queue
7997 * is a GPL only API, so the proprietary version of the driver would still
7998 * rely on the global work queue flush.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07007999 */
8000 flush_scheduled_work();
Sameer Thalappilbee426e2013-10-30 10:30:30 -07008001#endif
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008002
8003 /* We can be blocked while waiting for scheduled work to be
8004 * flushed, and the adapter structure can potentially be freed, in
8005 * which case the magic will have been reset. So make sure the
8006 * magic is still good, and hence the adapter structure is still
8007 * valid, before signaling completion */
8008 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
8009 {
8010 complete(&pAdapter->session_close_comp_var);
8011 }
8012
Jeff Johnson295189b2012-06-20 16:38:30 -07008013 return eHAL_STATUS_SUCCESS;
8014}
Manjeet Singh47ee8472016-04-11 11:57:18 +05308015/**
8016 * hdd_close_tx_queues() - close tx queues
8017 * @hdd_ctx: hdd global context
8018 *
8019 * Return: None
8020 */
8021static void hdd_close_tx_queues(hdd_context_t *hdd_ctx)
8022{
8023 VOS_STATUS status;
8024 hdd_adapter_t *adapter;
8025 hdd_adapter_list_node_t *adapter_node = NULL, *next_adapter = NULL;
8026 /* Not validating hdd_ctx as it's already done by the caller */
8027 ENTER();
8028 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
8029 while (NULL != adapter_node && VOS_STATUS_SUCCESS == status) {
8030 adapter = adapter_node->pAdapter;
8031 if (adapter && adapter->dev) {
8032 netif_tx_disable (adapter->dev);
8033 netif_carrier_off(adapter->dev);
8034 }
8035 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
8036 &next_adapter);
8037 adapter_node = next_adapter;
8038 }
8039 EXIT();
8040}
Jeff Johnson295189b2012-06-20 16:38:30 -07008041
8042VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
8043{
8044 struct net_device *pWlanDev = pAdapter->dev;
8045 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
8046 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
8047 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
8048 VOS_STATUS status = VOS_STATUS_E_FAILURE;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308049 long rc = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07008050
Nirav Shah7e3c8132015-06-22 23:51:42 +05308051 spin_lock_init( &pAdapter->sta_hash_lock);
8052 pAdapter->is_sta_id_hash_initialized = VOS_FALSE;
8053
Jeff Johnson295189b2012-06-20 16:38:30 -07008054 INIT_COMPLETION(pAdapter->session_open_comp_var);
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07008055 sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07008056 //Open a SME session for future operation
8057 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07008058 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07008059 if ( !HAL_STATUS_SUCCESS( halStatus ) )
8060 {
8061 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07008062 "sme_OpenSession() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07008063 halStatus, halStatus );
8064 status = VOS_STATUS_E_FAILURE;
8065 goto error_sme_open;
8066 }
8067
8068 //Block on a completion variable. Can't wait forever though.
Vinay Krishna Eranna0fe2e7c2014-04-09 21:32:08 +05308069 rc = wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07008070 &pAdapter->session_open_comp_var,
8071 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308072 if (rc <= 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07008073 {
8074 hddLog(VOS_TRACE_LEVEL_FATAL,
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308075 "Session is not opened within timeout period code %ld", rc );
Jeff Johnson295189b2012-06-20 16:38:30 -07008076 status = VOS_STATUS_E_FAILURE;
8077 goto error_sme_open;
8078 }
8079
8080 // Register wireless extensions
8081 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
8082 {
8083 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07008084 "hdd_register_wext() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07008085 halStatus, halStatus );
8086 status = VOS_STATUS_E_FAILURE;
8087 goto error_register_wext;
8088 }
Katya Nigam1fd24402015-02-16 14:52:19 +05308089
Jeff Johnson295189b2012-06-20 16:38:30 -07008090 //Safe to register the hard_start_xmit function again
Katya Nigam1fd24402015-02-16 14:52:19 +05308091 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
8092 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
8093 #else
8094 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
8095 #endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008096
8097 //Set the Connection State to Not Connected
Abhishek Singhf4669da2014-05-26 15:07:49 +05308098 hddLog(VOS_TRACE_LEVEL_INFO,
8099 "%s: Set HDD connState to eConnectionState_NotConnected",
8100 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008101 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
8102
8103 //Set the default operation channel
8104 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
8105
8106 /* Make the default Auth Type as OPEN*/
8107 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
8108
8109 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
8110 {
8111 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07008112 "hdd_init_tx_rx() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07008113 status, status );
8114 goto error_init_txrx;
8115 }
8116
8117 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
8118
8119 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
8120 {
8121 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07008122 "hdd_wmm_adapter_init() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07008123 status, status );
8124 goto error_wmm_init;
8125 }
8126
8127 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
8128
8129 return VOS_STATUS_SUCCESS;
8130
8131error_wmm_init:
8132 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
8133 hdd_deinit_tx_rx(pAdapter);
8134error_init_txrx:
8135 hdd_UnregisterWext(pWlanDev);
8136error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008137 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07008138 {
8139 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008140 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Agrawal Ashish5a3522c2016-03-02 15:08:28 +05308141 pAdapter->sessionId, FALSE, VOS_TRUE,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008142 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07008143 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308144 unsigned long rc;
8145
Jeff Johnson295189b2012-06-20 16:38:30 -07008146 //Block on a completion variable. Can't wait forever though.
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308147 rc = wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07008148 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008149 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308150 if (rc <= 0)
8151 hddLog(VOS_TRACE_LEVEL_ERROR,
8152 FL("Session is not opened within timeout period code %ld"), rc);
Jeff Johnson295189b2012-06-20 16:38:30 -07008153 }
8154}
8155error_sme_open:
8156 return status;
8157}
8158
Jeff Johnson295189b2012-06-20 16:38:30 -07008159void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
8160{
8161 hdd_cfg80211_state_t *cfgState;
8162
8163 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
8164
8165 if( NULL != cfgState->buf )
8166 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308167 long rc;
Jeff Johnson295189b2012-06-20 16:38:30 -07008168 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
8169 rc = wait_for_completion_interruptible_timeout(
8170 &pAdapter->tx_action_cnf_event,
8171 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308172 if (rc <= 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07008173 {
Deepthi Gowri91b3e9c2015-08-25 13:14:58 +05308174 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8175 "%s ERROR: HDD Wait for Action Confirmation Failed!! %ld"
8176 , __func__, rc);
8177
8178 // Inform tx status as FAILURE to upper layer and free cfgState->buf
8179 hdd_sendActionCnf( pAdapter, FALSE );
Jeff Johnson295189b2012-06-20 16:38:30 -07008180 }
8181 }
8182 return;
8183}
Jeff Johnson295189b2012-06-20 16:38:30 -07008184
c_hpothu002231a2015-02-05 14:58:51 +05308185void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
Jeff Johnson295189b2012-06-20 16:38:30 -07008186{
8187 ENTER();
8188 switch ( pAdapter->device_mode )
8189 {
Katya Nigam1fd24402015-02-16 14:52:19 +05308190 case WLAN_HDD_IBSS:
8191 {
8192 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
8193 {
8194 hdd_ibss_deinit_tx_rx( pAdapter );
8195 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
8196 }
8197 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008198 case WLAN_HDD_INFRA_STATION:
8199 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07008200 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07008201 {
8202 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
8203 {
8204 hdd_deinit_tx_rx( pAdapter );
8205 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
8206 }
8207
8208 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
8209 {
8210 hdd_wmm_adapter_close( pAdapter );
8211 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
8212 }
8213
Jeff Johnson295189b2012-06-20 16:38:30 -07008214 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07008215 break;
8216 }
8217
8218 case WLAN_HDD_SOFTAP:
8219 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07008220 {
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05308221
8222 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
8223 {
8224 hdd_wmm_adapter_close( pAdapter );
8225 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
8226 }
8227
Jeff Johnson295189b2012-06-20 16:38:30 -07008228 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07008229
c_hpothu002231a2015-02-05 14:58:51 +05308230 hdd_unregister_hostapd(pAdapter, rtnl_held);
Agrawal Ashisha0584d42016-09-29 13:03:45 +05308231 /* set con_mode to STA only when no SAP concurrency mode */
8232 if (!(hdd_get_concurrency_mode() & (VOS_SAP | VOS_P2P_GO)))
8233 hdd_set_conparam(0);
Jeff Johnson295189b2012-06-20 16:38:30 -07008234 break;
8235 }
8236
8237 case WLAN_HDD_MONITOR:
8238 {
Jeff Johnson295189b2012-06-20 16:38:30 -07008239 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
8240 {
8241 hdd_deinit_tx_rx( pAdapter );
8242 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
8243 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008244 break;
8245 }
8246
8247
8248 default:
8249 break;
8250 }
8251
8252 EXIT();
8253}
8254
8255void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
8256{
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -08008257 struct net_device *pWlanDev = NULL;
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05308258
8259 ENTER();
8260 if (NULL == pAdapter)
8261 {
8262 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8263 "%s: HDD adapter is Null", __func__);
8264 return;
8265 }
8266
8267 pWlanDev = pAdapter->dev;
Jeff Johnson295189b2012-06-20 16:38:30 -07008268
Rajeev79dbe4c2013-10-05 11:03:42 +05308269#ifdef FEATURE_WLAN_BATCH_SCAN
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05308270 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
8271 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Rajeev Kumarf999e582014-01-09 17:33:29 -08008272 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05308273 || (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)
8274 )
8275 {
Rajeev Kumarf999e582014-01-09 17:33:29 -08008276 if (pAdapter)
Rajeev79dbe4c2013-10-05 11:03:42 +05308277 {
Rajeev Kumarf999e582014-01-09 17:33:29 -08008278 if (eHDD_BATCH_SCAN_STATE_STARTED == pAdapter->batchScanState)
8279 {
8280 hdd_deinit_batch_scan(pAdapter);
8281 }
Rajeev79dbe4c2013-10-05 11:03:42 +05308282 }
Rajeev Kumarf999e582014-01-09 17:33:29 -08008283 }
Rajeev79dbe4c2013-10-05 11:03:42 +05308284#endif
8285
Jeff Johnson295189b2012-06-20 16:38:30 -07008286 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
8287 if( rtnl_held )
8288 {
8289 unregister_netdevice(pWlanDev);
8290 }
8291 else
8292 {
8293 unregister_netdev(pWlanDev);
8294 }
8295 // note that the pAdapter is no longer valid at this point
8296 // since the memory has been reclaimed
8297 }
8298
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05308299 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07008300}
8301
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008302void hdd_set_pwrparams(hdd_context_t *pHddCtx)
8303{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308304 VOS_STATUS status;
8305 hdd_adapter_t *pAdapter = NULL;
8306 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008307
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308308 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008309
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308310 /*loop through all adapters.*/
8311 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008312 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308313 pAdapter = pAdapterNode->pAdapter;
8314 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
8315 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008316
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308317 { // we skip this registration for modes other than STA and P2P client modes.
8318 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
8319 pAdapterNode = pNext;
8320 continue;
8321 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008322
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308323 //Apply Dynamic DTIM For P2P
8324 //Only if ignoreDynamicDtimInP2pMode is not set in ini
8325 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
8326 pHddCtx->cfg_ini->enableModulatedDTIM) &&
8327 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
8328 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
8329 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
8330 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
8331 (eConnectionState_Associated ==
8332 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
8333 (pHddCtx->cfg_ini->fIsBmpsEnabled))
8334 {
8335 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008336
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308337 powerRequest.uIgnoreDTIM = 1;
8338 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
8339
8340 if (pHddCtx->cfg_ini->enableModulatedDTIM)
8341 {
8342 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
8343 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
8344 }
8345 else
8346 {
8347 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
8348 }
8349
8350 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
8351 * specified during Enter/Exit BMPS when LCD off*/
8352 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
8353 NULL, eANI_BOOLEAN_FALSE);
8354 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
8355 NULL, eANI_BOOLEAN_FALSE);
8356
8357 /* switch to the DTIM specified in cfg.ini */
8358 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Abhishek Singh1e390cf2015-10-27 13:45:17 +05308359 "Switch to DTIM %d Listen interval %d",
8360 powerRequest.uDTIMPeriod,
8361 powerRequest.uListenInterval);
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308362 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
8363 break;
8364
8365 }
8366
8367 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
8368 pAdapterNode = pNext;
8369 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008370}
8371
8372void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
8373{
8374 /*Switch back to DTIM 1*/
8375 tSirSetPowerParamsReq powerRequest = { 0 };
8376
8377 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
8378 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07008379 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008380
8381 /* Update ignoreDTIM and ListedInterval in CFG with default values */
8382 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
8383 NULL, eANI_BOOLEAN_FALSE);
8384 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
8385 NULL, eANI_BOOLEAN_FALSE);
8386
8387 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8388 "Switch to DTIM%d",powerRequest.uListenInterval);
8389 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
8390
8391}
8392
Jeff Johnson295189b2012-06-20 16:38:30 -07008393VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
8394{
8395 VOS_STATUS status = VOS_STATUS_SUCCESS;
Sushant Kaushik4928e542014-12-29 15:25:54 +05308396 if (WLAN_HDD_IS_UNLOAD_IN_PROGRESS(pHddCtx))
8397 {
8398 hddLog( LOGE, FL("Wlan Unload in progress"));
8399 return VOS_STATUS_E_PERM;
8400 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008401 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
8402 {
8403 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
8404 }
8405
8406 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
8407 {
8408 sme_StartAutoBmpsTimer(pHddCtx->hHal);
8409 }
8410
8411 if (pHddCtx->cfg_ini->fIsImpsEnabled)
8412 {
8413 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
8414 }
8415
8416 return status;
8417}
8418
8419VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
8420{
8421 hdd_adapter_t *pAdapter = NULL;
8422 eHalStatus halStatus;
8423 VOS_STATUS status = VOS_STATUS_E_INVAL;
8424 v_BOOL_t disableBmps = FALSE;
8425 v_BOOL_t disableImps = FALSE;
8426
8427 switch(session_type)
8428 {
8429 case WLAN_HDD_INFRA_STATION:
8430 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07008431 case WLAN_HDD_P2P_CLIENT:
8432 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07008433 //Exit BMPS -> Is Sta/P2P Client is already connected
8434 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
8435 if((NULL != pAdapter)&&
8436 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
8437 {
8438 disableBmps = TRUE;
8439 }
8440
8441 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
8442 if((NULL != pAdapter)&&
8443 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
8444 {
8445 disableBmps = TRUE;
8446 }
8447
8448 //Exit both Bmps and Imps incase of Go/SAP Mode
8449 if((WLAN_HDD_SOFTAP == session_type) ||
8450 (WLAN_HDD_P2P_GO == session_type))
8451 {
8452 disableBmps = TRUE;
8453 disableImps = TRUE;
8454 }
8455
8456 if(TRUE == disableImps)
8457 {
8458 if (pHddCtx->cfg_ini->fIsImpsEnabled)
8459 {
8460 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
8461 }
8462 }
8463
8464 if(TRUE == disableBmps)
8465 {
8466 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
8467 {
8468 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
8469
8470 if(eHAL_STATUS_SUCCESS != halStatus)
8471 {
8472 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08008473 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008474 VOS_ASSERT(0);
8475 return status;
8476 }
8477 }
8478
8479 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
8480 {
8481 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
8482
8483 if(eHAL_STATUS_SUCCESS != halStatus)
8484 {
8485 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08008486 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008487 VOS_ASSERT(0);
8488 return status;
8489 }
8490 }
8491 }
8492
8493 if((TRUE == disableBmps) ||
8494 (TRUE == disableImps))
8495 {
8496 /* Now, get the chip into Full Power now */
8497 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
8498 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
8499 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
8500
8501 if(halStatus != eHAL_STATUS_SUCCESS)
8502 {
8503 if(halStatus == eHAL_STATUS_PMC_PENDING)
8504 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308505 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07008506 //Block on a completion variable. Can't wait forever though
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308507 ret = wait_for_completion_interruptible_timeout(
8508 &pHddCtx->full_pwr_comp_var,
8509 msecs_to_jiffies(1000));
8510 if (ret <= 0)
8511 {
8512 hddLog(VOS_TRACE_LEVEL_ERROR,
8513 "%s: wait on full_pwr_comp_var failed %ld",
8514 __func__, ret);
8515 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008516 }
8517 else
8518 {
8519 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08008520 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008521 VOS_ASSERT(0);
8522 return status;
8523 }
8524 }
8525
8526 status = VOS_STATUS_SUCCESS;
8527 }
8528
8529 break;
8530 }
8531 return status;
8532}
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +05308533
8534void hdd_monPostMsgCb(tANI_U32 *magic, struct completion *cmpVar)
8535{
8536 if (magic == NULL || cmpVar == NULL) {
8537 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8538 FL("invalid arguments %p %p"), magic, cmpVar);
8539 return;
8540 }
8541 if (*magic != MON_MODE_MSG_MAGIC) {
8542 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8543 FL("maic: %x"), *magic);
8544 return;
8545 }
8546
8547 complete(cmpVar);
8548 return;
8549}
8550
Katya Nigame7b69a82015-04-28 15:24:06 +05308551void hdd_init_mon_mode (hdd_adapter_t *pAdapter)
8552 {
8553 hdd_mon_ctx_t *pMonCtx = NULL;
8554 pMonCtx = WLAN_HDD_GET_MONITOR_CTX_PTR(pAdapter);
8555
8556 pMonCtx->state = 0;
8557 pMonCtx->ChannelNo = 1;
8558 pMonCtx->ChannelBW = 20;
Katya Nigamd7d3a1f2015-06-11 14:04:24 +05308559 pMonCtx->crcCheckEnabled = 1;
8560 pMonCtx->typeSubtypeBitmap = 0xFFFF00000000;
8561 pMonCtx->is80211to803ConReq = 1;
Katya Nigame7b69a82015-04-28 15:24:06 +05308562 pMonCtx->numOfMacFilters = 0;
8563 }
8564
Jeff Johnson295189b2012-06-20 16:38:30 -07008565
8566hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08008567 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07008568 tANI_U8 rtnl_held )
8569{
8570 hdd_adapter_t *pAdapter = NULL;
8571 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
8572 VOS_STATUS status = VOS_STATUS_E_FAILURE;
8573 VOS_STATUS exitbmpsStatus;
8574
Arif Hussain6d2a3322013-11-17 19:50:10 -08008575 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d",__func__,iface_name,session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07008576
Nirav Shah436658f2014-02-28 17:05:45 +05308577 if(macAddr == NULL)
8578 {
8579 /* Not received valid macAddr */
8580 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8581 "%s:Unable to add virtual intf: Not able to get"
8582 "valid mac address",__func__);
8583 return NULL;
8584 }
8585
Jeff Johnson295189b2012-06-20 16:38:30 -07008586 //Disable BMPS incase of Concurrency
8587 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
8588
8589 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
8590 {
8591 //Fail to Exit BMPS
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308592 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Exit BMPS", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008593 VOS_ASSERT(0);
8594 return NULL;
8595 }
8596
8597 switch(session_type)
8598 {
8599 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07008600 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07008601 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07008602 {
8603 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
8604
8605 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308606 {
8607 hddLog(VOS_TRACE_LEVEL_FATAL,
8608 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07008609 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308610 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008611
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05308612#ifdef FEATURE_WLAN_TDLS
8613 /* A Mutex Lock is introduced while changing/initializing the mode to
8614 * protect the concurrent access for the Adapters by TDLS module.
8615 */
Rajesh Chauhana34c6e62014-03-25 16:37:58 +05308616 mutex_lock(&pHddCtx->tdls_lock);
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05308617#endif
8618
Jeff Johnsone7245742012-09-05 17:12:55 -07008619 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
8620 NL80211_IFTYPE_P2P_CLIENT:
8621 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07008622
Jeff Johnson295189b2012-06-20 16:38:30 -07008623 pAdapter->device_mode = session_type;
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05308624#ifdef FEATURE_WLAN_TDLS
8625 mutex_unlock(&pHddCtx->tdls_lock);
8626#endif
Sunil Dutt66485cb2013-12-19 19:05:03 +05308627
Mahesh A Saptasagar67ab9222015-10-21 15:38:41 +05308628 hdd_initialize_adapter_common(pAdapter);
Sunil Dutt66485cb2013-12-19 19:05:03 +05308629 status = hdd_init_station_mode( pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07008630 if( VOS_STATUS_SUCCESS != status )
8631 goto err_free_netdev;
8632
8633 status = hdd_register_interface( pAdapter, rtnl_held );
8634 if( VOS_STATUS_SUCCESS != status )
8635 {
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05308636#ifdef FEATURE_WLAN_TDLS
8637 mutex_lock(&pHddCtx->tdls_lock);
8638#endif
c_hpothu002231a2015-02-05 14:58:51 +05308639 hdd_deinit_adapter(pHddCtx, pAdapter, rtnl_held);
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05308640#ifdef FEATURE_WLAN_TDLS
8641 mutex_unlock(&pHddCtx->tdls_lock);
8642#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008643 goto err_free_netdev;
8644 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05308645
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05308646 // Workqueue which gets scheduled in IPv4 notification callback.
Anand N Sunkaddc63c792015-06-03 14:33:24 +05308647 vos_init_work(&pAdapter->ipv4NotifierWorkQueue, hdd_ipv4_notifier_work_queue);
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05308648
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05308649#ifdef WLAN_NS_OFFLOAD
8650 // Workqueue which gets scheduled in IPv6 notification callback.
Anand N Sunkaddc63c792015-06-03 14:33:24 +05308651 vos_init_work(&pAdapter->ipv6NotifierWorkQueue, hdd_ipv6_notifier_work_queue);
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05308652#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008653 //Stop the Interface TX queue.
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05308654 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
Jeff Johnson295189b2012-06-20 16:38:30 -07008655 netif_tx_disable(pAdapter->dev);
8656 //netif_tx_disable(pWlanDev);
8657 netif_carrier_off(pAdapter->dev);
8658
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +05308659 if (WLAN_HDD_P2P_CLIENT == session_type ||
8660 WLAN_HDD_P2P_DEVICE == session_type)
8661 {
8662 /* Initialize the work queue to defer the
8663 * back to back RoC request */
Anand N Sunkaddc63c792015-06-03 14:33:24 +05308664 vos_init_delayed_work(&pAdapter->roc_work,
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +05308665 hdd_p2p_roc_work_queue);
8666 }
8667
Jeff Johnson295189b2012-06-20 16:38:30 -07008668 break;
8669 }
8670
Jeff Johnson295189b2012-06-20 16:38:30 -07008671 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07008672 case WLAN_HDD_SOFTAP:
8673 {
8674 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
8675 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308676 {
8677 hddLog(VOS_TRACE_LEVEL_FATAL,
8678 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07008679 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308680 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008681
Jeff Johnson295189b2012-06-20 16:38:30 -07008682 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
8683 NL80211_IFTYPE_AP:
8684 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07008685 pAdapter->device_mode = session_type;
8686
Mahesh A Saptasagar67ab9222015-10-21 15:38:41 +05308687 hdd_initialize_adapter_common(pAdapter);
Hanumanth Reddy Pothula15bc0fa2017-02-03 17:24:17 +05308688 status = hdd_init_ap_mode(pAdapter, false);
Jeff Johnson295189b2012-06-20 16:38:30 -07008689 if( VOS_STATUS_SUCCESS != status )
8690 goto err_free_netdev;
8691
Nirav Shah7e3c8132015-06-22 23:51:42 +05308692 status = hdd_sta_id_hash_attach(pAdapter);
8693 if (VOS_STATUS_SUCCESS != status)
8694 {
8695 hddLog(VOS_TRACE_LEVEL_FATAL,
8696 FL("failed to attach hash for session %d"), session_type);
8697 hdd_deinit_adapter(pHddCtx, pAdapter, rtnl_held);
8698 goto err_free_netdev;
8699 }
8700
Jeff Johnson295189b2012-06-20 16:38:30 -07008701 status = hdd_register_hostapd( pAdapter, rtnl_held );
8702 if( VOS_STATUS_SUCCESS != status )
8703 {
c_hpothu002231a2015-02-05 14:58:51 +05308704 hdd_deinit_adapter(pHddCtx, pAdapter, rtnl_held);
Jeff Johnson295189b2012-06-20 16:38:30 -07008705 goto err_free_netdev;
8706 }
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05308707 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
Jeff Johnson295189b2012-06-20 16:38:30 -07008708 netif_tx_disable(pAdapter->dev);
8709 netif_carrier_off(pAdapter->dev);
8710
8711 hdd_set_conparam( 1 );
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +05308712
8713 if (WLAN_HDD_P2P_GO == session_type)
8714 {
8715 /* Initialize the work queue to
8716 * defer the back to back RoC request */
8717 INIT_DELAYED_WORK(&pAdapter->roc_work,
8718 hdd_p2p_roc_work_queue);
8719 }
Bhargav Shahd0715912015-10-01 18:17:37 +05308720
Jeff Johnson295189b2012-06-20 16:38:30 -07008721 break;
8722 }
8723 case WLAN_HDD_MONITOR:
8724 {
Jeff Johnson295189b2012-06-20 16:38:30 -07008725 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
8726 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308727 {
8728 hddLog(VOS_TRACE_LEVEL_FATAL,
8729 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07008730 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308731 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008732
Katya Nigame7b69a82015-04-28 15:24:06 +05308733 // Register wireless extensions
8734 if( VOS_STATUS_SUCCESS != (status = hdd_register_wext(pAdapter->dev)))
8735 {
8736 hddLog(VOS_TRACE_LEVEL_FATAL,
8737 "hdd_register_wext() failed with status code %08d [x%08x]",
8738 status, status );
8739 status = VOS_STATUS_E_FAILURE;
8740 }
8741
Jeff Johnson295189b2012-06-20 16:38:30 -07008742 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
8743 pAdapter->device_mode = session_type;
Jeff Johnson295189b2012-06-20 16:38:30 -07008744#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
8745 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
8746#else
8747 pAdapter->dev->open = hdd_mon_open;
8748 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
Katya Nigame7b69a82015-04-28 15:24:06 +05308749 pAdapter->dev->stop = hdd_mon_stop;
8750 pAdapter->dev->do_ioctl = hdd_mon_ioctl;
Jeff Johnson295189b2012-06-20 16:38:30 -07008751#endif
Katya Nigame7b69a82015-04-28 15:24:06 +05308752 status = hdd_register_interface( pAdapter, rtnl_held );
8753 hdd_init_mon_mode( pAdapter );
Mahesh A Saptasagar67ab9222015-10-21 15:38:41 +05308754 hdd_initialize_adapter_common(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07008755 hdd_init_tx_rx( pAdapter );
8756 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
Katya Nigame7b69a82015-04-28 15:24:06 +05308757 //Stop the Interface TX queue.
8758 netif_tx_disable(pAdapter->dev);
8759 netif_carrier_off(pAdapter->dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07008760 }
8761 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07008762 case WLAN_HDD_FTM:
8763 {
8764 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
8765
8766 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308767 {
8768 hddLog(VOS_TRACE_LEVEL_FATAL,
8769 FL("failed to allocate adapter for session %d"), session_type);
8770 return NULL;
8771 }
8772
Jeff Johnson295189b2012-06-20 16:38:30 -07008773 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
8774 * message while loading driver in FTM mode. */
8775 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
8776 pAdapter->device_mode = session_type;
8777 status = hdd_register_interface( pAdapter, rtnl_held );
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05308778
Mahesh A Saptasagar67ab9222015-10-21 15:38:41 +05308779 hdd_initialize_adapter_common(pAdapter);
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05308780 hdd_init_tx_rx( pAdapter );
8781
8782 //Stop the Interface TX queue.
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05308783 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05308784 netif_tx_disable(pAdapter->dev);
8785 netif_carrier_off(pAdapter->dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07008786 }
8787 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07008788 default:
8789 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308790 hddLog(VOS_TRACE_LEVEL_FATAL,"%s Invalid session type %d",
8791 __func__, session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07008792 VOS_ASSERT(0);
8793 return NULL;
8794 }
8795 }
8796
Jeff Johnson295189b2012-06-20 16:38:30 -07008797 if( VOS_STATUS_SUCCESS == status )
8798 {
Mahesh A Saptasagar67ab9222015-10-21 15:38:41 +05308799 //Add it to the hdd's session list.
Jeff Johnson295189b2012-06-20 16:38:30 -07008800 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
8801 if( NULL == pHddAdapterNode )
8802 {
8803 status = VOS_STATUS_E_NOMEM;
8804 }
8805 else
8806 {
8807 pHddAdapterNode->pAdapter = pAdapter;
8808 status = hdd_add_adapter_back ( pHddCtx,
8809 pHddAdapterNode );
8810 }
8811 }
8812
8813 if( VOS_STATUS_SUCCESS != status )
8814 {
8815 if( NULL != pAdapter )
8816 {
8817 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
8818 pAdapter = NULL;
8819 }
8820 if( NULL != pHddAdapterNode )
8821 {
8822 vos_mem_free( pHddAdapterNode );
8823 }
8824
8825 goto resume_bmps;
8826 }
8827
8828 if(VOS_STATUS_SUCCESS == status)
8829 {
8830 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07008831 //Initialize the WoWL service
8832 if(!hdd_init_wowl(pAdapter))
8833 {
8834 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
8835 goto err_free_netdev;
8836 }
Manjeet Singh3ed79242017-01-11 19:04:32 +05308837 //Initialize the TSF capture data
8838 wlan_hdd_tsf_init(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07008839 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008840 return pAdapter;
8841
8842err_free_netdev:
8843 free_netdev(pAdapter->dev);
8844 wlan_hdd_release_intf_addr( pHddCtx,
8845 pAdapter->macAddressCurrent.bytes );
8846
8847resume_bmps:
8848 //If bmps disabled enable it
8849 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
8850 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308851 if (pHddCtx->hdd_wlan_suspended)
8852 {
8853 hdd_set_pwrparams(pHddCtx);
8854 }
8855 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07008856 }
8857 return NULL;
8858}
8859
8860VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
8861 tANI_U8 rtnl_held )
8862{
8863 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
8864 VOS_STATUS status;
8865
8866 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
8867 if( VOS_STATUS_SUCCESS != status )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308868 {
8869 hddLog(VOS_TRACE_LEVEL_WARN,"%s: adapter list empty %d",
8870 __func__, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07008871 return status;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308872 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008873
8874 while ( pCurrent->pAdapter != pAdapter )
8875 {
8876 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
8877 if( VOS_STATUS_SUCCESS != status )
8878 break;
8879
8880 pCurrent = pNext;
8881 }
8882 pAdapterNode = pCurrent;
8883 if( VOS_STATUS_SUCCESS == status )
8884 {
8885 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
8886 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05308887
8888#ifdef FEATURE_WLAN_TDLS
8889
8890 /* A Mutex Lock is introduced while changing/initializing the mode to
8891 * protect the concurrent access for the Adapters by TDLS module.
8892 */
Rajesh Chauhana34c6e62014-03-25 16:37:58 +05308893 mutex_lock(&pHddCtx->tdls_lock);
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05308894#endif
8895
Jeff Johnson295189b2012-06-20 16:38:30 -07008896 hdd_remove_adapter( pHddCtx, pAdapterNode );
8897 vos_mem_free( pAdapterNode );
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08008898 pAdapterNode = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07008899
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05308900#ifdef FEATURE_WLAN_TDLS
8901 mutex_unlock(&pHddCtx->tdls_lock);
8902#endif
8903
Jeff Johnson295189b2012-06-20 16:38:30 -07008904
8905 /* If there is a single session of STA/P2P client, re-enable BMPS */
Agarwal Ashish51325b52014-06-16 16:50:49 +05308906 if ((!vos_concurrent_open_sessions_running()) &&
8907 ((pHddCtx->no_of_open_sessions[VOS_STA_MODE] >= 1) ||
8908 (pHddCtx->no_of_open_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
Jeff Johnson295189b2012-06-20 16:38:30 -07008909 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308910 if (pHddCtx->hdd_wlan_suspended)
8911 {
8912 hdd_set_pwrparams(pHddCtx);
8913 }
8914 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07008915 }
8916
8917 return VOS_STATUS_SUCCESS;
8918 }
8919
8920 return VOS_STATUS_E_FAILURE;
8921}
8922
8923VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
8924{
8925 hdd_adapter_list_node_t *pHddAdapterNode;
8926 VOS_STATUS status;
8927
8928 ENTER();
8929
8930 do
8931 {
8932 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
8933 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
8934 {
8935 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
8936 vos_mem_free( pHddAdapterNode );
8937 }
8938 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
8939
8940 EXIT();
8941
8942 return VOS_STATUS_SUCCESS;
8943}
8944
8945void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
8946{
8947 v_U8_t addIE[1] = {0};
8948
8949 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
8950 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
8951 eANI_BOOLEAN_FALSE) )
8952 {
8953 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08008954 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07008955 }
8956
8957 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
8958 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
8959 eANI_BOOLEAN_FALSE) )
8960 {
8961 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08008962 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07008963 }
8964
8965 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
8966 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
8967 eANI_BOOLEAN_FALSE) )
8968 {
8969 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08008970 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07008971 }
8972}
8973
Anurag Chouhan83026002016-12-13 22:46:21 +05308974VOS_STATUS hdd_cleanup_ap_events(hdd_adapter_t *adapter)
8975{
8976#ifdef DHCP_SERVER_OFFLOAD
8977 vos_event_destroy(&adapter->dhcp_status.vos_event);
8978#endif
Anurag Chouhan0b29de02016-12-16 13:18:40 +05308979#ifdef MDNS_OFFLOAD
8980 vos_event_destroy(&adapter->mdns_status.vos_event);
8981#endif
Anurag Chouhan83026002016-12-13 22:46:21 +05308982 return VOS_STATUS_SUCCESS;
8983}
8984
8985
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05308986VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
8987 const v_BOOL_t bCloseSession )
Jeff Johnson295189b2012-06-20 16:38:30 -07008988{
8989 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
8990 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
Kaushik, Sushant4975a572014-10-21 16:07:48 +05308991 hdd_scaninfo_t *pScanInfo = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07008992 union iwreq_data wrqu;
Kaushik, Sushant7005e372014-04-08 11:36:54 +05308993 v_U8_t retry = 0;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308994 long ret;
Nirav Shah7e3c8132015-06-22 23:51:42 +05308995 VOS_STATUS status;
Jeff Johnson295189b2012-06-20 16:38:30 -07008996
Anand N Sunkad26d71b92014-12-24 18:08:22 +05308997 if (pHddCtx->isLogpInProgress) {
8998 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8999 "%s:LOGP in Progress. Ignore!!!",__func__);
9000 return VOS_STATUS_E_FAILURE;
9001 }
9002
Jeff Johnson295189b2012-06-20 16:38:30 -07009003 ENTER();
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +05309004
Kaushik, Sushant4975a572014-10-21 16:07:48 +05309005 pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07009006 switch(pAdapter->device_mode)
9007 {
Nirav Shah0cf4d892015-11-05 16:27:27 +05309008 case WLAN_HDD_IBSS:
9009 if ( VOS_TRUE == bCloseSession )
9010 {
9011 status = hdd_sta_id_hash_detach(pAdapter);
9012 if (status != VOS_STATUS_SUCCESS)
9013 hddLog(VOS_TRACE_LEVEL_ERROR,
9014 FL("sta id hash detach failed"));
9015 }
9016
Jeff Johnson295189b2012-06-20 16:38:30 -07009017 case WLAN_HDD_INFRA_STATION:
9018 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07009019 case WLAN_HDD_P2P_DEVICE:
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05309020 {
9021 hdd_station_ctx_t *pstation = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Mahesh A Saptasagare4d05d42015-07-02 16:17:20 +05309022#ifdef FEATURE_WLAN_TDLS
9023 mutex_lock(&pHddCtx->tdls_lock);
9024 wlan_hdd_tdls_exit(pAdapter, TRUE);
9025 mutex_unlock(&pHddCtx->tdls_lock);
9026#endif
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05309027 if( hdd_connIsConnected(pstation) ||
9028 (pstation->conn_info.connState == eConnectionState_Connecting) )
Jeff Johnson295189b2012-06-20 16:38:30 -07009029 {
Abhishek Singh99f17b82017-02-06 16:57:56 +05309030 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07009031 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
9032 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
9033 pAdapter->sessionId,
9034 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
9035 else
9036 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
9037 pAdapter->sessionId,
9038 eCSR_DISCONNECT_REASON_UNSPECIFIED);
Abhishek Singh7b52ed52016-02-11 17:45:54 +05309039 /* Success implies disconnect command got queued up successfully
9040 * Or cmd not queued as scan for SSID is in progress
9041 */
9042 if((eHAL_STATUS_SUCCESS == halStatus) ||
9043 (eHAL_STATUS_CMD_NOT_QUEUED == halStatus))
Jeff Johnson295189b2012-06-20 16:38:30 -07009044 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309045 ret = wait_for_completion_interruptible_timeout(
9046 &pAdapter->disconnect_comp_var,
9047 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Abhishek Singh7b52ed52016-02-11 17:45:54 +05309048 if (ret <= 0 &&
9049 (eHAL_STATUS_CMD_NOT_QUEUED != halStatus))
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309050 {
9051 hddLog(VOS_TRACE_LEVEL_ERROR,
9052 "%s: wait on disconnect_comp_var failed %ld",
9053 __func__, ret);
9054 }
9055 }
9056 else
9057 {
9058 hddLog(LOGE, "%s: failed to post disconnect event to SME",
9059 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009060 }
9061 memset(&wrqu, '\0', sizeof(wrqu));
9062 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
9063 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
9064 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
9065 }
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05309066 else if(pstation->conn_info.connState ==
9067 eConnectionState_Disconnecting)
9068 {
9069 ret = wait_for_completion_interruptible_timeout(
9070 &pAdapter->disconnect_comp_var,
9071 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
9072 if (ret <= 0)
9073 {
9074 hddLog(VOS_TRACE_LEVEL_ERROR,
9075 FL("wait on disconnect_comp_var failed %ld"), ret);
9076 }
9077 }
Sachin Ahuja27dd2402016-08-01 20:30:31 +05309078 if(pScanInfo != NULL && pHddCtx->scan_info.mScanPending)
Jeff Johnson295189b2012-06-20 16:38:30 -07009079 {
Mahesh A Saptasagar0b61dcc2016-02-15 14:23:38 +05309080 wlan_hdd_scan_abort(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07009081 }
Abhishek Singh3ac179b2015-09-21 10:01:34 +05309082 if ((pAdapter->device_mode != WLAN_HDD_INFRA_STATION) &&
9083 (pAdapter->device_mode != WLAN_HDD_IBSS))
Kaushik, Sushant7005e372014-04-08 11:36:54 +05309084 {
9085 while (pAdapter->is_roc_inprogress)
9086 {
9087 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9088 "%s: ROC in progress for session %d!!!",
9089 __func__, pAdapter->sessionId);
9090 // waiting for ROC to expire
9091 msleep(500);
9092 /* In GO present case , if retry exceeds 3,
9093 it means something went wrong. */
9094 if ( retry++ > MAX_WAIT_FOR_ROC_COMPLETION )
9095 {
9096 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9097 "%s: ROC completion is not received.!!!", __func__);
Deepthi Gowri70498252015-01-20 15:56:45 +05309098 if (eHAL_STATUS_SUCCESS !=
9099 sme_CancelRemainOnChannel( WLAN_HDD_GET_HAL_CTX( pAdapter),
9100 pAdapter->sessionId ))
9101 {
9102 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9103 FL("Failed to Cancel Remain on Channel"));
9104 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +05309105 wait_for_completion_interruptible_timeout(
9106 &pAdapter->cancel_rem_on_chan_var,
9107 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
9108 break;
9109 }
9110 }
Anand N Sunkaddc63c792015-06-03 14:33:24 +05309111 vos_flush_delayed_work(&pAdapter->roc_work);
Kaushik, Sushant7005e372014-04-08 11:36:54 +05309112 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05309113#ifdef WLAN_NS_OFFLOAD
Anand N Sunkaddc63c792015-06-03 14:33:24 +05309114 vos_flush_work(&pAdapter->ipv6NotifierWorkQueue);
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05309115#endif
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +05309116
Anand N Sunkaddc63c792015-06-03 14:33:24 +05309117 vos_flush_work(&pAdapter->ipv4NotifierWorkQueue);
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +05309118
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05309119 /* It is possible that the caller of this function does not
9120 * wish to close the session
9121 */
9122 if (VOS_TRUE == bCloseSession &&
9123 test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07009124 {
9125 INIT_COMPLETION(pAdapter->session_close_comp_var);
9126 if (eHAL_STATUS_SUCCESS ==
Agrawal Ashish5a3522c2016-03-02 15:08:28 +05309127 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId, FALSE,
9128 VOS_FALSE, hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07009129 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309130 unsigned long ret;
9131
Jeff Johnson295189b2012-06-20 16:38:30 -07009132 //Block on a completion variable. Can't wait forever though.
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309133 ret = wait_for_completion_timeout(
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05309134 &pAdapter->session_close_comp_var,
9135 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309136 if ( 0 >= ret)
9137 {
9138 hddLog(LOGE, "%s: failure waiting for session_close_comp_var %ld",
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05309139 __func__, ret);
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309140 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009141 }
9142 }
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05309143 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009144 break;
9145
9146 case WLAN_HDD_SOFTAP:
9147 case WLAN_HDD_P2P_GO:
Nirav Shah0cf4d892015-11-05 16:27:27 +05309148 if ( VOS_TRUE == bCloseSession )
9149 {
9150 status = hdd_sta_id_hash_detach(pAdapter);
9151 if (status != VOS_STATUS_SUCCESS)
9152 hddLog(VOS_TRACE_LEVEL_ERROR,
9153 FL("sta id hash detach failed"));
9154 }
9155
Jeff Johnson295189b2012-06-20 16:38:30 -07009156 //Any softap specific cleanup here...
Anurag Chouhan83026002016-12-13 22:46:21 +05309157 hdd_cleanup_ap_events(pAdapter);
Kaushik, Sushant7005e372014-04-08 11:36:54 +05309158 if (pAdapter->device_mode == WLAN_HDD_P2P_GO) {
9159 while (pAdapter->is_roc_inprogress) {
9160 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9161 "%s: ROC in progress for session %d!!!",
9162 __func__, pAdapter->sessionId);
9163 msleep(500);
9164 if ( retry++ > MAX_WAIT_FOR_ROC_COMPLETION ) {
9165 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9166 "%s: ROC completion is not received.!!!", __func__);
9167 WLANSAP_CancelRemainOnChannel(
9168 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
9169 wait_for_completion_interruptible_timeout(
9170 &pAdapter->cancel_rem_on_chan_var,
9171 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
9172 break;
9173 }
9174 }
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +05309175
Anand N Sunkaddc63c792015-06-03 14:33:24 +05309176 vos_flush_delayed_work(&pAdapter->roc_work);
Kaushik, Sushant7005e372014-04-08 11:36:54 +05309177 }
Agrawal Ashish17ef5082016-10-17 18:33:21 +05309178#ifdef SAP_AUTH_OFFLOAD
9179 if (pHddCtx->cfg_ini->enable_sap_auth_offload)
9180 hdd_set_sap_auth_offload(pAdapter, FALSE);
9181#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009182 mutex_lock(&pHddCtx->sap_lock);
9183 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
9184 {
9185 VOS_STATUS status;
9186 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9187
9188 //Stop Bss.
9189 status = WLANSAP_StopBss(pHddCtx->pvosContext);
9190 if (VOS_IS_STATUS_SUCCESS(status))
9191 {
9192 hdd_hostapd_state_t *pHostapdState =
9193 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
9194
9195 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
9196
9197 if (!VOS_IS_STATUS_SUCCESS(status))
9198 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309199 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss %d",
9200 __func__, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07009201 }
9202 }
9203 else
9204 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07009205 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009206 }
9207 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
Agarwal Ashish51325b52014-06-16 16:50:49 +05309208 wlan_hdd_decr_active_session(pHddCtx, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07009209
9210 if (eHAL_STATUS_FAILURE ==
9211 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
9212 0, NULL, eANI_BOOLEAN_FALSE))
9213 {
9214 hddLog(LOGE,
9215 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07009216 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009217 }
9218
9219 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
9220 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
9221 eANI_BOOLEAN_FALSE) )
9222 {
9223 hddLog(LOGE,
9224 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
9225 }
9226
9227 // Reset WNI_CFG_PROBE_RSP Flags
9228 wlan_hdd_reset_prob_rspies(pAdapter);
9229 kfree(pAdapter->sessionCtx.ap.beacon);
9230 pAdapter->sessionCtx.ap.beacon = NULL;
9231 }
9232 mutex_unlock(&pHddCtx->sap_lock);
9233 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07009234
Jeff Johnson295189b2012-06-20 16:38:30 -07009235 case WLAN_HDD_MONITOR:
9236 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07009237
Jeff Johnson295189b2012-06-20 16:38:30 -07009238 default:
9239 break;
9240 }
9241
9242 EXIT();
9243 return VOS_STATUS_SUCCESS;
9244}
9245
Kapil Gupta137ef892016-12-13 19:38:00 +05309246/**
9247 * wlan_hdd_restart_sap() - to restart SAP in driver internally
9248 * @ap_adapter: - Pointer to SAP hdd_adapter_t structure
9249 *
9250 * wlan_hdd_restart_sap first delete SAP and do cleanup.
9251 * After that WLANSAP_StartBss start re-start process of SAP.
9252 *
9253 * Return: None
9254 */
9255static void wlan_hdd_restart_sap(hdd_adapter_t *ap_adapter)
9256{
9257 hdd_ap_ctx_t *pHddApCtx;
9258 hdd_hostapd_state_t *pHostapdState;
9259 VOS_STATUS vos_status;
9260 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(ap_adapter);
9261#ifdef CFG80211_DEL_STA_V2
9262 struct station_del_parameters delStaParams;
9263#endif
9264 tsap_Config_t *pConfig;
9265
9266 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
9267 pConfig = &pHddApCtx->sapConfig;
9268
9269 mutex_lock(&pHddCtx->sap_lock);
9270 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags)) {
9271#ifdef CFG80211_DEL_STA_V2
9272 delStaParams.mac = NULL;
9273 delStaParams.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
9274 delStaParams.reason_code = eCsrForcedDeauthSta;
9275 wlan_hdd_cfg80211_del_station(ap_adapter->wdev.wiphy, ap_adapter->dev,
9276 &delStaParams);
9277#else
9278 wlan_hdd_cfg80211_del_station(ap_adapter->wdev.wiphy, ap_adapter->dev,
9279 NULL);
9280#endif
9281 hdd_cleanup_actionframe(pHddCtx, ap_adapter);
9282
9283 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
9284 vos_event_reset(&pHostapdState->vosEvent);
9285
9286 if (VOS_STATUS_SUCCESS == WLANSAP_StopBss(pHddCtx->pvosContext)) {
9287 vos_status = vos_wait_single_event(&pHostapdState->vosEvent,
9288 10000);
9289 if (!VOS_IS_STATUS_SUCCESS(vos_status)) {
9290 hddLog(LOGE, FL("SAP Stop Failed"));
9291 goto end;
9292 }
9293 }
9294 clear_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
9295 wlan_hdd_decr_active_session(pHddCtx, ap_adapter->device_mode);
9296 hddLog(LOG1, FL("SAP Stop Success"));
9297
9298 if (0 != wlan_hdd_cfg80211_update_apies(ap_adapter)) {
9299 hddLog(LOGE, FL("SAP Not able to set AP IEs"));
9300 goto end;
9301 }
9302
9303 if (WLANSAP_StartBss(pHddCtx->pvosContext, hdd_hostapd_SAPEventCB,
9304 pConfig, (v_PVOID_t)ap_adapter->dev) != VOS_STATUS_SUCCESS) {
9305 hddLog(LOGE, FL("SAP Start Bss fail"));
9306 goto end;
9307 }
9308
9309 hddLog(LOG1, FL("Waiting for SAP to start"));
9310 vos_status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
9311 if (!VOS_IS_STATUS_SUCCESS(vos_status)) {
9312 hddLog(LOGE, FL("SAP Start failed"));
9313 goto end;
9314 }
9315 hddLog(LOG1, FL("SAP Start Success"));
9316 set_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
9317 wlan_hdd_incr_active_session(pHddCtx, ap_adapter->device_mode);
9318 pHostapdState->bCommit = TRUE;
Anurag Chouhanb2951ae2017-03-12 13:41:35 +05309319 if (!VOS_IS_STATUS_SUCCESS(hdd_dhcp_mdns_offload(ap_adapter))) {
9320 hddLog(VOS_TRACE_LEVEL_ERROR, FL("DHCP/MDNS offload Failed!!"));
9321 vos_event_reset(&pHostapdState->vosEvent);
9322 if (VOS_STATUS_SUCCESS == WLANSAP_StopBss(pHddCtx->pvosContext)) {
9323 vos_status = vos_wait_single_event(&pHostapdState->vosEvent,
9324 10000);
9325 if (!VOS_IS_STATUS_SUCCESS(vos_status)) {
9326 hddLog(LOGE, FL("SAP Stop Failed"));
9327 goto end;
9328 }
9329 }
9330 }
Kapil Gupta137ef892016-12-13 19:38:00 +05309331 }
9332end:
9333 mutex_unlock(&pHddCtx->sap_lock);
9334 return;
9335}
9336
9337/**
9338 * __hdd_sap_restart_handle() - to handle restarting of SAP
9339 * @work: name of the work
9340 *
9341 * Purpose of this function is to trigger sap start. this function
9342 * will be called from workqueue.
9343 *
9344 * Return: void.
9345 */
9346static void __hdd_sap_restart_handle(struct work_struct *work)
9347{
9348 hdd_adapter_t *sap_adapter;
9349 hdd_context_t *hdd_ctx = container_of(work,
9350 hdd_context_t,
9351 sap_start_work);
9352 if (0 != wlan_hdd_validate_context(hdd_ctx)) {
9353 vos_ssr_unprotect(__func__);
9354 return;
9355 }
9356 sap_adapter = hdd_get_adapter(hdd_ctx,
9357 WLAN_HDD_SOFTAP);
9358 if (sap_adapter == NULL) {
9359 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9360 FL("sap_adapter is NULL"));
9361 vos_ssr_unprotect(__func__);
9362 return;
9363 }
9364
9365 if (hdd_ctx->is_ch_avoid_in_progress) {
9366 sap_adapter->sessionCtx.ap.sapConfig.channel = AUTO_CHANNEL_SELECT;
9367 wlan_hdd_restart_sap(sap_adapter);
9368 hdd_change_ch_avoidance_status(hdd_ctx, false);
9369 }
Agrawal Ashish574b3e62017-02-09 18:58:34 +05309370 if (hdd_ctx->cfg_ini->enable_sap_auth_offload)
9371 wlan_hdd_restart_sap(sap_adapter);
Kapil Gupta137ef892016-12-13 19:38:00 +05309372}
9373
9374/**
9375 * hdd_sap_restart_handle() - to handle restarting of SAP
9376 * @work: name of the work
9377 *
9378 * Purpose of this function is to trigger sap start. this function
9379 * will be called from workqueue.
9380 *
9381 * Return: void.
9382 */
9383static void hdd_sap_restart_handle(struct work_struct *work)
9384{
9385 vos_ssr_protect(__func__);
9386 __hdd_sap_restart_handle(work);
9387 vos_ssr_unprotect(__func__);
9388}
9389
9390
Jeff Johnson295189b2012-06-20 16:38:30 -07009391VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
9392{
9393 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
9394 VOS_STATUS status;
9395 hdd_adapter_t *pAdapter;
9396
9397 ENTER();
9398
9399 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
9400
9401 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
9402 {
9403 pAdapter = pAdapterNode->pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07009404
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05309405 hdd_stop_adapter( pHddCtx, pAdapter, VOS_TRUE );
Jeff Johnson295189b2012-06-20 16:38:30 -07009406
9407 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
9408 pAdapterNode = pNext;
9409 }
9410
9411 EXIT();
9412
9413 return VOS_STATUS_SUCCESS;
9414}
9415
Rajeev Kumarf999e582014-01-09 17:33:29 -08009416
9417#ifdef FEATURE_WLAN_BATCH_SCAN
9418/**---------------------------------------------------------------------------
9419
9420 \brief hdd_deinit_batch_scan () - This function cleans up batch scan data
9421 structures
9422
9423 \param - pAdapter Pointer to HDD adapter
9424
9425 \return - None
9426
9427 --------------------------------------------------------------------------*/
9428void hdd_deinit_batch_scan(hdd_adapter_t *pAdapter)
9429{
9430 tHddBatchScanRsp *pNode;
9431 tHddBatchScanRsp *pPrev;
9432
Siddharth Bhalb3e9b792014-02-24 15:14:16 +05309433 if (NULL == pAdapter)
Rajeev Kumarf999e582014-01-09 17:33:29 -08009434 {
Siddharth Bhalb3e9b792014-02-24 15:14:16 +05309435 hddLog(VOS_TRACE_LEVEL_ERROR,
9436 "%s: Adapter context is Null", __func__);
9437 return;
9438 }
9439
9440 pNode = pAdapter->pBatchScanRsp;
9441 while (pNode)
9442 {
9443 pPrev = pNode;
9444 pNode = pNode->pNext;
9445 vos_mem_free((v_VOID_t * )pPrev);
Rajeev Kumarf999e582014-01-09 17:33:29 -08009446 }
9447
9448 pAdapter->pBatchScanRsp = NULL;
9449 pAdapter->numScanList = 0;
9450 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
9451 pAdapter->prev_batch_id = 0;
9452
9453 return;
9454}
9455#endif
9456
9457
Jeff Johnson295189b2012-06-20 16:38:30 -07009458VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
9459{
9460 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
9461 VOS_STATUS status;
9462 hdd_adapter_t *pAdapter;
9463
9464 ENTER();
9465
9466 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
9467
9468 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
9469 {
9470 pAdapter = pAdapterNode->pAdapter;
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05309471 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
Jeff Johnson295189b2012-06-20 16:38:30 -07009472 netif_tx_disable(pAdapter->dev);
Hanumanth Reddy Pothulad864f312017-01-18 16:16:08 +05309473
9474 if (pHddCtx->cfg_ini->sap_internal_restart &&
9475 pAdapter->device_mode == WLAN_HDD_SOFTAP) {
9476 hddLog(LOG1, FL("driver supports sap restart"));
9477 vos_flush_work(&pHddCtx->sap_start_work);
9478 hdd_sap_indicate_disconnect_for_sta(pAdapter);
9479 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Hanumanth Reddy Pothula15bc0fa2017-02-03 17:24:17 +05309480 hdd_softap_deinit_tx_rx(pAdapter, true);
9481 hdd_sap_destroy_timers(pAdapter);
Hanumanth Reddy Pothulad864f312017-01-18 16:16:08 +05309482 } else {
9483 netif_carrier_off(pAdapter->dev);
9484 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009485
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07009486 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
9487
Jeff Johnson295189b2012-06-20 16:38:30 -07009488 hdd_deinit_tx_rx(pAdapter);
Agarwal Ashish6267caa2014-08-06 19:16:21 +05309489
Katya Nigam1fd24402015-02-16 14:52:19 +05309490 if(pAdapter->device_mode == WLAN_HDD_IBSS )
9491 hdd_ibss_deinit_tx_rx(pAdapter);
9492
Nirav Shah7e3c8132015-06-22 23:51:42 +05309493 status = hdd_sta_id_hash_detach(pAdapter);
9494 if (status != VOS_STATUS_SUCCESS)
9495 hddLog(VOS_TRACE_LEVEL_ERROR,
9496 FL("sta id hash detach failed for session id %d"),
9497 pAdapter->sessionId);
9498
Agarwal Ashish6267caa2014-08-06 19:16:21 +05309499 wlan_hdd_decr_active_session(pHddCtx, pAdapter->device_mode);
9500
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05309501 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
9502 {
9503 hdd_wmm_adapter_close( pAdapter );
9504 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
9505 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009506
Siddharth Bhal2db319d2014-12-03 12:37:18 +05309507 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
9508 {
9509 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
9510 }
9511
Rajeev Kumarf999e582014-01-09 17:33:29 -08009512#ifdef FEATURE_WLAN_BATCH_SCAN
9513 if (eHDD_BATCH_SCAN_STATE_STARTED == pAdapter->batchScanState)
9514 {
9515 hdd_deinit_batch_scan(pAdapter);
9516 }
9517#endif
9518
Mahesh A Saptasagarf5b8eff2015-01-31 01:07:07 +05309519#ifdef FEATURE_WLAN_TDLS
9520 mutex_lock(&pHddCtx->tdls_lock);
Pradeep Reddy POTTETI2d4d5c42015-03-03 14:34:19 +05309521 wlan_hdd_tdls_exit(pAdapter, TRUE);
Mahesh A Saptasagarf5b8eff2015-01-31 01:07:07 +05309522 mutex_unlock(&pHddCtx->tdls_lock);
9523#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009524 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
9525 pAdapterNode = pNext;
9526 }
9527
9528 EXIT();
9529
9530 return VOS_STATUS_SUCCESS;
9531}
9532
Abhishek Singhbbe0b2a2016-12-05 11:57:36 +05309533/**
Abhishek Singh5a597e62016-12-05 15:16:30 +05309534 * hdd_get_bss_entry() - Get the bss entry matching the chan, bssid and ssid
9535 * @wiphy: wiphy
9536 * @channel: channel of the BSS to find
9537 * @bssid: bssid of the BSS to find
9538 * @ssid: ssid of the BSS to find
9539 * @ssid_len: ssid len of of the BSS to find
9540 *
9541 * The API is a wrapper to get bss from kernel matching the chan,
9542 * bssid and ssid
9543 *
9544 * Return: Void
9545 */
9546#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) \
9547 && !defined(WITH_BACKPORTS) && !defined(IEEE80211_PRIVACY)
9548
9549struct cfg80211_bss* hdd_get_bss_entry(struct wiphy *wiphy,
9550 struct ieee80211_channel *channel,
9551 const u8 *bssid,
9552 const u8 *ssid, size_t ssid_len)
9553{
9554 return cfg80211_get_bss(wiphy, channel, bssid,
9555 ssid, ssid_len,
9556 WLAN_CAPABILITY_ESS,
9557 WLAN_CAPABILITY_ESS);
9558}
9559#else
9560struct cfg80211_bss* hdd_get_bss_entry(struct wiphy *wiphy,
9561 struct ieee80211_channel *channel,
9562 const u8 *bssid,
9563 const u8 *ssid, size_t ssid_len)
9564{
9565 return cfg80211_get_bss(wiphy, channel, bssid,
9566 ssid, ssid_len,
9567 IEEE80211_BSS_TYPE_ESS,
9568 IEEE80211_PRIVACY_ANY);
9569}
9570#endif
9571
9572/**
Abhishek Singhbbe0b2a2016-12-05 11:57:36 +05309573 * hdd_connect_result() - API to send connection status to supplicant
9574 * @dev: network device
9575 * @bssid: bssid to which we want to associate
9576 * @roam_info: information about connected bss
9577 * @req_ie: Request Information Element
9578 * @req_ie_len: len of the req IE
9579 * @resp_ie: Response IE
9580 * @resp_ie_len: len of ht response IE
9581 * @status: status
9582 * @gfp: Kernel Flag
9583 *
9584 * The API is a wrapper to send connection status to supplicant
9585 *
9586 * Return: Void
9587 */
9588#if defined CFG80211_CONNECT_BSS
9589void hdd_connect_result(struct net_device *dev,
9590 const u8 *bssid,
9591 tCsrRoamInfo *roam_info,
9592 const u8 *req_ie,
9593 size_t req_ie_len,
9594 const u8 *resp_ie,
9595 size_t resp_ie_len,
9596 u16 status,
9597 gfp_t gfp)
9598{
9599 hdd_adapter_t *padapter = (hdd_adapter_t *) netdev_priv(dev);
9600 struct cfg80211_bss *bss = NULL;
9601
9602 if (WLAN_STATUS_SUCCESS == status) {
9603 struct ieee80211_channel *chan;
9604 int freq;
9605 int chan_no = roam_info->pBssDesc->channelId;;
9606
9607 if (chan_no <= 14)
9608 freq = ieee80211_channel_to_frequency(chan_no,
9609 IEEE80211_BAND_2GHZ);
9610 else
9611 freq = ieee80211_channel_to_frequency(chan_no,
9612 IEEE80211_BAND_5GHZ);
9613
9614 chan = ieee80211_get_channel(padapter->wdev.wiphy, freq);
Abhishek Singh5a597e62016-12-05 15:16:30 +05309615 bss = hdd_get_bss_entry(padapter->wdev.wiphy,
9616 chan, bssid,
9617 roam_info->u.pConnectedProfile->SSID.ssId,
9618 roam_info->u.pConnectedProfile->SSID.length);
Abhishek Singhbbe0b2a2016-12-05 11:57:36 +05309619 }
9620
9621 cfg80211_connect_bss(dev, bssid, bss, req_ie, req_ie_len,
9622 resp_ie, resp_ie_len, status, gfp);
9623}
9624#else
9625void hdd_connect_result(struct net_device *dev,
9626 const u8 *bssid,
9627 tCsrRoamInfo *roam_info,
9628 const u8 *req_ie,
9629 size_t req_ie_len,
9630 const u8 * resp_ie,
9631 size_t resp_ie_len,
9632 u16 status,
9633 gfp_t gfp)
9634{
9635 cfg80211_connect_result(dev, bssid, req_ie, req_ie_len,
9636 resp_ie, resp_ie_len, status, gfp);
9637}
9638#endif
9639
Jeff Johnson295189b2012-06-20 16:38:30 -07009640VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
9641{
9642 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
9643 VOS_STATUS status;
9644 hdd_adapter_t *pAdapter;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05309645 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -07009646
9647 ENTER();
9648
9649 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
9650
9651 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
9652 {
9653 pAdapter = pAdapterNode->pAdapter;
9654
Kumar Anand82c009f2014-05-29 00:29:42 -07009655 hdd_wmm_init( pAdapter );
9656
Jeff Johnson295189b2012-06-20 16:38:30 -07009657 switch(pAdapter->device_mode)
9658 {
9659 case WLAN_HDD_INFRA_STATION:
9660 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07009661 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05309662
9663 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
9664
Jeff Johnson295189b2012-06-20 16:38:30 -07009665 hdd_init_station_mode(pAdapter);
9666 /* Open the gates for HDD to receive Wext commands */
9667 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07009668 pHddCtx->scan_info.mScanPending = FALSE;
9669 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07009670
9671 //Trigger the initial scan
Mukul Sharmae74e42c2015-08-06 23:55:49 +05309672 if (!pHddCtx->isLogpInProgress)
9673 hdd_wlan_initial_scan(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07009674
9675 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05309676 if (eConnectionState_Associated == connState ||
9677 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -07009678 {
9679 union iwreq_data wrqu;
9680 memset(&wrqu, '\0', sizeof(wrqu));
9681 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
9682 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
9683 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07009684 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07009685
Jeff Johnson295189b2012-06-20 16:38:30 -07009686 /* indicate disconnected event to nl80211 */
Mahesh A Saptasagar9ff4bcc2016-06-01 17:17:50 +05309687 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, false,
Mahesh A Saptasagarb5a15142016-05-25 11:27:43 +05309688 WLAN_REASON_UNSPECIFIED);
Jeff Johnson295189b2012-06-20 16:38:30 -07009689 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05309690 else if (eConnectionState_Connecting == connState)
9691 {
9692 /*
9693 * Indicate connect failure to supplicant if we were in the
9694 * process of connecting
9695 */
Abhishek Singhbbe0b2a2016-12-05 11:57:36 +05309696 hdd_connect_result(pAdapter->dev, NULL, NULL,
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05309697 NULL, 0, NULL, 0,
9698 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
9699 GFP_KERNEL);
9700 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009701 break;
9702
9703 case WLAN_HDD_SOFTAP:
Hanumanth Reddy Pothulad864f312017-01-18 16:16:08 +05309704 if (pHddCtx->cfg_ini->sap_internal_restart) {
Hanumanth Reddy Pothula15bc0fa2017-02-03 17:24:17 +05309705 hdd_init_ap_mode(pAdapter, true);
Hanumanth Reddy Pothulad864f312017-01-18 16:16:08 +05309706 status = hdd_sta_id_hash_attach(pAdapter);
9707 if (VOS_STATUS_SUCCESS != status)
9708 {
9709 hddLog(VOS_TRACE_LEVEL_FATAL,
9710 FL("failed to attach hash for"));
9711 }
9712 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009713 break;
9714
9715 case WLAN_HDD_P2P_GO:
Sameer Thalappiledf0d792013-08-09 14:31:03 -07009716 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send stop ap to supplicant",
Jeff Johnson295189b2012-06-20 16:38:30 -07009717 __func__);
Sameer Thalappiledf0d792013-08-09 14:31:03 -07009718 cfg80211_ap_stopped(pAdapter->dev, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07009719 break;
9720
9721 case WLAN_HDD_MONITOR:
9722 /* monitor interface start */
9723 break;
9724 default:
9725 break;
9726 }
9727
9728 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
9729 pAdapterNode = pNext;
9730 }
9731
9732 EXIT();
9733
9734 return VOS_STATUS_SUCCESS;
9735}
9736
9737VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
9738{
9739 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
9740 hdd_adapter_t *pAdapter;
9741 VOS_STATUS status;
9742 v_U32_t roamId;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309743 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07009744
9745 ENTER();
9746
9747 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
9748
9749 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
9750 {
9751 pAdapter = pAdapterNode->pAdapter;
9752
9753 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
9754 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
9755 {
9756 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9757 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
9758
Abhishek Singhf4669da2014-05-26 15:07:49 +05309759 hddLog(VOS_TRACE_LEVEL_INFO,
9760 "%s: Set HDD connState to eConnectionState_NotConnected",
9761 __func__);
Ganesh Kondabattini04338412015-09-14 15:39:09 +05309762 spin_lock_bh(&pAdapter->lock_for_active_session);
9763 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState)
9764 {
9765 wlan_hdd_decr_active_session(pHddCtx, pAdapter->device_mode);
9766 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009767 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
Ganesh Kondabattini04338412015-09-14 15:39:09 +05309768 spin_unlock_bh(&pAdapter->lock_for_active_session);
Jeff Johnson295189b2012-06-20 16:38:30 -07009769 init_completion(&pAdapter->disconnect_comp_var);
9770 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
9771 eCSR_DISCONNECT_REASON_UNSPECIFIED);
9772
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309773 ret = wait_for_completion_interruptible_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07009774 &pAdapter->disconnect_comp_var,
9775 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309776 if (0 >= ret)
9777 hddLog(LOGE, "%s: failure waiting for disconnect_comp_var %ld",
9778 __func__, ret);
Jeff Johnson295189b2012-06-20 16:38:30 -07009779
9780 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
9781 pHddCtx->isAmpAllowed = VOS_FALSE;
9782 sme_RoamConnect(pHddCtx->hHal,
9783 pAdapter->sessionId, &(pWextState->roamProfile),
9784 &roamId);
9785 }
9786
9787 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
9788 pAdapterNode = pNext;
9789 }
9790
9791 EXIT();
9792
9793 return VOS_STATUS_SUCCESS;
9794}
9795
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07009796void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
9797{
9798 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
9799 VOS_STATUS status;
9800 hdd_adapter_t *pAdapter;
9801 hdd_station_ctx_t *pHddStaCtx;
9802 hdd_ap_ctx_t *pHddApCtx;
9803 hdd_hostapd_state_t * pHostapdState;
9804 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
9805 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
9806 const char *p2pMode = "DEV";
9807 const char *ccMode = "Standalone";
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07009808
9809 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
9810 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
9811 {
9812 pAdapter = pAdapterNode->pAdapter;
9813 switch (pAdapter->device_mode) {
9814 case WLAN_HDD_INFRA_STATION:
9815 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9816 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
9817 staChannel = pHddStaCtx->conn_info.operationChannel;
9818 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
9819 }
9820 break;
9821 case WLAN_HDD_P2P_CLIENT:
9822 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9823 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
9824 p2pChannel = pHddStaCtx->conn_info.operationChannel;
9825 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
9826 p2pMode = "CLI";
9827 }
9828 break;
9829 case WLAN_HDD_P2P_GO:
9830 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
9831 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
9832 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
9833 p2pChannel = pHddApCtx->operatingChannel;
9834 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
9835 }
9836 p2pMode = "GO";
9837 break;
9838 case WLAN_HDD_SOFTAP:
9839 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
9840 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
9841 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
9842 apChannel = pHddApCtx->operatingChannel;
9843 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
9844 }
9845 break;
9846 default:
9847 break;
9848 }
9849 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
9850 pAdapterNode = pNext;
9851 }
9852 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
9853 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
9854 }
SaidiReddy Yenugaa8b32f92016-07-27 19:29:18 +05309855 hddLog(VOS_TRACE_LEVEL_INFO, "wlan(%d) " MAC_ADDRESS_STR " %s",
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07009856 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
9857 if (p2pChannel > 0) {
Sushant Kaushikdc3184b2015-10-09 12:00:21 +05309858 hddLog(VOS_TRACE_LEVEL_ERROR, "p2p-%s(%d) " MAC_ADDRESS_STR,
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07009859 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
9860 }
9861 if (apChannel > 0) {
Sushant Kaushikdc3184b2015-10-09 12:00:21 +05309862 hddLog(VOS_TRACE_LEVEL_ERROR, "AP(%d) " MAC_ADDRESS_STR,
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07009863 apChannel, MAC_ADDR_ARRAY(apBssid));
9864 }
9865
9866 if (p2pChannel > 0 && apChannel > 0) {
9867 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
9868 }
9869}
9870
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07009871bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07009872{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07009873 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07009874}
9875
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07009876/* Once SSR is disabled then it cannot be set. */
9877void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07009878{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07009879 if (HDD_SSR_DISABLED == isSsrRequired)
9880 return;
9881
Jeff Johnson295189b2012-06-20 16:38:30 -07009882 isSsrRequired = value;
9883}
9884
Hema Aparna Medicharla6b4d4f32015-06-23 04:09:12 +05309885void hdd_set_pre_close( hdd_context_t *pHddCtx)
9886{
9887 sme_PreClose(pHddCtx->hHal);
9888}
9889
Jeff Johnson295189b2012-06-20 16:38:30 -07009890VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
9891 hdd_adapter_list_node_t** ppAdapterNode)
9892{
9893 VOS_STATUS status;
Mukul Sharmaae1266d2015-06-26 15:29:53 +05309894 spin_lock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07009895 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
9896 (hdd_list_node_t**) ppAdapterNode );
Mukul Sharmaae1266d2015-06-26 15:29:53 +05309897 spin_unlock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07009898 return status;
9899}
9900
9901VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
9902 hdd_adapter_list_node_t* pAdapterNode,
9903 hdd_adapter_list_node_t** pNextAdapterNode)
9904{
9905 VOS_STATUS status;
Mukul Sharmaae1266d2015-06-26 15:29:53 +05309906 spin_lock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07009907 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
9908 (hdd_list_node_t*) pAdapterNode,
9909 (hdd_list_node_t**)pNextAdapterNode );
9910
Mukul Sharmaae1266d2015-06-26 15:29:53 +05309911 spin_unlock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07009912 return status;
9913}
9914
9915VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
9916 hdd_adapter_list_node_t* pAdapterNode)
9917{
9918 VOS_STATUS status;
Mukul Sharmaae1266d2015-06-26 15:29:53 +05309919 spin_lock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07009920 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
9921 &pAdapterNode->node );
Mukul Sharmaae1266d2015-06-26 15:29:53 +05309922 spin_unlock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07009923 return status;
9924}
9925
9926VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
9927 hdd_adapter_list_node_t** ppAdapterNode)
9928{
9929 VOS_STATUS status;
Mukul Sharmaae1266d2015-06-26 15:29:53 +05309930 spin_lock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07009931 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
9932 (hdd_list_node_t**) ppAdapterNode );
Mukul Sharmaae1266d2015-06-26 15:29:53 +05309933 spin_unlock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07009934 return status;
9935}
9936
9937VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
9938 hdd_adapter_list_node_t* pAdapterNode)
9939{
9940 VOS_STATUS status;
Mukul Sharmaae1266d2015-06-26 15:29:53 +05309941 spin_lock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07009942 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
9943 (hdd_list_node_t*) pAdapterNode );
Mukul Sharmaae1266d2015-06-26 15:29:53 +05309944 spin_unlock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07009945 return status;
9946}
9947
9948VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
9949 hdd_adapter_list_node_t* pAdapterNode)
9950{
9951 VOS_STATUS status;
Mukul Sharmaae1266d2015-06-26 15:29:53 +05309952 spin_lock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07009953 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
9954 (hdd_list_node_t*) pAdapterNode );
Mukul Sharmaae1266d2015-06-26 15:29:53 +05309955 spin_unlock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07009956 return status;
9957}
9958
9959hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
9960 tSirMacAddr macAddr )
9961{
9962 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
9963 hdd_adapter_t *pAdapter;
9964 VOS_STATUS status;
9965
9966 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
9967
9968 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
9969 {
9970 pAdapter = pAdapterNode->pAdapter;
9971
9972 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
9973 macAddr, sizeof(tSirMacAddr) ) )
9974 {
9975 return pAdapter;
9976 }
9977 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
9978 pAdapterNode = pNext;
9979 }
9980
9981 return NULL;
9982
9983}
9984
9985hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
9986{
9987 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
9988 hdd_adapter_t *pAdapter;
9989 VOS_STATUS status;
9990
9991 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
9992
9993 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
9994 {
9995 pAdapter = pAdapterNode->pAdapter;
9996
9997 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
9998 IFNAMSIZ ) )
9999 {
10000 return pAdapter;
10001 }
10002 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10003 pAdapterNode = pNext;
10004 }
10005
10006 return NULL;
10007
10008}
10009
Ganesh Kondabattinicbfdc392015-09-11 19:12:59 +053010010hdd_adapter_t *hdd_get_adapter_by_sme_session_id( hdd_context_t *pHddCtx,
10011 tANI_U32 sme_session_id )
10012{
10013 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
10014 hdd_adapter_t *pAdapter;
10015 VOS_STATUS vos_status;
10016
10017
10018 vos_status = hdd_get_front_adapter( pHddCtx, &pAdapterNode);
10019
10020 while ((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == vos_status))
10021 {
10022 pAdapter = pAdapterNode->pAdapter;
10023
10024 if (pAdapter->sessionId == sme_session_id)
10025 return pAdapter;
10026
10027 vos_status = hdd_get_next_adapter(pHddCtx, pAdapterNode, &pNext);
10028 pAdapterNode = pNext;
10029 }
10030
10031 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
10032 "%s: sme_session_id %d does not exist with host",
10033 __func__, sme_session_id);
10034
10035 return NULL;
10036}
10037
Jeff Johnson295189b2012-06-20 16:38:30 -070010038hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
10039{
10040 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
10041 hdd_adapter_t *pAdapter;
10042 VOS_STATUS status;
10043
10044 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10045
10046 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
10047 {
10048 pAdapter = pAdapterNode->pAdapter;
10049
10050 if( pAdapter && (mode == pAdapter->device_mode) )
10051 {
10052 return pAdapter;
10053 }
10054 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10055 pAdapterNode = pNext;
10056 }
10057
10058 return NULL;
10059
10060}
10061
10062//Remove this function later
10063hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
10064{
10065 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
10066 hdd_adapter_t *pAdapter;
10067 VOS_STATUS status;
10068
10069 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10070
10071 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
10072 {
10073 pAdapter = pAdapterNode->pAdapter;
10074
10075 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
10076 {
10077 return pAdapter;
10078 }
10079
10080 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10081 pAdapterNode = pNext;
10082 }
10083
10084 return NULL;
10085
10086}
10087
Jeff Johnson295189b2012-06-20 16:38:30 -070010088/**---------------------------------------------------------------------------
10089
Mahesh A Saptasgar64534612014-09-23 13:13:33 +053010090 \brief hdd_get_operating_channel() -
Jeff Johnson295189b2012-06-20 16:38:30 -070010091
10092 This API returns the operating channel of the requested device mode
10093
10094 \param - pHddCtx - Pointer to the HDD context.
10095 - mode - Device mode for which operating channel is required
10096 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
10097 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
10098 \return - channel number. "0" id the requested device is not found OR it is not connected.
10099 --------------------------------------------------------------------------*/
10100v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
10101{
10102 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
10103 VOS_STATUS status;
10104 hdd_adapter_t *pAdapter;
10105 v_U8_t operatingChannel = 0;
10106
10107 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10108
10109 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
10110 {
10111 pAdapter = pAdapterNode->pAdapter;
10112
10113 if( mode == pAdapter->device_mode )
10114 {
10115 switch(pAdapter->device_mode)
10116 {
10117 case WLAN_HDD_INFRA_STATION:
10118 case WLAN_HDD_P2P_CLIENT:
10119 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
10120 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
10121 break;
10122 case WLAN_HDD_SOFTAP:
10123 case WLAN_HDD_P2P_GO:
10124 /*softap connection info */
10125 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
10126 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
10127 break;
10128 default:
10129 break;
10130 }
10131
10132 break; //Found the device of interest. break the loop
10133 }
10134
10135 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10136 pAdapterNode = pNext;
10137 }
10138 return operatingChannel;
10139}
10140
10141#ifdef WLAN_FEATURE_PACKET_FILTERING
10142/**---------------------------------------------------------------------------
10143
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +053010144 \brief __hdd_set_multicast_list() -
Jeff Johnson295189b2012-06-20 16:38:30 -070010145
10146 This used to set the multicast address list.
10147
10148 \param - dev - Pointer to the WLAN device.
10149 - skb - Pointer to OS packet (sk_buff).
Mahesh A Saptasagar74088392015-02-05 17:22:09 +053010150 \return - success/fail
Jeff Johnson295189b2012-06-20 16:38:30 -070010151
10152 --------------------------------------------------------------------------*/
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +053010153static void __hdd_set_multicast_list(struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -070010154{
Mahesh A Saptasagar74088392015-02-05 17:22:09 +053010155 hdd_adapter_t *pAdapter;
10156 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -070010157 int mc_count;
Mahesh A Saptasagar74088392015-02-05 17:22:09 +053010158 int i = 0, ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -070010159 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +053010160
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +053010161 ENTER();
10162
Mahesh A Saptasagar74088392015-02-05 17:22:09 +053010163 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Gopichand Nakkala0f276812013-02-24 14:45:51 +053010164 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -070010165 {
10166 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +053010167 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -070010168 return;
10169 }
Mahesh A Saptasagar74088392015-02-05 17:22:09 +053010170 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10171 ret = wlan_hdd_validate_context(pHddCtx);
10172 if (0 != ret)
10173 {
Mahesh A Saptasagar74088392015-02-05 17:22:09 +053010174 return;
10175 }
Jeff Johnson295189b2012-06-20 16:38:30 -070010176 if (dev->flags & IFF_ALLMULTI)
10177 {
10178 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070010179 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +053010180 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -070010181 }
Mahesh A Saptasagar74088392015-02-05 17:22:09 +053010182 else
Jeff Johnson295189b2012-06-20 16:38:30 -070010183 {
10184 mc_count = netdev_mc_count(dev);
10185 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070010186 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -070010187 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
10188 {
10189 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070010190 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +053010191 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -070010192 return;
10193 }
10194
Gopichand Nakkala0f276812013-02-24 14:45:51 +053010195 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -070010196
10197 netdev_for_each_mc_addr(ha, dev) {
10198 if (i == mc_count)
10199 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +053010200 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
10201 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
Arif Hussain6d2a3322013-11-17 19:50:10 -080010202 hddLog(VOS_TRACE_LEVEL_INFO, "%s: mlist[%d] = "MAC_ADDRESS_STR,
Mahesh A Saptasagar74088392015-02-05 17:22:09 +053010203 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +053010204 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -070010205 i++;
10206 }
10207 }
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +053010208
Ganesh Kondabattinifb37e652015-10-09 15:46:47 +053010209 if (pHddCtx->hdd_wlan_suspended)
10210 {
10211 /*
10212 * Configure the Mcast address list to FW
10213 * If wlan is already in suspend mode
10214 */
10215 wlan_hdd_set_mc_addr_list(pAdapter, TRUE);
10216 }
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +053010217 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -070010218 return;
10219}
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +053010220
10221static void hdd_set_multicast_list(struct net_device *dev)
10222{
10223 vos_ssr_protect(__func__);
10224 __hdd_set_multicast_list(dev);
10225 vos_ssr_unprotect(__func__);
10226}
Jeff Johnson295189b2012-06-20 16:38:30 -070010227#endif
10228
10229/**---------------------------------------------------------------------------
10230
10231 \brief hdd_select_queue() -
10232
10233 This function is registered with the Linux OS for network
10234 core to decide which queue to use first.
10235
10236 \param - dev - Pointer to the WLAN device.
10237 - skb - Pointer to OS packet (sk_buff).
10238 \return - ac, Queue Index/access category corresponding to UP in IP header
10239
10240 --------------------------------------------------------------------------*/
10241v_U16_t hdd_select_queue(struct net_device *dev,
Anand N Sunkade9adb1b2015-07-29 09:56:45 +053010242 struct sk_buff *skb
10243#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0))
10244 , void *accel_priv
10245#endif
10246#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0))
10247 , select_queue_fallback_t fallback
10248#endif
10249)
Jeff Johnson295189b2012-06-20 16:38:30 -070010250{
10251 return hdd_wmm_select_queue(dev, skb);
10252}
10253
10254
10255/**---------------------------------------------------------------------------
10256
10257 \brief hdd_wlan_initial_scan() -
10258
10259 This function triggers the initial scan
10260
10261 \param - pAdapter - Pointer to the HDD adapter.
10262
10263 --------------------------------------------------------------------------*/
10264void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
10265{
10266 tCsrScanRequest scanReq;
10267 tCsrChannelInfo channelInfo;
10268 eHalStatus halStatus;
Jeff Johnson02797792013-10-26 19:17:13 -070010269 tANI_U32 scanId;
Jeff Johnson295189b2012-06-20 16:38:30 -070010270 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10271
10272 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
10273 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
10274 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
10275
10276 if(sme_Is11dSupported(pHddCtx->hHal))
10277 {
10278 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
10279 if ( HAL_STATUS_SUCCESS( halStatus ) )
10280 {
10281 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
10282 if( !scanReq.ChannelInfo.ChannelList )
10283 {
10284 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
10285 vos_mem_free(channelInfo.ChannelList);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -080010286 channelInfo.ChannelList = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -070010287 return;
10288 }
10289 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
10290 channelInfo.numOfChannels);
10291 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
10292 vos_mem_free(channelInfo.ChannelList);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -080010293 channelInfo.ChannelList = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -070010294 }
10295
10296 scanReq.scanType = eSIR_PASSIVE_SCAN;
10297 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
10298 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
10299 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
10300 }
10301 else
10302 {
10303 scanReq.scanType = eSIR_ACTIVE_SCAN;
10304 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
10305 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
10306 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
10307 }
10308
10309 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
10310 if ( !HAL_STATUS_SUCCESS( halStatus ) )
10311 {
10312 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
10313 __func__, halStatus );
10314 }
10315
10316 if(sme_Is11dSupported(pHddCtx->hHal))
10317 vos_mem_free(scanReq.ChannelInfo.ChannelList);
10318}
10319
Jeff Johnson295189b2012-06-20 16:38:30 -070010320/**---------------------------------------------------------------------------
10321
10322 \brief hdd_full_power_callback() - HDD full power callback function
10323
10324 This is the function invoked by SME to inform the result of a full power
10325 request issued by HDD
10326
10327 \param - callbackcontext - Pointer to cookie
10328 \param - status - result of request
10329
10330 \return - None
10331
10332 --------------------------------------------------------------------------*/
10333static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
10334{
Jeff Johnson72a40512013-12-19 10:14:15 -080010335 struct statsContext *pContext = callbackContext;
Jeff Johnson295189b2012-06-20 16:38:30 -070010336
10337 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +053010338 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -070010339
10340 if (NULL == callbackContext)
10341 {
10342 hddLog(VOS_TRACE_LEVEL_ERROR,
10343 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070010344 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -070010345 return;
10346 }
10347
Jeff Johnson72a40512013-12-19 10:14:15 -080010348 /* there is a race condition that exists between this callback
10349 function and the caller since the caller could time out either
10350 before or while this code is executing. we use a spinlock to
10351 serialize these actions */
10352 spin_lock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010353
10354 if (POWER_CONTEXT_MAGIC != pContext->magic)
10355 {
10356 /* the caller presumably timed out so there is nothing we can do */
Jeff Johnson72a40512013-12-19 10:14:15 -080010357 spin_unlock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010358 hddLog(VOS_TRACE_LEVEL_WARN,
10359 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070010360 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -070010361 return;
10362 }
10363
Jeff Johnson72a40512013-12-19 10:14:15 -080010364 /* context is valid so caller is still waiting */
10365
10366 /* paranoia: invalidate the magic */
10367 pContext->magic = 0;
10368
10369 /* notify the caller */
Jeff Johnson295189b2012-06-20 16:38:30 -070010370 complete(&pContext->completion);
Jeff Johnson72a40512013-12-19 10:14:15 -080010371
10372 /* serialization is complete */
10373 spin_unlock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010374}
10375
Katya Nigamf0511f62015-05-05 16:40:57 +053010376void wlan_hdd_mon_set_typesubtype( hdd_mon_ctx_t *pMonCtx,int type)
10377{
10378 pMonCtx->typeSubtypeBitmap = 0;
10379 if( type%10 ) /* Management Packets */
10380 pMonCtx->typeSubtypeBitmap |= 0xFFFF;
10381 type/=10;
10382 if( type%10 ) /* Control Packets */
10383 pMonCtx->typeSubtypeBitmap |= 0xFFFF0000;
10384 type/=10;
10385 if( type%10 ) /* Data Packets */
10386 pMonCtx->typeSubtypeBitmap |= 0xFFFF00000000;
10387}
10388
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053010389VOS_STATUS wlan_hdd_mon_postMsg(tANI_U32 *magic, struct completion *cmpVar,
10390 hdd_mon_ctx_t *pMonCtx , void* callback)
Katya Nigamf0511f62015-05-05 16:40:57 +053010391{
10392 vos_msg_t monMsg;
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053010393 tSirMonModeReq *pMonModeReq;
Katya Nigamf0511f62015-05-05 16:40:57 +053010394
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053010395 if (MON_MODE_START == pMonCtx->state)
10396 monMsg.type = WDA_MON_START_REQ;
10397 else if (MON_MODE_STOP == pMonCtx->state)
10398 monMsg.type = WDA_MON_STOP_REQ;
10399 else {
10400 hddLog(VOS_TRACE_LEVEL_ERROR,
10401 FL("invalid monitor state %d"), pMonCtx->state);
Katya Nigamf0511f62015-05-05 16:40:57 +053010402 return VOS_STATUS_E_FAILURE;
10403 }
10404
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053010405 pMonModeReq = vos_mem_malloc(sizeof(tSirMonModeReq));
10406 if (pMonModeReq == NULL) {
10407 hddLog(VOS_TRACE_LEVEL_ERROR,
10408 FL("fail to allocate memory for monitor mode req"));
10409 return VOS_STATUS_E_FAILURE;
10410 }
Katya Nigamf0511f62015-05-05 16:40:57 +053010411
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053010412 pMonModeReq->magic = magic;
10413 pMonModeReq->cmpVar = cmpVar;
10414 pMonModeReq->data = pMonCtx;
10415 pMonModeReq->callback = callback;
Katya Nigamf0511f62015-05-05 16:40:57 +053010416
Katya Nigamf0511f62015-05-05 16:40:57 +053010417 monMsg.reserved = 0;
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053010418 monMsg.bodyptr = pMonModeReq;
Katya Nigamf0511f62015-05-05 16:40:57 +053010419 monMsg.bodyval = 0;
10420
10421 if (VOS_STATUS_SUCCESS != vos_mq_post_message(
10422 VOS_MODULE_ID_WDA,(vos_msg_t *)&monMsg)) {
10423 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: : Failed to post Msg to HAL",__func__);
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053010424 vos_mem_free(pMonModeReq);
Katya Nigamf0511f62015-05-05 16:40:57 +053010425 }
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053010426 return VOS_STATUS_SUCCESS;
Katya Nigamf0511f62015-05-05 16:40:57 +053010427}
10428
Katya Nigame7b69a82015-04-28 15:24:06 +053010429void wlan_hdd_mon_close(hdd_context_t *pHddCtx)
10430{
10431 VOS_STATUS vosStatus;
10432 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053010433 long ret;
10434 hdd_mon_ctx_t *pMonCtx = NULL;
10435 v_U32_t magic;
10436 struct completion cmpVar;
Hanumantha Reddy Pothulac99bc062015-09-08 14:59:26 +053010437
Katya Nigame7b69a82015-04-28 15:24:06 +053010438 hdd_adapter_t *pAdapter = hdd_get_adapter(pHddCtx,WLAN_HDD_MONITOR);
10439 if(pAdapter == NULL || pVosContext == NULL)
10440 {
10441 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:pAdapter is NULL",__func__);
10442 return ;
10443 }
Katya Nigamf0511f62015-05-05 16:40:57 +053010444
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053010445 pMonCtx = WLAN_HDD_GET_MONITOR_CTX_PTR(pAdapter);
10446 if (pMonCtx!= NULL && pMonCtx->state == MON_MODE_START) {
10447 pMonCtx->state = MON_MODE_STOP;
10448 magic = MON_MODE_MSG_MAGIC;
10449 init_completion(&cmpVar);
10450 if (VOS_STATUS_SUCCESS !=
10451 wlan_hdd_mon_postMsg(&magic, &cmpVar,
10452 pMonCtx, hdd_monPostMsgCb)) {
10453 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
10454 FL("failed to post MON MODE REQ"));
10455 pMonCtx->state = MON_MODE_START;
10456 magic = 0;
10457 return;
10458 }
10459 ret = wait_for_completion_timeout(&cmpVar, MON_MODE_MSG_TIMEOUT);
10460 magic = 0;
10461 if (ret <= 0 ) {
10462 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
10463 FL("timeout on monitor mode completion %ld"), ret);
10464 }
10465 }
10466
Katya Nigame7b69a82015-04-28 15:24:06 +053010467 hdd_UnregisterWext(pAdapter->dev);
10468
10469 vos_mon_stop( pVosContext );
10470
10471 vosStatus = vos_sched_close( pVosContext );
10472 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
10473 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
10474 "%s: Failed to close VOSS Scheduler",__func__);
10475 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
10476 }
10477
10478 vosStatus = vos_nv_close();
10479 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
10480 {
10481 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
10482 "%s: Failed to close NV", __func__);
10483 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
10484 }
10485
10486 vos_close(pVosContext);
10487
10488 #ifdef WLAN_KD_READY_NOTIFIER
10489 nl_srv_exit(pHddCtx->ptt_pid);
10490 #else
10491 nl_srv_exit();
10492 #endif
10493
Katya Nigame7b69a82015-04-28 15:24:06 +053010494 hdd_close_all_adapters( pHddCtx );
Katya Nigame7b69a82015-04-28 15:24:06 +053010495}
Agrawal Ashish33ec71e2015-11-26 20:20:58 +053010496/**
10497 * hdd_wlan_free_wiphy_channels - free Channel pointer for wiphy
10498 * @ wiphy: the wiphy to validate against
10499 *
10500 * Return: void
10501 */
10502void hdd_wlan_free_wiphy_channels(struct wiphy *wiphy)
10503{
10504 int i =0;
10505 for (i = 0; i < IEEE80211_NUM_BANDS; i++)
10506 {
10507 if (NULL != wiphy->bands[i] &&
10508 (NULL != wiphy->bands[i]->channels))
10509 {
10510 vos_mem_free(wiphy->bands[i]->channels);
10511 wiphy->bands[i]->channels = NULL;
10512 }
10513 }
10514}
Jeff Johnson295189b2012-06-20 16:38:30 -070010515/**---------------------------------------------------------------------------
10516
10517 \brief hdd_wlan_exit() - HDD WLAN exit function
10518
10519 This is the driver exit point (invoked during rmmod)
10520
10521 \param - pHddCtx - Pointer to the HDD Context
10522
10523 \return - None
10524
10525 --------------------------------------------------------------------------*/
10526void hdd_wlan_exit(hdd_context_t *pHddCtx)
10527{
10528 eHalStatus halStatus;
10529 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
10530 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +053010531 struct wiphy *wiphy = pHddCtx->wiphy;
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -080010532 hdd_adapter_t* pAdapter = NULL;
Jeff Johnson72a40512013-12-19 10:14:15 -080010533 struct statsContext powerContext;
Jeff Johnson295189b2012-06-20 16:38:30 -070010534 long lrc;
c_hpothu5ab05e92014-06-13 17:34:05 +053010535 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -070010536
10537 ENTER();
10538
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053010539
Katya Nigame7b69a82015-04-28 15:24:06 +053010540 if (VOS_MONITOR_MODE == hdd_get_conparam())
10541 {
10542 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: MONITOR MODE",__func__);
10543 wlan_hdd_mon_close(pHddCtx);
Hanumantha Reddy Pothulac99bc062015-09-08 14:59:26 +053010544 goto free_hdd_ctx;
Katya Nigame7b69a82015-04-28 15:24:06 +053010545 }
10546 else if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -080010547 {
10548 // Unloading, restart logic is no more required.
10549 wlan_hdd_restart_deinit(pHddCtx);
Jeff Johnsone7245742012-09-05 17:12:55 -070010550
Agarwal Ashishb20e0ff2014-12-17 22:50:19 +053010551#ifdef FEATURE_WLAN_TDLS
10552 /* At the time of driver unloading; if tdls connection is present;
10553 * hdd_rx_packet_cbk calls wlan_hdd_tdls_find_peer.
10554 * wlan_hdd_tdls_find_peer always checks for valid context;
10555 * as load/unload in progress there can be a race condition.
10556 * hdd_rx_packet_cbk calls wlan_hdd_tdls_find_peer only
10557 * when tdls state is enabled.
10558 * As soon as driver set load/unload flag; tdls flag also needs
10559 * to be disabled so that hdd_rx_packet_cbk won't call
10560 * wlan_hdd_tdls_find_peer.
10561 */
Masti, Narayanraddi20494af2015-12-17 20:56:42 +053010562 wlan_hdd_tdls_set_mode(pHddCtx, eTDLS_SUPPORT_DISABLED, FALSE,
10563 HDD_SET_TDLS_MODE_SOURCE_USER);
Agarwal Ashishb20e0ff2014-12-17 22:50:19 +053010564#endif
10565
c_hpothu5ab05e92014-06-13 17:34:05 +053010566 vosStatus = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10567 while (NULL != pAdapterNode && VOS_STATUS_E_EMPTY != vosStatus)
Jeff Johnson295189b2012-06-20 16:38:30 -070010568 {
c_hpothu5ab05e92014-06-13 17:34:05 +053010569 pAdapter = pAdapterNode->pAdapter;
10570 if (NULL != pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -070010571 {
Mahesh A Saptasagar305e2632015-03-04 12:57:33 +053010572 /* Disable TX on the interface, after this hard_start_xmit() will
10573 * not be called on that interface
10574 */
10575 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
10576 netif_tx_disable(pAdapter->dev);
10577
10578 /* Mark the interface status as "down" for outside world */
10579 netif_carrier_off(pAdapter->dev);
10580
Agarwal Ashish9ffa5b92014-11-18 21:07:02 +053010581 /* DeInit the adapter. This ensures that all data packets
10582 * are freed.
10583 */
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +053010584#ifdef FEATURE_WLAN_TDLS
10585 mutex_lock(&pHddCtx->tdls_lock);
10586#endif
c_hpothu002231a2015-02-05 14:58:51 +053010587 hdd_deinit_adapter(pHddCtx, pAdapter, FALSE);
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +053010588#ifdef FEATURE_WLAN_TDLS
10589 mutex_unlock(&pHddCtx->tdls_lock);
10590#endif
Masti, Narayanraddi26378462016-01-05 18:20:28 +053010591 vos_flush_delayed_work(&pHddCtx->scan_ctxt.scan_work);
10592
10593 wlan_hdd_init_deinit_defer_scan_context(&pHddCtx->scan_ctxt);
Agarwal Ashish9ffa5b92014-11-18 21:07:02 +053010594
c_hpothu5ab05e92014-06-13 17:34:05 +053010595 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode ||
10596 WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)
10597 {
10598 wlan_hdd_cfg80211_deregister_frames(pAdapter);
10599 hdd_UnregisterWext(pAdapter->dev);
10600 }
Kaushik, Sushant4975a572014-10-21 16:07:48 +053010601
Jeff Johnson295189b2012-06-20 16:38:30 -070010602 }
c_hpothu5ab05e92014-06-13 17:34:05 +053010603 vosStatus = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10604 pAdapterNode = pNext;
Jeff Johnson295189b2012-06-20 16:38:30 -070010605 }
mukul sharmabab477d2015-06-11 17:14:55 +053010606
Kaushik, Sushant4975a572014-10-21 16:07:48 +053010607 // Cancel any outstanding scan requests. We are about to close all
10608 // of our adapters, but an adapter structure is what SME passes back
10609 // to our callback function. Hence if there are any outstanding scan
10610 // requests then there is a race condition between when the adapter
10611 // is closed and when the callback is invoked.We try to resolve that
10612 // race condition here by canceling any outstanding scans before we
10613 // close the adapters.
10614 // Note that the scans may be cancelled in an asynchronous manner,
10615 // so ideally there needs to be some kind of synchronization. Rather
10616 // than introduce a new synchronization here, we will utilize the
10617 // fact that we are about to Request Full Power, and since that is
10618 // synchronized, the expectation is that by the time Request Full
10619 // Power has completed all scans will be cancelled.
10620 if (pHddCtx->scan_info.mScanPending)
10621 {
Hema Aparna Medicharlaf05f6cd2015-01-21 14:44:19 +053010622 if(NULL != pAdapter)
10623 {
10624 hddLog(VOS_TRACE_LEVEL_INFO,
10625 FL("abort scan mode: %d sessionId: %d"),
10626 pAdapter->device_mode,
10627 pAdapter->sessionId);
10628 }
10629 hdd_abort_mac_scan(pHddCtx,
10630 pHddCtx->scan_info.sessionId,
10631 eCSR_SCAN_ABORT_DEFAULT);
Kaushik, Sushant4975a572014-10-21 16:07:48 +053010632 }
Jeff Johnson295189b2012-06-20 16:38:30 -070010633 }
c_hpothu5ab05e92014-06-13 17:34:05 +053010634 else
Jeff Johnson88ba7742013-02-27 14:36:02 -080010635 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +053010636 hddLog(VOS_TRACE_LEVEL_INFO,"%s: FTM MODE",__func__);
Hanumantha Reddy Pothula45af96b2015-02-12 16:07:58 +053010637 if (pHddCtx->ftm.ftm_state == WLAN_FTM_STARTING)
10638 {
10639 INIT_COMPLETION(pHddCtx->ftm.startCmpVar);
10640 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
10641 "%s: in middle of FTM START", __func__);
10642 lrc = wait_for_completion_timeout(&pHddCtx->ftm.startCmpVar,
10643 msecs_to_jiffies(20000));
10644 if(!lrc)
10645 {
10646 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
10647 "%s: timedout on ftmStartCmpVar fatal error", __func__);
10648 }
10649 }
Jeff Johnson88ba7742013-02-27 14:36:02 -080010650 wlan_hdd_ftm_close(pHddCtx);
10651 goto free_hdd_ctx;
10652 }
c_hpothu6ff1c3c2013-10-01 19:01:57 +053010653
Jeff Johnson295189b2012-06-20 16:38:30 -070010654 /* DeRegister with platform driver as client for Suspend/Resume */
10655 vosStatus = hddDeregisterPmOps(pHddCtx);
10656 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
10657 {
10658 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
10659 VOS_ASSERT(0);
10660 }
10661
10662 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
10663 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
10664 {
10665 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
10666 }
Jeff Johnson295189b2012-06-20 16:38:30 -070010667
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -070010668 //Stop the traffic monitor timer
Mahesh A Saptasagard461e432016-07-20 15:01:40 +053010669 if ((pHddCtx->cfg_ini->dynSplitscan) && (VOS_TIMER_STATE_RUNNING ==
10670 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr)))
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -070010671 {
10672 vos_timer_stop(&pHddCtx->tx_rx_trafficTmr);
10673 }
10674
10675 // Destroy the traffic monitor timer
Mahesh A Saptasagard461e432016-07-20 15:01:40 +053010676 if ((pHddCtx->cfg_ini->dynSplitscan) &&
10677 (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
10678 &pHddCtx->tx_rx_trafficTmr))))
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -070010679 {
10680 hddLog(VOS_TRACE_LEVEL_ERROR,
10681 "%s: Cannot deallocate Traffic monitor timer", __func__);
10682 }
10683
Bhargav Shahd0715912015-10-01 18:17:37 +053010684 if (VOS_TIMER_STATE_RUNNING ==
10685 vos_timer_getCurrentState(&pHddCtx->delack_timer)) {
10686 vos_timer_stop(&pHddCtx->delack_timer);
10687 }
10688
10689 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
10690 &pHddCtx->delack_timer))) {
10691 hddLog(VOS_TRACE_LEVEL_ERROR,
10692 "%s: Cannot deallocate Bus bandwidth timer", __func__);
10693 }
10694
Masti, Narayanraddi44b0db02015-12-22 11:54:35 +053010695 if (VOS_TIMER_STATE_RUNNING ==
10696 vos_timer_getCurrentState(&pHddCtx->tdls_source_timer)) {
10697 vos_timer_stop(&pHddCtx->tdls_source_timer);
10698 }
10699
Abhishek Singh8a3e4dc2017-01-02 10:39:18 +053010700 vos_set_snoc_high_freq_voting(false);
10701
Masti, Narayanraddi44b0db02015-12-22 11:54:35 +053010702 vos_timer_destroy(&pHddCtx->tdls_source_timer);
10703
Jeff Johnson295189b2012-06-20 16:38:30 -070010704 //Disable IMPS/BMPS as we do not want the device to enter any power
10705 //save mode during shutdown
10706 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
10707 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
10708 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
10709
10710 //Ensure that device is in full power as we will touch H/W during vos_Stop
10711 init_completion(&powerContext.completion);
10712 powerContext.magic = POWER_CONTEXT_MAGIC;
10713
10714 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
10715 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
10716
10717 if (eHAL_STATUS_SUCCESS != halStatus)
10718 {
10719 if (eHAL_STATUS_PMC_PENDING == halStatus)
10720 {
10721 /* request was sent -- wait for the response */
10722 lrc = wait_for_completion_interruptible_timeout(
10723 &powerContext.completion,
10724 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
Jeff Johnson295189b2012-06-20 16:38:30 -070010725 if (lrc <= 0)
10726 {
10727 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070010728 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -070010729 }
10730 }
10731 else
10732 {
10733 hddLog(VOS_TRACE_LEVEL_ERROR,
10734 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070010735 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -070010736 /* continue -- need to clean up as much as possible */
10737 }
10738 }
Hanumantha Reddy Pothula81b42b22015-05-12 13:52:00 +053010739 if ((eHAL_STATUS_SUCCESS == halStatus) ||
10740 (eHAL_STATUS_PMC_PENDING == halStatus && lrc > 0))
10741 {
10742 /* This will issue a dump command which will clean up
10743 BTQM queues and unblock MC thread */
10744 vos_fwDumpReq(274, 0, 0, 0, 0, 1);
10745 }
Jeff Johnson295189b2012-06-20 16:38:30 -070010746
Jeff Johnson72a40512013-12-19 10:14:15 -080010747 /* either we never sent a request, we sent a request and received a
10748 response or we sent a request and timed out. if we never sent a
10749 request or if we sent a request and got a response, we want to
10750 clear the magic out of paranoia. if we timed out there is a
10751 race condition such that the callback function could be
10752 executing at the same time we are. of primary concern is if the
10753 callback function had already verified the "magic" but had not
10754 yet set the completion variable when a timeout occurred. we
10755 serialize these activities by invalidating the magic while
10756 holding a shared spinlock which will cause us to block if the
10757 callback is currently executing */
10758 spin_lock(&hdd_context_lock);
10759 powerContext.magic = 0;
10760 spin_unlock(&hdd_context_lock);
10761
Hema Aparna Medicharlaa6cf65e2015-06-01 16:23:28 +053010762 /* If Device is shutdown, no point for SME to wait for responses
10763 from device. Pre Close SME */
10764 if(wcnss_device_is_shutdown())
10765 {
10766 sme_PreClose(pHddCtx->hHal);
10767 }
Yue Ma0d4891e2013-08-06 17:01:45 -070010768 hdd_debugfs_exit(pHddCtx);
10769
Ratheesh S P35ed8b12015-04-27 14:01:07 +053010770#ifdef WLAN_NS_OFFLOAD
Ratheesh S P36dbc932015-08-07 14:28:57 +053010771 hddLog(LOG1, FL("Unregister IPv6 notifier"));
Ratheesh S P35ed8b12015-04-27 14:01:07 +053010772 unregister_inet6addr_notifier(&pHddCtx->ipv6_notifier);
10773#endif
Ratheesh S P36dbc932015-08-07 14:28:57 +053010774 hddLog(LOG1, FL("Unregister IPv4 notifier"));
Ratheesh S P35ed8b12015-04-27 14:01:07 +053010775 unregister_inetaddr_notifier(&pHddCtx->ipv4_notifier);
10776
Jeff Johnson295189b2012-06-20 16:38:30 -070010777 // Unregister the Net Device Notifier
10778 unregister_netdevice_notifier(&hdd_netdev_notifier);
10779
Jeff Johnson295189b2012-06-20 16:38:30 -070010780 hdd_stop_all_adapters( pHddCtx );
10781
Jeff Johnson295189b2012-06-20 16:38:30 -070010782#ifdef WLAN_BTAMP_FEATURE
10783 vosStatus = WLANBAP_Stop(pVosContext);
10784 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
10785 {
10786 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
10787 "%s: Failed to stop BAP",__func__);
10788 }
10789#endif //WLAN_BTAMP_FEATURE
10790
10791 //Stop all the modules
10792 vosStatus = vos_stop( pVosContext );
10793 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
10794 {
10795 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
10796 "%s: Failed to stop VOSS",__func__);
10797 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
Hanumantha Reddy Pothulabd9601a2016-02-12 13:22:27 +053010798 if (isSsrPanicOnFailure())
10799 VOS_BUG(0);
Jeff Johnson295189b2012-06-20 16:38:30 -070010800 }
10801
Jeff Johnson295189b2012-06-20 16:38:30 -070010802 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -070010803 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -070010804
10805 //Close the scheduler before calling vos_close to make sure no thread is
10806 // scheduled after the each module close is called i.e after all the data
10807 // structures are freed.
10808 vosStatus = vos_sched_close( pVosContext );
10809 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
10810 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
10811 "%s: Failed to close VOSS Scheduler",__func__);
10812 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
10813 }
Jeff Johnsone7245742012-09-05 17:12:55 -070010814#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
10815 /* Destroy the wake lock */
Sushant Kaushik83392fa2015-05-05 17:44:40 +053010816 vos_wake_lock_destroy(&pHddCtx->rx_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -070010817#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -080010818 /* Destroy the wake lock */
Sushant Kaushik83392fa2015-05-05 17:44:40 +053010819 vos_wake_lock_destroy(&pHddCtx->sap_wake_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010820
Mihir Shete7a24b5f2013-12-21 12:18:31 +053010821#ifdef CONFIG_ENABLE_LINUX_REG
10822 vosStatus = vos_nv_close();
10823 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
10824 {
10825 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
10826 "%s: Failed to close NV", __func__);
10827 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
10828 }
10829#endif
10830
Jeff Johnson295189b2012-06-20 16:38:30 -070010831 //Close VOSS
10832 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
10833 vos_close(pVosContext);
10834
Jeff Johnson295189b2012-06-20 16:38:30 -070010835 //Close Watchdog
10836 if(pHddCtx->cfg_ini->fIsLogpEnabled)
10837 vos_watchdog_close(pVosContext);
10838
Gopichand Nakkalaa0358482013-06-12 17:05:47 +053010839 //Clean up HDD Nlink Service
10840 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Gopichand Nakkalaa0358482013-06-12 17:05:47 +053010841
Manjeet Singh47ee8472016-04-11 11:57:18 +053010842 hdd_close_tx_queues(pHddCtx);
c_manjeecfd1efb2015-09-25 19:32:34 +053010843 wlan_free_fwr_mem_dump_buffer();
10844 memdump_deinit();
10845
Vinay Krishna Erannad938c422014-03-10 17:14:21 +053010846#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +053010847 if (pHddCtx->cfg_ini->wlanLoggingEnable)
Vinay Krishna Erannad938c422014-03-10 17:14:21 +053010848 {
10849 wlan_logging_sock_deactivate_svc();
10850 }
10851#endif
10852
Vinay Krishna Erannaef30b522014-08-26 17:48:16 +053010853#ifdef WLAN_KD_READY_NOTIFIER
10854 nl_srv_exit(pHddCtx->ptt_pid);
10855#else
10856 nl_srv_exit();
10857#endif /* WLAN_KD_READY_NOTIFIER */
10858
Abhishek Singh00b71972016-01-07 10:51:04 +053010859#ifdef WLAN_FEATURE_RMC
10860 hdd_close_cesium_nl_sock();
10861#endif /* WLAN_FEATURE_RMC */
Vinay Krishna Erannaef30b522014-08-26 17:48:16 +053010862
Jeff Johnson295189b2012-06-20 16:38:30 -070010863 hdd_close_all_adapters( pHddCtx );
10864
Padma, Santhosh Kumar9cd38332015-11-17 12:18:10 +053010865 vos_flush_delayed_work(&pHddCtx->spoof_mac_addr_work);
Kapil Gupta137ef892016-12-13 19:38:00 +053010866 vos_flush_work(&pHddCtx->sap_start_work);
Padma, Santhosh Kumar9cd38332015-11-17 12:18:10 +053010867
Hanumantha Reddy Pothula97f9bc92015-08-10 17:21:20 +053010868free_hdd_ctx:
Jeff Johnson295189b2012-06-20 16:38:30 -070010869 /* free the power on lock from platform driver */
10870 if (free_riva_power_on_lock("wlan"))
10871 {
10872 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
10873 __func__);
10874 }
10875
c_hpothu78c7b602014-05-17 17:35:49 +053010876 //Free up dynamically allocated members inside HDD Adapter
10877 if (pHddCtx->cfg_ini)
10878 {
10879 kfree(pHddCtx->cfg_ini);
10880 pHddCtx->cfg_ini= NULL;
10881 }
10882
Hanumantha Reddy Pothula6fe221c2016-01-28 15:01:09 +053010883 /* FTM/MONITOR mode, WIPHY did not registered
Leo Changf04ddad2013-09-18 13:46:38 -070010884 If un-register here, system crash will happen */
Hanumantha Reddy Pothula6fe221c2016-01-28 15:01:09 +053010885 if (!(VOS_FTM_MODE == hdd_get_conparam() ||
10886 VOS_MONITOR_MODE == hdd_get_conparam()))
Leo Changf04ddad2013-09-18 13:46:38 -070010887 {
10888 wiphy_unregister(wiphy) ;
Agrawal Ashish33ec71e2015-11-26 20:20:58 +053010889 hdd_wlan_free_wiphy_channels(wiphy);
Leo Changf04ddad2013-09-18 13:46:38 -070010890 }
Jeff Johnson295189b2012-06-20 16:38:30 -070010891 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -070010892 if (hdd_is_ssr_required())
10893 {
10894 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -070010895 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -070010896 msleep(5000);
10897 }
10898 hdd_set_ssr_required (VOS_FALSE);
10899}
10900
10901
10902/**---------------------------------------------------------------------------
10903
10904 \brief hdd_update_config_from_nv() - Function to update the contents of
10905 the running configuration with parameters taken from NV storage
10906
10907 \param - pHddCtx - Pointer to the HDD global context
10908
10909 \return - VOS_STATUS_SUCCESS if successful
10910
10911 --------------------------------------------------------------------------*/
10912static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
10913{
Jeff Johnson295189b2012-06-20 16:38:30 -070010914 v_BOOL_t itemIsValid = VOS_FALSE;
10915 VOS_STATUS status;
10916 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
10917 v_U8_t macLoop;
10918
10919 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
10920 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
10921 if(status != VOS_STATUS_SUCCESS)
10922 {
Arif Hussain6d2a3322013-11-17 19:50:10 -080010923 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed");
Jeff Johnson295189b2012-06-20 16:38:30 -070010924 return VOS_STATUS_E_FAILURE;
10925 }
10926
10927 if (itemIsValid == VOS_TRUE)
10928 {
Arif Hussain6d2a3322013-11-17 19:50:10 -080010929 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV");
Jeff Johnson295189b2012-06-20 16:38:30 -070010930 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
10931 VOS_MAX_CONCURRENCY_PERSONA);
10932 if(status != VOS_STATUS_SUCCESS)
10933 {
10934 /* Get MAC from NV fail, not update CFG info
10935 * INI MAC value will be used for MAC setting */
Arif Hussain6d2a3322013-11-17 19:50:10 -080010936 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed");
Jeff Johnson295189b2012-06-20 16:38:30 -070010937 return VOS_STATUS_E_FAILURE;
10938 }
10939
10940 /* If first MAC is not valid, treat all others are not valid
10941 * Then all MACs will be got from ini file */
10942 if(vos_is_macaddr_zero(&macFromNV[0]))
10943 {
10944 /* MAC address in NV file is not configured yet */
10945 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
10946 return VOS_STATUS_E_INVAL;
10947 }
10948
10949 /* Get MAC address from NV, update CFG info */
10950 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
10951 {
10952 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
10953 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +053010954 hddLog(VOS_TRACE_LEVEL_ERROR,"not valid MAC from NV for %d", macLoop);
Jeff Johnson295189b2012-06-20 16:38:30 -070010955 /* This MAC is not valid, skip it
10956 * This MAC will be got from ini file */
10957 }
10958 else
10959 {
10960 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
10961 (v_U8_t *)&macFromNV[macLoop].bytes[0],
10962 VOS_MAC_ADDR_SIZE);
10963 }
10964 }
10965 }
10966 else
10967 {
10968 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
10969 return VOS_STATUS_E_FAILURE;
10970 }
Jeff Johnson295189b2012-06-20 16:38:30 -070010971
Jeff Johnson295189b2012-06-20 16:38:30 -070010972
10973 return VOS_STATUS_SUCCESS;
10974}
10975
10976/**---------------------------------------------------------------------------
10977
10978 \brief hdd_post_voss_start_config() - HDD post voss start config helper
10979
10980 \param - pAdapter - Pointer to the HDD
10981
10982 \return - None
10983
10984 --------------------------------------------------------------------------*/
10985VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
10986{
10987 eHalStatus halStatus;
10988 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +053010989 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -070010990
Jeff Johnson295189b2012-06-20 16:38:30 -070010991
10992 // Send ready indication to the HDD. This will kick off the MAC
10993 // into a 'running' state and should kick off an initial scan.
10994 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
10995 if ( !HAL_STATUS_SUCCESS( halStatus ) )
10996 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +053010997 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -070010998 "code %08d [x%08x]",__func__, halStatus, halStatus );
10999 return VOS_STATUS_E_FAILURE;
11000 }
11001
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +053011002 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -070011003 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
11004 // And RIVA will crash
11005 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
11006 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +053011007 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
11008 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
11009
11010
Jeff Johnson295189b2012-06-20 16:38:30 -070011011 return VOS_STATUS_SUCCESS;
11012}
11013
Jeff Johnson295189b2012-06-20 16:38:30 -070011014/* wake lock APIs for HDD */
Sushant Kaushik83392fa2015-05-05 17:44:40 +053011015void hdd_prevent_suspend(uint32_t reason)
Jeff Johnson295189b2012-06-20 16:38:30 -070011016{
Sushant Kaushik83392fa2015-05-05 17:44:40 +053011017
11018 vos_wake_lock_acquire(&wlan_wake_lock, reason);
11019
Jeff Johnson295189b2012-06-20 16:38:30 -070011020}
11021
Sushant Kaushik83392fa2015-05-05 17:44:40 +053011022void hdd_allow_suspend(uint32_t reason)
Jeff Johnson295189b2012-06-20 16:38:30 -070011023{
Sushant Kaushik83392fa2015-05-05 17:44:40 +053011024
11025 vos_wake_lock_release(&wlan_wake_lock, reason);
11026
Jeff Johnson295189b2012-06-20 16:38:30 -070011027}
11028
Sushant Kaushik83392fa2015-05-05 17:44:40 +053011029void hdd_prevent_suspend_timeout(v_U32_t timeout, uint32_t reason)
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -070011030{
Sushant Kaushik83392fa2015-05-05 17:44:40 +053011031
11032 vos_wake_lock_timeout_release(&wlan_wake_lock, timeout,
11033 reason);
11034
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -070011035}
11036
Jeff Johnson295189b2012-06-20 16:38:30 -070011037/**---------------------------------------------------------------------------
11038
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070011039 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
11040 information between Host and Riva
11041
11042 This function gets reported version of FW
11043 It also finds the version of Riva headers used to compile the host
11044 It compares the above two and prints a warning if they are different
11045 It gets the SW and HW version string
11046 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
11047 indicating the features they support through a bitmap
11048
11049 \param - pHddCtx - Pointer to HDD context
11050
11051 \return - void
11052
11053 --------------------------------------------------------------------------*/
11054
11055void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
11056{
11057
11058 tSirVersionType versionCompiled;
11059 tSirVersionType versionReported;
11060 tSirVersionString versionString;
11061 tANI_U8 fwFeatCapsMsgSupported = 0;
11062 VOS_STATUS vstatus;
11063
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -080011064 memset(&versionCompiled, 0, sizeof(versionCompiled));
11065 memset(&versionReported, 0, sizeof(versionReported));
11066
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070011067 /* retrieve and display WCNSS version information */
11068 do {
11069
11070 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
11071 &versionCompiled);
11072 if (!VOS_IS_STATUS_SUCCESS(vstatus))
11073 {
11074 hddLog(VOS_TRACE_LEVEL_FATAL,
11075 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070011076 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070011077 break;
11078 }
11079
11080 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
11081 &versionReported);
11082 if (!VOS_IS_STATUS_SUCCESS(vstatus))
11083 {
11084 hddLog(VOS_TRACE_LEVEL_FATAL,
11085 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070011086 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070011087 break;
11088 }
11089
11090 if ((versionCompiled.major != versionReported.major) ||
11091 (versionCompiled.minor != versionReported.minor) ||
11092 (versionCompiled.version != versionReported.version) ||
11093 (versionCompiled.revision != versionReported.revision))
11094 {
11095 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
11096 "Host expected %u.%u.%u.%u\n",
11097 WLAN_MODULE_NAME,
11098 (int)versionReported.major,
11099 (int)versionReported.minor,
11100 (int)versionReported.version,
11101 (int)versionReported.revision,
11102 (int)versionCompiled.major,
11103 (int)versionCompiled.minor,
11104 (int)versionCompiled.version,
11105 (int)versionCompiled.revision);
11106 }
11107 else
11108 {
11109 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
11110 WLAN_MODULE_NAME,
11111 (int)versionReported.major,
11112 (int)versionReported.minor,
11113 (int)versionReported.version,
11114 (int)versionReported.revision);
11115 }
11116
11117 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
11118 versionString,
11119 sizeof(versionString));
11120 if (!VOS_IS_STATUS_SUCCESS(vstatus))
11121 {
11122 hddLog(VOS_TRACE_LEVEL_FATAL,
11123 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070011124 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070011125 break;
11126 }
11127
11128 pr_info("%s: WCNSS software version %s\n",
11129 WLAN_MODULE_NAME, versionString);
Sushant Kaushik084f6592015-09-10 13:11:56 +053011130 vos_mem_copy(pHddCtx->fw_Version, versionString, sizeof(versionString));
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070011131
11132 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
11133 versionString,
11134 sizeof(versionString));
11135 if (!VOS_IS_STATUS_SUCCESS(vstatus))
11136 {
11137 hddLog(VOS_TRACE_LEVEL_FATAL,
11138 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070011139 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070011140 break;
11141 }
11142
11143 pr_info("%s: WCNSS hardware version %s\n",
11144 WLAN_MODULE_NAME, versionString);
11145
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -070011146 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
11147 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070011148 send the message only if it the riva is 1.1
11149 minor numbers for different riva branches:
11150 0 -> (1.0)Mainline Build
11151 1 -> (1.1)Mainline Build
11152 2->(1.04) Stability Build
11153 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -070011154 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070011155 ((versionReported.minor>=1) && (versionReported.version>=1)))
11156 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
11157 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -070011158
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070011159 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -080011160 {
11161#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
11162 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
11163 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
11164#endif
Ravi Joshid2ca7c42013-07-23 08:37:49 -070011165 /* Indicate if IBSS heartbeat monitoring needs to be offloaded */
11166 if (!pHddCtx->cfg_ini->enableIbssHeartBeatOffload)
11167 {
11168 sme_disableFeatureCapablity(IBSS_HEARTBEAT_OFFLOAD);
11169 }
11170
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070011171 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -080011172 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070011173
11174 } while (0);
11175
11176}
Neelansh Mittaledafed22014-09-04 18:54:39 +053011177void wlan_hdd_send_svc_nlink_msg(int type, void *data, int len)
11178{
11179 struct sk_buff *skb;
11180 struct nlmsghdr *nlh;
11181 tAniMsgHdr *ani_hdr;
Hanumantha Reddy Pothulacf2c7ea2015-04-27 14:50:47 +053011182 int flags = GFP_KERNEL;
Bhargav shah23c94942015-10-13 12:48:35 +053011183 void *nl_data = NULL;
Neelansh Mittaledafed22014-09-04 18:54:39 +053011184
Hanumantha Reddy Pothulacf2c7ea2015-04-27 14:50:47 +053011185 if (in_interrupt() || irqs_disabled() || in_atomic())
11186 flags = GFP_ATOMIC;
11187
11188 skb = alloc_skb(NLMSG_SPACE(WLAN_NL_MAX_PAYLOAD), flags);
Neelansh Mittaledafed22014-09-04 18:54:39 +053011189
11190 if(skb == NULL) {
11191 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
11192 "%s: alloc_skb failed", __func__);
11193 return;
11194 }
11195
11196 nlh = (struct nlmsghdr *)skb->data;
11197 nlh->nlmsg_pid = 0; /* from kernel */
11198 nlh->nlmsg_flags = 0;
11199 nlh->nlmsg_seq = 0;
11200 nlh->nlmsg_type = WLAN_NL_MSG_SVC;
11201
11202 ani_hdr = NLMSG_DATA(nlh);
11203 ani_hdr->type = type;
11204
11205 switch(type) {
11206 case WLAN_SVC_SAP_RESTART_IND:
11207 ani_hdr->length = 0;
11208 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr)));
11209 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr)));
11210 break;
Bhargav Shahd0715912015-10-01 18:17:37 +053011211 case WLAN_SVC_WLAN_TP_IND:
11212 ani_hdr->length = len;
11213 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr)
11214 + len));
11215 nl_data = (char *)ani_hdr + sizeof(tAniMsgHdr);
11216 memcpy(nl_data, data, len);
11217 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + len));
11218 break;
Bhargav shah23c94942015-10-13 12:48:35 +053011219 case WLAN_MSG_RPS_ENABLE_IND:
11220 ani_hdr->length = len;
11221 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + len));
11222 nl_data = (char *)ani_hdr + sizeof(tAniMsgHdr);
11223 memcpy(nl_data, data, len);
11224 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + len));
11225 break;
Neelansh Mittaledafed22014-09-04 18:54:39 +053011226 default:
11227 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
11228 "Attempt to send unknown nlink message %d", type);
11229 kfree_skb(skb);
11230 return;
11231 }
11232
11233 nl_srv_bcast(skb);
11234
11235 return;
11236}
11237
Bhargav Shahd0715912015-10-01 18:17:37 +053011238/**
11239 * hdd_request_tcp_delack() - Find the Delack value based on RX packet
11240 * @pHddCtx: Valid Global HDD context pointer
11241 * @rx_packets: Number of RX packet in perticular time
11242 *
11243 * Based on the RX packet this function calculate next value of tcp delack.
11244 * This function compare rx packet value to high and low threshold limit.
11245 *
11246 * Return: void
11247 */
11248void hdd_request_tcp_delack(hdd_context_t *pHddCtx, uint64_t rx_packets)
11249{
11250 /* average of rx_packets and prev_rx is taken so that
11251 bus width doesnot fluctuate much */
11252 uint64_t temp_rx = (rx_packets + pHddCtx->prev_rx)/2;
11253 TP_IND_TYPE next_rx_level = pHddCtx->cur_rx_level;
Neelansh Mittaledafed22014-09-04 18:54:39 +053011254
Bhargav Shahd0715912015-10-01 18:17:37 +053011255 pHddCtx->prev_rx = rx_packets;
11256 if (temp_rx > pHddCtx->cfg_ini->tcpDelAckThresholdHigh)
11257 next_rx_level = TP_IND_HIGH;
11258 else if (temp_rx <= pHddCtx->cfg_ini->tcpDelAckThresholdLow)
11259 next_rx_level = TP_IND_LOW;
11260
11261 hdd_set_delack_value(pHddCtx, next_rx_level);
11262}
11263
11264#define HDD_BW_GET_DIFF(x, y) ((x) >= (y) ? (x) - (y) : (ULONG_MAX - (y) + (x)))
11265
11266/**
11267 * hdd_tcp_delack_compute_function() - get link status
11268 * @priv: Valid Global HDD context pointer
11269 *
11270 * This function find number of RX packet during timer life span.
11271 * It request tcp delack with number of RX packet and re-configure delack timer
11272 * for tcpDelAckComputeInterval timer interval.
11273 *
11274 * Return: void
11275 */
11276void hdd_tcp_delack_compute_function(void *priv)
11277{
11278 hdd_context_t *pHddCtx = (hdd_context_t *)priv;
11279 hdd_adapter_t *pAdapter = NULL;
11280 v_U32_t rx_packets = 0;
11281 hdd_adapter_list_node_t *pAdapterNode = NULL;
11282 VOS_STATUS status = 0;
11283
11284 for (status = hdd_get_front_adapter(pHddCtx, &pAdapterNode);
11285 NULL != pAdapterNode && VOS_STATUS_SUCCESS == status;
11286 status = hdd_get_next_adapter(pHddCtx, pAdapterNode, &pAdapterNode)) {
11287 if ((pAdapter = pAdapterNode->pAdapter) == NULL)
11288 continue;
11289
11290 rx_packets += HDD_BW_GET_DIFF(pAdapter->stats.rx_packets,
11291 pAdapter->prev_rx_packets);
11292 pAdapter->prev_rx_packets = pAdapter->stats.rx_packets;
11293 }
11294
11295 hdd_request_tcp_delack(pHddCtx, rx_packets);
11296
11297 vos_timer_start(&pHddCtx->delack_timer,
11298 pHddCtx->cfg_ini->tcpDelAckComputeInterval);
11299}
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070011300
11301/**---------------------------------------------------------------------------
11302
Gopichand Nakkalafce506f2013-07-03 23:55:16 +053011303 \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
11304
11305 \param - pHddCtx - Pointer to the hdd context
11306
11307 \return - true if hardware supports 5GHz
11308
11309 --------------------------------------------------------------------------*/
Vinay Krishna Erannafacf5e22014-02-24 13:16:25 +053011310boolean hdd_is_5g_supported(hdd_context_t * pHddCtx)
Gopichand Nakkalafce506f2013-07-03 23:55:16 +053011311{
11312 /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
11313 * then hardware support 5Ghz.
11314 */
11315 if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode())
11316 {
Ratheesh S P36dbc932015-08-07 14:28:57 +053011317 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware supports 5Ghz", __func__);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +053011318 return true;
11319 }
11320 else
11321 {
Ratheesh S P36dbc932015-08-07 14:28:57 +053011322 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware doesn't supports 5Ghz",
Gopichand Nakkalafce506f2013-07-03 23:55:16 +053011323 __func__);
11324 return false;
11325 }
11326}
11327
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053011328/**---------------------------------------------------------------------------
11329
11330 \brief hdd_generate_iface_mac_addr_auto() - HDD Mac Interface Auto
11331 generate function
11332
11333 This is generate the random mac address for WLAN interface
11334
11335 \param - pHddCtx - Pointer to HDD context
11336 idx - Start interface index to get auto
11337 generated mac addr.
11338 mac_addr - Mac address
11339
11340 \return - 0 for success, < 0 for failure
11341
11342 --------------------------------------------------------------------------*/
11343
11344static int hdd_generate_iface_mac_addr_auto(hdd_context_t *pHddCtx,
11345 int idx, v_MACADDR_t mac_addr)
11346{
11347 int i;
11348 unsigned int serialno;
11349 serialno = wcnss_get_serial_number();
11350
11351 if (0 != serialno)
11352 {
11353 /* MAC address has 3 bytes of OUI so we have a maximum of 3
11354 bytes of the serial number that can be used to generate
11355 the other 3 bytes of the MAC address. Mask off all but
11356 the lower 3 bytes (this will also make sure we don't
11357 overflow in the next step) */
11358 serialno &= 0x00FFFFFF;
11359
11360 /* we need a unique address for each session */
11361 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
11362
11363 /* autogen other Mac addresses */
11364 for (i = idx; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
11365 {
11366 /* start with the entire default address */
11367 pHddCtx->cfg_ini->intfMacAddr[i] = mac_addr;
11368 /* then replace the lower 3 bytes */
11369 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
11370 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
11371 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
11372
11373 serialno++;
11374 hddLog(VOS_TRACE_LEVEL_ERROR,
11375 "%s: Derived Mac Addr: "
11376 MAC_ADDRESS_STR, __func__,
11377 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[i].bytes));
11378 }
11379
11380 }
11381 else
11382 {
11383 hddLog(LOGE, FL("Failed to Get Serial NO"));
11384 return -1;
11385 }
11386 return 0;
11387}
Gopichand Nakkalafce506f2013-07-03 23:55:16 +053011388
Katya Nigame7b69a82015-04-28 15:24:06 +053011389int wlan_hdd_mon_open(hdd_context_t *pHddCtx)
11390{
11391 VOS_STATUS status;
11392 v_CONTEXT_t pVosContext= NULL;
11393 hdd_adapter_t *pAdapter= NULL;
11394
11395 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
11396
11397 if (NULL == pVosContext)
11398 {
11399 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
11400 "%s: Trying to open VOSS without a PreOpen", __func__);
11401 VOS_ASSERT(0);
11402 return VOS_STATUS_E_FAILURE;
11403 }
11404
11405 status = vos_nv_open();
11406 if (!VOS_IS_STATUS_SUCCESS(status))
11407 {
11408 /* NV module cannot be initialized */
11409 hddLog( VOS_TRACE_LEVEL_FATAL,
11410 "%s: vos_nv_open failed", __func__);
11411 return VOS_STATUS_E_FAILURE;
11412 }
11413
11414 status = vos_init_wiphy_from_nv_bin();
11415 if (!VOS_IS_STATUS_SUCCESS(status))
11416 {
11417 /* NV module cannot be initialized */
11418 hddLog( VOS_TRACE_LEVEL_FATAL,
11419 "%s: vos_init_wiphy failed", __func__);
11420 goto err_vos_nv_close;
11421 }
11422
11423 status = vos_open( &pVosContext, pHddCtx->parent_dev);
11424 if ( !VOS_IS_STATUS_SUCCESS( status ))
11425 {
11426 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
11427 goto err_vos_nv_close;
11428 }
11429
11430 status = vos_mon_start( pVosContext );
11431 if ( !VOS_IS_STATUS_SUCCESS( status ) )
11432 {
11433 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
11434 goto err_vosclose;
11435 }
11436
11437 WLANTL_SetMonRxCbk( pVosContext, hdd_rx_packet_monitor_cbk );
11438 WDA_featureCapsExchange(pVosContext);
11439 wcnss_wlan_set_drvdata(pHddCtx->parent_dev, pHddCtx);
11440
11441 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_MONITOR, "wlan%d",
11442 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
11443 if( pAdapter == NULL )
11444 {
11445 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
11446 goto err_close_adapter;
11447 }
11448
11449 //Initialize the nlink service
11450 if(nl_srv_init() != 0)
11451 {
11452 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
11453 goto err_close_adapter;
11454 }
11455 return VOS_STATUS_SUCCESS;
11456
11457err_close_adapter:
11458 hdd_close_all_adapters( pHddCtx );
11459 vos_mon_stop( pVosContext );
11460err_vosclose:
11461 status = vos_sched_close( pVosContext );
11462 if (!VOS_IS_STATUS_SUCCESS(status)) {
11463 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
11464 "%s: Failed to close VOSS Scheduler", __func__);
11465 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
11466 }
11467 vos_close(pVosContext );
11468
11469err_vos_nv_close:
11470 vos_nv_close();
11471
11472return status;
11473}
Gopichand Nakkalafce506f2013-07-03 23:55:16 +053011474/**---------------------------------------------------------------------------
11475
Mihir Shetefc7ff5b2014-01-27 11:30:05 +053011476 \brief hdd_11d_scan_done - callback to be executed when 11d scan is
11477 completed to flush out the scan results
11478
11479 11d scan is done during driver load and is a passive scan on all
11480 channels supported by the device, 11d scans may find some APs on
11481 frequencies which are forbidden to be used in the regulatory domain
11482 the device is operating in. If these APs are notified to the supplicant
11483 it may try to connect to these APs, thus flush out all the scan results
11484 which are present in SME after 11d scan is done.
11485
11486 \return - eHalStatus
11487
11488 --------------------------------------------------------------------------*/
11489static eHalStatus hdd_11d_scan_done(tHalHandle halHandle, void *pContext,
11490 tANI_U32 scanId, eCsrScanStatus status)
11491{
11492 ENTER();
11493
11494 sme_ScanFlushResult(halHandle, 0);
11495
11496 EXIT();
11497
11498 return eHAL_STATUS_SUCCESS;
11499}
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011500/**---------------------------------------------------------------------------
11501
11502 \brief hdd_init_frame_logging_done - callback to be executed when mgmt frame
11503 logging is completed successfully.
11504
11505 \return - None
11506
11507 --------------------------------------------------------------------------*/
c_manjeecfd1efb2015-09-25 19:32:34 +053011508void hdd_init_frame_logging_done(void *fwlogInitCbContext, tAniLoggingInitRsp *pRsp)
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011509{
Siddharth Bhald1be97f2015-05-27 22:39:59 +053011510 hdd_context_t* pHddCtx = (hdd_context_t*)fwlogInitCbContext;
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011511
11512 if (NULL == pHddCtx)
11513 {
11514 hddLog(VOS_TRACE_LEVEL_ERROR,
11515 "%s: HDD context is NULL",__func__);
11516 return;
11517 }
11518
c_manjeecfd1efb2015-09-25 19:32:34 +053011519 if ((pRsp->status == VOS_STATUS_SUCCESS) &&
Mahesh A Saptasagarfabb1a02015-06-29 12:17:04 +053011520 (TRUE == pHddCtx->cfg_ini->enableMgmtLogging))
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011521 {
11522 hddLog(VOS_TRACE_LEVEL_INFO, FL("Mgmt Frame Logging init successful"));
11523 pHddCtx->mgmt_frame_logging = TRUE;
11524 }
11525 else
11526 {
11527 hddLog(VOS_TRACE_LEVEL_INFO, FL("Mgmt Frame Logging init not success"));
11528 pHddCtx->mgmt_frame_logging = FALSE;
c_manjeecfd1efb2015-09-25 19:32:34 +053011529 return;
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011530 }
11531
c_manjeecfd1efb2015-09-25 19:32:34 +053011532 /*Check feature supported by FW*/
11533 if(TRUE == sme_IsFeatureSupportedByFW(MEMORY_DUMP_SUPPORTED))
11534 {
11535 //Store fwr mem dump size given by firmware.
11536 wlan_store_fwr_mem_dump_size(pRsp->fw_mem_dump_max_size);
11537 }
11538 else
11539 {
11540 wlan_store_fwr_mem_dump_size(0);
11541 }
11542
11543
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011544}
11545/**---------------------------------------------------------------------------
11546
11547 \brief hdd_init_frame_logging - function to initialize frame logging.
11548 Currently only Mgmt Frames are logged in both TX
11549 and Rx direction and are sent to userspace
11550 application using logger thread when queried.
11551
11552 \return - None
11553
11554 --------------------------------------------------------------------------*/
Siddharth Bhald1be97f2015-05-27 22:39:59 +053011555void hdd_init_frame_logging(hdd_context_t* pHddCtx)
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011556{
11557 eHalStatus halStatus = eHAL_STATUS_FAILURE;
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053011558 tSirFWLoggingInitParam wlanFWLoggingInitParam = {0};
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011559
Siddharth Bhald1be97f2015-05-27 22:39:59 +053011560 if (TRUE != sme_IsFeatureSupportedByFW(MGMT_FRAME_LOGGING) &&
11561 TRUE != sme_IsFeatureSupportedByFW(LOGGING_ENHANCEMENT))
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011562 {
11563 hddLog(VOS_TRACE_LEVEL_INFO, FL("MGMT_FRAME_LOGGING not supp by FW"));
11564 return;
11565 }
11566
c_manjeecfd1efb2015-09-25 19:32:34 +053011567 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Configuring %s %s %s %s Logging",__func__,
Siddharth Bhald1be97f2015-05-27 22:39:59 +053011568 pHddCtx->cfg_ini->enableFWLogging?"FW Log,":"",
11569 pHddCtx->cfg_ini->enableContFWLogging ? "Cont FW log,":"",
c_manjeecfd1efb2015-09-25 19:32:34 +053011570 pHddCtx->cfg_ini->enableMgmtLogging ? "Mgmt Pkt Log":"",
11571 pHddCtx->cfg_ini->enableFwrMemDump ? "Fw Mem dump":"");
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011572
Siddharth Bhald1be97f2015-05-27 22:39:59 +053011573 if (pHddCtx->cfg_ini->enableFWLogging ||
11574 pHddCtx->cfg_ini->enableContFWLogging)
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011575 {
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053011576 wlanFWLoggingInitParam.enableFlag |= WLAN_QXDM_LOG_EN;
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011577 }
11578
Sushant Kaushik46804902015-07-08 14:46:03 +053011579 if (pHddCtx->cfg_ini->enableMgmtLogging)
11580 {
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053011581 wlanFWLoggingInitParam.enableFlag |= WLAN_FRAME_LOG_EN;
Sushant Kaushik46804902015-07-08 14:46:03 +053011582 }
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011583 if (pHddCtx->cfg_ini->enableBMUHWtracing)
11584 {
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053011585 wlanFWLoggingInitParam.enableFlag |= WLAN_BMUHW_TRACE_LOG_EN;
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011586 }
c_manjeecfd1efb2015-09-25 19:32:34 +053011587 if(pHddCtx->cfg_ini->enableFwrMemDump &&
11588 (TRUE == sme_IsFeatureSupportedByFW(MEMORY_DUMP_SUPPORTED)))
11589 {
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053011590 wlanFWLoggingInitParam.enableFlag |= WLAN_FW_MEM_DUMP_EN;
c_manjeecfd1efb2015-09-25 19:32:34 +053011591 }
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053011592 if( wlanFWLoggingInitParam.enableFlag == 0 )
c_manjeecfd1efb2015-09-25 19:32:34 +053011593 {
11594 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Logging not enabled", __func__);
11595 return;
11596 }
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053011597 wlanFWLoggingInitParam.frameType = WLAN_FRAME_LOGGING_FRAMETYPE_MGMT;
11598 wlanFWLoggingInitParam.frameSize = WLAN_MGMT_LOGGING_FRAMESIZE_128BYTES;
11599 wlanFWLoggingInitParam.bufferMode = WLAN_FRAME_LOGGING_BUFFERMODE_CIRCULAR;
11600 wlanFWLoggingInitParam.continuousFrameLogging =
Siddharth Bhald1be97f2015-05-27 22:39:59 +053011601 pHddCtx->cfg_ini->enableContFWLogging;
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011602
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053011603 wlanFWLoggingInitParam.enableFlag &= ~WLAN_DPU_TXP_LOG_EN;
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011604
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053011605 wlanFWLoggingInitParam.minLogBufferSize =
Siddharth Bhald1be97f2015-05-27 22:39:59 +053011606 pHddCtx->cfg_ini->minLoggingBufferSize;
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053011607 wlanFWLoggingInitParam.maxLogBufferSize =
Siddharth Bhald1be97f2015-05-27 22:39:59 +053011608 pHddCtx->cfg_ini->maxLoggingBufferSize;
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053011609 wlanFWLoggingInitParam.fwlogInitCallback = hdd_init_frame_logging_done;
11610 wlanFWLoggingInitParam.fwlogInitCbContext= pHddCtx;
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011611
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053011612 halStatus = sme_InitMgmtFrameLogging(pHddCtx->hHal, &wlanFWLoggingInitParam);
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011613
11614 if (eHAL_STATUS_SUCCESS != halStatus)
11615 {
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053011616 hddLog(LOGE, FL("sme_InitMgmtFrameLogging failed, returned %d"),
11617 halStatus);
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011618 }
11619
11620 return;
11621}
Mihir Shetefc7ff5b2014-01-27 11:30:05 +053011622
Bhargav shah23c94942015-10-13 12:48:35 +053011623static void hdd_dp_util_send_rps_ind(hdd_context_t *hdd_ctxt)
11624{
11625 hdd_adapter_t *adapter;
11626 hdd_adapter_list_node_t *adapter_node, *next;
11627 VOS_STATUS status = VOS_STATUS_SUCCESS;
11628 struct wlan_rps_data rps_data;
11629 int count;
11630
11631 if(!hdd_ctxt->cfg_ini->rps_mask)
11632 {
11633 return;
11634 }
11635
11636 for (count=0; count < WLAN_SVC_IFACE_NUM_QUEUES; count++)
11637 {
11638 rps_data.cpu_map[count] = hdd_ctxt->cfg_ini->rps_mask;
11639 }
11640
11641 rps_data.num_queues = WLAN_SVC_IFACE_NUM_QUEUES;
11642
11643 hddLog(LOG1, FL("0x%x 0x%x 0x%x 0x%x 0x%x 0x%x"),
11644 rps_data.cpu_map[0], rps_data.cpu_map[1],rps_data.cpu_map[2],
11645 rps_data.cpu_map[3], rps_data.cpu_map[4], rps_data.cpu_map[5]);
11646
11647 status = hdd_get_front_adapter (hdd_ctxt, &adapter_node);
11648
11649 while (NULL != adapter_node && VOS_STATUS_SUCCESS == status)
11650 {
11651 adapter = adapter_node->pAdapter;
11652 if (NULL != adapter) {
11653 strlcpy(rps_data.ifname, adapter->dev->name,
11654 sizeof(rps_data.ifname));
11655 wlan_hdd_send_svc_nlink_msg(WLAN_MSG_RPS_ENABLE_IND,
11656 (void *)&rps_data,sizeof(rps_data));
11657 }
11658 status = hdd_get_next_adapter (hdd_ctxt, adapter_node, &next);
11659 adapter_node = next;
11660 }
11661}
11662
Masti, Narayanraddi26378462016-01-05 18:20:28 +053011663void wlan_hdd_schedule_defer_scan(struct work_struct *work)
11664{
11665 scan_context_t *scan_ctx =
11666 container_of(work, scan_context_t, scan_work.work);
11667
11668 if (NULL == scan_ctx)
11669 {
11670 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
11671 FL("scan_ctx is NULL"));
11672 return;
11673 }
11674
11675 if (unlikely(TDLS_CTX_MAGIC != scan_ctx->magic))
11676 return;
11677
11678 scan_ctx->attempt++;
11679
11680 wlan_hdd_cfg80211_scan(scan_ctx->wiphy,
11681#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
11682 scan_ctx->dev,
11683#endif
11684 scan_ctx->scan_request);
11685}
11686
11687int wlan_hdd_copy_defer_scan_context(hdd_context_t *pHddCtx,
11688 struct wiphy *wiphy,
11689#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
11690 struct net_device *dev,
11691#endif
11692 struct cfg80211_scan_request *request)
11693{
11694 scan_context_t *scan_ctx;
11695
11696 ENTER();
11697 if (0 != (wlan_hdd_validate_context(pHddCtx)))
11698 {
11699 return -1;
11700 }
11701
11702 scan_ctx = &pHddCtx->scan_ctxt;
11703
11704 scan_ctx->wiphy = wiphy;
11705#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
11706 scan_ctx->dev = dev;
11707#endif
11708
11709 scan_ctx->scan_request = request;
11710
11711 EXIT();
11712 return 0;
11713}
11714
11715void wlan_hdd_defer_scan_init_work(hdd_context_t *pHddCtx,
11716 struct wiphy *wiphy,
11717#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
11718 struct net_device *dev,
11719#endif
11720 struct cfg80211_scan_request *request,
11721 unsigned long delay)
11722{
11723 if (TDLS_CTX_MAGIC != pHddCtx->scan_ctxt.magic)
11724 {
11725#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
11726 wlan_hdd_copy_defer_scan_context(pHddCtx, wiphy, dev, request);
11727#else
11728 wlan_hdd_copy_defer_scan_context(pHddCtx, wiphy, request);
11729#endif
11730 pHddCtx->scan_ctxt.attempt = 0;
11731 pHddCtx->scan_ctxt.magic = TDLS_CTX_MAGIC;
11732 }
11733 schedule_delayed_work(&pHddCtx->scan_ctxt.scan_work, delay);
11734}
11735
11736void wlan_hdd_init_deinit_defer_scan_context(scan_context_t *scan_ctx)
11737{
11738 scan_ctx->magic = 0;
11739 scan_ctx->attempt = 0;
11740 scan_ctx->reject = 0;
11741 scan_ctx->scan_request = NULL;
11742
11743 return;
11744}
11745
Mihir Shetefc7ff5b2014-01-27 11:30:05 +053011746/**---------------------------------------------------------------------------
11747
Jeff Johnson295189b2012-06-20 16:38:30 -070011748 \brief hdd_wlan_startup() - HDD init function
11749
11750 This is the driver startup code executed once a WLAN device has been detected
11751
11752 \param - dev - Pointer to the underlying device
11753
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -080011754 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -070011755
11756 --------------------------------------------------------------------------*/
11757
11758int hdd_wlan_startup(struct device *dev )
11759{
11760 VOS_STATUS status;
11761 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -070011762 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -070011763 hdd_context_t *pHddCtx = NULL;
11764 v_CONTEXT_t pVosContext= NULL;
11765#ifdef WLAN_BTAMP_FEATURE
11766 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
11767 WLANBAP_ConfigType btAmpConfig;
11768 hdd_config_t *pConfig;
11769#endif
11770 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -070011771 struct wiphy *wiphy;
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053011772 v_MACADDR_t mac_addr;
Jeff Johnson295189b2012-06-20 16:38:30 -070011773
11774 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -070011775 /*
11776 * cfg80211: wiphy allocation
11777 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +053011778 wiphy = wlan_hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t)) ;
Jeff Johnson295189b2012-06-20 16:38:30 -070011779
11780 if(wiphy == NULL)
11781 {
11782 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -080011783 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -070011784 }
Jeff Johnson295189b2012-06-20 16:38:30 -070011785 pHddCtx = wiphy_priv(wiphy);
11786
Jeff Johnson295189b2012-06-20 16:38:30 -070011787 //Initialize the adapter context to zeros.
11788 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
11789
Jeff Johnson295189b2012-06-20 16:38:30 -070011790 pHddCtx->wiphy = wiphy;
Sushant Kaushik83392fa2015-05-05 17:44:40 +053011791 hdd_prevent_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_INIT);
Mihir Shete18156292014-03-11 15:38:30 +053011792 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_LOAD_IN_PROGRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -070011793
11794 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
11795
Siddharth Bhalcd92b782015-06-29 12:25:40 +053011796 /* register for riva power on lock to platform driver
11797 * Locking power early to ensure FW doesn't reset by kernel while
11798 * host driver is busy initializing itself */
11799 if (req_riva_power_on_lock("wlan"))
11800 {
11801 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
11802 __func__);
11803 goto err_free_hdd_context;
11804 }
11805
Jeff Johnson295189b2012-06-20 16:38:30 -070011806 /*Get vos context here bcoz vos_open requires it*/
11807 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
11808
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -080011809 if(pVosContext == NULL)
11810 {
11811 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
11812 goto err_free_hdd_context;
11813 }
11814
Jeff Johnson295189b2012-06-20 16:38:30 -070011815 //Save the Global VOSS context in adapter context for future.
11816 pHddCtx->pvosContext = pVosContext;
11817
11818 //Save the adapter context in global context for future.
11819 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
11820
Jeff Johnson295189b2012-06-20 16:38:30 -070011821 pHddCtx->parent_dev = dev;
Sreelakshmi Konamkif0646d52016-12-09 12:35:31 +053011822 pHddCtx->last_scan_reject_session_id = 0xFF;
11823 pHddCtx->last_scan_reject_reason = 0;
Sreelakshmi Konamki20ebed92016-10-27 12:13:30 +053011824 pHddCtx->last_scan_reject_timestamp = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -070011825
11826 init_completion(&pHddCtx->full_pwr_comp_var);
11827 init_completion(&pHddCtx->standby_comp_var);
11828 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -070011829 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -080011830 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Kiet Lam46b8e4e2013-11-06 21:49:53 +053011831 init_completion(&pHddCtx->wiphy_channel_update_event);
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +053011832 init_completion(&pHddCtx->ssr_comp_var);
Mahesh A Saptasagar67ab9222015-10-21 15:38:41 +053011833 init_completion(&pHddCtx->mc_sus_event_var);
11834 init_completion(&pHddCtx->tx_sus_event_var);
11835 init_completion(&pHddCtx->rx_sus_event_var);
11836
Amar Singhala49cbc52013-10-08 18:37:44 -070011837
mukul sharma4bd8d2e2015-08-13 20:33:25 +053011838 hdd_init_ll_stats_ctx(pHddCtx);
Anurag Chouhan6ee81542017-02-09 18:09:27 +053011839 hdd_init_nud_stats_ctx(pHddCtx);
mukul sharma4bd8d2e2015-08-13 20:33:25 +053011840
Amar Singhala49cbc52013-10-08 18:37:44 -070011841#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhalfddc28c2013-09-05 13:03:40 -070011842 init_completion(&pHddCtx->linux_reg_req);
Amar Singhala49cbc52013-10-08 18:37:44 -070011843#else
11844 init_completion(&pHddCtx->driver_crda_req);
11845#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070011846
Padma, Santhosh Kumara1aa4a32015-06-19 19:00:46 +053011847#ifdef WLAN_FEATURE_EXTSCAN
11848 init_completion(&pHddCtx->ext_scan_context.response_event);
11849#endif /* WLAN_FEATURE_EXTSCAN */
11850
Kamath Vinayak4000c9a2013-08-23 14:24:27 +053011851 spin_lock_init(&pHddCtx->schedScan_lock);
Kapil Gupta137ef892016-12-13 19:38:00 +053011852 vos_spin_lock_init(&pHddCtx->sap_update_info_lock);
Kamath Vinayak4000c9a2013-08-23 14:24:27 +053011853
Jeff Johnson295189b2012-06-20 16:38:30 -070011854 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
11855
Padma, Santhosh Kumar9cd38332015-11-17 12:18:10 +053011856 vos_init_delayed_work(&pHddCtx->spoof_mac_addr_work,
11857 hdd_processSpoofMacAddrRequest);
Kapil Gupta137ef892016-12-13 19:38:00 +053011858 vos_init_work(&pHddCtx->sap_start_work, hdd_sap_restart_handle);
Padma, Santhosh Kumar9cd38332015-11-17 12:18:10 +053011859
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +053011860#ifdef FEATURE_WLAN_TDLS
11861 /* tdls_lock is initialized before an hdd_open_adapter ( which is
11862 * invoked by other instances also) to protect the concurrent
11863 * access for the Adapters by TDLS module.
11864 */
11865 mutex_init(&pHddCtx->tdls_lock);
11866#endif
Siddharth Bhal76972212014-10-15 16:22:51 +053011867 mutex_init(&pHddCtx->spoofMacAddr.macSpoofingLock);
Mukul Sharma1fd6efd2015-02-14 00:29:14 +053011868 mutex_init(&pHddCtx->wmmLock);
11869
Srinivas Girigowda8bf64cb2015-09-30 19:50:09 +053011870 hdd_init_offloaded_packets_ctx(pHddCtx);
Agarwal Ashish1f422872014-07-22 00:11:55 +053011871 /* By default Strict Regulatory For FCC should be false */
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +053011872
Agarwal Ashish1f422872014-07-22 00:11:55 +053011873 pHddCtx->nEnableStrictRegulatoryForFCC = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -070011874 // Load all config first as TL config is needed during vos_open
11875 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
11876 if(pHddCtx->cfg_ini == NULL)
11877 {
11878 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
11879 goto err_free_hdd_context;
11880 }
11881
11882 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
11883
11884 // Read and parse the qcom_cfg.ini file
11885 status = hdd_parse_config_ini( pHddCtx );
11886 if ( VOS_STATUS_SUCCESS != status )
11887 {
11888 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
11889 __func__, WLAN_INI_FILE);
11890 goto err_config;
11891 }
Arif Hussaind5218912013-12-05 01:10:55 -080011892#ifdef MEMORY_DEBUG
11893 if (pHddCtx->cfg_ini->IsMemoryDebugSupportEnabled)
11894 vos_mem_init();
11895
11896 hddLog(VOS_TRACE_LEVEL_INFO, "%s: gEnableMemoryDebug=%d",
11897 __func__, pHddCtx->cfg_ini->IsMemoryDebugSupportEnabled);
11898#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070011899
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +053011900 /* INI has been read, initialise the configuredMcastBcastFilter with
11901 * INI value as this will serve as the default value
11902 */
11903 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
11904 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
11905 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +053011906
11907 if (false == hdd_is_5g_supported(pHddCtx))
11908 {
11909 //5Ghz is not supported.
11910 if (1 != pHddCtx->cfg_ini->nBandCapability)
11911 {
11912 hddLog(VOS_TRACE_LEVEL_INFO,
11913 "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__);
11914 pHddCtx->cfg_ini->nBandCapability = 1;
11915 }
11916 }
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +053011917
11918 /* If SNR Monitoring is enabled, FW has to parse all beacons
11919 * for calcaluting and storing the average SNR, so set Nth beacon
11920 * filter to 1 to enable FW to parse all the beaocons
11921 */
11922 if (1 == pHddCtx->cfg_ini->fEnableSNRMonitoring)
11923 {
11924 /* The log level is deliberately set to WARN as overriding
11925 * nthBeaconFilter to 1 will increase power cosumption and this
11926 * might just prove helpful to detect the power issue.
11927 */
11928 hddLog(VOS_TRACE_LEVEL_WARN,
11929 "%s: Setting pHddCtx->cfg_ini->nthBeaconFilter = 1", __func__);
11930 pHddCtx->cfg_ini->nthBeaconFilter = 1;
11931 }
Jeff Johnson295189b2012-06-20 16:38:30 -070011932 /*
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +053011933 * cfg80211: Initialization ...
Jeff Johnson295189b2012-06-20 16:38:30 -070011934 */
Manjeet Singh61016fa2016-12-02 11:10:19 +053011935 if (0 < wlan_hdd_cfg80211_init(dev, wiphy, pHddCtx->cfg_ini))
Jeff Johnson295189b2012-06-20 16:38:30 -070011936 {
Manjeet Singh61016fa2016-12-02 11:10:19 +053011937 hddLog(VOS_TRACE_LEVEL_FATAL,
11938 "%s: wlan_hdd_cfg80211_init return failure", __func__);
11939 goto err_config;
Jeff Johnson295189b2012-06-20 16:38:30 -070011940 }
Jeff Johnson295189b2012-06-20 16:38:30 -070011941
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -080011942 // Update VOS trace levels based upon the cfg.ini
11943 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
11944 pHddCtx->cfg_ini->vosTraceEnableBAP);
11945 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
11946 pHddCtx->cfg_ini->vosTraceEnableTL);
11947 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
11948 pHddCtx->cfg_ini->vosTraceEnableWDI);
11949 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
11950 pHddCtx->cfg_ini->vosTraceEnableHDD);
11951 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
11952 pHddCtx->cfg_ini->vosTraceEnableSME);
11953 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
11954 pHddCtx->cfg_ini->vosTraceEnablePE);
Katya Nigam70d68332013-09-16 16:49:45 +053011955 hdd_vos_trace_enable(VOS_MODULE_ID_PMC,
11956 pHddCtx->cfg_ini->vosTraceEnablePMC);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -080011957 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
11958 pHddCtx->cfg_ini->vosTraceEnableWDA);
11959 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
11960 pHddCtx->cfg_ini->vosTraceEnableSYS);
11961 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
11962 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -080011963 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
11964 pHddCtx->cfg_ini->vosTraceEnableSAP);
11965 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
11966 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -080011967
Jeff Johnson295189b2012-06-20 16:38:30 -070011968 // Update WDI trace levels based upon the cfg.ini
11969 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
11970 pHddCtx->cfg_ini->wdiTraceEnableDAL);
11971 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
11972 pHddCtx->cfg_ini->wdiTraceEnableCTL);
11973 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
11974 pHddCtx->cfg_ini->wdiTraceEnableDAT);
11975 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
11976 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -070011977
Jeff Johnson88ba7742013-02-27 14:36:02 -080011978 if (VOS_FTM_MODE == hdd_get_conparam())
11979 {
Jeff Johnson295189b2012-06-20 16:38:30 -070011980 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
11981 {
11982 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
11983 goto err_free_hdd_context;
11984 }
11985 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
Sachin Ahuja38ef5e02015-03-13 17:31:16 +053011986 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_NO_LOAD_UNLOAD_IN_PROGRESS;
c_hpothu2de0ef62014-04-15 16:16:15 +053011987 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -070011988 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -080011989 }
Jeff Johnson295189b2012-06-20 16:38:30 -070011990
Katya Nigame7b69a82015-04-28 15:24:06 +053011991 if( VOS_MONITOR_MODE == hdd_get_conparam())
11992 {
11993 if ( VOS_STATUS_SUCCESS != wlan_hdd_mon_open(pHddCtx))
11994 {
11995 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_mon_open Failed",__func__);
11996 goto err_free_hdd_context;
11997 }
11998 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Driver loaded in Monitor Mode",__func__);
11999 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_NO_LOAD_UNLOAD_IN_PROGRESS;
12000 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
12001 return VOS_STATUS_SUCCESS;
12002 }
12003
Jeff Johnson88ba7742013-02-27 14:36:02 -080012004 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -070012005 if(pHddCtx->cfg_ini->fIsLogpEnabled)
12006 {
12007 status = vos_watchdog_open(pVosContext,
12008 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
12009
12010 if(!VOS_IS_STATUS_SUCCESS( status ))
12011 {
12012 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Ashish Kumar Dhanotiya532bdef2017-05-09 17:31:59 +053012013 goto err_config;
Jeff Johnson295189b2012-06-20 16:38:30 -070012014 }
12015 }
12016
12017 pHddCtx->isLogpInProgress = FALSE;
12018 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
12019
Amar Singhala49cbc52013-10-08 18:37:44 -070012020#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -070012021 /* initialize the NV module. This is required so that
12022 we can initialize the channel information in wiphy
12023 from the NV.bin data. The channel information in
12024 wiphy needs to be initialized before wiphy registration */
12025
12026 status = vos_nv_open();
12027 if (!VOS_IS_STATUS_SUCCESS(status))
12028 {
12029 /* NV module cannot be initialized */
12030 hddLog( VOS_TRACE_LEVEL_FATAL,
12031 "%s: vos_nv_open failed", __func__);
Vinay Krishna Eranna2025d892014-09-18 16:51:42 +053012032 goto err_wdclose;
Amar Singhal0a402232013-10-11 20:57:16 -070012033 }
12034
12035 status = vos_init_wiphy_from_nv_bin();
12036 if (!VOS_IS_STATUS_SUCCESS(status))
12037 {
12038 /* NV module cannot be initialized */
12039 hddLog( VOS_TRACE_LEVEL_FATAL,
12040 "%s: vos_init_wiphy failed", __func__);
12041 goto err_vos_nv_close;
12042 }
12043
Amar Singhala49cbc52013-10-08 18:37:44 -070012044#endif
Mahesh A Saptasagarc3ed0122016-01-19 16:45:11 +053012045 //Initialize the nlink service
12046 if(nl_srv_init() != 0)
12047 {
12048 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
12049 goto err_vos_nv_close;
12050 }
12051
12052#ifdef WLAN_KD_READY_NOTIFIER
12053 pHddCtx->kd_nl_init = 1;
12054#endif /* WLAN_KD_READY_NOTIFIER */
12055
Girish Gowlibf0e1ab2015-01-19 16:05:16 +053012056 vos_set_roam_delay_stats_enabled(pHddCtx->cfg_ini->gEnableRoamDelayStats);
Arun Kumar Khandavalliebb19482014-03-25 13:56:53 +053012057 status = vos_open( &pVosContext, pHddCtx->parent_dev);
Jeff Johnson295189b2012-06-20 16:38:30 -070012058 if ( !VOS_IS_STATUS_SUCCESS( status ))
12059 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -080012060 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
Mahesh A Saptasagarc3ed0122016-01-19 16:45:11 +053012061 goto err_nl_srv;
Jeff Johnson295189b2012-06-20 16:38:30 -070012062 }
12063
Jeff Johnson295189b2012-06-20 16:38:30 -070012064 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
12065
12066 if ( NULL == pHddCtx->hHal )
12067 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -080012068 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -070012069 goto err_vosclose;
12070 }
12071
Jeff Johnsonbc676b42013-02-14 16:04:08 -080012072 status = vos_preStart( pHddCtx->pvosContext );
12073 if ( !VOS_IS_STATUS_SUCCESS( status ) )
12074 {
12075 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053012076 goto err_vosclose;
Jeff Johnsonbc676b42013-02-14 16:04:08 -080012077 }
Jeff Johnsone7245742012-09-05 17:12:55 -070012078
Arif Hussaineaf68602013-12-30 23:10:44 -080012079 if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan)
12080 {
12081 pHddCtx->cfg_ini->enableDFSChnlScan = enable_dfs_chan_scan;
12082 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_dfs_chan_scan set to %d",
12083 __func__, enable_dfs_chan_scan);
12084 }
12085 if (0 == enable_11d || 1 == enable_11d)
12086 {
12087 pHddCtx->cfg_ini->Is11dSupportEnabled = enable_11d;
12088 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_11d set to %d",
12089 __func__, enable_11d);
12090 }
12091
Jeff Johnsonbc676b42013-02-14 16:04:08 -080012092 /* Note that the vos_preStart() sequence triggers the cfg download.
12093 The cfg download must occur before we update the SME config
12094 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -070012095 status = hdd_set_sme_config( pHddCtx );
12096
12097 if ( VOS_STATUS_SUCCESS != status )
12098 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -080012099 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053012100 goto err_vosclose;
Jeff Johnsonbc676b42013-02-14 16:04:08 -080012101 }
Jeff Johnson295189b2012-06-20 16:38:30 -070012102
Jeff Johnson295189b2012-06-20 16:38:30 -070012103 /* In the integrated architecture we update the configuration from
12104 the INI file and from NV before vOSS has been started so that
12105 the final contents are available to send down to the cCPU */
12106
12107 // Apply the cfg.ini to cfg.dat
12108 if (FALSE == hdd_update_config_dat(pHddCtx))
12109 {
12110 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053012111 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -070012112 }
12113
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053012114 // Get mac addr from platform driver
12115 ret = wcnss_get_wlan_mac_address((char*)&mac_addr.bytes);
12116
12117 if ((0 == ret) && (!vos_is_macaddr_zero(&mac_addr)))
Jeff Johnson295189b2012-06-20 16:38:30 -070012118 {
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053012119 /* Store the mac addr for first interface */
12120 pHddCtx->cfg_ini->intfMacAddr[0] = mac_addr;
12121
12122 hddLog(VOS_TRACE_LEVEL_ERROR,
12123 "%s: WLAN Mac Addr: "
12124 MAC_ADDRESS_STR, __func__,
12125 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
12126
12127 /* Here, passing Arg2 as 1 because we do not want to change the
12128 last 3 bytes (means non OUI bytes) of first interface mac
12129 addr.
12130 */
12131 if (0 != hdd_generate_iface_mac_addr_auto(pHddCtx, 1, mac_addr))
12132 {
12133 hddLog(VOS_TRACE_LEVEL_ERROR,
12134 "%s: Failed to generate wlan interface mac addr "
12135 "using MAC from ini file ", __func__);
12136 }
12137 }
12138 else if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
12139 {
12140 // Apply the NV to cfg.dat
12141 /* Prima Update MAC address only at here */
Jeff Johnson295189b2012-06-20 16:38:30 -070012142#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
12143 /* There was not a valid set of MAC Addresses in NV. See if the
12144 default addresses were modified by the cfg.ini settings. If so,
12145 we'll use them, but if not, we'll autogenerate a set of MAC
12146 addresses based upon the device serial number */
12147
12148 static const v_MACADDR_t default_address =
12149 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
Jeff Johnson295189b2012-06-20 16:38:30 -070012150
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053012151 if (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
12152 sizeof(default_address)))
Jeff Johnson295189b2012-06-20 16:38:30 -070012153 {
12154 /* cfg.ini has the default address, invoke autogen logic */
12155
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053012156 /* Here, passing Arg2 as 0 because we want to change the
12157 last 3 bytes (means non OUI bytes) of all the interfaces
12158 mac addr.
12159 */
12160 if (0 != hdd_generate_iface_mac_addr_auto(pHddCtx, 0,
12161 default_address))
Jeff Johnson295189b2012-06-20 16:38:30 -070012162 {
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053012163 hddLog(VOS_TRACE_LEVEL_ERROR,
12164 "%s: Failed to generate wlan interface mac addr "
12165 "using MAC from ini file " MAC_ADDRESS_STR, __func__,
12166 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
Jeff Johnson295189b2012-06-20 16:38:30 -070012167 }
Jeff Johnson295189b2012-06-20 16:38:30 -070012168 }
12169 else
12170#endif //WLAN_AUTOGEN_MACADDR_FEATURE
12171 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -080012172 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -070012173 "%s: Invalid MAC address in NV, using MAC from ini file "
12174 MAC_ADDRESS_STR, __func__,
12175 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
12176 }
12177 }
12178 {
12179 eHalStatus halStatus;
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053012180
12181 /* Set the MAC Address Currently this is used by HAL to
12182 * add self sta. Remove this once self sta is added as
12183 * part of session open.
12184 */
Jeff Johnson295189b2012-06-20 16:38:30 -070012185 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
12186 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
12187 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053012188
Jeff Johnson295189b2012-06-20 16:38:30 -070012189 if (!HAL_STATUS_SUCCESS( halStatus ))
12190 {
12191 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
12192 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053012193 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -070012194 }
12195 }
Jeff Johnson295189b2012-06-20 16:38:30 -070012196
12197 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
12198 Note: Firmware image will be read and downloaded inside vos_start API */
12199 status = vos_start( pHddCtx->pvosContext );
12200 if ( !VOS_IS_STATUS_SUCCESS( status ) )
12201 {
12202 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
Hanumantha Reddy Pothulabd9601a2016-02-12 13:22:27 +053012203 if (isSsrPanicOnFailure())
12204 VOS_BUG(0);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053012205 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -070012206 }
12207
Leo Chang6cec3e22014-01-21 15:33:49 -080012208#ifdef FEATURE_WLAN_CH_AVOID
12209 /* Plug in avoid channel notification callback
12210 * This should happen before ADD_SELF_STA
12211 * FW will send first IND with ADD_SELF_STA REQ from host */
Pradeep Reddy POTTETI5c2e16d2014-06-27 16:47:38 +053012212
12213 /* check the Channel Avoidance is enabled */
12214 if (TRUE == pHddCtx->cfg_ini->fenableCHAvoidance)
12215 {
12216 sme_AddChAvoidCallback(pHddCtx->hHal,
12217 hdd_hostapd_ch_avoid_cb);
12218 }
Leo Chang6cec3e22014-01-21 15:33:49 -080012219#endif /* FEATURE_WLAN_CH_AVOID */
12220
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070012221 /* Exchange capability info between Host and FW and also get versioning info from FW */
12222 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -070012223
Agarwal Ashishad9281b2014-06-10 14:57:30 +053012224#ifdef CONFIG_ENABLE_LINUX_REG
12225 status = wlan_hdd_init_channels(pHddCtx);
12226 if ( !VOS_IS_STATUS_SUCCESS( status ) )
12227 {
12228 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: wlan_hdd_init_channels failed",
12229 __func__);
12230 goto err_vosstop;
12231 }
12232#endif
12233
Jeff Johnson295189b2012-06-20 16:38:30 -070012234 status = hdd_post_voss_start_config( pHddCtx );
12235 if ( !VOS_IS_STATUS_SUCCESS( status ) )
12236 {
12237 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
12238 __func__);
12239 goto err_vosstop;
12240 }
Amar Singhala49cbc52013-10-08 18:37:44 -070012241
12242#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +053012243 wlan_hdd_cfg80211_update_reg_info( wiphy );
12244
12245 /* registration of wiphy dev with cfg80211 */
12246 if (0 > wlan_hdd_cfg80211_register(wiphy))
12247 {
12248 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
12249 goto err_vosstop;
12250 }
Amar Singhala49cbc52013-10-08 18:37:44 -070012251#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070012252
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053012253#ifdef CONFIG_ENABLE_LINUX_REG
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053012254 /* registration of wiphy dev with cfg80211 */
12255 if (0 > wlan_hdd_cfg80211_register(wiphy))
12256 {
12257 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
12258 goto err_vosstop;
12259 }
12260
Agarwal Ashish6db9d532014-09-30 18:19:10 +053012261 status = wlan_hdd_init_channels_for_cc(pHddCtx, INIT);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053012262 if ( !VOS_IS_STATUS_SUCCESS( status ) )
12263 {
12264 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: wlan_hdd_init_channels_for_cc failed",
12265 __func__);
12266 goto err_unregister_wiphy;
12267 }
12268#endif
12269
c_hpothu4a298be2014-12-22 21:12:51 +053012270 wcnss_wlan_set_drvdata(pHddCtx->parent_dev, pHddCtx);
12271
Jeff Johnson295189b2012-06-20 16:38:30 -070012272 if (VOS_STA_SAP_MODE == hdd_get_conparam())
12273 {
12274 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
12275 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
12276 }
12277 else
12278 {
Jeff Johnson295189b2012-06-20 16:38:30 -070012279 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
12280 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
12281 if (pAdapter != NULL)
12282 {
Katya Nigama7d81d72014-11-12 12:44:34 +053012283 if (pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated && !(pHddCtx->cfg_ini->intfMacAddr[0].bytes[0] & 0x02))
Jeff Johnson295189b2012-06-20 16:38:30 -070012284 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +053012285 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
12286 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
12287 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -070012288
Gopichand Nakkala49f96f62013-02-06 14:38:17 +053012289 /* Generate the P2P Device Address. This consists of the device's
12290 * primary MAC address with the locally administered bit set.
12291 */
12292 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -070012293 }
12294 else
12295 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +053012296 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
12297 if (p2p_dev_addr != NULL)
12298 {
12299 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
12300 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
12301 }
12302 else
12303 {
12304 hddLog(VOS_TRACE_LEVEL_FATAL,
12305 "%s: Failed to allocate mac_address for p2p_device",
12306 __func__);
12307 goto err_close_adapter;
12308 }
Jeff Johnson295189b2012-06-20 16:38:30 -070012309 }
Jeff Johnsone7245742012-09-05 17:12:55 -070012310
12311 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
12312 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
12313 if ( NULL == pP2pAdapter )
12314 {
12315 hddLog(VOS_TRACE_LEVEL_FATAL,
12316 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070012317 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -070012318 goto err_close_adapter;
12319 }
Jeff Johnsone7245742012-09-05 17:12:55 -070012320 }
Jeff Johnson295189b2012-06-20 16:38:30 -070012321 }
Jeff Johnson295189b2012-06-20 16:38:30 -070012322
12323 if( pAdapter == NULL )
12324 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -080012325 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
12326 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -070012327 }
Jeff Johnsone7245742012-09-05 17:12:55 -070012328
Arif Hussain66559122013-11-21 10:11:40 -080012329 if (country_code)
12330 {
12331 eHalStatus ret;
Arif Hussaincb607082013-12-20 11:57:42 -080012332 INIT_COMPLETION(pAdapter->change_country_code);
Arif Hussain66559122013-11-21 10:11:40 -080012333 hdd_checkandupdate_dfssetting(pAdapter, country_code);
12334#ifndef CONFIG_ENABLE_LINUX_REG
12335 hdd_checkandupdate_phymode(pAdapter, country_code);
12336#endif
Arif Hussaineaf68602013-12-30 23:10:44 -080012337 ret = sme_ChangeCountryCode(pHddCtx->hHal,
12338 (void *)(tSmeChangeCountryCallback)
12339 wlan_hdd_change_country_code_callback,
Arif Hussain66559122013-11-21 10:11:40 -080012340 country_code,
12341 pAdapter, pHddCtx->pvosContext,
Abhishek Singha306a442013-11-07 18:39:01 +053012342 eSIR_TRUE, eSIR_TRUE);
Arif Hussain66559122013-11-21 10:11:40 -080012343 if (eHAL_STATUS_SUCCESS == ret)
12344 {
Arif Hussaincb607082013-12-20 11:57:42 -080012345 ret = wait_for_completion_interruptible_timeout(
12346 &pAdapter->change_country_code,
12347 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
12348
12349 if (0 >= ret)
12350 {
12351 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
12352 "%s: SME while setting country code timed out", __func__);
12353 }
Arif Hussain66559122013-11-21 10:11:40 -080012354 }
12355 else
12356 {
Arif Hussaincb607082013-12-20 11:57:42 -080012357 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
12358 "%s: SME Change Country code from module param fail ret=%d",
12359 __func__, ret);
Arif Hussain66559122013-11-21 10:11:40 -080012360 }
12361 }
12362
Jeff Johnson295189b2012-06-20 16:38:30 -070012363#ifdef WLAN_BTAMP_FEATURE
12364 vStatus = WLANBAP_Open(pVosContext);
12365 if(!VOS_IS_STATUS_SUCCESS(vStatus))
12366 {
12367 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
12368 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -070012369 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -070012370 }
12371
12372 vStatus = BSL_Init(pVosContext);
12373 if(!VOS_IS_STATUS_SUCCESS(vStatus))
12374 {
12375 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
12376 "%s: Failed to Init BSL",__func__);
12377 goto err_bap_close;
12378 }
12379 vStatus = WLANBAP_Start(pVosContext);
12380 if (!VOS_IS_STATUS_SUCCESS(vStatus))
12381 {
12382 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
12383 "%s: Failed to start TL",__func__);
12384 goto err_bap_close;
12385 }
12386
12387 pConfig = pHddCtx->cfg_ini;
12388 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
12389 status = WLANBAP_SetConfig(&btAmpConfig);
12390
12391#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -070012392
Mihir Shete9c238772014-10-15 14:35:16 +053012393 /*
12394 * UapsdMask is 0xf if U-APSD is enbaled for all AC's...
12395 * The value of CFG_QOS_WMM_UAPSD_MASK_DEFAULT is 0xaa(Magic Value)
12396 * which is greater than 0xf. So the below check is safe to make
12397 * sure that there is no entry for UapsdMask in the ini
12398 */
12399 if (CFG_QOS_WMM_UAPSD_MASK_DEFAULT == pHddCtx->cfg_ini->UapsdMask)
12400 {
12401 if(IS_DYNAMIC_WMM_PS_ENABLED)
12402 {
12403 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: Enable UAPSD for VI & VO",
12404 __func__);
12405 pHddCtx->cfg_ini->UapsdMask =
12406 CFG_QOS_WMM_UAPSD_MASK_DYMANIC_WMM_PS_DEFAULT;
12407 }
12408 else
12409 {
12410 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: Do not enable UAPSD",
12411 __func__);
12412 pHddCtx->cfg_ini->UapsdMask =
12413 CFG_QOS_WMM_UAPSD_MASK_LEGACY_WMM_PS_DEFAULT;
12414 }
12415 }
12416
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -070012417#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
12418 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
12419 {
12420 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
12421 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
12422 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
12423 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
12424 }
12425#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070012426
Agarwal Ashish4b87f922014-06-18 03:03:21 +053012427 wlan_hdd_tdls_init(pHddCtx);
12428
Masti, Narayanraddi26378462016-01-05 18:20:28 +053012429 wlan_hdd_init_deinit_defer_scan_context(&pHddCtx->scan_ctxt);
12430
12431 vos_init_delayed_work(&pHddCtx->scan_ctxt.scan_work,
12432 wlan_hdd_schedule_defer_scan);
12433
Mihir Shetefc7ff5b2014-01-27 11:30:05 +053012434 sme_Register11dScanDoneCallback(pHddCtx->hHal, hdd_11d_scan_done);
12435
Jeff Johnson295189b2012-06-20 16:38:30 -070012436 /* Register with platform driver as client for Suspend/Resume */
12437 status = hddRegisterPmOps(pHddCtx);
12438 if ( !VOS_IS_STATUS_SUCCESS( status ) )
12439 {
12440 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
12441#ifdef WLAN_BTAMP_FEATURE
12442 goto err_bap_stop;
12443#else
Jeff Johnsone7245742012-09-05 17:12:55 -070012444 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -070012445#endif //WLAN_BTAMP_FEATURE
12446 }
12447
Yue Ma0d4891e2013-08-06 17:01:45 -070012448 /* Open debugfs interface */
12449 if (VOS_STATUS_SUCCESS != hdd_debugfs_init(pAdapter))
12450 {
12451 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
12452 "%s: hdd_debugfs_init failed!", __func__);
Yue Ma0d4891e2013-08-06 17:01:45 -070012453 }
12454
Jeff Johnson295189b2012-06-20 16:38:30 -070012455 /* Register TM level change handler function to the platform */
12456 status = hddDevTmRegisterNotifyCallback(pHddCtx);
12457 if ( !VOS_IS_STATUS_SUCCESS( status ) )
12458 {
12459 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
12460 goto err_unregister_pmops;
12461 }
Jeff Johnson295189b2012-06-20 16:38:30 -070012462
Jeff Johnson295189b2012-06-20 16:38:30 -070012463 // register net device notifier for device change notification
12464 ret = register_netdevice_notifier(&hdd_netdev_notifier);
12465
12466 if(ret < 0)
12467 {
12468 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
Siddharth Bhalcd92b782015-06-29 12:25:40 +053012469 goto err_unregister_pmops;
Jeff Johnson295189b2012-06-20 16:38:30 -070012470 }
12471
Jeff Johnson295189b2012-06-20 16:38:30 -070012472 //Initialize the BTC service
12473 if(btc_activate_service(pHddCtx) != 0)
12474 {
12475 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
Mahesh A Saptasagarc3ed0122016-01-19 16:45:11 +053012476 goto err_reg_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -070012477 }
12478
Padma, Santhosh Kumar2762e9d2015-10-20 15:02:57 +053012479#ifdef FEATURE_OEM_DATA_SUPPORT
12480 //Initialize the OEM service
12481 if (oem_activate_service(pHddCtx) != 0)
12482 {
12483 hddLog(VOS_TRACE_LEVEL_FATAL,
12484 "%s: oem_activate_service failed", __func__);
Mahesh A Saptasagarc3ed0122016-01-19 16:45:11 +053012485 goto err_reg_netdev;
Padma, Santhosh Kumar2762e9d2015-10-20 15:02:57 +053012486 }
12487#endif
12488
Jeff Johnson295189b2012-06-20 16:38:30 -070012489#ifdef PTT_SOCK_SVC_ENABLE
12490 //Initialize the PTT service
12491 if(ptt_sock_activate_svc(pHddCtx) != 0)
12492 {
12493 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
Mahesh A Saptasagarc3ed0122016-01-19 16:45:11 +053012494 goto err_reg_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -070012495 }
12496#endif
12497
Abhishek Singh00b71972016-01-07 10:51:04 +053012498#ifdef WLAN_FEATURE_RMC
12499 if (hdd_open_cesium_nl_sock() < 0)
12500 {
12501 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_open_cesium_nl_sock failed", __func__);
12502 goto err_reg_netdev;
12503 }
12504#endif
12505
Vinay Krishna Erannad938c422014-03-10 17:14:21 +053012506#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
12507 if(pHddCtx->cfg_ini && pHddCtx->cfg_ini->wlanLoggingEnable)
12508 {
Deepthi Gowri78083a32014-11-04 12:55:51 +053012509 if(wlan_logging_sock_activate_svc(
12510 pHddCtx->cfg_ini->wlanLoggingFEToConsole,
Sushant Kaushik33200572015-08-05 16:46:20 +053012511 pHddCtx->cfg_ini->wlanLoggingNumBuf,
12512 pHddCtx->cfg_ini->wlanPerPktStatsLogEnable,
12513 pHddCtx->cfg_ini->wlanPerPktStatsNumBuf))
Deepthi Gowri78083a32014-11-04 12:55:51 +053012514 {
12515 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wlan_logging_sock_activate_svc"
12516 " failed", __func__);
Mahesh A Saptasagarc3ed0122016-01-19 16:45:11 +053012517 goto err_reg_netdev;
Deepthi Gowri78083a32014-11-04 12:55:51 +053012518 }
12519 //TODO: To Remove enableDhcpDebug and use gEnableDebugLog for
12520 //EAPOL and DHCP
Sachin Ahuja8c65f382014-12-12 15:34:21 +053012521 if (!pHddCtx->cfg_ini->gEnableDebugLog)
12522 pHddCtx->cfg_ini->gEnableDebugLog =
Sushant Kaushik6e4e2bc2015-10-05 17:23:07 +053012523 VOS_PKT_PROTO_TYPE_EAPOL | VOS_PKT_PROTO_TYPE_DHCP |
12524 VOS_PKT_PROTO_TYPE_ARP;
Vinay Krishna Erannad938c422014-03-10 17:14:21 +053012525 }
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012526
Siddharth Bhald1be97f2015-05-27 22:39:59 +053012527 if (pHddCtx->cfg_ini->wlanLoggingEnable &&
12528 (pHddCtx->cfg_ini->enableFWLogging ||
Siddharth Bhaldb963232015-06-25 19:34:35 +053012529 pHddCtx->cfg_ini->enableMgmtLogging ||
c_manjeecfd1efb2015-09-25 19:32:34 +053012530 pHddCtx->cfg_ini->enableContFWLogging ||
12531 pHddCtx->cfg_ini->enableFwrMemDump )
12532 )
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012533 {
Siddharth Bhald1be97f2015-05-27 22:39:59 +053012534 hdd_init_frame_logging(pHddCtx);
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012535 }
12536 else
12537 {
Siddharth Bhald1be97f2015-05-27 22:39:59 +053012538 hddLog(VOS_TRACE_LEVEL_INFO, FL("Logging disabled in ini"));
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012539 }
12540
Vinay Krishna Erannad938c422014-03-10 17:14:21 +053012541#endif
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012542
Agrawal Ashish17ef5082016-10-17 18:33:21 +053012543#ifdef SAP_AUTH_OFFLOAD
12544 if (!sme_IsFeatureSupportedByFW(SAP_OFFLOADS))
12545 {
12546 hddLog(VOS_TRACE_LEVEL_INFO, FL(" SAP AUTH OFFLOAD not supp by FW"));
12547 pHddCtx->cfg_ini->enable_sap_auth_offload = 0;
12548 }
12549#endif
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012550
Sushant Kaushik215778f2015-05-21 14:05:36 +053012551 if (vos_is_multicast_logging())
12552 wlan_logging_set_log_level();
12553
Jeff Johnson295189b2012-06-20 16:38:30 -070012554 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -070012555 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -070012556 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -070012557 /* Action frame registered in one adapter which will
12558 * applicable to all interfaces
12559 */
Agarwal Ashish8fa0e9a2014-05-23 00:40:12 +053012560 wlan_hdd_cfg80211_register_frames(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -070012561 }
Jeff Johnson295189b2012-06-20 16:38:30 -070012562
12563 mutex_init(&pHddCtx->sap_lock);
Mahesh A Saptasagar60627942014-10-13 13:55:14 +053012564 mutex_init(&pHddCtx->roc_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070012565
Jeff Johnsone7245742012-09-05 17:12:55 -070012566#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
12567 /* Initialize the wake lcok */
Sushant Kaushik83392fa2015-05-05 17:44:40 +053012568 vos_wake_lock_init(&pHddCtx->rx_wake_lock,
Jeff Johnsone7245742012-09-05 17:12:55 -070012569 "qcom_rx_wakelock");
Sushant Kaushik83392fa2015-05-05 17:44:40 +053012570
Jeff Johnsone7245742012-09-05 17:12:55 -070012571#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -080012572 /* Initialize the wake lcok */
Sushant Kaushik83392fa2015-05-05 17:44:40 +053012573 vos_wake_lock_init(&pHddCtx->sap_wake_lock,
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -080012574 "qcom_sap_wakelock");
Sushant Kaushik83392fa2015-05-05 17:44:40 +053012575
Jeff Johnsone7245742012-09-05 17:12:55 -070012576
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -070012577 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
12578 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -070012579
Katya Nigam5c306ea2014-06-19 15:39:54 +053012580 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_NO_LOAD_UNLOAD_IN_PROGRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -070012581 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
Sushant Kaushik83392fa2015-05-05 17:44:40 +053012582 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_INIT);
Katya Nigam5c306ea2014-06-19 15:39:54 +053012583
12584#ifdef FEATURE_WLAN_SCAN_PNO
12585 /*SME must send channel update configuration to RIVA*/
12586 sme_UpdateChannelConfig(pHddCtx->hHal);
12587#endif
Abhishek Singhf644b272014-08-21 02:59:39 +053012588 /* Send the update default channel list to the FW*/
12589 sme_UpdateChannelList(pHddCtx->hHal);
Mukul Sharma45063942015-04-01 20:07:59 +053012590
12591 /* Fwr capabilities received, Set the Dot11 mode */
Abhishek Singh41ebce12016-02-03 10:43:21 +053012592 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter),
12593 hdd_cfg_xlate_to_csr_phy_mode(pHddCtx->cfg_ini->dot11Mode));
Mukul Sharma45063942015-04-01 20:07:59 +053012594 sme_SetDefDot11Mode(pHddCtx->hHal);
12595
Abhishek Singha306a442013-11-07 18:39:01 +053012596#ifndef CONFIG_ENABLE_LINUX_REG
12597 /*updating wiphy so that regulatory user hints can be processed*/
12598 if (wiphy)
12599 {
12600 regulatory_hint(wiphy, "00");
12601 }
12602#endif
Jeff Johnsone7245742012-09-05 17:12:55 -070012603 // Initialize the restart logic
12604 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +053012605
Hanumanth Reddy Pothula146bca42016-11-08 12:01:07 +053012606 if (pHddCtx->cfg_ini->fIsLogpEnabled) {
12607 vos_wdthread_init_timer_work(vos_process_wd_timer);
12608 /* Initialize the timer to detect thread stuck issues */
12609 vos_thread_stuck_timer_init(
12610 &((VosContextType*)pVosContext)->vosWatchdog);
12611 }
12612
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -070012613 //Register the traffic monitor timer now
12614 if ( pHddCtx->cfg_ini->dynSplitscan)
12615 {
12616 vos_timer_init(&pHddCtx->tx_rx_trafficTmr,
12617 VOS_TIMER_TYPE_SW,
12618 hdd_tx_rx_pkt_cnt_stat_timer_handler,
12619 (void *)pHddCtx);
12620 }
Srinivas Dasari030bad32015-02-18 23:23:54 +053012621 wlan_hdd_cfg80211_nan_init(pHddCtx);
12622
Bhargav Shahd0715912015-10-01 18:17:37 +053012623 mutex_init(&pHddCtx->cur_rx_level_lock);
12624 vos_timer_init(&pHddCtx->delack_timer, VOS_TIMER_TYPE_SW,
12625 hdd_tcp_delack_compute_function,(void *)pHddCtx);
Masti, Narayanraddi44b0db02015-12-22 11:54:35 +053012626 vos_timer_init(&pHddCtx->tdls_source_timer, VOS_TIMER_TYPE_SW,
12627 wlan_hdd_change_tdls_mode, (void *)pHddCtx);
Bhargav Shahd0715912015-10-01 18:17:37 +053012628
Dino Mycle6fb96c12014-06-10 11:52:40 +053012629#ifdef WLAN_FEATURE_EXTSCAN
12630 sme_EXTScanRegisterCallback(pHddCtx->hHal,
12631 wlan_hdd_cfg80211_extscan_callback,
12632 pHddCtx);
12633#endif /* WLAN_FEATURE_EXTSCAN */
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053012634
Padma, Santhosh Kumar2ccac212015-10-20 17:27:27 +053012635#ifdef FEATURE_OEM_DATA_SUPPORT
12636 sme_OemDataRegisterCallback(pHddCtx->hHal,
12637 wlan_hdd_cfg80211_oemdata_callback,
12638 pHddCtx);
12639#endif /* FEATURE_OEM_DATA_SUPPORT */
12640
Gupta, Kapil7c34b322015-09-30 13:12:35 +053012641 sme_set_rssi_threshold_breached_cb(pHddCtx->hHal, hdd_rssi_threshold_breached_cb);
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053012642#ifdef WLAN_NS_OFFLOAD
12643 // Register IPv6 notifier to notify if any change in IP
12644 // So that we can reconfigure the offload parameters
12645 pHddCtx->ipv6_notifier.notifier_call = wlan_hdd_ipv6_changed;
12646 ret = register_inet6addr_notifier(&pHddCtx->ipv6_notifier);
12647 if (ret)
12648 {
Ratheesh S P36dbc932015-08-07 14:28:57 +053012649 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Failed to register IPv6 notifier"));
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053012650 }
12651 else
12652 {
Ratheesh S P36dbc932015-08-07 14:28:57 +053012653 hddLog(VOS_TRACE_LEVEL_INFO, FL("Registered IPv6 notifier"));
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053012654 }
12655#endif
12656
Sravan Kumar Kairamb0edc612016-10-26 13:55:24 +053012657 vos_mem_set((uint8_t *)&pHddCtx->bad_sta, HDD_MAX_STA_COUNT, 0);
12658
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053012659 // Register IPv4 notifier to notify if any change in IP
12660 // So that we can reconfigure the offload parameters
12661 pHddCtx->ipv4_notifier.notifier_call = wlan_hdd_ipv4_changed;
12662 ret = register_inetaddr_notifier(&pHddCtx->ipv4_notifier);
12663 if (ret)
12664 {
Ratheesh S P36dbc932015-08-07 14:28:57 +053012665 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Failed to register IPv4 notifier"));
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053012666 }
12667 else
12668 {
Ratheesh S P36dbc932015-08-07 14:28:57 +053012669 hddLog(VOS_TRACE_LEVEL_INFO, FL("Registered IPv4 notifier"));
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053012670 }
c_manjeecfd1efb2015-09-25 19:32:34 +053012671 /*Fw mem dump procfs initialization*/
12672 memdump_init();
Bhargav shah23c94942015-10-13 12:48:35 +053012673 hdd_dp_util_send_rps_ind(pHddCtx);
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053012674
Nishank Aggarwalc11826c2016-12-15 18:54:10 +053012675 pHddCtx->is_ap_mode_wow_supported =
12676 sme_IsFeatureSupportedByFW(SAP_MODE_WOW);
Sravan Kumar Kairam091e5b62017-01-23 14:14:20 +053012677
12678 hdd_assoc_registerFwdEapolCB(pVosContext);
12679
Jeff Johnson295189b2012-06-20 16:38:30 -070012680 goto success;
12681
Jeff Johnson295189b2012-06-20 16:38:30 -070012682err_reg_netdev:
12683 unregister_netdevice_notifier(&hdd_netdev_notifier);
12684
Jeff Johnson295189b2012-06-20 16:38:30 -070012685err_unregister_pmops:
12686 hddDevTmUnregisterNotifyCallback(pHddCtx);
12687 hddDeregisterPmOps(pHddCtx);
12688
Yue Ma0d4891e2013-08-06 17:01:45 -070012689 hdd_debugfs_exit(pHddCtx);
12690
Jeff Johnson295189b2012-06-20 16:38:30 -070012691#ifdef WLAN_BTAMP_FEATURE
12692err_bap_stop:
12693 WLANBAP_Stop(pVosContext);
12694#endif
12695
12696#ifdef WLAN_BTAMP_FEATURE
12697err_bap_close:
12698 WLANBAP_Close(pVosContext);
12699#endif
12700
Jeff Johnson295189b2012-06-20 16:38:30 -070012701err_close_adapter:
12702 hdd_close_all_adapters( pHddCtx );
Mahesh A Saptasagar9ecefe42014-07-15 18:43:49 +053012703#ifdef CONFIG_ENABLE_LINUX_REG
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053012704err_unregister_wiphy:
Mahesh A Saptasagar9ecefe42014-07-15 18:43:49 +053012705#endif
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +053012706 wiphy_unregister(wiphy) ;
Agrawal Ashish33ec71e2015-11-26 20:20:58 +053012707 hdd_wlan_free_wiphy_channels(wiphy);
12708
Jeff Johnson295189b2012-06-20 16:38:30 -070012709err_vosstop:
12710 vos_stop(pVosContext);
12711
Amar Singhala49cbc52013-10-08 18:37:44 -070012712err_vosclose:
Jeff Johnson295189b2012-06-20 16:38:30 -070012713 status = vos_sched_close( pVosContext );
12714 if (!VOS_IS_STATUS_SUCCESS(status)) {
12715 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
12716 "%s: Failed to close VOSS Scheduler", __func__);
12717 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
12718 }
Amar Singhala49cbc52013-10-08 18:37:44 -070012719 vos_close(pVosContext );
12720
Mahesh A Saptasagarc3ed0122016-01-19 16:45:11 +053012721err_nl_srv:
12722#ifdef WLAN_KD_READY_NOTIFIER
12723 nl_srv_exit(pHddCtx->ptt_pid);
12724#else
12725 nl_srv_exit();
12726#endif /* WLAN_KD_READY_NOTIFIER */
Amar Singhal0a402232013-10-11 20:57:16 -070012727err_vos_nv_close:
12728
c_hpothue6a36282014-03-19 12:27:38 +053012729#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -070012730 vos_nv_close();
12731
c_hpothu70f8d812014-03-22 22:59:23 +053012732#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070012733
12734err_wdclose:
12735 if(pHddCtx->cfg_ini->fIsLogpEnabled)
12736 vos_watchdog_close(pVosContext);
12737
Jeff Johnson295189b2012-06-20 16:38:30 -070012738err_config:
12739 kfree(pHddCtx->cfg_ini);
12740 pHddCtx->cfg_ini= NULL;
12741
12742err_free_hdd_context:
Sushant Kaushik83392fa2015-05-05 17:44:40 +053012743 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_INIT);
Siddharth Bhalcd92b782015-06-29 12:25:40 +053012744 free_riva_power_on_lock("wlan");
Jeff Johnson295189b2012-06-20 16:38:30 -070012745 wiphy_free(wiphy) ;
12746 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -070012747 VOS_BUG(1);
12748
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -080012749 if (hdd_is_ssr_required())
12750 {
12751 /* WDI timeout had happened during load, so SSR is needed here */
12752 subsystem_restart("wcnss");
12753 msleep(5000);
12754 }
12755 hdd_set_ssr_required (VOS_FALSE);
12756
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -080012757 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -070012758
12759success:
12760 EXIT();
12761 return 0;
12762}
12763
12764/**---------------------------------------------------------------------------
12765
Jeff Johnson32d95a32012-09-10 13:15:23 -070012766 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -070012767
Jeff Johnson32d95a32012-09-10 13:15:23 -070012768 This is the driver entry point - called in different timeline depending
12769 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -070012770
12771 \param - None
12772
12773 \return - 0 for success, non zero for failure
12774
12775 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -070012776static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -070012777{
12778 VOS_STATUS status;
12779 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -070012780 struct device *dev = NULL;
12781 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -070012782#ifdef HAVE_WCNSS_CAL_DOWNLOAD
12783 int max_retries = 0;
12784#endif
Siddharth Bhalc7e79b62014-10-10 22:37:38 +053012785#ifdef HAVE_CBC_DONE
12786 int max_cbc_retries = 0;
12787#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070012788
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +053012789#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
12790 wlan_logging_sock_init_svc();
12791#endif
12792
Jeff Johnson295189b2012-06-20 16:38:30 -070012793 ENTER();
12794
Sushant Kaushik83392fa2015-05-05 17:44:40 +053012795 vos_wake_lock_init(&wlan_wake_lock, "wlan");
Jeff Johnson295189b2012-06-20 16:38:30 -070012796
12797 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
12798 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
12799
Jeff Johnson295189b2012-06-20 16:38:30 -070012800#ifdef ANI_BUS_TYPE_PCI
12801
12802 dev = wcnss_wlan_get_device();
12803
12804#endif // ANI_BUS_TYPE_PCI
12805
12806#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -070012807
12808#ifdef HAVE_WCNSS_CAL_DOWNLOAD
12809 /* wait until WCNSS driver downloads NV */
Ravi Kumar Bokka7a139e62016-11-17 21:32:55 +053012810 while (!wcnss_device_ready() && 10 >= ++max_retries) {
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -070012811 msleep(1000);
12812 }
Siddharth Bhalc7e79b62014-10-10 22:37:38 +053012813
Ravi Kumar Bokka7a139e62016-11-17 21:32:55 +053012814 if (max_retries >= 10) {
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -070012815 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
Sushant Kaushik83392fa2015-05-05 17:44:40 +053012816 vos_wake_lock_destroy(&wlan_wake_lock);
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +053012817#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
12818 wlan_logging_sock_deinit_svc();
12819#endif
12820
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -070012821 return -ENODEV;
12822 }
12823#endif
12824
Siddharth Bhalc7e79b62014-10-10 22:37:38 +053012825#ifdef HAVE_CBC_DONE
12826 while (!wcnss_cbc_complete() && 10 >= ++max_cbc_retries) {
12827 msleep(1000);
12828 }
12829 if (max_cbc_retries >= 10) {
12830 hddLog(VOS_TRACE_LEVEL_FATAL, "%s:CBC not completed", __func__);
12831 }
12832#endif
12833
Jeff Johnson295189b2012-06-20 16:38:30 -070012834 dev = wcnss_wlan_get_device();
12835#endif // ANI_BUS_TYPE_PLATFORM
12836
12837
12838 do {
12839 if (NULL == dev) {
12840 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
12841 ret_status = -1;
12842 break;
12843 }
12844
Jeff Johnson295189b2012-06-20 16:38:30 -070012845#ifdef TIMER_MANAGER
12846 vos_timer_manager_init();
12847#endif
12848
12849 /* Preopen VOSS so that it is ready to start at least SAL */
12850 status = vos_preOpen(&pVosContext);
12851
12852 if (!VOS_IS_STATUS_SUCCESS(status))
12853 {
12854 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
12855 ret_status = -1;
12856 break;
12857 }
12858
Sushant Kaushik02beb352015-06-04 15:15:01 +053012859 hddTraceInit();
Padma, Santhosh Kumar9093b202015-07-21 15:37:38 +053012860 hdd_register_debug_callback();
12861
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070012862#ifndef MODULE
12863 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
12864 */
12865 hdd_set_conparam((v_UINT_t)con_mode);
12866#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070012867
12868 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -080012869 if (hdd_wlan_startup(dev))
12870 {
Jeff Johnson295189b2012-06-20 16:38:30 -070012871 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -080012872 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -070012873 vos_preClose( &pVosContext );
12874 ret_status = -1;
12875 break;
12876 }
12877
Jeff Johnson295189b2012-06-20 16:38:30 -070012878 } while (0);
12879
12880 if (0 != ret_status)
12881 {
Jeff Johnson295189b2012-06-20 16:38:30 -070012882#ifdef TIMER_MANAGER
12883 vos_timer_exit();
12884#endif
12885#ifdef MEMORY_DEBUG
12886 vos_mem_exit();
12887#endif
Sushant Kaushik83392fa2015-05-05 17:44:40 +053012888 vos_wake_lock_destroy(&wlan_wake_lock);
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +053012889#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
12890 wlan_logging_sock_deinit_svc();
12891#endif
12892
Jeff Johnson295189b2012-06-20 16:38:30 -070012893 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
12894 }
12895 else
12896 {
12897 //Send WLAN UP indication to Nlink Service
12898 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
12899
12900 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Jeff Johnson295189b2012-06-20 16:38:30 -070012901 }
12902
12903 EXIT();
12904
12905 return ret_status;
12906}
12907
Jeff Johnson32d95a32012-09-10 13:15:23 -070012908/**---------------------------------------------------------------------------
12909
12910 \brief hdd_module_init() - Init Function
12911
12912 This is the driver entry point (invoked when module is loaded using insmod)
12913
12914 \param - None
12915
12916 \return - 0 for success, non zero for failure
12917
12918 --------------------------------------------------------------------------*/
12919#ifdef MODULE
12920static int __init hdd_module_init ( void)
12921{
12922 return hdd_driver_init();
12923}
Jeff Johnson32d95a32012-09-10 13:15:23 -070012924#else /* #ifdef MODULE */
12925static int __init hdd_module_init ( void)
12926{
12927 /* Driver initialization is delayed to fwpath_changed_handler */
12928 return 0;
12929}
Jeff Johnson32d95a32012-09-10 13:15:23 -070012930#endif /* #ifdef MODULE */
12931
Jeff Johnson295189b2012-06-20 16:38:30 -070012932
12933/**---------------------------------------------------------------------------
12934
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070012935 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -070012936
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070012937 This is the driver exit point (invoked when module is unloaded using rmmod
12938 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -070012939
12940 \param - None
12941
12942 \return - None
12943
12944 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070012945static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -070012946{
12947 hdd_context_t *pHddCtx = NULL;
12948 v_CONTEXT_t pVosContext = NULL;
Agarwal Ashish5e414792014-06-08 15:25:23 +053012949 v_REGDOMAIN_t regId;
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +053012950 unsigned long rc = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -070012951
12952 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
12953
12954 //Get the global vos context
12955 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
12956
12957 if(!pVosContext)
12958 {
12959 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
12960 goto done;
12961 }
12962
12963 //Get the HDD context.
12964 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
12965
12966 if(!pHddCtx)
12967 {
12968 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
12969 }
Katya Nigame7b69a82015-04-28 15:24:06 +053012970 else if (VOS_MONITOR_MODE == hdd_get_conparam())
12971 {
12972 hddLog(VOS_TRACE_LEVEL_INFO,"%s: MONITOR MODE",__func__);
12973 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_UNLOAD_IN_PROGRESS;
12974 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
12975 hdd_wlan_exit(pHddCtx);
12976 vos_preClose( &pVosContext );
12977 goto done;
12978 }
Jeff Johnson295189b2012-06-20 16:38:30 -070012979 else
12980 {
Siddharth Bhal2e5871b2015-03-24 16:20:51 +053012981 /* We wait for active entry threads to exit from driver
12982 * by waiting until rtnl_lock is available.
12983 */
12984 rtnl_lock();
12985 rtnl_unlock();
12986
Siddharth Bhal3c29dca2015-02-19 00:41:40 +053012987 INIT_COMPLETION(pHddCtx->ssr_comp_var);
12988 if ((pHddCtx->isLogpInProgress) && (FALSE ==
12989 vos_is_wlan_in_badState(VOS_MODULE_ID_HDD, NULL)))
12990 {
Siddharth Bhala204f572015-01-17 02:03:36 +053012991 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Siddharth Bhal3c29dca2015-02-19 00:41:40 +053012992 "%s:SSR in Progress; block rmmod !!!", __func__);
Siddharth Bhala204f572015-01-17 02:03:36 +053012993 rc = wait_for_completion_timeout(&pHddCtx->ssr_comp_var,
12994 msecs_to_jiffies(30000));
12995 if(!rc)
12996 {
12997 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
12998 "%s:SSR timedout, fatal error", __func__);
12999 VOS_BUG(0);
13000 }
13001 }
13002
Siddharth Bhal3c29dca2015-02-19 00:41:40 +053013003 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_UNLOAD_IN_PROGRESS;
13004 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
Jeff Johnson295189b2012-06-20 16:38:30 -070013005
c_hpothu8adb97b2014-12-08 19:38:20 +053013006 /* Driver Need to send country code 00 in below condition
13007 * 1) If gCountryCodePriority is set to 1; and last country
13008 * code set is through 11d. This needs to be done in case
13009 * when NV country code is 00.
13010 * This Needs to be done as when kernel store last country
13011 * code and if stored country code is not through 11d,
13012 * in sme_HandleChangeCountryCodeByUser we will disable 11d
13013 * in next load/unload as soon as we get any country through
13014 * 11d. In sme_HandleChangeCountryCodeByUser
13015 * pMsg->countryCode will be last countryCode and
13016 * pMac->scan.countryCode11d will be country through 11d so
13017 * due to mismatch driver will disable 11d.
13018 *
13019 */
Agarwal Ashish8db39882014-07-30 21:56:07 +053013020
c_hpothu8adb97b2014-12-08 19:38:20 +053013021 if ((eANI_BOOLEAN_TRUE == sme_Is11dCountrycode(pHddCtx->hHal) &&
Agarwal Ashish8dcd2862014-07-25 11:58:52 +053013022 pHddCtx->cfg_ini->fSupplicantCountryCodeHasPriority &&
Abhishek Singh2a705962014-10-30 14:47:28 +053013023 sme_Is11dSupported(pHddCtx->hHal)))
c_hpothu8adb97b2014-12-08 19:38:20 +053013024 {
13025 hddLog(VOS_TRACE_LEVEL_INFO,
Agarwal Ashish8dcd2862014-07-25 11:58:52 +053013026 FL("CountryCode 00 is being set while unloading driver"));
c_hpothu8adb97b2014-12-08 19:38:20 +053013027 vos_nv_getRegDomainFromCountryCode(&regId , "00", COUNTRY_USER);
13028 }
Agarwal Ashish5e414792014-06-08 15:25:23 +053013029
c_hpothu8adb97b2014-12-08 19:38:20 +053013030 //Do all the cleanup before deregistering the driver
13031 hdd_wlan_exit(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -070013032 }
13033
Jeff Johnson295189b2012-06-20 16:38:30 -070013034 vos_preClose( &pVosContext );
13035
13036#ifdef TIMER_MANAGER
13037 vos_timer_exit();
13038#endif
13039#ifdef MEMORY_DEBUG
13040 vos_mem_exit();
13041#endif
13042
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +053013043#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
13044 wlan_logging_sock_deinit_svc();
13045#endif
13046
Jeff Johnson295189b2012-06-20 16:38:30 -070013047done:
Sushant Kaushik83392fa2015-05-05 17:44:40 +053013048 vos_wake_lock_destroy(&wlan_wake_lock);
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +053013049
Jeff Johnson295189b2012-06-20 16:38:30 -070013050 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
13051}
13052
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070013053/**---------------------------------------------------------------------------
13054
13055 \brief hdd_module_exit() - Exit function
13056
13057 This is the driver exit point (invoked when module is unloaded using rmmod)
13058
13059 \param - None
13060
13061 \return - None
13062
13063 --------------------------------------------------------------------------*/
13064static void __exit hdd_module_exit(void)
13065{
13066 hdd_driver_exit();
13067}
13068
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070013069#ifdef MODULE
13070static int fwpath_changed_handler(const char *kmessage,
13071 struct kernel_param *kp)
13072{
Jeff Johnson76052702013-04-16 13:55:05 -070013073 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070013074}
13075
13076static int con_mode_handler(const char *kmessage,
13077 struct kernel_param *kp)
13078{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -070013079 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070013080}
13081#else /* #ifdef MODULE */
13082/**---------------------------------------------------------------------------
13083
Jeff Johnson76052702013-04-16 13:55:05 -070013084 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070013085
Jeff Johnson76052702013-04-16 13:55:05 -070013086 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070013087 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -070013088 - invoked when module parameter fwpath is modified from userspace to signal
13089 initializing the WLAN driver or when con_mode is modified from userspace
13090 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070013091
13092 \return - 0 for success, non zero for failure
13093
13094 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -070013095static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070013096{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -070013097 int ret_status;
13098
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070013099 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -070013100 ret_status = hdd_driver_init();
13101 wlan_hdd_inited = ret_status ? 0 : 1;
13102 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070013103 }
13104
13105 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -070013106
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070013107 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -070013108
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -070013109 ret_status = hdd_driver_init();
13110 wlan_hdd_inited = ret_status ? 0 : 1;
13111 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070013112}
13113
Jeff Johnson295189b2012-06-20 16:38:30 -070013114/**---------------------------------------------------------------------------
13115
Jeff Johnson76052702013-04-16 13:55:05 -070013116 \brief fwpath_changed_handler() - Handler Function
13117
13118 Handle changes to the fwpath parameter
13119
13120 \return - 0 for success, non zero for failure
13121
13122 --------------------------------------------------------------------------*/
13123static int fwpath_changed_handler(const char *kmessage,
13124 struct kernel_param *kp)
13125{
13126 int ret;
13127
13128 ret = param_set_copystring(kmessage, kp);
13129 if (0 == ret)
13130 ret = kickstart_driver();
13131 return ret;
13132}
13133
13134/**---------------------------------------------------------------------------
13135
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070013136 \brief con_mode_handler() -
13137
13138 Handler function for module param con_mode when it is changed by userspace
13139 Dynamically linked - do nothing
13140 Statically linked - exit and init driver, as in rmmod and insmod
13141
Jeff Johnson76052702013-04-16 13:55:05 -070013142 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070013143
Jeff Johnson76052702013-04-16 13:55:05 -070013144 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070013145
13146 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -070013147static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070013148{
Jeff Johnson76052702013-04-16 13:55:05 -070013149 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070013150
Jeff Johnson76052702013-04-16 13:55:05 -070013151 ret = param_set_int(kmessage, kp);
13152 if (0 == ret)
13153 ret = kickstart_driver();
13154 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070013155}
13156#endif /* #ifdef MODULE */
13157
13158/**---------------------------------------------------------------------------
13159
Jeff Johnson295189b2012-06-20 16:38:30 -070013160 \brief hdd_get_conparam() -
13161
13162 This is the driver exit point (invoked when module is unloaded using rmmod)
13163
13164 \param - None
13165
13166 \return - tVOS_CON_MODE
13167
13168 --------------------------------------------------------------------------*/
13169tVOS_CON_MODE hdd_get_conparam ( void )
13170{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070013171#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -070013172 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070013173#else
13174 return (tVOS_CON_MODE)curr_con_mode;
13175#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070013176}
13177void hdd_set_conparam ( v_UINT_t newParam )
13178{
13179 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070013180#ifndef MODULE
13181 curr_con_mode = con_mode;
13182#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070013183}
13184/**---------------------------------------------------------------------------
13185
13186 \brief hdd_softap_sta_deauth() - function
13187
13188 This to take counter measure to handle deauth req from HDD
13189
13190 \param - pAdapter - Pointer to the HDD
13191
13192 \param - enable - boolean value
13193
13194 \return - None
13195
13196 --------------------------------------------------------------------------*/
13197
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +053013198VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter,
13199 struct tagCsrDelStaParams *pDelStaParams)
Jeff Johnson295189b2012-06-20 16:38:30 -070013200{
Jeff Johnson295189b2012-06-20 16:38:30 -070013201 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -080013202 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -070013203
13204 ENTER();
13205
Rajesh Chauhan18488fc2013-08-22 10:15:03 -070013206 hddLog(LOG1, "hdd_softap_sta_deauth:(%p, false)",
13207 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -070013208
13209 //Ignore request to deauth bcmc station
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +053013210 if (pDelStaParams->peerMacAddr[0] & 0x1)
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -080013211 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -070013212
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +053013213 vosStatus = WLANSAP_DeauthSta(pVosContext, pDelStaParams);
Jeff Johnson295189b2012-06-20 16:38:30 -070013214
13215 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -080013216 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -070013217}
13218
13219/**---------------------------------------------------------------------------
13220
Rashmi Ramanna1f0948d2014-08-28 15:33:48 +053013221 \brief hdd_del_all_sta() - function
13222
13223 This function removes all the stations associated on stopping AP/P2P GO.
13224
13225 \param - pAdapter - Pointer to the HDD
13226
13227 \return - None
13228
13229 --------------------------------------------------------------------------*/
13230
13231int hdd_del_all_sta(hdd_adapter_t *pAdapter)
13232{
13233 v_U16_t i;
13234 VOS_STATUS vos_status;
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +053013235 v_CONTEXT_t pVosContext = ( WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
13236 ptSapContext pSapCtx = NULL;
13237 pSapCtx = VOS_GET_SAP_CB(pVosContext);
13238 if(pSapCtx == NULL){
13239 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
13240 FL("psapCtx is NULL"));
13241 return 1;
13242 }
Rashmi Ramanna1f0948d2014-08-28 15:33:48 +053013243 ENTER();
13244
13245 hddLog(VOS_TRACE_LEVEL_INFO,
13246 "%s: Delete all STAs associated.",__func__);
13247 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
13248 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
13249 )
13250 {
13251 for(i = 0; i < WLAN_MAX_STA_COUNT; i++)
13252 {
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +053013253 if ((pSapCtx->aStaInfo[i].isUsed) &&
13254 (!pSapCtx->aStaInfo[i].isDeauthInProgress))
Rashmi Ramanna1f0948d2014-08-28 15:33:48 +053013255 {
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +053013256 struct tagCsrDelStaParams delStaParams;
13257
13258 WLANSAP_PopulateDelStaParams(
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +053013259 pSapCtx->aStaInfo[i].macAddrSTA.bytes,
Sushant Kaushik4cd28f62014-12-26 14:23:50 +053013260 eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
13261 SIR_MAC_MGMT_DEAUTH >> 4,
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +053013262 &delStaParams);
13263 vos_status = hdd_softap_sta_deauth(pAdapter, &delStaParams);
Rashmi Ramanna1f0948d2014-08-28 15:33:48 +053013264 if (VOS_IS_STATUS_SUCCESS(vos_status))
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +053013265 pSapCtx->aStaInfo[i].isDeauthInProgress = TRUE;
Rashmi Ramanna1f0948d2014-08-28 15:33:48 +053013266 }
13267 }
13268 }
13269
13270 EXIT();
13271 return 0;
13272}
13273
13274/**---------------------------------------------------------------------------
13275
Jeff Johnson295189b2012-06-20 16:38:30 -070013276 \brief hdd_softap_sta_disassoc() - function
13277
13278 This to take counter measure to handle deauth req from HDD
13279
13280 \param - pAdapter - Pointer to the HDD
13281
13282 \param - enable - boolean value
13283
13284 \return - None
13285
13286 --------------------------------------------------------------------------*/
13287
13288void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
13289{
13290 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
13291
13292 ENTER();
13293
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +053013294 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -070013295
13296 //Ignore request to disassoc bcmc station
13297 if( pDestMacAddress[0] & 0x1 )
13298 return;
13299
13300 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
13301}
13302
13303void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
13304{
13305 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
13306
13307 ENTER();
13308
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +053013309 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -070013310
13311 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
13312}
13313
Jeff Johnson295189b2012-06-20 16:38:30 -070013314/**---------------------------------------------------------------------------
13315 *
13316 * \brief hdd_get__concurrency_mode() -
13317 *
13318 *
13319 * \param - None
13320 *
13321 * \return - CONCURRENCY MODE
13322 *
13323 * --------------------------------------------------------------------------*/
13324tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
13325{
13326 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
13327 hdd_context_t *pHddCtx;
13328
13329 if (NULL != pVosContext)
13330 {
13331 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
13332 if (NULL != pHddCtx)
13333 {
13334 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
13335 }
13336 }
13337
13338 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070013339 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -070013340 return VOS_STA;
13341}
Sushant Kaushikabb7ee62014-07-18 16:20:12 +053013342v_BOOL_t
13343wlan_hdd_is_GO_power_collapse_allowed (hdd_context_t* pHddCtx)
13344{
13345 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -070013346
Sushant Kaushikabb7ee62014-07-18 16:20:12 +053013347 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_GO);
13348 if (pAdapter == NULL)
13349 {
13350 hddLog(VOS_TRACE_LEVEL_INFO,
13351 FL("GO doesn't exist"));
13352 return TRUE;
13353 }
13354 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
13355 {
13356 hddLog(VOS_TRACE_LEVEL_INFO,
13357 FL("GO started"));
13358 return TRUE;
13359 }
13360 else
13361 /* wait till GO changes its interface to p2p device */
13362 hddLog(VOS_TRACE_LEVEL_INFO,
13363 FL("Del_bss called, avoid apps suspend"));
13364 return FALSE;
13365
13366}
Jeff Johnson295189b2012-06-20 16:38:30 -070013367/* Decide whether to allow/not the apps power collapse.
13368 * Allow apps power collapse if we are in connected state.
13369 * if not, allow only if we are in IMPS */
13370v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
13371{
13372 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -080013373 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -080013374 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -070013375 hdd_config_t *pConfig = pHddCtx->cfg_ini;
13376 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
13377 hdd_adapter_t *pAdapter = NULL;
13378 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -080013379 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -070013380
Jeff Johnson295189b2012-06-20 16:38:30 -070013381 if (VOS_STA_SAP_MODE == hdd_get_conparam())
13382 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -070013383
Yathish9f22e662012-12-10 14:21:35 -080013384 concurrent_state = hdd_get_concurrency_mode();
13385
Sushant Kaushikabb7ee62014-07-18 16:20:12 +053013386 if ((concurrent_state == (VOS_STA | VOS_P2P_GO)) &&
13387 !(wlan_hdd_is_GO_power_collapse_allowed(pHddCtx)))
13388 return FALSE;
Yathish9f22e662012-12-10 14:21:35 -080013389#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
Sushant Kaushikabb7ee62014-07-18 16:20:12 +053013390
Yathish9f22e662012-12-10 14:21:35 -080013391 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
Sushant Kaushikabb7ee62014-07-18 16:20:12 +053013392 (concurrent_state == (VOS_STA | VOS_P2P_GO)))&&
Yathish9f22e662012-12-10 14:21:35 -080013393 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
13394 return TRUE;
13395#endif
13396
Jeff Johnson295189b2012-06-20 16:38:30 -070013397 /*loop through all adapters. TBD fix for Concurrency */
13398 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
13399 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
13400 {
13401 pAdapter = pAdapterNode->pAdapter;
13402 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
13403 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
13404 {
Srikant Kuppafef66a72013-01-30 17:32:44 -080013405 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
c_hpothu4e8faac2014-05-16 17:38:44 +053013406 && (pmcState != IMPS && pmcState != BMPS && pmcState != UAPSD
c_hpothu1c6957d2015-01-06 18:19:47 +053013407 && pmcState != STOPPED && pmcState != STANDBY &&
13408 pmcState != WOWL)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -080013409 (eANI_BOOLEAN_TRUE == scanRspPending) ||
13410 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -070013411 {
Mukul Sharma4be88422015-03-09 20:29:07 +053013412 if(pmcState == FULL_POWER &&
13413 sme_IsCoexScoIndicationSet(pHddCtx->hHal))
13414 {
13415 /*
13416 * When SCO indication comes from Coex module , host will
13417 * enter in to full power mode, but this should not prevent
13418 * apps processor power collapse.
13419 */
13420 hddLog(LOG1,
13421 FL("Allow apps power collapse"
13422 "even when sco indication is set"));
13423 return TRUE;
13424 }
Srikant Kuppafef66a72013-01-30 17:32:44 -080013425 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Deepthi Gowri03a979f2016-11-03 15:20:19 +053013426 "pmcState = %d scanRspPending = %d "
13427 "inMiddleOfRoaming = %d connected = %d",
13428 __func__, pmcState, scanRspPending,
13429 inMiddleOfRoaming, hdd_connIsConnected(
13430 WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )));
13431 wlan_hdd_get_tdls_stats(pAdapter);
13432 return FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -070013433 }
13434 }
13435 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
13436 pAdapterNode = pNext;
13437 }
13438 return TRUE;
13439}
13440
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -080013441/* Decides whether to send suspend notification to Riva
13442 * if any adapter is in BMPS; then it is required */
13443v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
13444{
13445 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
13446 hdd_config_t *pConfig = pHddCtx->cfg_ini;
13447
13448 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
13449 {
13450 return TRUE;
13451 }
13452 return FALSE;
13453}
13454
Jeff Johnson295189b2012-06-20 16:38:30 -070013455void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
13456{
13457 switch(mode)
13458 {
Chilam Ngc4244af2013-04-01 15:37:32 -070013459 case VOS_STA_MODE:
13460 case VOS_P2P_CLIENT_MODE:
13461 case VOS_P2P_GO_MODE:
13462 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -070013463 pHddCtx->concurrency_mode |= (1 << mode);
Agarwal Ashish51325b52014-06-16 16:50:49 +053013464 pHddCtx->no_of_open_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -070013465 break;
13466 default:
13467 break;
Jeff Johnson295189b2012-06-20 16:38:30 -070013468 }
Agarwal Ashish51325b52014-06-16 16:50:49 +053013469 hddLog(VOS_TRACE_LEVEL_INFO, FL("concurrency_mode = 0x%x "
13470 "Number of open sessions for mode %d = %d"),
13471 pHddCtx->concurrency_mode, mode,
13472 pHddCtx->no_of_open_sessions[mode]);
Jeff Johnson295189b2012-06-20 16:38:30 -070013473}
13474
13475
13476void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
13477{
13478 switch(mode)
13479 {
Chilam Ngc4244af2013-04-01 15:37:32 -070013480 case VOS_STA_MODE:
13481 case VOS_P2P_CLIENT_MODE:
13482 case VOS_P2P_GO_MODE:
13483 case VOS_STA_SAP_MODE:
Agarwal Ashish51325b52014-06-16 16:50:49 +053013484 pHddCtx->no_of_open_sessions[mode]--;
13485 if (!(pHddCtx->no_of_open_sessions[mode]))
13486 pHddCtx->concurrency_mode &= (~(1 << mode));
Jeff Johnson295189b2012-06-20 16:38:30 -070013487 break;
13488 default:
13489 break;
13490 }
Agarwal Ashish51325b52014-06-16 16:50:49 +053013491 hddLog(VOS_TRACE_LEVEL_INFO, FL("concurrency_mode = 0x%x "
13492 "Number of open sessions for mode %d = %d"),
13493 pHddCtx->concurrency_mode, mode, pHddCtx->no_of_open_sessions[mode]);
13494
13495}
13496/**---------------------------------------------------------------------------
13497 *
13498 * \brief wlan_hdd_incr_active_session()
13499 *
13500 * This function increments the number of active sessions
13501 * maintained per device mode
13502 * Incase of STA/P2P CLI/IBSS upon connection indication it is incremented
13503 * Incase of SAP/P2P GO upon bss start it is incremented
13504 *
13505 * \param pHddCtx - HDD Context
13506 * \param mode - device mode
13507 *
13508 * \return - None
13509 *
13510 * --------------------------------------------------------------------------*/
13511void wlan_hdd_incr_active_session(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
13512{
13513 switch (mode) {
13514 case VOS_STA_MODE:
13515 case VOS_P2P_CLIENT_MODE:
13516 case VOS_P2P_GO_MODE:
13517 case VOS_STA_SAP_MODE:
13518 pHddCtx->no_of_active_sessions[mode]++;
13519 break;
13520 default:
13521 hddLog(VOS_TRACE_LEVEL_INFO, FL("Not Expected Mode %d"), mode);
13522 break;
13523 }
13524 hddLog(VOS_TRACE_LEVEL_INFO, FL("No.# of active sessions for mode %d = %d"),
13525 mode,
13526 pHddCtx->no_of_active_sessions[mode]);
13527}
13528
13529/**---------------------------------------------------------------------------
13530 *
13531 * \brief wlan_hdd_decr_active_session()
13532 *
13533 * This function decrements the number of active sessions
13534 * maintained per device mode
13535 * Incase of STA/P2P CLI/IBSS upon disconnection it is decremented
13536 * Incase of SAP/P2P GO upon bss stop it is decremented
13537 *
13538 * \param pHddCtx - HDD Context
13539 * \param mode - device mode
13540 *
13541 * \return - None
13542 *
13543 * --------------------------------------------------------------------------*/
13544void wlan_hdd_decr_active_session(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
13545{
Bhargav Shahd0715912015-10-01 18:17:37 +053013546
Agarwal Ashish51325b52014-06-16 16:50:49 +053013547 switch (mode) {
13548 case VOS_STA_MODE:
13549 case VOS_P2P_CLIENT_MODE:
13550 case VOS_P2P_GO_MODE:
13551 case VOS_STA_SAP_MODE:
Agarwal Ashish5325f522014-08-06 00:58:44 +053013552 if (pHddCtx->no_of_active_sessions[mode] > 0)
13553 pHddCtx->no_of_active_sessions[mode]--;
13554 else
13555 hddLog(VOS_TRACE_LEVEL_INFO, FL(" No.# of Active sessions"
13556 "is already Zero"));
Agarwal Ashish51325b52014-06-16 16:50:49 +053013557 break;
13558 default:
13559 hddLog(VOS_TRACE_LEVEL_INFO, FL("Not Expected Mode %d"), mode);
13560 break;
13561 }
13562 hddLog(VOS_TRACE_LEVEL_INFO, FL("No.# of active sessions for mode %d = %d"),
13563 mode,
13564 pHddCtx->no_of_active_sessions[mode]);
Jeff Johnson295189b2012-06-20 16:38:30 -070013565}
13566
Jeff Johnsone7245742012-09-05 17:12:55 -070013567/**---------------------------------------------------------------------------
13568 *
13569 * \brief wlan_hdd_restart_init
13570 *
13571 * This function initalizes restart timer/flag. An internal function.
13572 *
13573 * \param - pHddCtx
13574 *
13575 * \return - None
13576 *
13577 * --------------------------------------------------------------------------*/
13578
13579static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
13580{
13581 /* Initialize */
13582 pHddCtx->hdd_restart_retries = 0;
13583 atomic_set(&pHddCtx->isRestartInProgress, 0);
13584 vos_timer_init(&pHddCtx->hdd_restart_timer,
13585 VOS_TIMER_TYPE_SW,
13586 wlan_hdd_restart_timer_cb,
13587 pHddCtx);
13588}
13589/**---------------------------------------------------------------------------
13590 *
13591 * \brief wlan_hdd_restart_deinit
13592 *
13593 * This function cleans up the resources used. An internal function.
13594 *
13595 * \param - pHddCtx
13596 *
13597 * \return - None
13598 *
13599 * --------------------------------------------------------------------------*/
13600
13601static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
13602{
13603
13604 VOS_STATUS vos_status;
13605 /* Block any further calls */
13606 atomic_set(&pHddCtx->isRestartInProgress, 1);
13607 /* Cleanup */
13608 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
13609 if (!VOS_IS_STATUS_SUCCESS(vos_status))
c_hpothu6ff1c3c2013-10-01 19:01:57 +053013610 hddLog(LOGE, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -070013611 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
13612 if (!VOS_IS_STATUS_SUCCESS(vos_status))
c_hpothu6ff1c3c2013-10-01 19:01:57 +053013613 hddLog(LOGE, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -070013614
13615}
13616
13617/**---------------------------------------------------------------------------
13618 *
13619 * \brief wlan_hdd_framework_restart
13620 *
13621 * This function uses a cfg80211 API to start a framework initiated WLAN
13622 * driver module unload/load.
13623 *
13624 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
13625 *
13626 *
13627 * \param - pHddCtx
13628 *
13629 * \return - VOS_STATUS_SUCCESS: Success
13630 * VOS_STATUS_E_EMPTY: Adapter is Empty
13631 * VOS_STATUS_E_NOMEM: No memory
13632
13633 * --------------------------------------------------------------------------*/
13634
13635static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
13636{
13637 VOS_STATUS status = VOS_STATUS_SUCCESS;
13638 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -070013639 int len = (sizeof (struct ieee80211_mgmt));
13640 struct ieee80211_mgmt *mgmt = NULL;
13641
13642 /* Prepare the DEAUTH managment frame with reason code */
13643 mgmt = kzalloc(len, GFP_KERNEL);
13644 if(mgmt == NULL)
13645 {
13646 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
13647 "%s: memory allocation failed (%d bytes)", __func__, len);
13648 return VOS_STATUS_E_NOMEM;
13649 }
13650 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -070013651
13652 /* Iterate over all adapters/devices */
13653 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Hanumantha Reddy Pothulada0fe362015-02-27 18:37:03 +053013654 if ((NULL == pAdapterNode) || (VOS_STATUS_SUCCESS != status))
13655 {
13656 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
13657 FL("fail to get adapter: %p %d"), pAdapterNode, status);
13658 goto end;
13659 }
13660
Jeff Johnsone7245742012-09-05 17:12:55 -070013661 do
13662 {
Hanumantha Reddy Pothulada0fe362015-02-27 18:37:03 +053013663 if(pAdapterNode->pAdapter &&
13664 WLAN_HDD_ADAPTER_MAGIC == pAdapterNode->pAdapter->magic)
Jeff Johnsone7245742012-09-05 17:12:55 -070013665 {
13666 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
13667 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
13668 pAdapterNode->pAdapter->dev->name,
13669 pAdapterNode->pAdapter->device_mode,
13670 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -070013671 /*
13672 * CFG80211 event to restart the driver
13673 *
13674 * 'cfg80211_send_unprot_deauth' sends a
13675 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
13676 * of SME(Linux Kernel) state machine.
13677 *
13678 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
13679 * the driver.
13680 *
13681 */
Abhishek Singh00b71972016-01-07 10:51:04 +053013682
Anand N Sunkade9adb1b2015-07-29 09:56:45 +053013683#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
13684 cfg80211_rx_unprot_mlme_mgmt(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len);
13685#else
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -070013686 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Anand N Sunkade9adb1b2015-07-29 09:56:45 +053013687#endif
Jeff Johnsone7245742012-09-05 17:12:55 -070013688 }
13689 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
13690 pAdapterNode = pNext;
13691 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
13692
Hanumantha Reddy Pothulada0fe362015-02-27 18:37:03 +053013693 end:
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -070013694 /* Free the allocated management frame */
13695 kfree(mgmt);
13696
Jeff Johnsone7245742012-09-05 17:12:55 -070013697 /* Retry until we unload or reach max count */
13698 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
13699 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
13700
13701 return status;
13702
13703}
13704/**---------------------------------------------------------------------------
13705 *
13706 * \brief wlan_hdd_restart_timer_cb
13707 *
13708 * Restart timer callback. An internal function.
13709 *
13710 * \param - User data:
13711 *
13712 * \return - None
13713 *
13714 * --------------------------------------------------------------------------*/
13715
13716void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
13717{
13718 hdd_context_t *pHddCtx = usrDataForCallback;
13719 wlan_hdd_framework_restart(pHddCtx);
13720 return;
13721
13722}
13723
13724
13725/**---------------------------------------------------------------------------
13726 *
13727 * \brief wlan_hdd_restart_driver
13728 *
13729 * This function sends an event to supplicant to restart the WLAN driver.
13730 *
13731 * This function is called from vos_wlanRestart.
13732 *
13733 * \param - pHddCtx
13734 *
13735 * \return - VOS_STATUS_SUCCESS: Success
13736 * VOS_STATUS_E_EMPTY: Adapter is Empty
13737 * VOS_STATUS_E_ALREADY: Request already in progress
13738
13739 * --------------------------------------------------------------------------*/
13740VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
13741{
13742 VOS_STATUS status = VOS_STATUS_SUCCESS;
13743
13744 /* A tight check to make sure reentrancy */
13745 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
13746 {
Mihir Shetefd528652014-06-23 19:07:50 +053013747 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnsone7245742012-09-05 17:12:55 -070013748 "%s: WLAN restart is already in progress", __func__);
13749
13750 return VOS_STATUS_E_ALREADY;
13751 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -070013752 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -080013753#ifdef HAVE_WCNSS_RESET_INTR
Siddharth Bhal864e7e82015-04-07 20:07:24 +053013754 wcnss_reset_fiq(TRUE);
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -070013755#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -070013756
Jeff Johnsone7245742012-09-05 17:12:55 -070013757 return status;
13758}
13759
Bhargav Shahd0715912015-10-01 18:17:37 +053013760/**
13761 * hdd_get_total_sessions() - provide total number of active sessions
13762 * @pHddCtx: Valid Global HDD context pointer
13763 *
13764 * This function iterates through pAdaptors and find the number of all active
13765 * sessions. This active sessions includes connected sta, p2p client and number
13766 * of client connected to sap/p2p go.
13767 *
13768 * Return: Total number of active sessions.
13769 */
13770v_U8_t hdd_get_total_sessions(hdd_context_t *pHddCtx)
13771{
13772 v_U8_t active_session = 0;
13773 hdd_station_ctx_t *pHddStaCtx;
13774 hdd_adapter_list_node_t *pAdapterNode, *pNext;
13775 hdd_adapter_t *pAdapter;
13776 VOS_STATUS status;
13777
13778 status = hdd_get_front_adapter(pHddCtx, &pAdapterNode);
13779 while (NULL != pAdapterNode && VOS_STATUS_SUCCESS == status) {
13780 pAdapter = pAdapterNode->pAdapter;
13781 switch (pAdapter->device_mode) {
13782 case VOS_STA_MODE:
13783 case VOS_P2P_CLIENT_MODE:
13784 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13785 if(eConnectionState_Associated == pHddStaCtx->conn_info.connState)
13786 active_session += 1;
13787 break;
13788 case VOS_STA_SAP_MODE:
13789 case VOS_P2P_GO_MODE:
13790 active_session += hdd_softap_get_connected_sta(pAdapter);
13791 break;
13792 default:
13793 break;
13794 }
13795
13796 status = hdd_get_next_adapter(pHddCtx, pAdapterNode, &pNext);
13797 pAdapterNode = pNext;
13798 }
13799
13800 return active_session;
13801}
13802
13803/**
13804 * hdd_set_delack_value() - Set delack value
13805 * @pHddCtx: Valid Global HDD context pointer
13806 * @next_rx_level: Value to set for delack
13807 *
13808 * This function compare present value and next value of delack. If the both
13809 * are diffrent then it sets next value .
13810 *
13811 * Return: void.
13812 */
13813void hdd_set_delack_value(hdd_context_t *pHddCtx, v_U32_t next_rx_level)
13814{
13815 if (pHddCtx->cur_rx_level != next_rx_level) {
13816 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_DEBUG,
13817 "%s: TCP DELACK trigger level %d",
13818 __func__, next_rx_level);
13819 mutex_lock(&pHddCtx->cur_rx_level_lock);
13820 pHddCtx->cur_rx_level = next_rx_level;
13821 mutex_unlock(&pHddCtx->cur_rx_level_lock);
13822 wlan_hdd_send_svc_nlink_msg(WLAN_SVC_WLAN_TP_IND, &next_rx_level,
13823 sizeof(next_rx_level));
13824 }
13825}
13826
13827/**
13828 * hdd_set_default_stop_delack_timer() - Start delack timer
13829 * @pHddCtx: Valid Global HDD context pointer
13830 *
13831 * This function stop delack timer and set delack value to default..
13832 *
13833 * Return: void.
13834 */
13835
13836void hdd_set_default_stop_delack_timer(hdd_context_t *pHddCtx)
13837{
13838 if (VOS_TIMER_STATE_RUNNING !=
13839 vos_timer_getCurrentState(&pHddCtx->delack_timer)) {
13840 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_DEBUG,
13841 "%s: Can not stop timer", __func__);
13842 return;
13843 }
13844
13845 vos_timer_stop(&pHddCtx->delack_timer);
13846 hdd_set_delack_value(pHddCtx, TP_IND_LOW);
13847}
13848
13849/**
13850 * hdd_start_delack_timer() - Start delack timer
13851 * @pHddCtx: Valid Global HDD context pointer
13852 *
13853 * This function starts the delack timer for tcpDelAckComputeInterval time
13854 * interval.The default timer value is 2 second.
13855 *
13856 * Return: void.
13857 */
13858void hdd_start_delack_timer(hdd_context_t *pHddCtx)
13859{
13860 if (VOS_TIMER_STATE_RUNNING ==
13861 vos_timer_getCurrentState(&pHddCtx->delack_timer)) {
13862 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_DEBUG,
13863 "%s: Timer is already running", __func__);
13864 return;
13865 }
13866
13867 vos_timer_start(&pHddCtx->delack_timer,
13868 pHddCtx->cfg_ini->tcpDelAckComputeInterval);
13869}
13870
13871/**
13872 * hdd_update_prev_rx_packet_count() - Update previous rx packet count
13873 * @pHddCtx: Valid Global HDD context pointer
13874 *
13875 * This function updates the prev_rx_packets count from the corresponding
13876 * pAdapter states. This prev_rx_packets will diffed with the packet count
13877 * at the end of delack timer. That can give number of RX packet is spacific
13878 * time.
13879 *
13880 * Return: void.
13881 */
13882void hdd_update_prev_rx_packet_count(hdd_context_t *pHddCtx)
13883{
13884 hdd_adapter_list_node_t *pAdapterNode, *pNext;
13885 hdd_adapter_t *pAdapter;
13886 VOS_STATUS status;
13887
13888 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
13889 while (NULL != pAdapterNode && VOS_STATUS_SUCCESS == status) {
13890 pAdapter = pAdapterNode->pAdapter;
13891 pAdapter->prev_rx_packets = pAdapter->stats.rx_packets;
13892 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
13893 pAdapterNode = pNext;
13894 }
13895}
13896
13897/**
13898 * hdd_manage_delack_timer() - start\stop delack timer
13899 * @pHddCtx: Valid Global HDD context pointer
13900 *
13901 * This function check the number of concerent session present, it starts the
13902 * delack timer if only one session is present.
13903 * In the case of BT_COEX and TDLS mode it blindly stop delack functionality.
13904 *
13905 * Return: void.
13906 */
13907void hdd_manage_delack_timer(hdd_context_t *pHddCtx)
13908{
13909 uint8_t sessions;
13910
13911 if (!pHddCtx->cfg_ini->enable_delack) {
13912 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_DEBUG,
13913 "%s: TCP DELACK is not enabled", __func__);
13914 return;
13915 }
13916
13917 /* Blindly stop timer of BTCOEX and TDLS Session is up */
13918 if (pHddCtx->mode != 0) {
13919 hdd_set_default_stop_delack_timer(pHddCtx);
13920 return;
13921 }
13922
13923 sessions = hdd_get_total_sessions(pHddCtx);
13924 if (sessions == 1) {
13925 hdd_update_prev_rx_packet_count(pHddCtx);
13926 hdd_start_delack_timer(pHddCtx);
13927 } else {
13928 hdd_set_default_stop_delack_timer(pHddCtx);
13929 }
13930}
13931
Mihir Shetee1093ba2014-01-21 20:13:32 +053013932/**---------------------------------------------------------------------------
13933 *
13934 * \brief wlan_hdd_init_channels
13935 *
13936 * This function is used to initialize the channel list in CSR
13937 *
13938 * This function is called from hdd_wlan_startup
13939 *
13940 * \param - pHddCtx: HDD context
13941 *
13942 * \return - VOS_STATUS_SUCCESS: Success
13943 * VOS_STATUS_E_FAULT: Failure reported by SME
13944
13945 * --------------------------------------------------------------------------*/
13946static VOS_STATUS wlan_hdd_init_channels(hdd_context_t *pHddCtx)
13947{
13948 eHalStatus status;
13949
13950 status = sme_InitChannels(pHddCtx->hHal);
13951 if (HAL_STATUS_SUCCESS(status))
13952 {
13953 return VOS_STATUS_SUCCESS;
13954 }
13955 else
13956 {
13957 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Channel initialization failed(%d)",
13958 __func__, status);
13959 return VOS_STATUS_E_FAULT;
13960 }
13961}
13962
Mihir Shete04206452014-11-20 17:50:58 +053013963#ifdef CONFIG_ENABLE_LINUX_REG
Agarwal Ashish6db9d532014-09-30 18:19:10 +053013964VOS_STATUS wlan_hdd_init_channels_for_cc(hdd_context_t *pHddCtx, driver_load_type init )
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053013965{
13966 eHalStatus status;
13967
Agarwal Ashish6db9d532014-09-30 18:19:10 +053013968 status = sme_InitChannelsForCC(pHddCtx->hHal, init);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053013969 if (HAL_STATUS_SUCCESS(status))
13970 {
13971 return VOS_STATUS_SUCCESS;
13972 }
13973 else
13974 {
13975 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Issue reg hint failed(%d)",
13976 __func__, status);
13977 return VOS_STATUS_E_FAULT;
13978 }
13979}
Mihir Shete04206452014-11-20 17:50:58 +053013980#endif
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -070013981/*
13982 * API to find if there is any STA or P2P-Client is connected
13983 */
13984VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
13985{
13986 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
13987}
Jeff Johnsone7245742012-09-05 17:12:55 -070013988
Mihir Shetee2ae82a2015-03-16 14:08:49 +053013989
13990/*
13991 * API to find if the firmware will send logs using DXE channel
13992 */
13993v_U8_t hdd_is_fw_logging_enabled(void)
13994{
13995 hdd_context_t *pHddCtx;
13996
13997 pHddCtx = vos_get_context(VOS_MODULE_ID_HDD,
13998 vos_get_global_context(VOS_MODULE_ID_HDD, NULL));
13999
Sachin Ahuja084313e2015-05-21 17:57:10 +053014000 return (pHddCtx && pHddCtx->cfg_ini->enableMgmtLogging);
Mihir Shetee2ae82a2015-03-16 14:08:49 +053014001}
14002
Agarwal Ashish57e84372014-12-05 18:26:53 +053014003/*
Mihir Shetebe94ebb2015-05-26 12:07:14 +053014004 * API to find if the firmware will send trace logs using DXE channel
14005 */
14006v_U8_t hdd_is_fw_ev_logging_enabled(void)
14007{
14008 hdd_context_t *pHddCtx;
14009
14010 pHddCtx = vos_get_context(VOS_MODULE_ID_HDD,
14011 vos_get_global_context(VOS_MODULE_ID_HDD, NULL));
14012
14013 return (pHddCtx && pHddCtx->cfg_ini->enableFWLogging);
14014}
14015/*
Agarwal Ashish57e84372014-12-05 18:26:53 +053014016 * API to find if there is any session connected
14017 */
14018VOS_STATUS hdd_is_any_session_connected(hdd_context_t *pHddCtx)
14019{
14020 return sme_is_any_session_connected(pHddCtx->hHal);
14021}
14022
14023
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053014024int wlan_hdd_scan_abort(hdd_adapter_t *pAdapter)
14025{
14026 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14027 hdd_scaninfo_t *pScanInfo = NULL;
Girish Gowli4bf7a632014-06-12 13:42:11 +053014028 long status = 0;
c_hpothua3d45d52015-01-05 14:11:17 +053014029 tSirAbortScanStatus abortScanStatus;
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053014030
14031 pScanInfo = &pHddCtx->scan_info;
Ratnam Rachuric7681132015-06-30 10:35:13 +053014032 INIT_COMPLETION(pScanInfo->abortscan_event_var);
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053014033 if (pScanInfo->mScanPending)
14034 {
c_hpothua3d45d52015-01-05 14:11:17 +053014035 abortScanStatus = hdd_abort_mac_scan(pHddCtx, pScanInfo->sessionId,
14036 eCSR_SCAN_ABORT_DEFAULT);
14037 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
14038 FL("abortScanStatus: %d"), abortScanStatus);
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053014039
c_hpothua3d45d52015-01-05 14:11:17 +053014040 /* If there is active scan command lets wait for the completion else
14041 * there is no need to wait as scan command might be in the SME pending
14042 * command list.
14043 */
14044 if (abortScanStatus == eSIR_ABORT_ACTIVE_SCAN_LIST_NOT_EMPTY)
14045 {
c_hpothua3d45d52015-01-05 14:11:17 +053014046 status = wait_for_completion_interruptible_timeout(
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053014047 &pScanInfo->abortscan_event_var,
14048 msecs_to_jiffies(5000));
c_hpothua3d45d52015-01-05 14:11:17 +053014049 if (0 >= status)
14050 {
14051 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Girish Gowli4bf7a632014-06-12 13:42:11 +053014052 "%s: Timeout or Interrupt occurred while waiting for abort"
14053 "scan, status- %ld", __func__, status);
c_hpothua3d45d52015-01-05 14:11:17 +053014054 return -ETIMEDOUT;
14055 }
14056 }
14057 else if (abortScanStatus == eSIR_ABORT_SCAN_FAILURE)
14058 {
14059 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
14060 FL("hdd_abort_mac_scan failed"));
14061 return -VOS_STATUS_E_FAILURE;
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053014062 }
14063 }
Girish Gowli4bf7a632014-06-12 13:42:11 +053014064 return 0;
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053014065}
14066
Abhishek Singh7d624e12015-11-30 14:29:27 +053014067/**
14068 * hdd_indicate_mgmt_frame() - Wrapper to indicate management frame to
14069 * user space
14070 * @frame_ind: Management frame data to be informed.
14071 *
14072 * This function is used to indicate management frame to
14073 * user space
14074 *
14075 * Return: None
14076 *
14077 */
14078void hdd_indicate_mgmt_frame(tSirSmeMgmtFrameInd *frame_ind)
14079{
14080 hdd_context_t *hdd_ctx = NULL;
14081 hdd_adapter_t *adapter = NULL;
14082 v_CONTEXT_t vos_context = NULL;
14083
14084 /* Get the global VOSS context.*/
14085 vos_context = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
14086 if (!vos_context) {
14087 hddLog(LOGE, FL("Global VOS context is Null"));
14088 return;
14089 }
14090 /* Get the HDD context.*/
14091 hdd_ctx =
14092 (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, vos_context );
14093
14094 if (0 != wlan_hdd_validate_context(hdd_ctx))
14095 {
14096 return;
14097 }
14098 adapter = hdd_get_adapter_by_sme_session_id(hdd_ctx,
14099 frame_ind->sessionId);
14100
14101 if ((NULL != adapter) &&
14102 (WLAN_HDD_ADAPTER_MAGIC == adapter->magic))
14103 __hdd_indicate_mgmt_frame(adapter,
14104 frame_ind->frameLen,
14105 frame_ind->frameBuf,
14106 frame_ind->frameType,
14107 frame_ind->rxChan,
14108 frame_ind->rxRssi);
14109 return;
14110
14111}
14112
c_hpothu225aa7c2014-10-22 17:45:13 +053014113VOS_STATUS wlan_hdd_cancel_remain_on_channel(hdd_context_t *pHddCtx)
14114{
14115 hdd_adapter_t *pAdapter;
14116 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
14117 VOS_STATUS vosStatus;
14118
14119 vosStatus = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
14120 while (NULL != pAdapterNode && VOS_STATUS_E_EMPTY != vosStatus)
14121 {
14122 pAdapter = pAdapterNode->pAdapter;
14123 if (NULL != pAdapter)
14124 {
14125 if (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode ||
14126 WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ||
14127 WLAN_HDD_P2P_GO == pAdapter->device_mode)
14128 {
14129 hddLog(LOG1, FL("abort ROC deviceMode: %d"),
14130 pAdapter->device_mode);
14131 if (VOS_STATUS_SUCCESS !=
14132 wlan_hdd_cancel_existing_remain_on_channel(pAdapter))
14133 {
14134 hddLog(LOGE, FL("failed to abort ROC"));
14135 return VOS_STATUS_E_FAILURE;
14136 }
14137 }
14138 }
14139 vosStatus = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
14140 pAdapterNode = pNext;
14141 }
14142 return VOS_STATUS_SUCCESS;
14143}
Mahesh A Saptasagard477b092015-02-06 15:12:16 +053014144
Mihir Shete0be28772015-02-17 18:42:14 +053014145hdd_remain_on_chan_ctx_t *hdd_get_remain_on_channel_ctx(hdd_context_t *pHddCtx)
14146{
14147 hdd_adapter_t *pAdapter;
14148 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
14149 hdd_cfg80211_state_t *cfgState;
14150 hdd_remain_on_chan_ctx_t *pRemainChanCtx = NULL;
14151 VOS_STATUS vosStatus;
14152
14153 vosStatus = hdd_get_front_adapter (pHddCtx, &pAdapterNode);
14154 while (NULL != pAdapterNode && VOS_STATUS_E_EMPTY != vosStatus)
14155 {
14156 pAdapter = pAdapterNode->pAdapter;
14157 if (NULL != pAdapter)
14158 {
14159 cfgState = WLAN_HDD_GET_CFG_STATE_PTR(pAdapter);
14160 pRemainChanCtx = cfgState->remain_on_chan_ctx;
14161 if (pRemainChanCtx)
14162 break;
14163 }
14164 vosStatus = hdd_get_next_adapter (pHddCtx, pAdapterNode, &pNext);
14165 pAdapterNode = pNext;
14166 }
14167 return pRemainChanCtx;
14168}
14169
Padma, Santhosh Kumar778d8382015-03-04 17:41:22 +053014170/**
14171 * wlan_hdd_handle_dfs_chan_scan () - handles disable/enable DFS channels
14172 *
14173 * @pHddCtx: HDD context within host driver
14174 * @dfsScanMode: dfsScanMode passed from ioctl
14175 *
14176 */
14177
14178VOS_STATUS wlan_hdd_handle_dfs_chan_scan(hdd_context_t *pHddCtx,
14179 tANI_U8 dfsScanMode)
14180{
14181 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
14182 hdd_adapter_t *pAdapter;
14183 VOS_STATUS vosStatus;
14184 hdd_station_ctx_t *pHddStaCtx;
14185 eHalStatus status = eHAL_STATUS_SUCCESS;
14186
14187 if(!pHddCtx)
14188 {
14189 hddLog(LOGE, FL("HDD context is Null"));
14190 return eHAL_STATUS_FAILURE;
14191 }
14192
14193 if (pHddCtx->scan_info.mScanPending)
14194 {
14195 hddLog(LOG1, FL("Aborting scan for sessionId: %d"),
14196 pHddCtx->scan_info.sessionId);
14197 hdd_abort_mac_scan(pHddCtx,
14198 pHddCtx->scan_info.sessionId,
14199 eCSR_SCAN_ABORT_DEFAULT);
14200 }
14201
14202 if (!dfsScanMode)
14203 {
14204 vosStatus = hdd_get_front_adapter( pHddCtx, &pAdapterNode);
14205 while ((NULL != pAdapterNode) &&
14206 (VOS_STATUS_SUCCESS == vosStatus))
14207 {
14208 pAdapter = pAdapterNode->pAdapter;
14209
14210 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
14211 {
14212 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14213
14214 if(!pHddStaCtx)
14215 {
14216 hddLog(LOGE, FL("HDD STA context is Null"));
14217 return eHAL_STATUS_FAILURE;
14218 }
14219
14220 /* if STA is already connected on DFS channel,
14221 disconnect immediately*/
14222 if (hdd_connIsConnected(pHddStaCtx) &&
14223 (NV_CHANNEL_DFS ==
14224 vos_nv_getChannelEnabledState(
14225 pHddStaCtx->conn_info.operationChannel)))
14226 {
14227 status = sme_RoamDisconnect(pHddCtx->hHal,
14228 pAdapter->sessionId,
14229 eCSR_DISCONNECT_REASON_UNSPECIFIED);
14230 hddLog(LOG1, FL("Client connected on DFS channel %d,"
14231 "sme_RoamDisconnect returned with status: %d"
14232 "for sessionid: %d"), pHddStaCtx->conn_info.
14233 operationChannel, status, pAdapter->sessionId);
14234 }
14235 }
14236
14237 vosStatus = hdd_get_next_adapter(pHddCtx, pAdapterNode,
14238 &pNext);
14239 pAdapterNode = pNext;
14240 }
14241 }
14242
14243 sme_UpdateDFSScanMode(pHddCtx->hHal, dfsScanMode);
14244 sme_UpdateDFSRoamMode(pHddCtx->hHal,
14245 (dfsScanMode != DFS_CHNL_SCAN_DISABLED));
14246
14247 status = sme_HandleDFSChanScan(pHddCtx->hHal);
14248 if (!HAL_STATUS_SUCCESS(status))
14249 {
14250 hddLog(LOGE,
14251 FL("Failed in sme_HandleDFSChanScan (err=%d)"), status);
14252 return status;
14253 }
14254
14255 return status;
14256}
14257
Nirav Shah7e3c8132015-06-22 23:51:42 +053014258static int hdd_log2_ceil(unsigned value)
14259{
14260 /* need to switch to unsigned math so that negative values
14261 * will right-shift towards 0 instead of -1
14262 */
14263 unsigned tmp = value;
14264 int log2 = -1;
14265
14266 if (value == 0)
14267 return 0;
14268
14269 while (tmp) {
14270 log2++;
14271 tmp >>= 1;
14272 }
14273 if (1U << log2 != value)
14274 log2++;
14275
14276 return log2;
14277}
14278
14279/**
14280 * hdd_sta_id_hash_attach() - initialize sta id to macaddr hash
14281 * @pAdapter: adapter handle
14282 *
14283 * Return: vos status
14284 */
14285VOS_STATUS hdd_sta_id_hash_attach(hdd_adapter_t *pAdapter)
14286{
14287 int hash_elem, log2, i;
14288
14289 spin_lock_bh( &pAdapter->sta_hash_lock);
14290 if (pAdapter->is_sta_id_hash_initialized == VOS_TRUE) {
14291 spin_unlock_bh( &pAdapter->sta_hash_lock);
14292 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
14293 "%s: hash already attached for session id %d",
14294 __func__, pAdapter->sessionId);
14295 return VOS_STATUS_SUCCESS;
14296 }
14297 spin_unlock_bh( &pAdapter->sta_hash_lock);
14298
14299 hash_elem = WLAN_MAX_STA_COUNT;
14300 hash_elem *= HDD_STA_ID_HASH_MULTIPLIER;
14301 log2 = hdd_log2_ceil(hash_elem);
14302 hash_elem = 1 << log2;
14303
14304 pAdapter->sta_id_hash.mask = hash_elem - 1;
14305 pAdapter->sta_id_hash.idx_bits = log2;
14306 pAdapter->sta_id_hash.bins =
14307 vos_mem_malloc(hash_elem *sizeof(hdd_list_t));
14308 if (!pAdapter->sta_id_hash.bins) {
14309 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
14310 "%s: malloc failed for session %d",
14311 __func__, pAdapter->sessionId);
14312 return VOS_STATUS_E_NOMEM;
14313 }
14314
14315 for (i = 0; i < hash_elem; i++)
14316 hdd_list_init(&pAdapter->sta_id_hash.bins[i], WLAN_MAX_STA_COUNT);
14317
14318 spin_lock_bh( &pAdapter->sta_hash_lock);
14319 pAdapter->is_sta_id_hash_initialized = VOS_TRUE;
14320 spin_unlock_bh( &pAdapter->sta_hash_lock);
14321 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
14322 "%s: Station ID Hash attached for session id %d",
14323 __func__, pAdapter->sessionId);
14324
14325 return VOS_STATUS_SUCCESS;
14326}
14327
14328/**
14329 * hdd_sta_id_hash_detach() - deinit sta_id to macaddr hash
14330 * @pAdapter: adapter handle
14331 *
14332 * Return: vos status
14333 */
14334VOS_STATUS hdd_sta_id_hash_detach(hdd_adapter_t *pAdapter)
14335{
14336 int hash_elem, i;
14337 v_SIZE_t size;
14338
14339 spin_lock_bh( &pAdapter->sta_hash_lock);
14340 if (pAdapter->is_sta_id_hash_initialized != VOS_TRUE) {
14341 spin_unlock_bh( &pAdapter->sta_hash_lock);
14342 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
14343 "%s: hash not initialized for session id %d",
14344 __func__, pAdapter->sessionId);
14345 return VOS_STATUS_SUCCESS;
14346 }
14347
14348 pAdapter->is_sta_id_hash_initialized = VOS_FALSE;
14349 spin_unlock_bh( &pAdapter->sta_hash_lock);
14350
14351 hash_elem = 1 << pAdapter->sta_id_hash.idx_bits;
14352
14353 /* free all station info*/
14354 for (i = 0; i < hash_elem; i++) {
14355 hdd_list_size(&pAdapter->sta_id_hash.bins[i], &size);
14356 if (size != 0) {
14357 VOS_STATUS status;
14358 hdd_staid_hash_node_t *sta_info_node = NULL;
14359 hdd_staid_hash_node_t *next_node = NULL;
14360 status = hdd_list_peek_front ( &pAdapter->sta_id_hash.bins[i],
14361 (hdd_list_node_t**) &sta_info_node );
14362
14363 while ( NULL != sta_info_node && VOS_STATUS_SUCCESS == status )
14364 {
14365 status = hdd_list_remove_node( &pAdapter->sta_id_hash.bins[i],
14366 &sta_info_node->node);
14367 vos_mem_free(sta_info_node);
14368
14369 status = hdd_list_peek_next (&pAdapter->sta_id_hash.bins[i],
14370 (hdd_list_node_t*)sta_info_node,
14371 (hdd_list_node_t**)&next_node);
14372 sta_info_node = next_node;
14373 }
14374 }
14375 }
14376
14377 vos_mem_free(pAdapter->sta_id_hash.bins);
14378 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
14379 "%s: Station ID Hash detached for session id %d",
14380 __func__, pAdapter->sessionId);
14381 return VOS_STATUS_SUCCESS;
14382}
14383
14384/**
14385 * hdd_sta_id_hash_calculate_index() - derive index from macaddr
14386 * @pAdapter: adapter handle
14387 * @mac_addr_in: input mac address
14388 *
14389 * Return: index derived from mac address
14390 */
14391int hdd_sta_id_hash_calculate_index(hdd_adapter_t *pAdapter,
14392 v_MACADDR_t *mac_addr_in)
14393{
14394 uint16 index;
14395 struct hdd_align_mac_addr_t * mac_addr =
14396 (struct hdd_align_mac_addr_t *)mac_addr_in;
14397
14398 index = mac_addr->bytes_ab ^
14399 mac_addr->bytes_cd ^ mac_addr->bytes_ef;
14400 index ^= index >> pAdapter->sta_id_hash.idx_bits;
14401 index &= pAdapter->sta_id_hash.mask;
14402 return index;
14403}
14404
14405/**
14406 * hdd_sta_id_hash_add_entry() - add entry in hash
14407 * @pAdapter: adapter handle
14408 * @sta_id: station id
14409 * @mac_addr: mac address
14410 *
14411 * Return: vos status
14412 */
14413VOS_STATUS hdd_sta_id_hash_add_entry(hdd_adapter_t *pAdapter,
14414 v_U8_t sta_id, v_MACADDR_t *mac_addr)
14415{
14416 uint16 index;
14417 hdd_staid_hash_node_t *sta_info_node = NULL;
14418
Nirav Shah7e3c8132015-06-22 23:51:42 +053014419 index = hdd_sta_id_hash_calculate_index(pAdapter, mac_addr);
14420 sta_info_node = vos_mem_malloc(sizeof(hdd_staid_hash_node_t));
14421 if (!sta_info_node) {
Nirav Shah7e3c8132015-06-22 23:51:42 +053014422 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
14423 "%s: malloc failed", __func__);
14424 return VOS_STATUS_E_NOMEM;
14425 }
14426
14427 sta_info_node->sta_id = sta_id;
14428 vos_mem_copy(&sta_info_node->mac_addr, mac_addr, sizeof(v_MACADDR_t));
14429
Nirav Shah303ed5c2015-08-24 10:29:25 +053014430 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_mem_free(sta_info_node);
14434 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
14435 "%s: hash is not initialized for session id %d",
14436 __func__, pAdapter->sessionId);
14437 return VOS_STATUS_E_FAILURE;
14438 }
14439
Nirav Shah7e3c8132015-06-22 23:51:42 +053014440 hdd_list_insert_back ( &pAdapter->sta_id_hash.bins[index],
14441 (hdd_list_node_t*) sta_info_node );
14442 spin_unlock_bh( &pAdapter->sta_hash_lock);
14443 return VOS_STATUS_SUCCESS;
14444}
14445
14446/**
14447 * hdd_sta_id_hash_remove_entry() - remove entry from hash
14448 * @pAdapter: adapter handle
14449 * @sta_id: station id
14450 * @mac_addr: mac address
14451 *
14452 * Return: vos status
14453 */
14454VOS_STATUS hdd_sta_id_hash_remove_entry(hdd_adapter_t *pAdapter,
14455 v_U8_t sta_id, v_MACADDR_t *mac_addr)
14456{
14457 uint16 index;
14458 VOS_STATUS status;
14459 hdd_staid_hash_node_t *sta_info_node = NULL;
14460 hdd_staid_hash_node_t *next_node = NULL;
14461
14462 spin_lock_bh( &pAdapter->sta_hash_lock);
14463 if (pAdapter->is_sta_id_hash_initialized != VOS_TRUE) {
14464 spin_unlock_bh( &pAdapter->sta_hash_lock);
14465 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
14466 "%s: hash is not initialized for session id %d",
14467 __func__, pAdapter->sessionId);
14468 return VOS_STATUS_E_FAILURE;
14469 }
14470
14471 index = hdd_sta_id_hash_calculate_index(pAdapter, mac_addr);
14472 status = hdd_list_peek_front ( &pAdapter->sta_id_hash.bins[index],
14473 (hdd_list_node_t**) &sta_info_node );
14474
14475 while ( NULL != sta_info_node && VOS_STATUS_SUCCESS == status )
14476 {
14477 if (sta_info_node->sta_id == sta_id) {
14478 status = hdd_list_remove_node( &pAdapter->sta_id_hash.bins[index],
14479 &sta_info_node->node);
14480 vos_mem_free(sta_info_node);
14481 break;
14482 }
14483 status = hdd_list_peek_next (&pAdapter->sta_id_hash.bins[index],
14484 (hdd_list_node_t*)sta_info_node, (hdd_list_node_t**)&next_node);
14485 sta_info_node = next_node;
14486 }
14487 spin_unlock_bh( &pAdapter->sta_hash_lock);
14488 return status;
14489}
14490
14491/**
14492 * hdd_sta_id_find_from_mac_addr() - find sta id from mac address
14493 * @pAdapter: adapter handle
14494 * @mac_addr_in: mac address
14495 *
14496 * Return: station id
14497 */
14498int hdd_sta_id_find_from_mac_addr(hdd_adapter_t *pAdapter,
14499 v_MACADDR_t *mac_addr_in)
14500{
14501 uint8 is_found = 0;
14502 uint8 sta_id = HDD_WLAN_INVALID_STA_ID;
14503 uint16 index;
14504 VOS_STATUS status;
14505 hdd_staid_hash_node_t *sta_info_node = NULL;
14506 hdd_staid_hash_node_t *next_node = NULL;
14507
14508 spin_lock_bh( &pAdapter->sta_hash_lock);
14509 if (pAdapter->is_sta_id_hash_initialized != VOS_TRUE) {
14510 spin_unlock_bh( &pAdapter->sta_hash_lock);
Bhargav Shahce3b32c2015-08-10 12:29:24 +053014511 hddLog(VOS_TRACE_LEVEL_INFO,
Nirav Shah7e3c8132015-06-22 23:51:42 +053014512 FL("hash is not initialized for session id %d"),
14513 pAdapter->sessionId);
14514 return HDD_WLAN_INVALID_STA_ID;
14515 }
14516
14517 index = hdd_sta_id_hash_calculate_index(pAdapter, mac_addr_in);
14518 status = hdd_list_peek_front ( &pAdapter->sta_id_hash.bins[index],
14519 (hdd_list_node_t**) &sta_info_node );
14520
14521 while ( NULL != sta_info_node && VOS_STATUS_SUCCESS == status )
14522 {
14523 if (vos_mem_compare(&sta_info_node->mac_addr,
14524 mac_addr_in, sizeof(v_MACADDR_t))) {
14525 is_found = 1;
14526 sta_id = sta_info_node->sta_id;
14527 break;
14528 }
14529 status = hdd_list_peek_next (&pAdapter->sta_id_hash.bins[index],
14530 (hdd_list_node_t*)sta_info_node,
14531 (hdd_list_node_t**)&next_node);
14532 sta_info_node = next_node;
14533 }
14534 spin_unlock_bh( &pAdapter->sta_hash_lock);
14535 return sta_id;
14536}
14537
c_manjeecfd1efb2015-09-25 19:32:34 +053014538/*FW memory dump feature*/
14539/**
14540 * This structure hold information about the /proc file
14541 *
14542 */
14543static struct proc_dir_entry *proc_file, *proc_dir;
14544
14545/**
14546 * memdump_read() - perform read operation in memory dump proc file
14547 *
14548 * @file - handle for the proc file.
14549 * @buf - pointer to user space buffer.
14550 * @count - number of bytes to be read.
14551 * @pos - offset in the from buffer.
14552 *
14553 * This function performs read operation for the memory dump proc file.
14554 *
14555 * Return: number of bytes read on success, error code otherwise.
14556 */
14557static ssize_t memdump_read(struct file *file, char __user *buf,
14558 size_t count, loff_t *pos)
14559{
14560 int status;
14561 hdd_context_t *hdd_ctx = (hdd_context_t *)PDE_DATA(file_inode(file));
14562 size_t ret_count;
c_manjeef1495642015-10-13 18:35:01 +053014563 loff_t bytes_left;
c_manjeecfd1efb2015-09-25 19:32:34 +053014564 ENTER();
14565
14566 hddLog(LOG1, FL("Read req for size:%zu pos:%llu"), count, *pos);
14567 status = wlan_hdd_validate_context(hdd_ctx);
14568 if (0 != status) {
14569 return -EINVAL;
14570 }
14571
14572 if (!wlan_fwr_mem_dump_test_and_set_read_allowed_bit()) {
14573 hddLog(LOGE, FL("Current mem dump request timed out/failed"));
14574 return -EINVAL;
14575 }
14576
14577 /* run fs_read_handler in an atomic context*/
14578 vos_ssr_protect(__func__);
c_manjeef1495642015-10-13 18:35:01 +053014579 ret_count = wlan_fwr_mem_dump_fsread_handler( buf, count, pos, &bytes_left);
14580 if(bytes_left == 0)
c_manjeecfd1efb2015-09-25 19:32:34 +053014581 {
14582 /*Free the fwr mem dump buffer */
14583 wlan_free_fwr_mem_dump_buffer();
14584 wlan_set_fwr_mem_dump_state(FW_MEM_DUMP_IDLE);
c_manjeef1495642015-10-13 18:35:01 +053014585 ret_count=0;
c_manjeecfd1efb2015-09-25 19:32:34 +053014586 }
14587 /*if SSR/unload code is waiting for memdump_read to finish,signal it*/
14588 vos_ssr_unprotect(__func__);
14589 EXIT();
14590 return ret_count;
14591}
14592
14593/**
14594 * struct memdump_fops - file operations for memory dump feature
14595 * @read - read function for memory dump operation.
14596 *
14597 * This structure initialize the file operation handle for memory
14598 * dump feature
14599 */
14600static const struct file_operations memdump_fops = {
14601 read: memdump_read
14602};
14603
14604/*
14605* wlan_hdd_fw_mem_dump_cb : callback for Fw mem dump request
14606* To be passed by HDD to WDA and called upon receiving of response
14607* from firmware
14608* @fwMemDumpReqContext : memory dump request context
14609* @dump_rsp : dump response from HAL
14610* Returns none
14611*/
14612void wlan_hdd_fw_mem_dump_cb(void *fwMemDumpReqContext,
14613 tAniFwrDumpRsp *dump_rsp)
14614{
c_manjeef1495642015-10-13 18:35:01 +053014615 struct hdd_fw_mem_dump_req_ctx *pHddFwMemDumpCtx = (struct hdd_fw_mem_dump_req_ctx *)fwMemDumpReqContext;
c_manjeecfd1efb2015-09-25 19:32:34 +053014616
c_manjeef1495642015-10-13 18:35:01 +053014617 ENTER();
14618 spin_lock(&hdd_context_lock);
14619 if(!pHddFwMemDumpCtx || (FW_MEM_DUMP_MAGIC != pHddFwMemDumpCtx->magic)) {
14620 spin_unlock(&hdd_context_lock);
14621 return;
14622 }
14623 /* report the status to requesting function and free mem.*/
c_manjeecfd1efb2015-09-25 19:32:34 +053014624 if (dump_rsp->dump_status != eHAL_STATUS_SUCCESS) {
c_manjeef1495642015-10-13 18:35:01 +053014625 hddLog(LOGE, FL("fw dump request declined by fwr"));
14626 //set the request completion variable
14627 complete(&(pHddFwMemDumpCtx->req_completion));
c_manjeecfd1efb2015-09-25 19:32:34 +053014628 //Free the allocated fwr dump
14629 wlan_free_fwr_mem_dump_buffer();
14630 wlan_set_fwr_mem_dump_state(FW_MEM_DUMP_IDLE);
c_manjeecfd1efb2015-09-25 19:32:34 +053014631 }
c_manjeef1495642015-10-13 18:35:01 +053014632 else {
14633 hddLog(LOG1, FL("fw dump request accepted by fwr"));
14634 /* register the HDD callback which will be called by SVC */
14635 wlan_set_svc_fw_mem_dump_req_cb((void*)wlan_hdd_fw_mem_dump_req_cb,(void*)pHddFwMemDumpCtx);
14636 }
14637 spin_unlock(&hdd_context_lock);
c_manjeecfd1efb2015-09-25 19:32:34 +053014638 EXIT();
14639
14640}
14641
14642/**
14643 * memdump_procfs_remove() - Remove file/dir under procfs for memory dump
14644 *
14645 * This function removes file/dir under proc file system that was
14646 * processing firmware memory dump
14647 *
14648 * Return: None
14649 */
14650static void memdump_procfs_remove(void)
14651{
14652 remove_proc_entry(PROCFS_MEMDUMP_NAME, proc_dir);
14653 hddLog(LOG1 , FL("/proc/%s/%s removed\n"),
14654 PROCFS_MEMDUMP_DIR, PROCFS_MEMDUMP_NAME);
14655 remove_proc_entry(PROCFS_MEMDUMP_DIR, NULL);
14656 hddLog(LOG1 , FL("/proc/%s removed\n"), PROCFS_MEMDUMP_DIR);
14657}
14658
14659/**
14660 * memdump_procfs_init() - Initialize procfs for memory dump
14661 *
14662 * @vos_ctx - Global vos context.
14663 *
14664 * This function create file under proc file system to be used later for
14665 * processing firmware memory dump
14666 *
14667 * Return: 0 on success, error code otherwise.
14668 */
14669static int memdump_procfs_init(void *vos_ctx)
14670{
14671 hdd_context_t *hdd_ctx;
14672
14673 hdd_ctx = vos_get_context(VOS_MODULE_ID_HDD, vos_ctx);
14674 if (!hdd_ctx) {
14675 hddLog(LOGE , FL("Invalid HDD context"));
14676 return -EINVAL;
14677 }
14678
14679 proc_dir = proc_mkdir(PROCFS_MEMDUMP_DIR, NULL);
14680 if (proc_dir == NULL) {
14681 remove_proc_entry(PROCFS_MEMDUMP_DIR, NULL);
14682 hddLog(LOGE , FL("Error: Could not initialize /proc/%s"),
14683 PROCFS_MEMDUMP_DIR);
14684 return -ENOMEM;
14685 }
14686
14687 proc_file = proc_create_data(PROCFS_MEMDUMP_NAME,
14688 S_IRUSR | S_IWUSR, proc_dir,
14689 &memdump_fops, hdd_ctx);
14690 if (proc_file == NULL) {
14691 remove_proc_entry(PROCFS_MEMDUMP_NAME, proc_dir);
14692 hddLog(LOGE , FL("Error: Could not initialize /proc/%s"),
14693 PROCFS_MEMDUMP_NAME);
14694 return -ENOMEM;
14695 }
14696
14697 hddLog(LOG1 , FL("/proc/%s/%s created"),
14698 PROCFS_MEMDUMP_DIR, PROCFS_MEMDUMP_NAME);
14699
14700 return 0;
14701}
14702
14703/**
14704 * memdump_init() - Initialization function for memory dump feature
14705 *
14706 * This function creates proc file for memdump feature and registers
14707 * HDD callback function with SME.
14708 *
14709 * Return - 0 on success, error otherwise
14710 */
14711int memdump_init(void)
14712{
14713 hdd_context_t *hdd_ctx;
14714 void *vos_ctx;
14715 int status = 0;
14716
14717 vos_ctx = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
14718 if (!vos_ctx) {
14719 hddLog(LOGE, FL("Invalid VOS context"));
14720 return -EINVAL;
14721 }
14722
14723 hdd_ctx = vos_get_context(VOS_MODULE_ID_HDD, vos_ctx);
14724 if (!hdd_ctx) {
14725 hddLog(LOGE , FL("Invalid HDD context"));
14726 return -EINVAL;
14727 }
14728
14729 status = memdump_procfs_init(vos_ctx);
14730 if (status) {
14731 hddLog(LOGE , FL("Failed to create proc file"));
14732 return status;
14733 }
14734
14735 return 0;
14736}
14737
14738/**
14739 * memdump_deinit() - De initialize memdump feature
14740 *
14741 * This function removes proc file created for memdump feature.
14742 *
14743 * Return: None
14744 */
14745int memdump_deinit(void)
14746{
14747 hdd_context_t *hdd_ctx;
14748 void *vos_ctx;
14749
14750 vos_ctx = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
14751 if (!vos_ctx) {
14752 hddLog(LOGE, FL("Invalid VOS context"));
14753 return -EINVAL;
14754 }
14755
14756 hdd_ctx = vos_get_context(VOS_MODULE_ID_HDD, vos_ctx);
14757 if(!hdd_ctx) {
14758 hddLog(LOGE , FL("Invalid HDD context"));
14759 return -EINVAL;
14760 }
14761
14762 memdump_procfs_remove();
14763 return 0;
14764}
14765
14766/**
14767 * wlan_hdd_fw_mem_dump_req(pHddCtx) - common API(cfg80211/ioctl) for requesting fw mem dump to SME
14768 * Return: HAL status
14769 */
14770
14771int wlan_hdd_fw_mem_dump_req(hdd_context_t * pHddCtx)
14772{
14773 tAniFwrDumpReq fw_mem_dump_req={0};
c_manjeef1495642015-10-13 18:35:01 +053014774 struct hdd_fw_mem_dump_req_ctx fw_mem_dump_ctx;
c_manjeecfd1efb2015-09-25 19:32:34 +053014775 eHalStatus status = eHAL_STATUS_FAILURE;
Abhishek Singh4eca9822015-12-09 18:07:34 +053014776 int ret=0, result;
c_manjeecfd1efb2015-09-25 19:32:34 +053014777 ENTER();
c_manjeef1495642015-10-13 18:35:01 +053014778
c_manjeecfd1efb2015-09-25 19:32:34 +053014779 /*Check whether a dump request is already going on
14780 *Caution this function will free previously held memory if new dump request is allowed*/
14781 if (!wlan_fwr_mem_dump_test_and_set_write_allowed_bit()) {
14782 hddLog(LOGE, FL("Fw memdump already in progress"));
14783 return -EBUSY;
14784 }
14785 //Allocate memory for fw mem dump buffer
14786 ret = wlan_fwr_mem_dump_buffer_allocation();
14787 if(ret == -EFAULT)
14788 {
14789 hddLog(LOGE, FL("Fwr mem dump not supported by FW"));
14790 return ret;
14791 }
14792 if (0 != ret) {
14793 hddLog(LOGE, FL("Fwr mem Allocation failed"));
14794 return -ENOMEM;
14795 }
c_manjeef1495642015-10-13 18:35:01 +053014796 init_completion(&fw_mem_dump_ctx.req_completion);
14797 fw_mem_dump_ctx.magic = FW_MEM_DUMP_MAGIC;
14798 fw_mem_dump_ctx.status = false;
14799
c_manjeecfd1efb2015-09-25 19:32:34 +053014800 fw_mem_dump_req.fwMemDumpReqCallback = wlan_hdd_fw_mem_dump_cb;
c_manjeef1495642015-10-13 18:35:01 +053014801 fw_mem_dump_req.fwMemDumpReqContext = &fw_mem_dump_ctx;
c_manjeecfd1efb2015-09-25 19:32:34 +053014802 status = sme_FwMemDumpReq(pHddCtx->hHal, &fw_mem_dump_req);
14803 if(eHAL_STATUS_SUCCESS != status)
14804 {
14805 hddLog(VOS_TRACE_LEVEL_ERROR,
14806 "%s: fw_mem_dump_req failed ", __func__);
14807 wlan_free_fwr_mem_dump_buffer();
c_manjeef1495642015-10-13 18:35:01 +053014808 ret = -EFAULT;
14809 goto cleanup;
c_manjeecfd1efb2015-09-25 19:32:34 +053014810 }
c_manjeef1495642015-10-13 18:35:01 +053014811 /*wait for fw mem dump completion to send event to userspace*/
Abhishek Singh4eca9822015-12-09 18:07:34 +053014812 result =
14813 wait_for_completion_timeout(&fw_mem_dump_ctx.req_completion,
14814 msecs_to_jiffies(FW_MEM_DUMP_TIMEOUT_MS));
14815 if (0 >= result )
c_manjeef1495642015-10-13 18:35:01 +053014816 {
14817 hddLog(VOS_TRACE_LEVEL_ERROR,
Abhishek Singh4eca9822015-12-09 18:07:34 +053014818 "%s: fw_mem_dump_req timeout %d ", __func__,result);
14819 ret = -ETIMEDOUT;
c_manjeef1495642015-10-13 18:35:01 +053014820 }
14821cleanup:
14822 spin_lock(&hdd_context_lock);
14823 fw_mem_dump_ctx.magic = 0;
Abhishek Singh4eca9822015-12-09 18:07:34 +053014824 if(!ret && !fw_mem_dump_ctx.status)
14825 ret = -EFAULT;
c_manjeef1495642015-10-13 18:35:01 +053014826 spin_unlock(&hdd_context_lock);
c_manjeecfd1efb2015-09-25 19:32:34 +053014827
c_manjeef1495642015-10-13 18:35:01 +053014828 EXIT();
Abhishek Singh4eca9822015-12-09 18:07:34 +053014829 return ret;
c_manjeef1495642015-10-13 18:35:01 +053014830}
14831
14832/**
14833 * HDD callback which will be called by SVC to indicate mem dump completion.
14834 */
14835void wlan_hdd_fw_mem_dump_req_cb(struct hdd_fw_mem_dump_req_ctx* pHddFwMemDumpCtx)
14836{
14837 if (!pHddFwMemDumpCtx) {
14838 hddLog(VOS_TRACE_LEVEL_ERROR,
14839 "%s: HDD context not valid ", __func__);
14840 return;
14841 }
14842 spin_lock(&hdd_context_lock);
14843 /* check the req magic and set status */
14844 if (pHddFwMemDumpCtx->magic == FW_MEM_DUMP_MAGIC)
14845 {
14846 pHddFwMemDumpCtx->status = true;
14847 //signal the completion
14848 complete(&(pHddFwMemDumpCtx->req_completion));
14849 }
14850 else
14851 {
14852 hddLog(VOS_TRACE_LEVEL_ERROR,
14853 "%s: fw mem dump request possible timeout ", __func__);
14854 }
14855 spin_unlock(&hdd_context_lock);
c_manjeecfd1efb2015-09-25 19:32:34 +053014856}
14857
Mahesh A Saptasagar67ab9222015-10-21 15:38:41 +053014858void hdd_initialize_adapter_common(hdd_adapter_t *pAdapter)
14859{
14860 if (NULL == pAdapter)
14861 {
14862 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: pAdapter is NULL ", __func__);
14863 return;
14864 }
14865 init_completion(&pAdapter->session_open_comp_var);
14866 init_completion(&pAdapter->session_close_comp_var);
14867 init_completion(&pAdapter->disconnect_comp_var);
14868 init_completion(&pAdapter->linkup_event_var);
14869 init_completion(&pAdapter->cancel_rem_on_chan_var);
14870 init_completion(&pAdapter->rem_on_chan_ready_event);
14871 init_completion(&pAdapter->pno_comp_var);
14872#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
14873 init_completion(&pAdapter->offchannel_tx_event);
14874#endif
14875 init_completion(&pAdapter->tx_action_cnf_event);
14876#ifdef FEATURE_WLAN_TDLS
14877 init_completion(&pAdapter->tdls_add_station_comp);
14878 init_completion(&pAdapter->tdls_del_station_comp);
14879 init_completion(&pAdapter->tdls_mgmt_comp);
14880 init_completion(&pAdapter->tdls_link_establish_req_comp);
14881#endif
14882
14883#ifdef WLAN_FEATURE_RMC
14884 init_completion(&pAdapter->ibss_peer_info_comp);
14885#endif /* WLAN_FEATURE_RMC */
14886 init_completion(&pAdapter->ula_complete);
14887 init_completion(&pAdapter->change_country_code);
14888
14889#ifdef FEATURE_WLAN_BATCH_SCAN
14890 init_completion(&pAdapter->hdd_set_batch_scan_req_var);
14891 init_completion(&pAdapter->hdd_get_batch_scan_req_var);
14892#endif
Kapil Gupta2b44acb2016-12-30 16:49:51 +053014893 init_completion(&pAdapter->wlan_suspend_comp_var);
Mahesh A Saptasagar67ab9222015-10-21 15:38:41 +053014894
14895 return;
14896}
c_manjeecfd1efb2015-09-25 19:32:34 +053014897
Anurag Chouhan0b29de02016-12-16 13:18:40 +053014898#ifdef MDNS_OFFLOAD
14899
14900/**
14901 * hdd_mdns_enable_offload_done() - mdns enable offload response api
14902 * @padapter: holds adapter
14903 * @status: response status
14904 *
14905 * Return - None
14906 */
14907void hdd_mdns_enable_offload_done(void *padapter, VOS_STATUS status)
14908{
14909 hdd_adapter_t* adapter = (hdd_adapter_t*) padapter;
14910
14911 ENTER();
14912
14913 if (NULL == adapter)
14914 {
14915 hddLog(VOS_TRACE_LEVEL_ERROR,
14916 "%s: adapter is NULL",__func__);
14917 return;
14918 }
14919
14920 adapter->mdns_status.mdns_enable_status = status;
14921 vos_event_set(&adapter->mdns_status.vos_event);
14922 return;
14923}
14924
14925/**
14926 * hdd_mdns_fqdn_offload_done() - mdns fqdn offload response api
14927 * @padapter: holds adapter
14928 * @status: responce status
14929 *
14930 * Return - None
14931 */
14932void hdd_mdns_fqdn_offload_done(void *padapter, VOS_STATUS status)
14933{
14934 hdd_adapter_t* adapter = (hdd_adapter_t*) padapter;
14935
14936 ENTER();
14937
14938 if (NULL == adapter)
14939 {
14940 hddLog(VOS_TRACE_LEVEL_ERROR,
14941 "%s: adapter is NULL",__func__);
14942 return;
14943 }
14944
14945 adapter->mdns_status.mdns_fqdn_status = status;
14946 return;
14947}
14948
14949/**
14950 * hdd_mdns_resp_offload_done() - mdns resp offload response api
14951 * @padapter: holds adapter
14952 * @status: responce status
14953 *
14954 * Return - None
14955 */
14956void hdd_mdns_resp_offload_done(void *padapter, VOS_STATUS status)
14957{
14958 hdd_adapter_t* adapter = (hdd_adapter_t*) padapter;
14959
14960 ENTER();
14961
14962 if (NULL == adapter)
14963 {
14964 hddLog(VOS_TRACE_LEVEL_ERROR,
14965 "%s: adapter is NULL",__func__);
14966 return;
14967 }
14968
14969 adapter->mdns_status.mdns_resp_status = status;
14970 return;
14971}
14972
14973/**
14974 * wlan_hdd_mdns_process_response_dname() - Process mDNS domain name
14975 * @response: Pointer to a struct hdd_mdns_resp_info
14976 * @resp_info: Pointer to a struct tSirMDNSResponseInfo
14977 *
14978 * This function will pack the whole domain name without compression. It will
14979 * add the leading len for each field and add zero length octet to terminate
14980 * the domain name.
14981 *
14982 * Return: Return boolean. TRUE for success, FALSE for fail.
14983 */
14984static bool
14985wlan_hdd_mdns_process_response_dname(struct hdd_mdns_resp_info *response,
14986 sir_mdns_resp_info resp_info)
14987{
14988 uint8_t num;
14989 uint16_t idx;
14990 uint8_t len = 0;
14991
14992 if ((response == NULL) || (response->data == NULL) ||
14993 (response->offset == NULL)) {
14994 hddLog(LOGE, FL("Either data or offset in response is NULL!"));
14995 return FALSE;
14996 }
14997
14998 if ((resp_info == NULL) ||
14999 (resp_info->resp_len >= MAX_MDNS_RESP_LEN)) {
15000 hddLog(LOGE, FL("resp_len exceeds %d!"), MAX_MDNS_RESP_LEN);
15001 return FALSE;
15002 }
15003
15004 for (num = 0; num < response->num_entries; num++) {
15005 response->offset[num] =
15006 resp_info->resp_len + MDNS_HEADER_LEN;
15007 idx = num * MAX_LEN_DOMAINNAME_FIELD;
15008 len = strlen((char *)&response->data[idx]);
15009 if ((resp_info->resp_len + len + 1) >= MAX_MDNS_RESP_LEN) {
15010 hddLog(LOGE, FL("resp_len exceeds %d!"),
15011 MAX_MDNS_RESP_LEN);
15012 return FALSE;
15013 }
15014 resp_info->resp_data[resp_info->resp_len] = len;
15015 resp_info->resp_len++;
15016 vos_mem_copy(&resp_info->resp_data[resp_info->resp_len],
15017 &response->data[idx], len);
15018 resp_info->resp_len += len;
15019 }
15020
15021 /* The domain name terminates with the zero length octet */
15022 if (num == response->num_entries) {
15023 if (resp_info->resp_len >= MAX_MDNS_RESP_LEN) {
15024 hddLog(LOGE, FL("resp_len exceeds %d!"),
15025 MAX_MDNS_RESP_LEN);
15026 return FALSE;
15027 }
15028 resp_info->resp_data[resp_info->resp_len] = 0;
15029 resp_info->resp_len++;
15030 }
15031
15032 return TRUE;
15033}
15034
15035/**
15036 * wlan_hdd_mdns_format_response_u16() - Form uint16_t response data
15037 * @value: The uint16_t value is formed to the struct tSirMDNSResponseInfo
15038 * @resp_info: Pointer to a struct tSirMDNSResponseInfo
15039 *
15040 * Return: None
15041 */
15042static void wlan_hdd_mdns_format_response_u16(uint16_t value,
15043 sir_mdns_resp_info resp_info)
15044{
15045 uint8_t val_u8;
15046
15047 if ((resp_info == NULL) || (resp_info->resp_data == NULL))
15048 return;
15049 val_u8 = (value & 0xff00) >> 8;
15050 resp_info->resp_data[resp_info->resp_len++] = val_u8;
15051 val_u8 = value & 0xff;
15052 resp_info->resp_data[resp_info->resp_len++] = val_u8;
15053}
15054
15055/**
15056 * wlan_hdd_mdns_format_response_u32() - Form uint32_t response data
15057 * @value: The uint32_t value is formed to the struct tSirMDNSResponseInfo
15058 * @resp_info: Pointer to a struct tSirMDNSResponseInfo
15059 *
15060 * Return: None
15061 */
15062static void wlan_hdd_mdns_format_response_u32(uint32_t value,
15063 sir_mdns_resp_info resp_info)
15064{
15065 uint8_t val_u8;
15066
15067 if ((resp_info == NULL) || (resp_info->resp_data == NULL))
15068 return;
15069 val_u8 = (value & 0xff000000) >> 24;
15070 resp_info->resp_data[resp_info->resp_len++] = val_u8;
15071 val_u8 = (value & 0xff0000) >> 16;
15072 resp_info->resp_data[resp_info->resp_len++] = val_u8;
15073 val_u8 = (value & 0xff00) >> 8;
15074 resp_info->resp_data[resp_info->resp_len++] = val_u8;
15075 val_u8 = value & 0xff;
15076 resp_info->resp_data[resp_info->resp_len++] = val_u8;
15077}
15078
15079/**
15080 * wlan_hdd_mdns_process_response_misc() - Process misc info in mDNS response
15081 * @resp_type: Response type for mDNS
15082 * @resp_info: Pointer to a struct tSirMDNSResponseInfo
15083 *
15084 * This function will pack the response type, class and TTL (Time To Live).
15085 *
15086 * Return: Return boolean. TRUE for success, FALSE for fail.
15087 */
15088static bool wlan_hdd_mdns_process_response_misc(uint16_t resp_type,
15089 sir_mdns_resp_info resp_info)
15090{
15091 uint16_t len;
15092
15093 if (resp_info == NULL) {
15094 hddLog(LOGE, FL("resp_info is NULL!"));
15095 return FALSE;
15096 }
15097
15098 len = resp_info->resp_len + (2 * sizeof(uint16_t) + sizeof(uint32_t));
15099 if (len >= MAX_MDNS_RESP_LEN) {
15100 hddLog(LOGE, FL("resp_len exceeds %d!"), MAX_MDNS_RESP_LEN);
15101 return FALSE;
15102 }
15103
15104 /* Fill Type, Class, TTL */
15105 wlan_hdd_mdns_format_response_u16(resp_type, resp_info);
15106 wlan_hdd_mdns_format_response_u16(MDNS_CLASS, resp_info);
15107 wlan_hdd_mdns_format_response_u32(MDNS_TTL, resp_info);
15108
15109 return TRUE;
15110}
15111
15112/**
15113 * wlan_hdd_mdns_compress_data() - Compress the domain name in mDNS response
15114 * @resp_info: Pointer to a struct tSirMDNSResponseInfo
15115 * @response_dst: The response which domain name is compressed.
15116 * @response_src: The response which domain name is matched with response_dst.
15117 * Its offset is used for data compression.
15118 * @num_matched: The number of matched entries between response_dst and
15119 * response_src
15120 *
15121 * This function will form the different fields of domain name in response_dst
15122 * if any. Then use the offset of the matched domain name in response_src to
15123 * compress the matched domain name.
15124 *
15125 * Return: Return boolean. TRUE for success, FALSE for fail.
15126 */
15127static bool
15128wlan_hdd_mdns_compress_data(sir_mdns_resp_info resp_info,
15129 struct hdd_mdns_resp_info *response_dst,
15130 struct hdd_mdns_resp_info *response_src,
15131 uint8_t num_matched)
15132{
15133 uint8_t num, num_diff;
15134 uint16_t value, idx;
15135 uint8_t len = 0;
15136
15137 if ((response_src == NULL) || (response_dst == NULL) ||
15138 (resp_info == NULL)) {
15139 hddLog(LOGE, FL("response info is NULL!"));
15140 return FALSE;
15141 }
15142
15143 if (response_dst->num_entries < num_matched) {
15144 hddLog(LOGE, FL("num_entries is less than num_matched!"));
15145 return FALSE;
15146 }
15147
15148 if (resp_info->resp_len >= MAX_MDNS_RESP_LEN) {
15149 hddLog(LOGE, FL("resp_len exceeds %d!"), MAX_MDNS_RESP_LEN);
15150 return FALSE;
15151 }
15152
15153 num_diff = response_dst->num_entries - num_matched;
15154 if ((num_diff > 0) && (response_dst->data == NULL)) {
15155 hddLog(LOGE, FL("response_dst->data is NULL!"));
15156 return FALSE;
15157 }
15158
15159 /*
15160 * Handle the unmatched string at the beginning
15161 * Store the length of octets and the octets
15162 */
15163 for (num = 0; num < num_diff; num++) {
15164 response_dst->offset[num] =
15165 resp_info->resp_len + MDNS_HEADER_LEN;
15166 idx = num * MAX_LEN_DOMAINNAME_FIELD;
15167 len = strlen((char *)&response_dst->data[idx]);
15168 if ((resp_info->resp_len + len + 1) >= MAX_MDNS_RESP_LEN) {
15169 hddLog(LOGE, FL("resp_len exceeds %d!"),
15170 MAX_MDNS_RESP_LEN);
15171 return FALSE;
15172 }
15173 resp_info->resp_data[resp_info->resp_len] = len;
15174 resp_info->resp_len++;
15175 vos_mem_copy(&resp_info->resp_data[resp_info->resp_len],
15176 &response_dst->data[idx], len);
15177 resp_info->resp_len += len;
15178 }
15179 /*
15180 * Handle the matched string from the end
15181 * Just keep the offset and mask the leading two bit
15182 */
15183 if (response_src->num_entries >= num_matched) {
15184 num_diff = response_src->num_entries - num_matched;
15185 value = response_src->offset[num_diff];
15186 if (value > 0) {
15187 value |= 0xc000;
15188 if ((resp_info->resp_len + sizeof(uint16_t)) >=
15189 MAX_MDNS_RESP_LEN) {
15190 hddLog(LOGE, FL("resp_len exceeds %d!"),
15191 MAX_MDNS_RESP_LEN);
15192 return FALSE;
15193 }
15194 wlan_hdd_mdns_format_response_u16(value, resp_info);
15195 return TRUE;
15196 }
15197 }
15198 return FALSE;
15199}
15200
15201/**
15202 * wlan_hdd_mdns_reset_response() - Reset the response info
15203 * @response: The response which info is reset.
15204 *
15205 * Return: None
15206 */
15207static void wlan_hdd_mdns_reset_response(struct hdd_mdns_resp_info *response)
15208{
15209 if (response == NULL)
15210 return;
15211 response->num_entries = 0;
15212 response->data = NULL;
15213 response->offset = NULL;
15214}
15215
15216/**
15217 * wlan_hdd_mdns_init_response() - Initialize the response info
15218 * @response: The response which info is initiatized.
15219 * @resp_dname: The domain name string which might be tokenized.
15220 *
15221 * This function will allocate the memory for both response->data and
15222 * response->offset. Besides, it will also tokenize the domain name to some
15223 * entries and fill response->num_entries with the num of entries.
15224 *
15225 * Return: Return boolean. TRUE for success, FALSE for fail.
15226 */
15227static bool wlan_hdd_mdns_init_response(struct hdd_mdns_resp_info *response,
15228 uint8_t *resp_dname, char separator)
15229{
15230 uint16_t size;
15231
15232 if ((resp_dname == NULL) || (response == NULL)) {
15233 hddLog(LOGE, FL("resp_dname or response is NULL!"));
15234 return FALSE;
15235 }
15236
15237 size = MAX_NUM_FIELD_DOMAINNAME * MAX_LEN_DOMAINNAME_FIELD;
15238 response->data = vos_mem_malloc(size);
15239 if (response->data) {
15240 vos_mem_zero(response->data, size);
15241 if (VOS_STATUS_SUCCESS !=
15242 hdd_string_to_string_array((char *)resp_dname,
15243 response->data,
15244 separator,
15245 &response->num_entries,
15246 MAX_NUM_FIELD_DOMAINNAME,
15247 MAX_LEN_DOMAINNAME_FIELD)) {
15248 hddLog(LOGE, FL("hdd_string_to_string_array fail!"));
15249 goto err_init_resp;
15250 }
15251
15252 if ((response->num_entries > 0) &&
15253 (strlen((char *)&response->data[0]) > 0)) {
15254 size = sizeof(uint16_t) * response->num_entries;
15255 response->offset = vos_mem_malloc(size);
15256 if (response->offset) {
15257 vos_mem_zero(response->offset, size);
15258 return TRUE;
15259 }
15260 }
15261 }
15262
15263err_init_resp:
15264 if (response->data)
15265 vos_mem_free(response->data);
15266 wlan_hdd_mdns_reset_response(response);
15267 return FALSE;
15268}
15269
15270/**
15271 * wlan_hdd_mdns_find_entries_from_end() - Find the matched entries
15272 * @response1: The response info is used to be compared.
15273 * @response2: The response info is used to be compared.
15274 *
15275 * This function will find the matched entries from the end.
15276 *
15277 * Return: Return the number of the matched entries.
15278 */
15279static uint8_t
15280wlan_hdd_mdns_find_entries_from_end(struct hdd_mdns_resp_info *response1,
15281 struct hdd_mdns_resp_info *response2)
15282{
15283 uint8_t min, len1, i;
15284 uint16_t num1, num2;
15285 uint8_t num_matched = 0;
15286
15287 min = VOS_MIN(response1->num_entries, response2->num_entries);
15288
15289 for (i = 1; i <= min; i++) {
15290 num1 = (response1->num_entries - i);
15291 num1 *= MAX_LEN_DOMAINNAME_FIELD;
15292 num2 = (response2->num_entries - i);
15293 num2 *= MAX_LEN_DOMAINNAME_FIELD;
15294 len1 = strlen((char *)&response1->data[num1]);
15295
15296 if ((len1 == 0) ||
15297 (len1 != strlen((char *)&response2->data[num2])))
15298 break;
15299 if (memcmp(&response1->data[num1],
15300 &response2->data[num2], len1))
15301 break;
15302 else
15303 num_matched++;
15304 }
15305
15306 return num_matched;
15307}
15308
15309/**
15310 * wlan_hdd_mdns_find_max() - Find the maximum number of the matched entries
15311 * @matchedlist: Pointer to the array of struct hdd_mdns_resp_matched
15312 * @numlist: The number of the elements in the array matchedlist.
15313 *
15314 * Find the max number of the matched entries among the array matchedlist.
15315 *
15316 * Return: None
15317 */
15318static void wlan_hdd_mdns_find_max(struct hdd_mdns_resp_matched *matchedlist,
15319 uint8_t numlist)
15320{
15321 int j;
15322 struct hdd_mdns_resp_matched tmp;
15323
15324 /* At least two values are used for sorting */
15325 if ((numlist < 2) || (matchedlist == NULL)) {
15326 hddLog(LOGE, FL("At least two values are used for sorting!"));
15327 return;
15328 }
15329
15330 for (j = 0; j < numlist-1; j++) {
15331 if (matchedlist[j].num_matched >
15332 matchedlist[j+1].num_matched) {
15333 vos_mem_copy(&tmp, &matchedlist[j],
15334 sizeof(struct hdd_mdns_resp_matched));
15335 vos_mem_copy(&matchedlist[j], &matchedlist[j+1],
15336 sizeof(struct hdd_mdns_resp_matched));
15337 vos_mem_copy(&matchedlist[j+1], &tmp,
15338 sizeof(struct hdd_mdns_resp_matched));
15339 }
15340 }
15341}
15342
15343/**
15344 * wlan_hdd_mdns_pack_response_type_a() - Pack Type A response
15345 * @ini_config: Pointer to the struct hdd_config_t
15346 * @resp_info: Pointer to the struct tSirMDNSResponseInfo
15347 * @resptype_a: Pointer to the struct hdd_mdns_resp_info of Type A
15348 *
15349 * Type A response include QName, response type, class, TTL and Ipv4.
15350 *
15351 * Return: Return boolean. TRUE for success, FALSE for fail.
15352 */
15353static bool
15354wlan_hdd_mdns_pack_response_type_a(hdd_config_t *ini_config,
15355 sir_mdns_resp_info resp_info,
15356 struct hdd_mdns_resp_info *resptype_a)
15357{
15358 uint16_t value;
15359 uint32_t len;
15360
15361 ENTER();
15362 if ((ini_config == NULL) || (resp_info == NULL) ||
15363 (resptype_a == NULL)) {
15364 hddLog(LOGE, FL("ini_config or response info is NULL!"));
15365 return FALSE;
15366 }
15367
15368 /* No Type A response */
15369 if (strlen((char *)ini_config->mdns_resp_type_a) <= 0)
15370 return TRUE;
15371
15372 /* Wrong response is assigned, just ignore this response */
15373 if (!wlan_hdd_mdns_init_response(resptype_a,
15374 ini_config->mdns_resp_type_a, '.'))
15375 return TRUE;
15376
15377 /* Process response domain name */
15378 if (!wlan_hdd_mdns_process_response_dname(resptype_a, resp_info)) {
15379 hddLog(LOGE, FL("Fail to process mDNS response (%d)!"),
15380 MDNS_TYPE_A);
15381 return FALSE;
15382 }
15383
15384 /* Process response Type, Class, TTL */
15385 if (!wlan_hdd_mdns_process_response_misc(MDNS_TYPE_A, resp_info)) {
15386 hddLog(LOGE, FL("Fail to process mDNS misc response (%d)!"),
15387 MDNS_TYPE_A);
15388 return FALSE;
15389 }
15390
15391 /* Process response RDLength, RData */
15392 len = sizeof(uint16_t) + sizeof(uint32_t);
15393 len += resp_info->resp_len;
15394 if (len >= MAX_MDNS_RESP_LEN) {
15395 hddLog(LOGE, FL("resp_len exceeds %d!"), MAX_MDNS_RESP_LEN);
15396 return FALSE;
15397 }
15398 value = sizeof(uint32_t);
15399 wlan_hdd_mdns_format_response_u16(value, resp_info);
15400 wlan_hdd_mdns_format_response_u32(ini_config->mdns_resp_type_a_ipv4,
15401 resp_info);
15402
15403 EXIT();
15404 return TRUE;
15405}
15406
15407/**
15408 * wlan_hdd_mdns_pack_response_type_txt() - Pack Type Txt response
15409 * @ini_config: Pointer to the struct hdd_config_t
15410 * @resp_info: Pointer to the struct tSirMDNSResponseInfo
15411 * @resptype_txt: Pointer to the struct hdd_mdns_resp_info of Type txt
15412 * @resptype_a: Pointer to the struct hdd_mdns_resp_info of Type A
15413 *
15414 * Type Txt response include QName, response type, class, TTL and text content.
15415 * Also, it will find the matched QName from resptype_A and compress the data.
15416 *
15417 * Return: Return boolean. TRUE for success, FALSE for fail.
15418 */
15419static bool
15420wlan_hdd_mdns_pack_response_type_txt(hdd_config_t *ini_config,
15421 sir_mdns_resp_info resp_info,
15422 struct hdd_mdns_resp_info *resptype_txt,
15423 struct hdd_mdns_resp_info *resptype_a)
15424{
15425 uint8_t num_matched;
15426 uint8_t num;
15427 uint16_t idx;
15428 uint16_t value = 0;
15429 uint32_t len;
15430 uint32_t total_len;
15431 bool status;
15432 struct hdd_mdns_resp_info resptype_content;
15433
15434 ENTER();
15435
15436 if ((ini_config == NULL) || (resp_info == NULL) ||
15437 (resptype_txt == NULL)) {
15438 hddLog(LOGE, FL("ini_config or response info is NULL!"));
15439 return FALSE;
15440 }
15441
15442 /* No Type Txt response */
15443 if (strlen((char *)ini_config->mdns_resp_type_txt) <= 0)
15444 return TRUE;
15445
15446 /* Wrong response is assigned, just ignore this response */
15447 if (!wlan_hdd_mdns_init_response(resptype_txt,
15448 ini_config->mdns_resp_type_txt, '.'))
15449 return TRUE;
15450
15451 /*
15452 * For data compression
15453 * Check if any strings are matched with Type A response
15454 */
15455 if (resptype_a && (resptype_a->num_entries > 0)) {
15456 num_matched = wlan_hdd_mdns_find_entries_from_end(resptype_txt,
15457 resptype_a);
15458 if (num_matched > 0) {
15459 if (!wlan_hdd_mdns_compress_data(resp_info,
15460 resptype_txt, resptype_a, num_matched)) {
15461 hddLog(LOGE, FL("Fail to compress mDNS "
15462 "response (%d)!"), MDNS_TYPE_TXT);
15463 return FALSE;
15464 }
15465 } else {
15466 /*
15467 * num_matched is zero. Error!
15468 * At least ".local" is needed.
15469 */
15470 hddLog(LOGE, FL("No matched string! Fail to pack mDNS "
15471 "response (%d)!"), MDNS_TYPE_TXT);
15472 return FALSE;
15473 }
15474 } else {
15475 /* no TypeA response, so show the whole data */
15476 if (!wlan_hdd_mdns_process_response_dname(resptype_txt,
15477 resp_info)) {
15478 hddLog(LOGE, FL("Fail to process mDNS response (%d)!"),
15479 MDNS_TYPE_TXT);
15480 return FALSE;
15481 }
15482 }
15483
15484 /* Process response Type, Class, TTL */
15485 if (!wlan_hdd_mdns_process_response_misc(MDNS_TYPE_TXT, resp_info)) {
15486 hddLog(LOGE, FL("Fail to process mDNS misc response (%d)!"),
15487 MDNS_TYPE_TXT);
15488 return FALSE;
15489 }
15490
15491 /*
15492 * Process response RDLength, RData.
15493 * TypeTxt RData include len.
15494 */
15495 status = wlan_hdd_mdns_init_response(&resptype_content,
15496 ini_config->mdns_resp_type_txt_content,
15497 '/');
15498 if (status == FALSE) {
15499 hddLog(LOGE, FL("wlan_hdd_mdns_init_response FAIL"));
15500 return FALSE;
15501 }
15502
15503 for (num = 0; num < resptype_content.num_entries; num++) {
15504 idx = num * MAX_LEN_DOMAINNAME_FIELD;
15505 value += strlen((char *)&resptype_content.data[idx]);
15506 }
15507
15508 /* content len is uint16_t */
15509 total_len = sizeof(uint16_t);
15510 total_len += resp_info->resp_len + value +
15511 resptype_content.num_entries;
15512
15513 if (total_len >= MAX_MDNS_RESP_LEN) {
15514 hddLog(LOGE, FL("resp_len exceeds %d!"), MAX_MDNS_RESP_LEN);
15515 return FALSE;
15516 }
15517 wlan_hdd_mdns_format_response_u16(value + resptype_content.num_entries,
15518 resp_info);
15519
15520 for (num = 0; num < resptype_content.num_entries; num++) {
15521 idx = num * MAX_LEN_DOMAINNAME_FIELD;
15522 len = strlen((char *)&resptype_content.data[idx]);
15523 resp_info->resp_data[resp_info->resp_len] = len;
15524 resp_info->resp_len++;
15525
15526 vos_mem_copy(&resp_info->resp_data[resp_info->resp_len],
15527 &resptype_content.data[idx], len);
15528
15529 resp_info->resp_len += len;
15530 hddLog(LOG1, FL("index = %d, len = %d, str = %s"),
15531 num, len, &resptype_content.data[idx]);
15532 }
15533
15534 EXIT();
15535 return TRUE;
15536}
15537
15538/**
15539 * wlan_hdd_mdns_pack_response_type_ptr_dname() - Pack Type PTR domain name
15540 * @ini_config: Pointer to the struct hdd_config_t
15541 * @resp_info: Pointer to the struct tSirMDNSResponseInfo
15542 * @resptype_ptr_dn: Pointer to the struct hdd_mdns_resp_info of Type Ptr
15543 * domain name
15544 * @resptype_ptr: Pointer to the struct hdd_mdns_resp_info of Type Ptr
15545 * @resptype_txt: Pointer to the struct hdd_mdns_resp_info of Type Txt
15546 * @resptype_a: Pointer to the struct hdd_mdns_resp_info of Type A
15547 *
15548 * The Type Ptr response include Type PTR domain name in its data field.
15549 * Also, it will find the matched QName from the existing resptype_ptr,
15550 * resptype_txt, resptype_a and then compress the data.
15551 *
15552 * Return: Return boolean. TRUE for success, FALSE for fail.
15553 */
15554static bool
15555wlan_hdd_mdns_pack_response_type_ptr_dname(hdd_config_t *ini_config,
15556 sir_mdns_resp_info resp_info,
15557 struct hdd_mdns_resp_info *resptype_ptr_dn,
15558 struct hdd_mdns_resp_info *resptype_ptr,
15559 struct hdd_mdns_resp_info *resptype_txt,
15560 struct hdd_mdns_resp_info *resptype_a)
15561{
15562 uint8_t num_matched, numlist, size;
15563 struct hdd_mdns_resp_matched matchedlist[MAX_MDNS_RESP_TYPE-1];
15564 struct hdd_mdns_resp_info *resp;
15565
15566 if ((ini_config == NULL) || (resp_info == NULL) ||
15567 (resptype_ptr == NULL) || (resptype_ptr_dn == NULL)) {
15568 hddLog(LOGE, FL("ini_config or response info is NULL!"));
15569 return FALSE;
15570 }
15571
15572 /* No Type Ptr domain name response */
15573 if (strlen((char *)ini_config->mdns_resp_type_ptr_dname) <= 0)
15574 return TRUE;
15575
15576 /* Wrong response is assigned, just ignore this response */
15577 if (!wlan_hdd_mdns_init_response(resptype_ptr_dn,
15578 ini_config->mdns_resp_type_ptr_dname, '.'))
15579 return TRUE;
15580
15581 /*
15582 * For data compression
15583 * Check if any strings are matched with previous
15584 * response.
15585 */
15586 numlist = 0;
15587 size = (MAX_MDNS_RESP_TYPE-1);
15588 size *= sizeof(struct hdd_mdns_resp_matched);
15589 vos_mem_zero(matchedlist, size);
15590 num_matched = wlan_hdd_mdns_find_entries_from_end(resptype_ptr_dn,
15591 resptype_ptr);
15592 if (num_matched > 0) {
15593 matchedlist[numlist].num_matched = num_matched;
15594 matchedlist[numlist].type = MDNS_TYPE_PTR;
15595 numlist++;
15596 }
15597 if (resptype_txt && (resptype_txt->num_entries > 0)) {
15598 num_matched = wlan_hdd_mdns_find_entries_from_end(
15599 resptype_ptr_dn, resptype_txt);
15600 if (num_matched > 0) {
15601 matchedlist[numlist].num_matched = num_matched;
15602 matchedlist[numlist].type = MDNS_TYPE_TXT;
15603 numlist++;
15604 }
15605 }
15606 if (resptype_a && (resptype_a->num_entries > 0)) {
15607 num_matched = wlan_hdd_mdns_find_entries_from_end(
15608 resptype_ptr_dn,resptype_a);
15609 if (num_matched > 0) {
15610 matchedlist[numlist].num_matched = num_matched;
15611 matchedlist[numlist].type = MDNS_TYPE_A;
15612 numlist++;
15613 }
15614 }
15615 if (numlist > 0) {
15616 if (numlist > 1)
15617 wlan_hdd_mdns_find_max(matchedlist, numlist);
15618 resp = NULL;
15619 switch (matchedlist[numlist-1].type) {
15620 case MDNS_TYPE_A:
15621 resp = resptype_a;
15622 break;
15623 case MDNS_TYPE_TXT:
15624 resp = resptype_txt;
15625 break;
15626 case MDNS_TYPE_PTR:
15627 resp = resptype_ptr;
15628 break;
15629 default:
15630 hddLog(LOGE, FL("Fail to compress mDNS response "
15631 "(%d)!"), MDNS_TYPE_PTR_DNAME);
15632 return FALSE;
15633 }
15634 num_matched = matchedlist[numlist-1].num_matched;
15635 if (!wlan_hdd_mdns_compress_data(resp_info, resptype_ptr_dn,
15636 resp, num_matched)) {
15637 hddLog(LOGE, FL("Fail to compress mDNS response "
15638 "(%d)!"), MDNS_TYPE_PTR_DNAME);
15639 return FALSE;
15640 }
15641 } else {
15642 /* num = 0 -> no matched string */
15643 if (!wlan_hdd_mdns_process_response_dname(resptype_ptr_dn,
15644 resp_info)) {
15645 hddLog(LOGE, FL("Fail to process mDNS response (%d)!"),
15646 MDNS_TYPE_PTR_DNAME);
15647 return FALSE;
15648 }
15649 }
15650
15651 return TRUE;
15652}
15653
15654/**
15655 * wlan_hdd_mdns_pack_response_type_ptr() - Pack Type PTR response
15656 * @ini_config: Pointer to the struct hdd_config_t
15657 * @resp_info: Pointer to the struct tSirMDNSResponseInfo
15658 * @resptype_ptr: Pointer to the struct hdd_mdns_resp_info of Type Ptr
15659 * @resptype_ptr_dn: Pointer to the struct hdd_mdns_resp_info of Type Ptr
15660 * domain name
15661 * @resptype_txt: Pointer to the struct hdd_mdns_resp_info of Type Txt
15662 * @resptype_a: Pointer to the struct hdd_mdns_resp_info of Type A
15663 *
15664 * The Type Ptr response include QName, response type, class, TTL and
15665 * Type PTR domain name. Also, it will find the matched QName from the
15666 * existing resptype_txt, resptype_a and then compress the data.
15667 *
15668 * Return: Return boolean. TRUE for success, FALSE for fail.
15669 */
15670static bool
15671wlan_hdd_mdns_pack_response_type_ptr(hdd_config_t *ini_config,
15672 sir_mdns_resp_info resp_info,
15673 struct hdd_mdns_resp_info *resptype_ptr,
15674 struct hdd_mdns_resp_info *resptype_ptr_dn,
15675 struct hdd_mdns_resp_info *resptype_txt,
15676 struct hdd_mdns_resp_info *resptype_a)
15677{
15678 uint8_t num_matched, num_matched1;
15679 uint16_t value;
15680 uint8_t val_u8;
15681 uint32_t offset_data_len, len;
15682
15683 ENTER();
15684 if ((ini_config == NULL) || (resp_info == NULL) ||
15685 (resptype_ptr == NULL) || (resptype_ptr_dn == NULL)) {
15686 hddLog(LOGE, FL("ini_config or response info is NULL!"));
15687 return FALSE;
15688 }
15689
15690 /* No Type Ptr response */
15691 if (strlen((char *)ini_config->mdns_resp_type_ptr) <= 0)
15692 return TRUE;
15693
15694 /* Wrong response is assigned, just ignore this response */
15695 if (!wlan_hdd_mdns_init_response(resptype_ptr,
15696 ini_config->mdns_resp_type_ptr, '.'))
15697 return TRUE;
15698
15699 /*
15700 * For data compression
15701 * Check if any strings are matched with Type A response
15702 */
15703 num_matched = 0;
15704 num_matched1 = 0;
15705 if (resptype_a && (resptype_a->num_entries > 0)) {
15706 num_matched = wlan_hdd_mdns_find_entries_from_end(resptype_ptr,
15707 resptype_a);
15708 }
15709 if (resptype_txt && (resptype_txt->num_entries > 0)) {
15710 num_matched1 = wlan_hdd_mdns_find_entries_from_end(
15711 resptype_ptr, resptype_txt);
15712 }
15713 if ((num_matched != num_matched1) ||
15714 ((num_matched > 0) && (num_matched1 > 0))) {
15715 if (num_matched >= num_matched1) {
15716 if (!wlan_hdd_mdns_compress_data(resp_info,
15717 resptype_ptr, resptype_a, num_matched)) {
15718 hddLog(LOGE, FL("Fail to compress mDNS "
15719 "response (%d)!"), MDNS_TYPE_PTR);
15720 return FALSE;
15721 }
15722 } else {
15723 /* num_matched is less than num_matched1 */
15724 if (!wlan_hdd_mdns_compress_data(resp_info,
15725 resptype_ptr, resptype_txt, num_matched1)) {
15726 hddLog(LOGE, FL("Fail to compress mDNS "
15727 "response (%d)!"), MDNS_TYPE_PTR);
15728 return FALSE;
15729 }
15730 }
15731 } else {
15732 /*
15733 * Both num_matched and num_matched1 are zero.
15734 * no TypeA & TypeTxt
15735 */
15736 if (!wlan_hdd_mdns_process_response_dname(resptype_ptr,
15737 resp_info)) {
15738 hddLog(LOGE, FL("Fail to process mDNS response (%d)!"),
15739 MDNS_TYPE_PTR);
15740 return FALSE;
15741 }
15742 }
15743
15744 /* Process response Type, Class, TTL */
15745 if (!wlan_hdd_mdns_process_response_misc(MDNS_TYPE_PTR, resp_info)) {
15746 hddLog(LOGE, FL("Fail to process mDNS misc response (%d)!"),
15747 MDNS_TYPE_PTR);
15748 return FALSE;
15749 }
15750
15751 /*
15752 * Process response RDLength, RData (Ptr domain name)
15753 * Save the offset of RData length
15754 */
15755 offset_data_len = resp_info->resp_len;
15756 resp_info->resp_len += sizeof(uint16_t);
15757
15758 if (!wlan_hdd_mdns_pack_response_type_ptr_dname(ini_config, resp_info,
15759 resptype_ptr_dn, resptype_ptr,
15760 resptype_txt, resptype_a)) {
15761 return FALSE;
15762 }
15763 /* Set the RData length */
15764 len = offset_data_len + sizeof(uint16_t);
15765 if ((resptype_ptr_dn->num_entries > 0) &&
15766 (resp_info->resp_len > len)) {
15767 value = resp_info->resp_len - len;
15768 val_u8 = (value & 0xff00) >> 8;
15769 resp_info->resp_data[offset_data_len] = val_u8;
15770 val_u8 = value & 0xff;
15771 resp_info->resp_data[offset_data_len+1] = val_u8;
15772 } else {
15773 hddLog(LOGE, FL("Fail to process mDNS response (%d)!"),
15774 MDNS_TYPE_PTR);
15775 return FALSE;
15776 }
15777
15778 EXIT();
15779 return TRUE;
15780}
15781
15782/**
15783 * wlan_hdd_mdns_pack_response_type_srv_target()- Pack Type Service Target
15784 * @ini_config: Pointer to the struct hdd_config_t
15785 * @resp_info: Pointer to the struct tSirMDNSResponseInfo
15786 * @resptype_srv_tgt: Pointer to the struct hdd_mdns_resp_info of Type Srv
15787 * target
15788 * @resptype_srv: Pointer to the struct hdd_mdns_resp_info of Type Srv
15789 * @resptype_ptr: Pointer to the struct hdd_mdns_resp_info of Type Ptr
15790 * @resptype_ptr_dn: Pointer to the struct hdd_mdns_resp_info of Type Ptr
15791 * domain name
15792 * @resptype_txt: Pointer to the struct hdd_mdns_resp_info of Type Txt
15793 * @resptype_a: Pointer to the struct hdd_mdns_resp_info of Type A
15794 *
15795 * The Type service target is one of the data field in the Type SRV response.
15796 * Also, it will find the matched QName from the existing resptype_srv,
15797 * resptype_ptr, resptype_ptr_dn, resptype_txt, resptype_a and then compress
15798 * the data.
15799 *
15800 * Return: Return boolean. TRUE for success, FALSE for fail.
15801 */
15802static bool
15803wlan_hdd_mdns_pack_response_type_srv_target(hdd_config_t *ini_config,
15804 sir_mdns_resp_info resp_info,
15805 struct hdd_mdns_resp_info *resptype_srv_tgt,
15806 struct hdd_mdns_resp_info *resptype_srv,
15807 struct hdd_mdns_resp_info *resptype_ptr,
15808 struct hdd_mdns_resp_info *resptype_ptr_dn,
15809 struct hdd_mdns_resp_info *resptype_txt,
15810 struct hdd_mdns_resp_info *resptype_a)
15811{
15812 uint8_t num_matched, num, size;
15813 struct hdd_mdns_resp_matched matchedlist[MAX_MDNS_RESP_TYPE-1];
15814 struct hdd_mdns_resp_info *resp;
15815
15816 if ((ini_config == NULL) || (resp_info == NULL) ||
15817 (resptype_srv == NULL) || (resptype_srv_tgt == NULL)) {
15818 hddLog(LOGE, FL("ini_config or response info is NULL!"));
15819 return FALSE;
15820 }
15821
15822 /* No Type Srv Target response */
15823 if (strlen((char *)ini_config->mdns_resp_type_srv_target) <= 0)
15824 return TRUE;
15825
15826 /* Wrong response is assigned, just ignore this response */
15827 if (!wlan_hdd_mdns_init_response(resptype_srv_tgt,
15828 ini_config->mdns_resp_type_srv_target, '.'))
15829 return TRUE;
15830
15831 /*
15832 * For data compression
15833 * Check if any strings are matched with previous response.
15834 */
15835 num = 0;
15836 size = (MAX_MDNS_RESP_TYPE-1);
15837 size *= sizeof(struct hdd_mdns_resp_matched);
15838 vos_mem_zero(matchedlist, size);
15839 num_matched = wlan_hdd_mdns_find_entries_from_end(resptype_srv_tgt,
15840 resptype_srv);
15841 if (num_matched > 0) {
15842 matchedlist[num].num_matched = num_matched;
15843 matchedlist[num].type = MDNS_TYPE_SRV;
15844 num++;
15845 }
15846 if (resptype_ptr && (resptype_ptr->num_entries > 0)) {
15847 if (resptype_ptr_dn && (resptype_ptr_dn->num_entries > 0)) {
15848 num_matched = wlan_hdd_mdns_find_entries_from_end(
15849 resptype_srv_tgt, resptype_ptr_dn);
15850 if (num_matched > 0) {
15851 matchedlist[num].num_matched = num_matched;
15852 matchedlist[num].type = MDNS_TYPE_PTR_DNAME;
15853 num++;
15854 }
15855 }
15856 num_matched = wlan_hdd_mdns_find_entries_from_end(
15857 resptype_srv_tgt, resptype_ptr);
15858 if (num_matched > 0) {
15859 matchedlist[num].num_matched = num_matched;
15860 matchedlist[num].type = MDNS_TYPE_PTR;
15861 num++;
15862 }
15863 }
15864 if (resptype_txt && (resptype_txt->num_entries > 0)) {
15865 num_matched = wlan_hdd_mdns_find_entries_from_end(
15866 resptype_srv_tgt, resptype_txt);
15867 if (num_matched > 0) {
15868 matchedlist[num].num_matched = num_matched;
15869 matchedlist[num].type = MDNS_TYPE_TXT;
15870 num++;
15871 }
15872 }
15873 if (resptype_a && (resptype_a->num_entries > 0)) {
15874 num_matched = wlan_hdd_mdns_find_entries_from_end(
15875 resptype_srv_tgt, resptype_a);
15876 if (num_matched > 0) {
15877 matchedlist[num].num_matched = num_matched;
15878 matchedlist[num].type = MDNS_TYPE_A;
15879 num++;
15880 }
15881 }
15882 if (num > 0) {
15883 if (num > 1)
15884 wlan_hdd_mdns_find_max(matchedlist, num);
15885 resp = NULL;
15886 switch (matchedlist[num-1].type) {
15887 case MDNS_TYPE_A:
15888 resp = resptype_a;
15889 break;
15890 case MDNS_TYPE_TXT:
15891 resp = resptype_txt;
15892 break;
15893 case MDNS_TYPE_PTR:
15894 resp = resptype_ptr;
15895 break;
15896 case MDNS_TYPE_PTR_DNAME:
15897 resp = resptype_ptr_dn;
15898 break;
15899 case MDNS_TYPE_SRV:
15900 resp = resptype_srv;
15901 break;
15902 default:
15903 hddLog(LOGE, FL("Fail to compress mDNS response "
15904 "(%d)!"), MDNS_TYPE_SRV_TARGET);
15905 return FALSE;
15906 }
15907 num_matched = matchedlist[num-1].num_matched;
15908 if (!wlan_hdd_mdns_compress_data(resp_info, resptype_srv_tgt,
15909 resp, num_matched)) {
15910 hddLog(LOGE, FL("Fail to compress mDNS response "
15911 "(%d)!"), MDNS_TYPE_SRV_TARGET);
15912 return FALSE;
15913 }
15914 } else {
15915 /* num = 0 -> no matched string */
15916 if (!wlan_hdd_mdns_process_response_dname(resptype_srv_tgt,
15917 resp_info)) {
15918 hddLog(LOGE, FL("Fail to process mDNS response (%d)!"),
15919 MDNS_TYPE_SRV_TARGET);
15920 return FALSE;
15921 }
15922 }
15923
15924 return TRUE;
15925}
15926
15927/**
15928 * wlan_hdd_mdns_pack_response_type_srv()- Pack Type Service response
15929 * @ini_config: Pointer to the struct hdd_config_t
15930 * @resp_info: Pointer to the struct tSirMDNSResponseInfo
15931 * @resptype_srv: Pointer to the struct hdd_mdns_resp_info of Type Srv
15932 * @resptype_srv_tgt: Pointer to the struct hdd_mdns_resp_info of Type Srv
15933 * target
15934 * @resptype_ptr: Pointer to the struct hdd_mdns_resp_info of Type Ptr
15935 * @resptype_ptr_dn: Pointer to the struct hdd_mdns_resp_info of Type Ptr
15936 * domain name
15937 * @resptype_txt: Pointer to the struct hdd_mdns_resp_info of Type Txt
15938 * @resptype_a: Pointer to the struct hdd_mdns_resp_info of Type A
15939 *
15940 * The Type SRV (Service) response include QName, response type, class, TTL
15941 * and four kinds of data fields. Also, it will find the matched QName from
15942 * the existing resptype_ptr, resptype_ptr_dn, resptype_txt, resptype_a and
15943 * then compress the data.
15944 *
15945 * Return: Return boolean. TRUE for success, FALSE for fail.
15946 */
15947static bool
15948wlan_hdd_mdns_pack_response_type_srv(hdd_config_t *ini_config,
15949 sir_mdns_resp_info resp_info,
15950 struct hdd_mdns_resp_info *resptype_srv,
15951 struct hdd_mdns_resp_info *resptype_srv_tgt,
15952 struct hdd_mdns_resp_info *resptype_ptr,
15953 struct hdd_mdns_resp_info *resptype_ptr_dn,
15954 struct hdd_mdns_resp_info *resptype_txt,
15955 struct hdd_mdns_resp_info *resptype_a)
15956{
15957 uint8_t num_matched, num, size;
15958 uint16_t value;
15959 uint8_t val_u8;
15960 uint32_t offset_data_len, len;
15961 struct hdd_mdns_resp_info *resp;
15962 struct hdd_mdns_resp_matched matchedlist[MAX_MDNS_RESP_TYPE-1];
15963
15964 ENTER();
15965
15966 if ((ini_config == NULL) || (resp_info == NULL) ||
15967 (resptype_srv == NULL) || (resptype_srv_tgt == NULL)) {
15968 hddLog(LOGE, FL("ini_config or response info is NULL!"));
15969 return FALSE;
15970 }
15971
15972 /* No Type Srv response */
15973 if (strlen((char *)ini_config->mdns_resp_type_srv) <= 0)
15974 return TRUE;
15975
15976 /* Wrong response is assigned, just ignore this response */
15977 if (!wlan_hdd_mdns_init_response(resptype_srv,
15978 ini_config->mdns_resp_type_srv, '.'))
15979 return TRUE;
15980
15981 /*
15982 * For data compression
15983 * Check if any strings are matched with Type A response
15984 */
15985 num = 0;
15986 size = (MAX_MDNS_RESP_TYPE-1);
15987 size *= sizeof(struct hdd_mdns_resp_matched);
15988 vos_mem_zero(matchedlist, size);
15989 if (resptype_ptr && (resptype_ptr->num_entries > 0)) {
15990 if (resptype_ptr_dn && (resptype_ptr_dn->num_entries > 0)) {
15991 num_matched = wlan_hdd_mdns_find_entries_from_end(
15992 resptype_srv,
15993 resptype_ptr_dn);
15994 if (num_matched > 0) {
15995 matchedlist[num].num_matched = num_matched;
15996 matchedlist[num].type = MDNS_TYPE_PTR_DNAME;
15997 num++;
15998 }
15999 }
16000 num_matched = wlan_hdd_mdns_find_entries_from_end(resptype_srv,
16001 resptype_ptr);
16002 if (num_matched > 0) {
16003 matchedlist[num].num_matched = num_matched;
16004 matchedlist[num].type = MDNS_TYPE_PTR;
16005 num++;
16006 }
16007 }
16008 if (resptype_txt && (resptype_txt->num_entries > 0)) {
16009 num_matched = wlan_hdd_mdns_find_entries_from_end(resptype_srv,
16010 resptype_txt);
16011 if (num_matched > 0) {
16012 matchedlist[num].num_matched =num_matched;
16013 matchedlist[num].type = MDNS_TYPE_TXT;
16014 num++;
16015 }
16016 }
16017 if (resptype_a && (resptype_a->num_entries > 0)) {
16018 num_matched = wlan_hdd_mdns_find_entries_from_end(resptype_srv,
16019 resptype_a);
16020 if (num_matched > 0) {
16021 matchedlist[num].num_matched = num_matched;
16022 matchedlist[num].type = MDNS_TYPE_A;
16023 num++;
16024 }
16025 }
16026 if (num > 0) {
16027 if (num > 1)
16028 wlan_hdd_mdns_find_max(matchedlist, num);
16029 resp = NULL;
16030 switch (matchedlist[num-1].type) {
16031 case MDNS_TYPE_A:
16032 resp = resptype_a;
16033 break;
16034 case MDNS_TYPE_TXT:
16035 resp = resptype_txt;
16036 break;
16037 case MDNS_TYPE_PTR:
16038 resp = resptype_ptr;
16039 break;
16040 case MDNS_TYPE_PTR_DNAME:
16041 resp = resptype_ptr_dn;
16042 break;
16043 default:
16044 hddLog(LOGE, FL("Fail to compress mDNS response "
16045 "(%d)!"), MDNS_TYPE_SRV);
16046 return FALSE;
16047 }
16048 num_matched = matchedlist[num-1].num_matched;
16049 if (!wlan_hdd_mdns_compress_data(resp_info, resptype_srv,
16050 resp, num_matched)) {
16051 hddLog(LOGE, FL("Fail to compress mDNS response "
16052 "(%d)!"), MDNS_TYPE_SRV);
16053 return FALSE;
16054 }
16055 } else {
16056 /* num = 0 -> no matched string */
16057 if (!wlan_hdd_mdns_process_response_dname(resptype_srv,
16058 resp_info)) {
16059 hddLog(LOGE, FL("Fail to process mDNS response (%d)!"),
16060 MDNS_TYPE_SRV);
16061 return FALSE;
16062 }
16063 }
16064
16065 /* Process response Type, Class, TTL */
16066 if (!wlan_hdd_mdns_process_response_misc(MDNS_TYPE_SRV, resp_info)) {
16067 hddLog(LOGE, FL("Fail to process mDNS misc response (%d)!"),
16068 MDNS_TYPE_SRV);
16069 return FALSE;
16070 }
16071
16072 /*
16073 * Process response RDLength, RData (Srv target name)
16074 * Save the offset of RData length
16075 */
16076 offset_data_len = resp_info->resp_len;
16077 resp_info->resp_len += sizeof(uint16_t);
16078
16079 len = resp_info->resp_len + (3 * sizeof(uint16_t));
16080 if (len >= MAX_MDNS_RESP_LEN) {
16081 hddLog(LOGE, FL("resp_len exceeds %d!"), MAX_MDNS_RESP_LEN);
16082 return FALSE;
16083 }
16084
16085 /* set Srv Priority */
16086 value = ini_config->mdns_resp_type_srv_priority;
16087 wlan_hdd_mdns_format_response_u16(value, resp_info);
16088 /* set Srv Weight */
16089 value = ini_config->mdns_resp_type_srv_weight;
16090 wlan_hdd_mdns_format_response_u16(value, resp_info);
16091 /* set Srv Port */
16092 value = ini_config->mdns_resp_type_srv_port;
16093 wlan_hdd_mdns_format_response_u16(value, resp_info);
16094
16095 if (!wlan_hdd_mdns_pack_response_type_srv_target(ini_config, resp_info,
16096 resptype_srv_tgt, resptype_srv,
16097 resptype_ptr, resptype_ptr_dn,
16098 resptype_txt, resptype_a)) {
16099 return FALSE;
16100 }
16101 /* Set the RData length */
16102 len = offset_data_len + sizeof(uint16_t);
16103 if ((resptype_srv_tgt->num_entries > 0) &&
16104 (resp_info->resp_len > len)) {
16105 value = resp_info->resp_len - len;
16106 val_u8 = (value & 0xff00) >> 8;
16107 resp_info->resp_data[offset_data_len] = val_u8;
16108 val_u8 = value & 0xff;
16109 resp_info->resp_data[offset_data_len+1] = val_u8;
16110 } else {
16111 hddLog(LOGE, FL("Fail to process mDNS response (%d)!"),
16112 MDNS_TYPE_SRV);
16113 return FALSE;
16114 }
16115
16116 EXIT();
16117 return TRUE;
16118}
16119
16120/**
16121 * wlan_hdd_mdns_free_mem() - Free the allocated memory
16122 * @response: Pointer to the struct hdd_mdns_resp_info
16123 *
16124 * Return: None
16125 */
16126static void wlan_hdd_mdns_free_mem(struct hdd_mdns_resp_info *response)
16127{
16128 if (response && response->data)
16129 vos_mem_free(response->data);
16130 if (response && response->offset)
16131 vos_mem_free(response->offset);
16132}
16133
16134/**
16135 * wlan_hdd_mdns_pack_response() - Pack mDNS response
16136 * @ini_config: Pointer to the struct hdd_config_t
16137 * @resp_info: Pointer to the struct tSirMDNSResponseInfo
16138 *
16139 * This function will pack four types of responses (Type A, Type Txt, Type Ptr
16140 * and Type Service). Each response contains QName, response type, class, TTL
16141 * and data fields.
16142 *
16143 * Return: Return boolean. TRUE for success, FALSE for fail.
16144 */
16145static bool wlan_hdd_mdns_pack_response(hdd_config_t *ini_config,
16146 sir_mdns_resp_info resp_info)
16147{
16148 struct hdd_mdns_resp_info resptype_a, resptype_txt;
16149 struct hdd_mdns_resp_info resptype_ptr, resptype_ptr_dn;
16150 struct hdd_mdns_resp_info resptype_srv, resptype_srv_tgt;
16151 uint32_t num_res_records = 0;
16152 bool status = FALSE;
16153
16154 ENTER();
16155
16156 wlan_hdd_mdns_reset_response(&resptype_a);
16157 wlan_hdd_mdns_reset_response(&resptype_txt);
16158 wlan_hdd_mdns_reset_response(&resptype_ptr);
16159 wlan_hdd_mdns_reset_response(&resptype_ptr_dn);
16160 wlan_hdd_mdns_reset_response(&resptype_srv);
16161 wlan_hdd_mdns_reset_response(&resptype_srv_tgt);
16162
16163 resp_info->resp_len = 0;
16164
16165 /* Process Type A response */
16166 if (!wlan_hdd_mdns_pack_response_type_a(ini_config, resp_info,
16167 &resptype_a))
16168 goto err_resptype_a;
16169
16170 if ((resptype_a.num_entries > 0) &&
16171 (strlen((char *)&resptype_a.data[0]) > 0))
16172 num_res_records++;
16173
16174 /* Process Type TXT response */
16175 if (!wlan_hdd_mdns_pack_response_type_txt(ini_config, resp_info,
16176 &resptype_txt, &resptype_a))
16177 goto err_resptype_txt;
16178
16179 if ((resptype_txt.num_entries > 0) &&
16180 (strlen((char *)&resptype_txt.data[0]) > 0))
16181 num_res_records++;
16182
16183 /* Process Type PTR response */
16184 if (!wlan_hdd_mdns_pack_response_type_ptr(ini_config, resp_info,
16185 &resptype_ptr, &resptype_ptr_dn,
16186 &resptype_txt, &resptype_a))
16187 goto err_resptype_ptr;
16188
16189 if ((resptype_ptr.num_entries > 0) &&
16190 (strlen((char *)&resptype_ptr.data[0]) > 0))
16191 num_res_records++;
16192
16193 /* Process Type SRV response */
16194 if (!wlan_hdd_mdns_pack_response_type_srv(ini_config, resp_info,
16195 &resptype_srv, &resptype_srv_tgt,
16196 &resptype_ptr, &resptype_ptr_dn,
16197 &resptype_txt, &resptype_a))
16198 goto err_resptype_srv;
16199
16200 if ((resptype_srv.num_entries > 0) &&
16201 (strlen((char *)&resptype_srv.data[0]) > 0))
16202 num_res_records++;
16203
16204 resp_info->resourceRecord_count = num_res_records;
16205 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
16206 "%s: Pack mDNS response data successfully!", __func__);
16207 status = TRUE;
16208
16209err_resptype_srv:
16210 wlan_hdd_mdns_free_mem(&resptype_srv);
16211 wlan_hdd_mdns_free_mem(&resptype_srv_tgt);
16212
16213err_resptype_ptr:
16214 wlan_hdd_mdns_free_mem(&resptype_ptr);
16215 wlan_hdd_mdns_free_mem(&resptype_ptr_dn);
16216
16217err_resptype_txt:
16218 wlan_hdd_mdns_free_mem(&resptype_txt);
16219
16220err_resptype_a:
16221 wlan_hdd_mdns_free_mem(&resptype_a);
16222
16223 EXIT();
16224 return status;
16225}
16226
16227/**
16228 * wlan_hdd_set_mdns_offload() - Enable mDNS offload
16229 * @hostapd_adapter: Pointer to the struct hdd_adapter_t
16230 *
16231 * This function will set FQDN/unique FQDN (full qualified domain name)
16232 * and the mDNS response. Then send them to SME.
16233 *
16234 * Return: Return boolean. TRUE for success, FALSE for fail.
16235 */
16236bool wlan_hdd_set_mdns_offload(hdd_adapter_t *hostapd_adapter)
16237{
16238 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(hostapd_adapter);
16239 sir_mdns_offload_info mdns_offload_info;
16240 sir_mdns_fqdn_info mdns_fqdn_info;
16241 sir_mdns_resp_info mdns_resp_info;
16242 uint32_t fqdn_len, ufqdn_len;
16243
16244 ENTER();
16245
16246 /* 1. Prepare the MDNS fqdn request to send to SME */
16247 fqdn_len = strlen(hdd_ctx->cfg_ini->mdns_fqdn);
16248 ufqdn_len = strlen(hdd_ctx->cfg_ini->mdns_uniquefqdn);
16249 if ((fqdn_len == 0) && (ufqdn_len == 0)) {
16250 hddLog(LOGE, FL("No mDNS FQDN or UFQDN is assigned fqdn_len %d,"
16251 "ufqdn_len %d!"), fqdn_len, ufqdn_len);
16252 return FALSE;
16253 }
16254
16255 mdns_fqdn_info = vos_mem_malloc(sizeof(*mdns_fqdn_info));
16256 if (NULL == mdns_fqdn_info) {
16257 hddLog(LOGE, FL("could not allocate tSirMDNSFqdnInfo!"));
16258 return FALSE;
16259 }
16260 /* MDNS fqdn request */
16261 if (fqdn_len > 0) {
16262 vos_mem_zero(mdns_fqdn_info, sizeof(*mdns_fqdn_info));
16263 mdns_fqdn_info->bss_idx = hostapd_adapter->sessionId;
16264 mdns_fqdn_info->fqdn_type = MDNS_FQDN_TYPE_GENERAL;
16265 mdns_fqdn_info->fqdn_len = fqdn_len;
16266 mdns_fqdn_info->mdns_fqdn_callback = hdd_mdns_fqdn_offload_done;
16267 mdns_fqdn_info->mdns_fqdn_cb_context = hostapd_adapter;
16268 vos_mem_copy(mdns_fqdn_info->fqdn_data,
16269 hdd_ctx->cfg_ini->mdns_fqdn,
16270 mdns_fqdn_info->fqdn_len);
16271
16272 if (eHAL_STATUS_SUCCESS !=
16273 sme_set_mdns_fqdn(hdd_ctx->hHal, mdns_fqdn_info)) {
16274 hddLog(LOGE, FL("sme_set_mdns_fqdn fail!"));
16275 vos_mem_free(mdns_fqdn_info);
16276 return FALSE;
16277 }
16278 }
16279 /* MDNS unique fqdn request */
16280 if (ufqdn_len > 0) {
16281 vos_mem_zero(mdns_fqdn_info, sizeof(*mdns_fqdn_info));
16282 mdns_fqdn_info->bss_idx = hostapd_adapter->sessionId;
16283 mdns_fqdn_info->fqdn_type = MDNS_FQDN_TYPE_UNIQUE;
16284 mdns_fqdn_info->fqdn_len = ufqdn_len;
16285 mdns_fqdn_info->mdns_fqdn_callback = hdd_mdns_fqdn_offload_done;
16286 mdns_fqdn_info->mdns_fqdn_cb_context = hostapd_adapter;
16287 vos_mem_copy(mdns_fqdn_info->fqdn_data,
16288 hdd_ctx->cfg_ini->mdns_uniquefqdn,
16289 mdns_fqdn_info->fqdn_len);
16290 if (eHAL_STATUS_SUCCESS !=
16291 sme_set_mdns_fqdn(hdd_ctx->hHal, mdns_fqdn_info)) {
16292 hddLog(LOGE, FL("sme_set_mdns_fqdn fail!"));
16293 vos_mem_free(mdns_fqdn_info);
16294 return FALSE;
16295 }
16296 }
16297 vos_mem_free(mdns_fqdn_info);
16298
16299 /* 2. Prepare the MDNS response request to send to SME */
16300 mdns_resp_info = vos_mem_malloc(sizeof(*mdns_resp_info));
16301 if (NULL == mdns_resp_info) {
16302 hddLog(LOGE, FL("could not allocate tSirMDNSResponseInfo!"));
16303 return FALSE;
16304 }
16305
16306 vos_mem_zero(mdns_resp_info, sizeof(*mdns_resp_info));
16307 mdns_resp_info->bss_idx = hostapd_adapter->sessionId;
16308 mdns_resp_info->mdns_resp_callback = hdd_mdns_resp_offload_done;
16309 mdns_resp_info->mdns_resp_cb_context = hostapd_adapter;
16310 if (!wlan_hdd_mdns_pack_response(hdd_ctx->cfg_ini, mdns_resp_info)) {
16311 hddLog(LOGE, FL("wlan_hdd_pack_mdns_response fail!"));
16312 vos_mem_free(mdns_resp_info);
16313 return FALSE;
16314 }
16315 if (eHAL_STATUS_SUCCESS !=
16316 sme_set_mdns_resp(hdd_ctx->hHal, mdns_resp_info)) {
16317 hddLog(LOGE, FL("sme_set_mdns_resp fail!"));
16318 vos_mem_free(mdns_resp_info);
16319 return FALSE;
16320 }
16321 vos_mem_free(mdns_resp_info);
16322
16323 /* 3. Prepare the MDNS Enable request to send to SME */
16324 mdns_offload_info = vos_mem_malloc(sizeof(*mdns_offload_info));
16325 if (NULL == mdns_offload_info) {
16326 hddLog(LOGE, FL("could not allocate tSirMDNSOffloadInfo!"));
16327 return FALSE;
16328 }
16329
16330 vos_mem_zero(mdns_offload_info, sizeof(*mdns_offload_info));
16331
16332 mdns_offload_info->bss_idx = hostapd_adapter->sessionId;
16333 mdns_offload_info->enable = hdd_ctx->cfg_ini->enable_mdns_offload;
16334 mdns_offload_info->mdns_enable_callback = hdd_mdns_enable_offload_done;
16335 mdns_offload_info->mdns_enable_cb_context = hostapd_adapter;
16336 if (eHAL_STATUS_SUCCESS !=
16337 sme_set_mdns_offload(hdd_ctx->hHal, mdns_offload_info)) {
16338 hddLog(LOGE, FL("sme_set_mdns_offload fail!"));
16339 vos_mem_free(mdns_offload_info);
16340 return FALSE;
16341 }
16342
16343 vos_mem_free(mdns_offload_info);
16344 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
16345 "%s: enable mDNS offload successfully!", __func__);
16346 return TRUE;
16347}
Manjeet Singh3ed79242017-01-11 19:04:32 +053016348
16349
Anurag Chouhan0b29de02016-12-16 13:18:40 +053016350#endif /* MDNS_OFFLOAD */
c_manjeecfd1efb2015-09-25 19:32:34 +053016351
Hanumanth Reddy Pothulad864f312017-01-18 16:16:08 +053016352/**
16353 * wlan_hdd_start_sap() - This function starts bss of SAP.
16354 * @ap_adapter: SAP adapter
16355 *
16356 * This function will process the starting of sap adapter.
16357 *
16358 * Return: void.
16359 */
16360void wlan_hdd_start_sap(hdd_adapter_t *ap_adapter)
16361{
16362 hdd_ap_ctx_t *hdd_ap_ctx;
16363 hdd_hostapd_state_t *hostapd_state;
16364 VOS_STATUS vos_status;
16365 hdd_context_t *hdd_ctx;
16366 tsap_Config_t *pConfig;
16367
16368 if (NULL == ap_adapter) {
16369 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
16370 FL("ap_adapter is NULL here"));
16371 return;
16372 }
16373
16374 hdd_ctx = WLAN_HDD_GET_CTX(ap_adapter);
16375 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
16376 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
16377 pConfig = &ap_adapter->sessionCtx.ap.sapConfig;
16378
16379 mutex_lock(&hdd_ctx->sap_lock);
16380 if (test_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags))
16381 goto end;
16382
16383 if (0 != wlan_hdd_cfg80211_update_apies(ap_adapter)) {
16384 hddLog(LOGE, FL("SAP Not able to set AP IEs"));
16385 goto end;
16386 }
16387
16388 vos_event_reset(&hostapd_state->vosEvent);
16389 if (WLANSAP_StartBss(hdd_ctx->pvosContext, hdd_hostapd_SAPEventCB,
16390 &hdd_ap_ctx->sapConfig, (v_PVOID_t)ap_adapter->dev)
16391 != VOS_STATUS_SUCCESS) {
16392 goto end;
16393 }
16394
16395 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
16396 FL("Waiting for SAP to start"));
16397 vos_status = vos_wait_single_event(&hostapd_state->vosEvent, 10000);
16398 if (!VOS_IS_STATUS_SUCCESS(vos_status)) {
16399 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
16400 FL("SAP Start failed"));
16401 goto end;
16402 }
16403 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
16404 FL("SAP Start Success"));
16405 set_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags);
16406
16407 wlan_hdd_incr_active_session(hdd_ctx, ap_adapter->device_mode);
16408 hostapd_state->bCommit = TRUE;
16409
16410end:
16411 mutex_unlock(&hdd_ctx->sap_lock);
16412 return;
16413}
16414
Manjeet Singh3ed79242017-01-11 19:04:32 +053016415#ifdef WLAN_FEATURE_TSF
16416
16417/**
16418 * hdd_tsf_cb() - handle tsf request callback
16419 *
16420 * @pcb_cxt: pointer to the hdd_contex
16421 * @ptsf: pointer to struct stsf
16422 *
16423 * Based on the request sent .
16424 *
16425 * Return: Describe the execute result of this routine
16426 */
16427static int hdd_tsf_cb(void *pcb_ctx, struct stsf *ptsf)
16428{
16429 hdd_context_t *hddctx;
16430 int status;
16431 hdd_adapter_t* adapter = (hdd_adapter_t*)pcb_ctx;
16432
16433 if (pcb_ctx == NULL || ptsf == NULL) {
16434 hddLog(VOS_TRACE_LEVEL_ERROR,
16435 FL("HDD context is not valid"));
16436 return -EINVAL;
16437 }
16438
16439 hddctx = (hdd_context_t *)pcb_ctx;
16440 status = wlan_hdd_validate_context(hddctx);
16441 if (0 != status)
16442 return -EINVAL;
16443
16444 if (NULL == adapter) {
16445 hddLog(VOS_TRACE_LEVEL_ERROR,
16446 FL("failed to find adapter"));
16447 return -EINVAL;
16448 }
16449
16450 hddLog(VOS_TRACE_LEVEL_INFO,
16451 FL("tsf cb handle event, device_mode is %d"),
16452 adapter->device_mode);
16453
16454 /* copy the return value to hdd_tsf_ctx in adapter*/
16455 if (ptsf->tsf_req_status) {
16456
16457 vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
16458 adapter->tsf_cap_ctx.tsf_get_state = TSF_NOT_RETURNED_BY_FW;
16459 adapter->tsf_cap_ctx.tsf_capture_state = TSF_IDLE;
16460 vos_event_set (&adapter->tsf_cap_ctx.tsf_capture_done_event);
16461 vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
16462
16463 hddLog(VOS_TRACE_LEVEL_ERROR, FL("tsf req failure :%d"),
16464 ptsf->tsf_req_status);
16465 return ptsf->tsf_req_status;
16466 }
16467 /* If this is a get request.Store the tsf values in adapter. */
16468 if (!ptsf->set_tsf_req) {
16469 vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
16470 adapter->tsf_cap_ctx.tsf_low = ptsf->tsf_low;
16471 adapter->tsf_cap_ctx.tsf_high = ptsf->tsf_high;
16472 adapter->tsf_cap_ctx.tsf_get_state = TSF_RETURN;
16473 adapter->tsf_cap_ctx.tsf_capture_state = TSF_IDLE;
16474 vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
16475
16476 hddLog(VOS_TRACE_LEVEL_INFO,
16477 FL("hdd_get_tsf_cb sta=%u, tsf_low=%u, tsf_high=%u"),
16478 adapter->sessionId, ptsf->tsf_low, ptsf->tsf_high);
16479 }
16480 else {
16481 vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
16482 adapter->tsf_cap_ctx.tsf_capture_state = TSF_CAP_STATE;
16483 adapter->tsf_cap_ctx.tsf_get_state = TSF_CURRENT_IN_CAP_STATE;
16484 vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
16485 }
16486 vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
16487 vos_event_set (&adapter->tsf_cap_ctx.tsf_capture_done_event);
16488 vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
16489
16490 /* free allocated mem */
16491 vos_mem_free(ptsf);
16492
16493 return 0;
16494}
16495
16496/**
16497 * hdd_capture_tsf() - capture tsf
16498 *
16499 * @adapter: pointer to adapter
16500 * @buf: pointer to upper layer buf
16501 * @len : the length of buf
16502 *
16503 * This function returns tsf value to uplayer.
16504 *
16505 * Return: Describe the execute result of this routine
16506 */
16507int hdd_capture_tsf(hdd_adapter_t *adapter, uint32_t *buf, int len)
16508{
16509 int ret = 0;
16510 hdd_station_ctx_t *hdd_sta_ctx;
16511 hdd_context_t *hdd_ctx;
16512 tSirCapTsfParams cap_tsf_params;
16513 VOS_STATUS status;
16514
16515 if (adapter == NULL || buf == NULL) {
16516 hddLog(VOS_TRACE_LEVEL_ERROR,
16517 FL("invalid pointer"));
16518 return -EINVAL;
16519 }
16520 if (len != 1)
16521 return -EINVAL;
16522
16523 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
16524
16525 if (wlan_hdd_validate_context(hdd_ctx)) {
16526 hddLog(VOS_TRACE_LEVEL_ERROR,
16527 FL("invalid hdd ctx"));
16528 return -EINVAL;
16529 }
16530 if (adapter->device_mode == WLAN_HDD_INFRA_STATION ||
16531 adapter->device_mode == WLAN_HDD_P2P_CLIENT) {
16532 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
16533 if (hdd_sta_ctx->conn_info.connState !=
16534 eConnectionState_Associated) {
16535
16536 hddLog(VOS_TRACE_LEVEL_INFO,
16537 FL("failed to cap tsf, not connect with ap"));
16538 buf[0] = TSF_STA_NOT_CONNECTED_NO_TSF;
16539 return ret;
16540 }
16541 }
16542 if ((adapter->device_mode == WLAN_HDD_SOFTAP ||
16543 adapter->device_mode == WLAN_HDD_P2P_GO) &&
16544 !(test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags))) {
16545 hddLog(VOS_TRACE_LEVEL_INFO,
16546 FL("Soft AP / P2p GO not beaconing"));
16547 buf[0] = TSF_SAP_NOT_STARTED_NO_TSF;
16548 return ret;
16549 }
16550 if (adapter->tsf_cap_ctx.tsf_capture_state == TSF_CAP_STATE) {
16551 hddLog(VOS_TRACE_LEVEL_INFO,
16552 FL("current in capture state, pls reset"));
16553 buf[0] = TSF_CURRENT_IN_CAP_STATE;
16554 } else {
16555 hddLog(VOS_TRACE_LEVEL_INFO, FL("ioctl issue cap tsf cmd"));
16556 buf[0] = TSF_RETURN;
16557 cap_tsf_params.session_id = adapter->sessionId;
16558 cap_tsf_params.tsf_rsp_cb_func = hdd_tsf_cb;
16559 cap_tsf_params.tsf_rsp_cb_ctx = adapter;
16560
16561 vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
16562 adapter->tsf_cap_ctx.tsf_capture_state = TSF_CAP_STATE;
16563 adapter->tsf_cap_ctx.tsf_get_state = TSF_CURRENT_IN_CAP_STATE;
16564 vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
16565
16566 ret = sme_capture_tsf_req(hdd_ctx->hHal, cap_tsf_params);
16567
16568 if (ret != VOS_STATUS_SUCCESS) {
16569 hddLog(VOS_TRACE_LEVEL_ERROR, FL("capture fail"));
16570 buf[0] = TSF_CAPTURE_FAIL;
16571 vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
16572 adapter->tsf_cap_ctx.tsf_capture_state = TSF_IDLE;
16573 vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
16574 return -EINVAL;
16575 }
16576 /* wait till we get a response from fw */
16577 status = vos_wait_single_event(&adapter->tsf_cap_ctx.
16578 tsf_capture_done_event,
16579 HDD_TSF_CAP_REQ_TIMEOUT);
16580
16581 if (!VOS_IS_STATUS_SUCCESS(status)) {
16582 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
16583 ("capture tsf vos wait for single_event failed!! %d"),
16584 adapter->tsf_cap_ctx.tsf_get_state);
16585
16586 vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
16587 adapter->tsf_cap_ctx.tsf_capture_state = TSF_IDLE;
16588 vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
16589
16590 return -EINVAL;
16591 }
16592 }
16593 buf[0] = TSF_RETURN;
16594 hddLog(VOS_TRACE_LEVEL_INFO,
16595 FL("ioctl return cap tsf cmd, ret = %d"), ret);
16596 return ret;
16597}
16598
16599/**
16600 * hdd_indicate_tsf() - return tsf to uplayer
16601 *
16602 * @adapter: pointer to adapter
16603 * @buf: pointer to uplayer buf
16604 * @len : the length of buf
16605 *
16606 * This function returns tsf value to uplayer.
16607 *
16608 * Return: Describe the execute result of this routine
16609 */
16610int hdd_indicate_tsf(hdd_adapter_t *adapter, uint32_t *buf, int len)
16611{
16612 int ret = 0;
16613 hdd_station_ctx_t *hdd_sta_ctx;
16614 hdd_context_t *hdd_ctx;
16615 tSirCapTsfParams cap_tsf_params;
16616 VOS_STATUS status;
16617
16618 if (adapter == NULL || buf == NULL) {
16619 hddLog(VOS_TRACE_LEVEL_ERROR,
16620 FL("invalid pointer"));
16621 return -EINVAL;
16622 }
16623 if (len != 3)
16624 return -EINVAL;
16625
16626 buf [1] = 0;
16627 buf [2] = 0;
16628 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
16629
16630 if (wlan_hdd_validate_context(hdd_ctx)) {
16631 hddLog(VOS_TRACE_LEVEL_ERROR,
16632 FL("invalid hdd ctx"));
16633 return -EINVAL;
16634 }
16635 if (adapter->device_mode == WLAN_HDD_INFRA_STATION ||
16636 adapter->device_mode == WLAN_HDD_P2P_CLIENT) {
16637 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
16638 if (hdd_sta_ctx->conn_info.connState !=
16639 eConnectionState_Associated) {
16640
16641 hddLog(VOS_TRACE_LEVEL_INFO,
16642 FL("failed to cap tsf, not connect with ap"));
16643 buf[0] = TSF_STA_NOT_CONNECTED_NO_TSF;
16644 return ret;
16645 }
16646 }
16647 if ((adapter->device_mode == WLAN_HDD_SOFTAP ||
16648 adapter->device_mode == WLAN_HDD_P2P_GO) &&
16649 !(test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags))) {
16650 hddLog(VOS_TRACE_LEVEL_INFO,
16651 FL("Soft AP / P2p GO not beaconing"));
16652 buf[0] = TSF_SAP_NOT_STARTED_NO_TSF;
16653 return ret;
16654 }
16655
16656 if (adapter->tsf_cap_ctx.tsf_capture_state != TSF_CAP_STATE ||
16657 adapter->tsf_cap_ctx.tsf_get_state != TSF_CURRENT_IN_CAP_STATE ) {
16658 hddLog(VOS_TRACE_LEVEL_INFO,
16659 FL("Not in capture state,Enter capture state first"));
16660 buf[0] = TSF_GET_FAIL;
16661 } else {
16662 hddLog(VOS_TRACE_LEVEL_INFO, FL("ioctl issue cap tsf cmd"));
16663 cap_tsf_params.session_id = adapter->sessionId;
16664 cap_tsf_params.tsf_rsp_cb_func = hdd_tsf_cb;
16665 cap_tsf_params.tsf_rsp_cb_ctx = adapter;
16666
16667 ret = sme_get_tsf_req(hdd_ctx->hHal, cap_tsf_params);
16668
16669 if (ret != VOS_STATUS_SUCCESS) {
16670 hddLog(VOS_TRACE_LEVEL_ERROR, FL("capture fail"));
16671 buf[0] = TSF_CAPTURE_FAIL;
16672 vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
16673 adapter->tsf_cap_ctx.tsf_capture_state = TSF_IDLE;
16674 vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
16675 return -EINVAL;
16676 }
16677 /* wait till we get a response from fw */
16678 status = vos_wait_single_event(&adapter->tsf_cap_ctx.
16679 tsf_capture_done_event,
16680 HDD_TSF_GET_REQ_TIMEOUT);
16681
16682 if (!VOS_IS_STATUS_SUCCESS(status)) {
16683 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
16684 ("capture tsf vos wait for single_event failed!! %d"),
16685 status);
16686
16687 vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
16688 adapter->tsf_cap_ctx.tsf_capture_state = TSF_IDLE;
16689 vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
16690 return status;
16691 }
16692 buf[1] = adapter->tsf_cap_ctx.tsf_low;
16693 buf[2] = adapter->tsf_cap_ctx.tsf_high;
16694
16695 hddLog(VOS_TRACE_LEVEL_INFO,
16696 FL("get tsf cmd,status=%u, tsf_low=%u, tsf_high=%u"),
16697 buf[0], buf[1], buf[2]);
16698 }
16699 hddLog(VOS_TRACE_LEVEL_INFO,
16700 FL("ioctl return cap tsf cmd, ret = %d"), ret);
16701 return ret;
16702}
16703
16704void wlan_hdd_tsf_init(hdd_adapter_t *adapter)
16705{
16706
16707 if (adapter == NULL) {
16708 hddLog(VOS_TRACE_LEVEL_ERROR,
16709 FL("TSF init on a null adapter!"));
16710 return;
16711 }
16712
16713 adapter->tsf_cap_ctx.tsf_get_state = TSF_RETURN;
16714 adapter->tsf_cap_ctx.tsf_capture_state = TSF_IDLE;
16715 vos_event_init(&adapter->tsf_cap_ctx.tsf_capture_done_event);
16716 vos_spin_lock_init(&adapter->tsf_cap_ctx.tsf_lock);
16717 adapter->tsf_cap_ctx.tsf_high = 0;
16718 adapter->tsf_cap_ctx.tsf_low = 0;
16719}
16720
16721#endif
16722
Jeff Johnson295189b2012-06-20 16:38:30 -070016723//Register the module init/exit functions
16724module_init(hdd_module_init);
16725module_exit(hdd_module_exit);
16726
16727MODULE_LICENSE("Dual BSD/GPL");
16728MODULE_AUTHOR("Qualcomm Atheros, Inc.");
16729MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
16730
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070016731module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
16732 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -070016733
Jeff Johnson76052702013-04-16 13:55:05 -070016734module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -070016735 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Arif Hussain66559122013-11-21 10:11:40 -080016736
16737module_param(enable_dfs_chan_scan, int,
16738 S_IRUSR | S_IRGRP | S_IROTH);
16739
16740module_param(enable_11d, int,
16741 S_IRUSR | S_IRGRP | S_IROTH);
16742
16743module_param(country_code, charp,
16744 S_IRUSR | S_IRGRP | S_IROTH);