blob: 7536f9aeb29ded084f8708bf9c1325c3e0c36d0b [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Masti, Narayanraddi44b0db02015-12-22 11:54:35 +05302 * Copyright (c) 2012-2016 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, Sridhar3714c4d2016-06-22 15:19:12 +05303059 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3060 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3061
3062 /* if not associated, no need to proceed with reassoc */
3063 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
3064 hddLog(LOG1, FL("Not associated!"));
3065 return eHAL_STATUS_FAILURE;
3066 }
3067
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05303068 ret = hdd_parse_reassoc_command_v1_data(value, targetApBssid, &channel);
3069 if (ret) {
Selvaraj, Sridhar3714c4d2016-06-22 15:19:12 +05303070 hddLog(LOGE, FL("Failed to parse reassoc command data"));
3071 return eHAL_STATUS_FAILURE;
3072 }
3073
3074 /* if the target bssid is same as currently associated AP,
3075 then no need to proceed with reassoc */
3076 if (vos_mem_compare(targetApBssid,
3077 pHddStaCtx->conn_info.bssId,
3078 sizeof(tSirMacAddr))) {
3079 hddLog(LOG1, FL("Reassoc BSSID is same as currently associated AP bssid"));
3080 return eHAL_STATUS_FAILURE;
3081 }
3082
3083 /* Check channel number is a valid channel number */
3084 if (VOS_STATUS_SUCCESS !=
3085 wlan_hdd_validate_operation_channel(pAdapter, channel)) {
3086 hddLog(LOGE, FL("Invalid Channel [%d]"), channel);
3087 return eHAL_STATUS_FAILURE;
3088 }
3089
3090 /* Proceed with reassoc */
3091 wlan_hdd_fastreassoc_handoff_request(pHddCtx, channel, targetApBssid);
3092
3093 /* Proceed with scan/roam */
3094 csr_fastroam_neighbor_ap_event(pAdapter, channel, targetApBssid);
3095
3096 return eHAL_STATUS_SUCCESS;
3097}
3098
3099/**
3100 * hdd_assign_reassoc_handoff - Set handoff source as REASSOC
3101 * @handoffInfo: Pointer to the csr Handoff Request.
3102 *
3103 * Return: None
3104 */
3105#ifndef QCA_WIFI_ISOC
3106static inline void hdd_assign_reassoc_handoff(tCsrHandoffRequest *handoffInfo)
3107{
3108 handoffInfo->src = REASSOC;
3109}
3110#else
3111static inline void hdd_assign_reassoc_handoff(tCsrHandoffRequest *handoffInfo)
3112{
3113}
3114#endif
3115
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003116static int hdd_driver_command(hdd_adapter_t *pAdapter,
3117 hdd_priv_data_t *ppriv_data)
Jeff Johnson295189b2012-06-20 16:38:30 -07003118{
Jeff Johnson295189b2012-06-20 16:38:30 -07003119 hdd_priv_data_t priv_data;
3120 tANI_U8 *command = NULL;
Kaushik, Sushant96122442014-10-21 16:40:18 +05303121 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3122 hdd_scaninfo_t *pScanInfo = NULL;
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003123 int ret = 0;
Kaushik, Sushant96122442014-10-21 16:40:18 +05303124 int status;
Anand N Sunkade9adb1b2015-07-29 09:56:45 +05303125#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0))
3126 struct cfg80211_mgmt_tx_params params;
3127#endif
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05303128
3129 ENTER();
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003130 /*
3131 * Note that valid pointers are provided by caller
3132 */
Jeff Johnson295189b2012-06-20 16:38:30 -07003133
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003134 /* copy to local struct to avoid numerous changes to legacy code */
3135 priv_data = *ppriv_data;
Jeff Johnson295189b2012-06-20 16:38:30 -07003136
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003137 if (priv_data.total_len <= 0 ||
3138 priv_data.total_len > WLAN_PRIV_DATA_MAX_LEN)
Sameer Thalappil8ef3a0e2013-04-05 14:36:04 -07003139 {
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003140 hddLog(VOS_TRACE_LEVEL_WARN,
3141 "%s:invalid priv_data.total_len(%d)!!!", __func__,
3142 priv_data.total_len);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003143 ret = -EINVAL;
3144 goto exit;
3145 }
Kaushik, Sushant96122442014-10-21 16:40:18 +05303146 status = wlan_hdd_validate_context(pHddCtx);
3147 if (0 != status)
3148 {
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05303149 ret = -EINVAL;
3150 goto exit;
Kaushik, Sushant96122442014-10-21 16:40:18 +05303151 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003152 /* Allocate +1 for '\0' */
3153 command = kmalloc(priv_data.total_len + 1, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07003154 if (!command)
3155 {
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003156 hddLog(VOS_TRACE_LEVEL_ERROR,
3157 "%s: failed to allocate memory", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003158 ret = -ENOMEM;
3159 goto exit;
3160 }
3161
3162 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
3163 {
3164 ret = -EFAULT;
3165 goto exit;
3166 }
3167
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003168 /* Make sure the command is NUL-terminated */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003169 command[priv_data.total_len] = '\0';
3170
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003171 /* at one time the following block of code was conditional. braces
3172 * have been retained to avoid re-indenting the legacy code
3173 */
Jeff Johnson295189b2012-06-20 16:38:30 -07003174 {
3175 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
3176
3177 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07003178 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -07003179
3180 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
3181 {
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303182 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3183 TRACE_CODE_HDD_P2P_DEV_ADDR_IOCTL,
3184 pAdapter->sessionId, (unsigned)
3185 (*(pHddCtx->p2pDeviceAddress.bytes+2)<<24 |
3186 *(pHddCtx->p2pDeviceAddress.bytes+3)<<16 |
3187 *(pHddCtx->p2pDeviceAddress.bytes+4)<<8 |
3188 *(pHddCtx->p2pDeviceAddress.bytes+5))));
Jeff Johnson295189b2012-06-20 16:38:30 -07003189 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
3190 sizeof(tSirMacAddr)))
3191 {
3192 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Arif Hussain6d2a3322013-11-17 19:50:10 -08003193 "%s: failed to copy data to user buffer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003194 ret = -EFAULT;
3195 }
3196 }
Amar Singhal0974e402013-02-12 14:27:46 -08003197 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07003198 {
Amar Singhal0974e402013-02-12 14:27:46 -08003199 tANI_U8 *ptr = command ;
Srinivas Girigowdade697412013-02-14 16:31:48 -08003200
Jeff Johnson295189b2012-06-20 16:38:30 -07003201 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -08003202
3203 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -07003204 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07003205 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -08003206 "%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 +05303207 if(VOS_FTM_MODE != hdd_get_conparam())
3208 {
3209 /* Change band request received */
3210 ret = hdd_setBand_helper(pAdapter->dev, ptr);
3211 if(ret < 0)
3212 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
3213 "%s: failed to set band ret=%d", __func__, ret);
3214 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08003215 }
Kiet Lamf040f472013-11-20 21:15:23 +05303216 else if(strncmp(command, "SETWMMPS", 8) == 0)
3217 {
3218 tANI_U8 *ptr = command;
3219 ret = hdd_wmmps_helper(pAdapter, ptr);
3220 }
Agarwal Ashishef54a182014-12-16 15:07:31 +05303221
3222 else if(strncmp(command, "TDLSSCAN", 8) == 0)
3223 {
3224 tANI_U8 *ptr = command;
3225 ret = hdd_set_tdls_scan_type(pAdapter, ptr);
3226 }
3227
Jeff Johnson32d95a32012-09-10 13:15:23 -07003228 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
3229 {
3230 char *country_code;
3231
3232 country_code = command + 8;
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07003233
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07003234 INIT_COMPLETION(pAdapter->change_country_code);
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07003235 hdd_checkandupdate_dfssetting(pAdapter, country_code);
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -07003236#ifndef CONFIG_ENABLE_LINUX_REG
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +05303237 hdd_checkandupdate_phymode(pAdapter, country_code);
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -07003238#endif
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07003239 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal,
3240 (void *)(tSmeChangeCountryCallback)
3241 wlan_hdd_change_country_code_callback,
Abhishek Singha306a442013-11-07 18:39:01 +05303242 country_code, pAdapter, pHddCtx->pvosContext, eSIR_TRUE, eSIR_TRUE);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07003243 if (eHAL_STATUS_SUCCESS == ret)
3244 {
3245 ret = wait_for_completion_interruptible_timeout(
3246 &pAdapter->change_country_code,
3247 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
3248 if (0 >= ret)
3249 {
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003250 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: SME while setting country code timed out %d",
c_hpothu6ff1c3c2013-10-01 19:01:57 +05303251 __func__, ret);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07003252 }
3253 }
3254 else
Jeff Johnson32d95a32012-09-10 13:15:23 -07003255 {
3256 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003257 "%s: SME Change Country code fail ret=%d", __func__, ret);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07003258 ret = -EINVAL;
Jeff Johnson32d95a32012-09-10 13:15:23 -07003259 }
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07003260
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07003261 }
3262 /*
3263 command should be a string having format
3264 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
3265 */
Amar Singhal0974e402013-02-12 14:27:46 -08003266 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07003267 {
Amar Singhal0974e402013-02-12 14:27:46 -08003268 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07003269
3270 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003271 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07003272
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -08003273 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -07003274 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -08003275 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
3276 {
3277 int suspend = 0;
3278 tANI_U8 *ptr = (tANI_U8*)command + 15;
3279
3280 suspend = *ptr - '0';
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303281 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3282 TRACE_CODE_HDD_SETSUSPENDMODE_IOCTL,
3283 pAdapter->sessionId, suspend));
Sameer Thalappil45931fb2013-02-01 11:18:05 -08003284 hdd_set_wlan_suspend_mode(suspend);
3285 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08003286#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
3287 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
3288 {
3289 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003290 tANI_S8 rssi = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08003291 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
3292 eHalStatus status = eHAL_STATUS_SUCCESS;
3293
3294 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
3295 value = value + 15;
3296
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003297 /* Convert the value from ascii to integer */
3298 ret = kstrtos8(value, 10, &rssi);
3299 if (ret < 0)
3300 {
3301 /* If the input value is greater than max value of datatype, then also
3302 kstrtou8 fails */
3303 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3304 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdafa7157d2013-10-31 10:14:22 -07003305 __func__,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003306 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
3307 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
3308 ret = -EINVAL;
3309 goto exit;
3310 }
3311
Srinivas Girigowdade697412013-02-14 16:31:48 -08003312 lookUpThreshold = abs(rssi);
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003313
Srinivas Girigowdade697412013-02-14 16:31:48 -08003314 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
3315 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
3316 {
3317 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3318 "Neighbor lookup threshold value %d is out of range"
3319 " (Min: %d Max: %d)", lookUpThreshold,
3320 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
3321 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
3322 ret = -EINVAL;
3323 goto exit;
3324 }
3325
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303326 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3327 TRACE_CODE_HDD_SETROAMTRIGGER_IOCTL,
3328 pAdapter->sessionId, lookUpThreshold));
Srinivas Girigowdade697412013-02-14 16:31:48 -08003329 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3330 "%s: Received Command to Set Roam trigger"
3331 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
3332
3333 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
3334 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
3335 if (eHAL_STATUS_SUCCESS != status)
3336 {
3337 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3338 "%s: Failed to set roam trigger, try again", __func__);
3339 ret = -EPERM;
3340 goto exit;
3341 }
3342
3343 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
mukul sharmad6e1fdd2014-06-23 19:19:09 +05303344 pHddCtx->cfg_ini->nNeighborReassocRssiThreshold = lookUpThreshold + 5;
Srinivas Girigowdade697412013-02-14 16:31:48 -08003345 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
3346 }
3347 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
3348 {
3349 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
3350 int rssi = (-1) * lookUpThreshold;
3351 char extra[32];
3352 tANI_U8 len = 0;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303353 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3354 TRACE_CODE_HDD_GETROAMTRIGGER_IOCTL,
3355 pAdapter->sessionId, lookUpThreshold));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003356 len = scnprintf(extra, sizeof(extra), "%s %d", command, rssi);
Srinivas Girigowda91719232015-07-13 15:10:10 +05303357 len = VOS_MIN(priv_data.total_len, len + 1);
3358 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdade697412013-02-14 16:31:48 -08003359 {
3360 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3361 "%s: failed to copy data to user buffer", __func__);
3362 ret = -EFAULT;
3363 goto exit;
3364 }
3365 }
3366 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
3367 {
3368 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003369 tANI_U8 roamScanPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003370 tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003371
Srinivas Girigowdade697412013-02-14 16:31:48 -08003372 /* input refresh period is in terms of seconds */
3373 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
3374 value = value + 18;
3375 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003376 ret = kstrtou8(value, 10, &roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08003377 if (ret < 0)
3378 {
3379 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003380 kstrtou8 fails */
Srinivas Girigowdade697412013-02-14 16:31:48 -08003381 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003382 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdade697412013-02-14 16:31:48 -08003383 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07003384 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
3385 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08003386 ret = -EINVAL;
3387 goto exit;
3388 }
3389
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003390 if ((roamScanPeriod < (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000)) ||
3391 (roamScanPeriod > (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000)))
Srinivas Girigowdade697412013-02-14 16:31:48 -08003392 {
3393 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003394 "Roam scan period value %d is out of range"
3395 " (Min: %d Max: %d)", roamScanPeriod,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07003396 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
3397 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08003398 ret = -EINVAL;
3399 goto exit;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303400 }
3401 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3402 TRACE_CODE_HDD_SETROAMSCANPERIOD_IOCTL,
3403 pAdapter->sessionId, roamScanPeriod));
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003404 neighborEmptyScanRefreshPeriod = roamScanPeriod * 1000;
Srinivas Girigowdade697412013-02-14 16:31:48 -08003405
3406 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3407 "%s: Received Command to Set roam scan period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003408 " (Empty Scan refresh period) = %d", __func__, roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08003409
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003410 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod;
3411 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08003412 }
3413 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
3414 {
3415 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
3416 char extra[32];
3417 tANI_U8 len = 0;
3418
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303419 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3420 TRACE_CODE_HDD_GETROAMSCANPERIOD_IOCTL,
3421 pAdapter->sessionId, nEmptyScanRefreshPeriod));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003422 len = scnprintf(extra, sizeof(extra), "%s %d",
3423 "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08003424 /* Returned value is in units of seconds */
Ratnam Rachuria72ba112015-07-17 13:27:03 +05303425 len = VOS_MIN(priv_data.total_len, len + 1);
3426 if (copy_to_user(priv_data.buf, &extra, len)) {
Srinivas Girigowdade697412013-02-14 16:31:48 -08003427 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3428 "%s: failed to copy data to user buffer", __func__);
3429 ret = -EFAULT;
3430 goto exit;
3431 }
3432 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003433 else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0)
3434 {
3435 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003436 tANI_U8 roamScanRefreshPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003437 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003438
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003439 /* input refresh period is in terms of seconds */
3440 /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */
3441 value = value + 25;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003442
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003443 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003444 ret = kstrtou8(value, 10, &roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003445 if (ret < 0)
3446 {
3447 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003448 kstrtou8 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003449 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003450 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003451 __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003452 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
3453 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
3454 ret = -EINVAL;
3455 goto exit;
3456 }
3457
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003458 if ((roamScanRefreshPeriod < (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000)) ||
3459 (roamScanRefreshPeriod > (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000)))
3460 {
3461 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3462 "Neighbor scan results refresh period value %d is out of range"
3463 " (Min: %d Max: %d)", roamScanRefreshPeriod,
3464 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
3465 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
3466 ret = -EINVAL;
3467 goto exit;
3468 }
3469 neighborScanRefreshPeriod = roamScanRefreshPeriod * 1000;
3470
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003471 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3472 "%s: Received Command to Set roam scan refresh period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003473 " (Scan refresh period) = %d", __func__, roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003474
3475 pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod;
3476 sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
3477 }
3478 else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0)
3479 {
3480 tANI_U16 value = sme_getNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
3481 char extra[32];
3482 tANI_U8 len = 0;
3483
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003484 len = scnprintf(extra, sizeof(extra), "%s %d",
3485 "GETROAMSCANREFRESHPERIOD", (value/1000));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003486 /* Returned value is in units of seconds */
Ratnam Rachuri2c9d6702015-07-17 13:25:16 +05303487 len = VOS_MIN(priv_data.total_len, len + 1);
3488 if (copy_to_user(priv_data.buf, &extra, len)) {
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003489 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3490 "%s: failed to copy data to user buffer", __func__);
3491 ret = -EFAULT;
3492 goto exit;
3493 }
3494 }
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07003495#ifdef FEATURE_WLAN_LFR
3496 /* SETROAMMODE */
3497 else if (strncmp(command, "SETROAMMODE", SIZE_OF_SETROAMMODE) == 0)
3498 {
3499 tANI_U8 *value = command;
3500 tANI_BOOLEAN roamMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
3501
3502 /* Move pointer to ahead of SETROAMMODE<delimiter> */
3503 value = value + SIZE_OF_SETROAMMODE + 1;
3504
3505 /* Convert the value from ascii to integer */
3506 ret = kstrtou8(value, SIZE_OF_SETROAMMODE, &roamMode);
3507 if (ret < 0)
3508 {
3509 /* If the input value is greater than max value of datatype, then also
3510 kstrtou8 fails */
3511 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3512 "%s: kstrtou8 failed range [%d - %d]", __func__,
3513 CFG_LFR_FEATURE_ENABLED_MIN,
3514 CFG_LFR_FEATURE_ENABLED_MAX);
3515 ret = -EINVAL;
3516 goto exit;
3517 }
3518 if ((roamMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
3519 (roamMode > CFG_LFR_FEATURE_ENABLED_MAX))
3520 {
3521 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3522 "Roam Mode value %d is out of range"
3523 " (Min: %d Max: %d)", roamMode,
3524 CFG_LFR_FEATURE_ENABLED_MIN,
3525 CFG_LFR_FEATURE_ENABLED_MAX);
3526 ret = -EINVAL;
3527 goto exit;
3528 }
3529
3530 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3531 "%s: Received Command to Set Roam Mode = %d", __func__, roamMode);
3532 /*
3533 * Note that
3534 * SETROAMMODE 0 is to enable LFR while
3535 * SETROAMMODE 1 is to disable LFR, but
3536 * NotifyIsFastRoamIniFeatureEnabled 0/1 is to enable/disable.
3537 * So, we have to invert the value to call sme_UpdateIsFastRoamIniFeatureEnabled.
3538 */
3539 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
3540 roamMode = CFG_LFR_FEATURE_ENABLED_MAX; /* Roam enable */
3541 else
3542 roamMode = CFG_LFR_FEATURE_ENABLED_MIN; /* Roam disable */
3543
3544 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = roamMode;
3545 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), roamMode);
3546 }
3547 /* GETROAMMODE */
Mahesh A Saptasagarec7d1092015-04-02 13:41:34 +05303548 else if (strncmp(command, "GETROAMMODE", SIZE_OF_GETROAMMODE) == 0)
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07003549 {
3550 tANI_BOOLEAN roamMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
3551 char extra[32];
3552 tANI_U8 len = 0;
3553
3554 /*
3555 * roamMode value shall be inverted because the sementics is different.
3556 */
3557 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
3558 roamMode = CFG_LFR_FEATURE_ENABLED_MAX;
3559 else
3560 roamMode = CFG_LFR_FEATURE_ENABLED_MIN;
3561
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003562 len = scnprintf(extra, sizeof(extra), "%s %d", command, roamMode);
Ratnam Rachuri28693eb2015-07-17 13:23:42 +05303563 len = VOS_MIN(priv_data.total_len, len + 1);
3564 if (copy_to_user(priv_data.buf, &extra, len)) {
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07003565 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3566 "%s: failed to copy data to user buffer", __func__);
3567 ret = -EFAULT;
3568 goto exit;
3569 }
3570 }
3571#endif
Srinivas Girigowdade697412013-02-14 16:31:48 -08003572#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003573#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -08003574 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
3575 {
3576 tANI_U8 *value = command;
3577 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
3578
3579 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
3580 value = value + 13;
3581 /* Convert the value from ascii to integer */
3582 ret = kstrtou8(value, 10, &roamRssiDiff);
3583 if (ret < 0)
3584 {
3585 /* If the input value is greater than max value of datatype, then also
3586 kstrtou8 fails */
3587 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3588 "%s: kstrtou8 failed range [%d - %d]", __func__,
3589 CFG_ROAM_RSSI_DIFF_MIN,
3590 CFG_ROAM_RSSI_DIFF_MAX);
3591 ret = -EINVAL;
3592 goto exit;
3593 }
3594
3595 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
3596 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
3597 {
3598 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3599 "Roam rssi diff value %d is out of range"
3600 " (Min: %d Max: %d)", roamRssiDiff,
3601 CFG_ROAM_RSSI_DIFF_MIN,
3602 CFG_ROAM_RSSI_DIFF_MAX);
3603 ret = -EINVAL;
3604 goto exit;
3605 }
3606
3607 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3608 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
3609
3610 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
3611 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
3612 }
Mahesh A Saptasagarec7d1092015-04-02 13:41:34 +05303613 else if (strncmp(command, "GETROAMDELTA", 12) == 0)
Srinivas Girigowdade697412013-02-14 16:31:48 -08003614 {
3615 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
3616 char extra[32];
3617 tANI_U8 len = 0;
3618
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303619 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3620 TRACE_CODE_HDD_GETROAMDELTA_IOCTL,
3621 pAdapter->sessionId, roamRssiDiff));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003622 len = scnprintf(extra, sizeof(extra), "%s %d",
3623 command, roamRssiDiff);
Ratnam Rachuri22a3b402015-07-17 13:21:49 +05303624 len = VOS_MIN(priv_data.total_len, len + 1);
3625 if (copy_to_user(priv_data.buf, &extra, len)) {
Srinivas Girigowdade697412013-02-14 16:31:48 -08003626 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3627 "%s: failed to copy data to user buffer", __func__);
3628 ret = -EFAULT;
3629 goto exit;
3630 }
3631 }
3632#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003633#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -08003634 else if (strncmp(command, "GETBAND", 7) == 0)
3635 {
3636 int band = -1;
3637 char extra[32];
3638 tANI_U8 len = 0;
3639 hdd_getBand_helper(pHddCtx, &band);
3640
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303641 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3642 TRACE_CODE_HDD_GETBAND_IOCTL,
3643 pAdapter->sessionId, band));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003644 len = scnprintf(extra, sizeof(extra), "%s %d", command, band);
Ratnam Rachuri52139592015-07-17 13:17:29 +05303645 len = VOS_MIN(priv_data.total_len, len + 1);
3646 if (copy_to_user(priv_data.buf, &extra, len)) {
Srinivas Girigowdade697412013-02-14 16:31:48 -08003647 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3648 "%s: failed to copy data to user buffer", __func__);
3649 ret = -EFAULT;
3650 goto exit;
3651 }
3652 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08003653 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
3654 {
3655 tANI_U8 *value = command;
3656 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
3657 tANI_U8 numChannels = 0;
3658 eHalStatus status = eHAL_STATUS_SUCCESS;
3659
3660 status = hdd_parse_channellist(value, ChannelList, &numChannels);
3661 if (eHAL_STATUS_SUCCESS != status)
3662 {
3663 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3664 "%s: Failed to parse channel list information", __func__);
3665 ret = -EINVAL;
3666 goto exit;
3667 }
3668
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303669 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3670 TRACE_CODE_HDD_SETROAMSCANCHANNELS_IOCTL,
3671 pAdapter->sessionId, numChannels));
Srinivas Girigowdade697412013-02-14 16:31:48 -08003672 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
3673 {
3674 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3675 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
3676 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
3677 ret = -EINVAL;
3678 goto exit;
3679 }
3680 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
3681 numChannels);
3682 if (eHAL_STATUS_SUCCESS != status)
3683 {
3684 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3685 "%s: Failed to update channel list information", __func__);
3686 ret = -EINVAL;
3687 goto exit;
3688 }
3689 }
3690 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
3691 {
3692 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
3693 tANI_U8 numChannels = 0;
Jeff Johnson51b67782013-04-05 12:35:41 -07003694 tANI_U8 j = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08003695 char extra[128] = {0};
Jeff Johnson51b67782013-04-05 12:35:41 -07003696 int len;
Srinivas Girigowdade697412013-02-14 16:31:48 -08003697
3698 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
3699 ChannelList, &numChannels ))
3700 {
3701 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3702 "%s: failed to get roam scan channel list", __func__);
3703 ret = -EFAULT;
3704 goto exit;
3705 }
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303706 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3707 TRACE_CODE_HDD_GETROAMSCANCHANNELS_IOCTL,
3708 pAdapter->sessionId, numChannels));
Srinivas Girigowdade697412013-02-14 16:31:48 -08003709 /* output channel list is of the format
3710 [Number of roam scan channels][Channel1][Channel2]... */
3711 /* copy the number of channels in the 0th index */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003712 len = scnprintf(extra, sizeof(extra), "%s %d", command, numChannels);
Sushant Kaushika08ca192015-09-16 15:52:04 +05303713 for (j = 0; (j < numChannels) && len <= sizeof(extra); j++)
Srinivas Girigowdade697412013-02-14 16:31:48 -08003714 {
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003715 len += scnprintf(extra + len, sizeof(extra) - len, " %d",
3716 ChannelList[j]);
Srinivas Girigowdade697412013-02-14 16:31:48 -08003717 }
3718
Sushant Kaushikc9b8be52015-07-15 16:41:27 +05303719 len = VOS_MIN(priv_data.total_len, len + 1);
3720 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdade697412013-02-14 16:31:48 -08003721 {
3722 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3723 "%s: failed to copy data to user buffer", __func__);
3724 ret = -EFAULT;
3725 goto exit;
3726 }
3727 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003728 else if (strncmp(command, "GETCCXMODE", 10) == 0)
3729 {
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003730 tANI_BOOLEAN eseMode = sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003731 char extra[32];
3732 tANI_U8 len = 0;
3733
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003734 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003735 then this operation is not permitted (return FAILURE) */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003736 if (eseMode &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003737 hdd_is_okc_mode_enabled(pHddCtx) &&
3738 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
3739 {
3740 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003741 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003742 " hence this operation is not permitted!", __func__);
3743 ret = -EPERM;
3744 goto exit;
3745 }
3746
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003747 len = scnprintf(extra, sizeof(extra), "%s %d",
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003748 "GETCCXMODE", eseMode);
Sushant Kaushikf8abd352015-07-15 16:37:49 +05303749 len = VOS_MIN(priv_data.total_len, len + 1);
3750 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003751 {
3752 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3753 "%s: failed to copy data to user buffer", __func__);
3754 ret = -EFAULT;
3755 goto exit;
3756 }
3757 }
3758 else if (strncmp(command, "GETOKCMODE", 10) == 0)
3759 {
3760 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
3761 char extra[32];
3762 tANI_U8 len = 0;
3763
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003764 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003765 then this operation is not permitted (return FAILURE) */
3766 if (okcMode &&
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003767 sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003768 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
3769 {
3770 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003771 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003772 " hence this operation is not permitted!", __func__);
3773 ret = -EPERM;
3774 goto exit;
3775 }
3776
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003777 len = scnprintf(extra, sizeof(extra), "%s %d",
3778 "GETOKCMODE", okcMode);
Sushant Kaushikbc2fb5c2015-07-15 16:43:16 +05303779 len = VOS_MIN(priv_data.total_len, len + 1);
3780 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003781 {
3782 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3783 "%s: failed to copy data to user buffer", __func__);
3784 ret = -EFAULT;
3785 goto exit;
3786 }
3787 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07003788 else if (strncmp(command, "GETFASTROAM", 11) == 0)
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003789 {
3790 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
3791 char extra[32];
3792 tANI_U8 len = 0;
3793
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003794 len = scnprintf(extra, sizeof(extra), "%s %d",
3795 "GETFASTROAM", lfrMode);
Sushant Kaushik4da7ec92015-07-15 16:39:32 +05303796 len = VOS_MIN(priv_data.total_len, len + 1);
3797 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003798 {
3799 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3800 "%s: failed to copy data to user buffer", __func__);
3801 ret = -EFAULT;
3802 goto exit;
3803 }
3804 }
3805 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
3806 {
3807 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
3808 char extra[32];
3809 tANI_U8 len = 0;
3810
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003811 len = scnprintf(extra, sizeof(extra), "%s %d",
3812 "GETFASTTRANSITION", ft);
Sushant Kaushik231a4452015-07-15 16:23:56 +05303813 len = VOS_MIN(priv_data.total_len, len + 1);
3814 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003815 {
3816 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3817 "%s: failed to copy data to user buffer", __func__);
3818 ret = -EFAULT;
3819 goto exit;
3820 }
3821 }
3822 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
3823 {
3824 tANI_U8 *value = command;
3825 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
3826
3827 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
3828 value = value + 26;
3829 /* Convert the value from ascii to integer */
3830 ret = kstrtou8(value, 10, &minTime);
3831 if (ret < 0)
3832 {
3833 /* If the input value is greater than max value of datatype, then also
3834 kstrtou8 fails */
3835 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3836 "%s: kstrtou8 failed range [%d - %d]", __func__,
3837 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
3838 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
3839 ret = -EINVAL;
3840 goto exit;
3841 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003842 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
3843 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
3844 {
3845 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3846 "scan min channel time value %d is out of range"
3847 " (Min: %d Max: %d)", minTime,
3848 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
3849 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
3850 ret = -EINVAL;
3851 goto exit;
3852 }
3853
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303854 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3855 TRACE_CODE_HDD_SETROAMSCANCHANNELMINTIME_IOCTL,
3856 pAdapter->sessionId, minTime));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003857 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3858 "%s: Received Command to change channel min time = %d", __func__, minTime);
3859
3860 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
3861 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
3862 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003863 else if (strncmp(command, "SENDACTIONFRAME", 15) == 0)
3864 {
3865 tANI_U8 *value = command;
3866 tANI_U8 channel = 0;
3867 tANI_U8 dwellTime = 0;
3868 tANI_U8 bufLen = 0;
3869 tANI_U8 *buf = NULL;
3870 tSirMacAddr targetApBssid;
3871 eHalStatus status = eHAL_STATUS_SUCCESS;
3872 struct ieee80211_channel chan;
3873 tANI_U8 finalLen = 0;
3874 tANI_U8 *finalBuf = NULL;
3875 tANI_U8 temp = 0;
3876 u64 cookie;
3877 hdd_station_ctx_t *pHddStaCtx = NULL;
3878 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3879
3880 /* if not associated, no need to send action frame */
3881 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3882 {
3883 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
3884 ret = -EINVAL;
3885 goto exit;
3886 }
3887
3888 status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel,
3889 &dwellTime, &buf, &bufLen);
3890 if (eHAL_STATUS_SUCCESS != status)
3891 {
3892 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3893 "%s: Failed to parse send action frame data", __func__);
3894 ret = -EINVAL;
3895 goto exit;
3896 }
3897
3898 /* if the target bssid is different from currently associated AP,
3899 then no need to send action frame */
3900 if (VOS_TRUE != vos_mem_compare(targetApBssid,
3901 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
3902 {
3903 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__);
3904 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07003905 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08003906 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003907 goto exit;
3908 }
3909
3910 /* if the channel number is different from operating channel then
3911 no need to send action frame */
3912 if (channel != pHddStaCtx->conn_info.operationChannel)
3913 {
3914 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3915 "%s: channel(%d) is different from operating channel(%d)",
3916 __func__, channel, pHddStaCtx->conn_info.operationChannel);
3917 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07003918 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08003919 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003920 goto exit;
3921 }
3922 chan.center_freq = sme_ChnToFreq(channel);
3923
3924 finalLen = bufLen + 24;
3925 finalBuf = vos_mem_malloc(finalLen);
3926 if (NULL == finalBuf)
3927 {
3928 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__);
3929 ret = -ENOMEM;
Jeff Johnson11c33152013-04-16 17:52:40 -07003930 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08003931 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003932 goto exit;
3933 }
3934 vos_mem_zero(finalBuf, finalLen);
3935
3936 /* Fill subtype */
3937 temp = SIR_MAC_MGMT_ACTION << 4;
3938 vos_mem_copy(finalBuf + 0, &temp, sizeof(temp));
3939
3940 /* Fill type */
3941 temp = SIR_MAC_MGMT_FRAME;
3942 vos_mem_copy(finalBuf + 2, &temp, sizeof(temp));
3943
3944 /* Fill destination address (bssid of the AP) */
3945 vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid));
3946
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07003947 /* Fill source address (STA mac address) */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003948 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
3949
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07003950 /* Fill BSSID (AP mac address) */
3951 vos_mem_copy(finalBuf + 16, targetApBssid, sizeof(targetApBssid));
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003952
3953 /* Fill received buffer from 24th address */
3954 vos_mem_copy(finalBuf + 24, buf, bufLen);
3955
Jeff Johnson11c33152013-04-16 17:52:40 -07003956 /* done with the parsed buffer */
3957 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08003958 buf = NULL;
Jeff Johnson11c33152013-04-16 17:52:40 -07003959
Anand N Sunkade9adb1b2015-07-29 09:56:45 +05303960#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0))
3961 params.chan = &chan;
3962 params.offchan = 0;
3963 params.wait = dwellTime;
3964 params.buf = finalBuf;
3965 params.len = finalLen;
3966 params.no_cck = 1;
3967 params.dont_wait_for_ack = 1;
3968 ret = wlan_hdd_mgmt_tx(NULL, &pAdapter->wdev, &params, &cookie);
3969#else
DARAM SUDHA39eede62014-02-12 11:16:40 +05303970 wlan_hdd_mgmt_tx( NULL,
Yue Maf49ba872013-08-19 12:04:25 -07003971#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
3972 &(pAdapter->wdev),
3973#else
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07003974 pAdapter->dev,
Yue Maf49ba872013-08-19 12:04:25 -07003975#endif
3976 &chan, 0,
3977#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
3978 NL80211_CHAN_HT20, 1,
3979#endif
3980 dwellTime, finalBuf, finalLen, 1,
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003981 1, &cookie );
Anand N Sunkade9adb1b2015-07-29 09:56:45 +05303982#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0)*/
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003983 vos_mem_free(finalBuf);
3984 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003985 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
3986 {
3987 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
3988 char extra[32];
3989 tANI_U8 len = 0;
3990
3991 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003992 len = scnprintf(extra, sizeof(extra), "%s %d",
3993 "GETROAMSCANCHANNELMINTIME", val);
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05303994 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
3995 TRACE_CODE_HDD_GETROAMSCANCHANNELMINTIME_IOCTL,
3996 pAdapter->sessionId, val));
Sushant Kaushikbb8c52c2015-07-15 16:36:23 +05303997 len = VOS_MIN(priv_data.total_len, len + 1);
3998 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003999 {
4000 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4001 "%s: failed to copy data to user buffer", __func__);
4002 ret = -EFAULT;
4003 goto exit;
4004 }
4005 }
4006 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
4007 {
4008 tANI_U8 *value = command;
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07004009 tANI_U16 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004010
4011 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
4012 value = value + 19;
4013 /* Convert the value from ascii to integer */
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07004014 ret = kstrtou16(value, 10, &maxTime);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004015 if (ret < 0)
4016 {
4017 /* If the input value is greater than max value of datatype, then also
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07004018 kstrtou16 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004019 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07004020 "%s: kstrtou16 failed range [%d - %d]", __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004021 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
4022 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
4023 ret = -EINVAL;
4024 goto exit;
4025 }
4026
4027 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
4028 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
4029 {
4030 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4031 "lfr mode value %d is out of range"
4032 " (Min: %d Max: %d)", maxTime,
4033 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
4034 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
4035 ret = -EINVAL;
4036 goto exit;
4037 }
4038
4039 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4040 "%s: Received Command to change channel max time = %d", __func__, maxTime);
4041
4042 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
4043 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
4044 }
4045 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
4046 {
4047 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
4048 char extra[32];
4049 tANI_U8 len = 0;
4050
4051 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004052 len = scnprintf(extra, sizeof(extra), "%s %d",
4053 "GETSCANCHANNELTIME", val);
Ratheesh S Pacbfa932015-07-16 15:27:18 +05304054 len = VOS_MIN(priv_data.total_len, len + 1);
4055 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004056 {
4057 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4058 "%s: failed to copy data to user buffer", __func__);
4059 ret = -EFAULT;
4060 goto exit;
4061 }
4062 }
4063 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
4064 {
4065 tANI_U8 *value = command;
4066 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
4067
4068 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
4069 value = value + 16;
4070 /* Convert the value from ascii to integer */
4071 ret = kstrtou16(value, 10, &val);
4072 if (ret < 0)
4073 {
4074 /* If the input value is greater than max value of datatype, then also
4075 kstrtou16 fails */
4076 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4077 "%s: kstrtou16 failed range [%d - %d]", __func__,
4078 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
4079 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
4080 ret = -EINVAL;
4081 goto exit;
4082 }
4083
4084 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
4085 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
4086 {
4087 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4088 "scan home time value %d is out of range"
4089 " (Min: %d Max: %d)", val,
4090 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
4091 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
4092 ret = -EINVAL;
4093 goto exit;
4094 }
4095
4096 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4097 "%s: Received Command to change scan home time = %d", __func__, val);
4098
4099 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
4100 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
4101 }
4102 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
4103 {
4104 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
4105 char extra[32];
4106 tANI_U8 len = 0;
4107
4108 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004109 len = scnprintf(extra, sizeof(extra), "%s %d",
4110 "GETSCANHOMETIME", val);
Ratheesh S P728d7c62015-07-16 15:38:58 +05304111 len = VOS_MIN(priv_data.total_len, len + 1);
4112 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004113 {
4114 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4115 "%s: failed to copy data to user buffer", __func__);
4116 ret = -EFAULT;
4117 goto exit;
4118 }
4119 }
4120 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
4121 {
4122 tANI_U8 *value = command;
4123 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
4124
4125 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
4126 value = value + 17;
4127 /* Convert the value from ascii to integer */
4128 ret = kstrtou8(value, 10, &val);
4129 if (ret < 0)
4130 {
4131 /* If the input value is greater than max value of datatype, then also
4132 kstrtou8 fails */
4133 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4134 "%s: kstrtou8 failed range [%d - %d]", __func__,
4135 CFG_ROAM_INTRA_BAND_MIN,
4136 CFG_ROAM_INTRA_BAND_MAX);
4137 ret = -EINVAL;
4138 goto exit;
4139 }
4140
4141 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
4142 (val > CFG_ROAM_INTRA_BAND_MAX))
4143 {
4144 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4145 "intra band mode value %d is out of range"
4146 " (Min: %d Max: %d)", val,
4147 CFG_ROAM_INTRA_BAND_MIN,
4148 CFG_ROAM_INTRA_BAND_MAX);
4149 ret = -EINVAL;
4150 goto exit;
4151 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004152 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4153 "%s: Received Command to change intra band = %d", __func__, val);
4154
4155 pHddCtx->cfg_ini->nRoamIntraBand = val;
4156 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
4157 }
4158 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
4159 {
4160 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
4161 char extra[32];
4162 tANI_U8 len = 0;
4163
4164 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004165 len = scnprintf(extra, sizeof(extra), "%s %d",
4166 "GETROAMINTRABAND", val);
Ratheesh S P2dd2a3e2015-07-16 15:34:23 +05304167 len = VOS_MIN(priv_data.total_len, len + 1);
4168 if (copy_to_user(priv_data.buf, &extra, len))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004169 {
4170 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4171 "%s: failed to copy data to user buffer", __func__);
4172 ret = -EFAULT;
4173 goto exit;
4174 }
4175 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004176 else if (strncmp(command, "SETSCANNPROBES", 14) == 0)
4177 {
4178 tANI_U8 *value = command;
4179 tANI_U8 nProbes = CFG_ROAM_SCAN_N_PROBES_DEFAULT;
4180
4181 /* Move pointer to ahead of SETSCANNPROBES<delimiter> */
4182 value = value + 15;
4183 /* Convert the value from ascii to integer */
4184 ret = kstrtou8(value, 10, &nProbes);
4185 if (ret < 0)
4186 {
4187 /* If the input value is greater than max value of datatype, then also
4188 kstrtou8 fails */
4189 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4190 "%s: kstrtou8 failed range [%d - %d]", __func__,
4191 CFG_ROAM_SCAN_N_PROBES_MIN,
4192 CFG_ROAM_SCAN_N_PROBES_MAX);
4193 ret = -EINVAL;
4194 goto exit;
4195 }
4196
4197 if ((nProbes < CFG_ROAM_SCAN_N_PROBES_MIN) ||
4198 (nProbes > CFG_ROAM_SCAN_N_PROBES_MAX))
4199 {
4200 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4201 "NProbes value %d is out of range"
4202 " (Min: %d Max: %d)", nProbes,
4203 CFG_ROAM_SCAN_N_PROBES_MIN,
4204 CFG_ROAM_SCAN_N_PROBES_MAX);
4205 ret = -EINVAL;
4206 goto exit;
4207 }
4208
4209 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4210 "%s: Received Command to Set nProbes = %d", __func__, nProbes);
4211
4212 pHddCtx->cfg_ini->nProbes = nProbes;
4213 sme_UpdateRoamScanNProbes((tHalHandle)(pHddCtx->hHal), nProbes);
4214 }
Mahesh A Saptasagarec7d1092015-04-02 13:41:34 +05304215 else if (strncmp(command, "GETSCANNPROBES", 14) == 0)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004216 {
4217 tANI_U8 val = sme_getRoamScanNProbes((tHalHandle)(pHddCtx->hHal));
4218 char extra[32];
4219 tANI_U8 len = 0;
4220
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004221 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Ratnam Rachuri6da525d2015-08-07 13:55:54 +05304222 len = VOS_MIN(priv_data.total_len, len + 1);
4223 if (copy_to_user(priv_data.buf, &extra, len)) {
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004224 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4225 "%s: failed to copy data to user buffer", __func__);
4226 ret = -EFAULT;
4227 goto exit;
4228 }
4229 }
4230 else if (strncmp(command, "SETSCANHOMEAWAYTIME", 19) == 0)
4231 {
4232 tANI_U8 *value = command;
4233 tANI_U16 homeAwayTime = CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT;
4234
4235 /* Move pointer to ahead of SETSCANHOMEAWAYTIME<delimiter> */
4236 /* input value is in units of msec */
4237 value = value + 20;
4238 /* Convert the value from ascii to integer */
4239 ret = kstrtou16(value, 10, &homeAwayTime);
4240 if (ret < 0)
4241 {
4242 /* If the input value is greater than max value of datatype, then also
4243 kstrtou8 fails */
4244 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4245 "%s: kstrtou8 failed range [%d - %d]", __func__,
4246 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
4247 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
4248 ret = -EINVAL;
4249 goto exit;
4250 }
4251
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004252 if ((homeAwayTime < CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN) ||
4253 (homeAwayTime > CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX))
4254 {
4255 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4256 "homeAwayTime value %d is out of range"
4257 " (Min: %d Max: %d)", homeAwayTime,
4258 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
4259 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
4260 ret = -EINVAL;
4261 goto exit;
4262 }
4263
4264 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4265 "%s: Received Command to Set scan away time = %d", __func__, homeAwayTime);
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07004266 if (pHddCtx->cfg_ini->nRoamScanHomeAwayTime != homeAwayTime)
4267 {
4268 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
4269 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_TRUE);
4270 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004271 }
Mahesh A Saptasagarec7d1092015-04-02 13:41:34 +05304272 else if (strncmp(command, "GETSCANHOMEAWAYTIME", 19) == 0)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004273 {
4274 tANI_U16 val = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
4275 char extra[32];
4276 tANI_U8 len = 0;
4277
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004278 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Ratnam Rachuri51a5ad12015-08-07 14:06:37 +05304279 len = VOS_MIN(priv_data.total_len, len + 1);
4280 if (copy_to_user(priv_data.buf, &extra, len)) {
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004281 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4282 "%s: failed to copy data to user buffer", __func__);
4283 ret = -EFAULT;
4284 goto exit;
4285 }
4286 }
4287 else if (strncmp(command, "REASSOC", 7) == 0)
4288 {
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05304289 ret = hdd_parse_reassoc(pAdapter, command);
4290 if (!ret)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004291 goto exit;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004292 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07004293 else if (strncmp(command, "SETWESMODE", 10) == 0)
4294 {
4295 tANI_U8 *value = command;
4296 tANI_BOOLEAN wesMode = CFG_ENABLE_WES_MODE_NAME_DEFAULT;
4297
4298 /* Move pointer to ahead of SETWESMODE<delimiter> */
4299 value = value + 11;
4300 /* Convert the value from ascii to integer */
4301 ret = kstrtou8(value, 10, &wesMode);
4302 if (ret < 0)
4303 {
4304 /* If the input value is greater than max value of datatype, then also
4305 kstrtou8 fails */
4306 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4307 "%s: kstrtou8 failed range [%d - %d]", __func__,
4308 CFG_ENABLE_WES_MODE_NAME_MIN,
4309 CFG_ENABLE_WES_MODE_NAME_MAX);
4310 ret = -EINVAL;
4311 goto exit;
4312 }
4313
4314 if ((wesMode < CFG_ENABLE_WES_MODE_NAME_MIN) ||
4315 (wesMode > CFG_ENABLE_WES_MODE_NAME_MAX))
4316 {
4317 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4318 "WES Mode value %d is out of range"
4319 " (Min: %d Max: %d)", wesMode,
4320 CFG_ENABLE_WES_MODE_NAME_MIN,
4321 CFG_ENABLE_WES_MODE_NAME_MAX);
4322 ret = -EINVAL;
4323 goto exit;
4324 }
4325 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4326 "%s: Received Command to Set WES Mode rssi diff = %d", __func__, wesMode);
4327
4328 pHddCtx->cfg_ini->isWESModeEnabled = wesMode;
4329 sme_UpdateWESMode((tHalHandle)(pHddCtx->hHal), wesMode);
4330 }
Mahesh A Saptasagarec7d1092015-04-02 13:41:34 +05304331 else if (strncmp(command, "GETWESMODE", 10) == 0)
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07004332 {
4333 tANI_BOOLEAN wesMode = sme_GetWESMode((tHalHandle)(pHddCtx->hHal));
4334 char extra[32];
4335 tANI_U8 len = 0;
4336
Arif Hussain826d9412013-11-12 16:44:54 -08004337 len = scnprintf(extra, sizeof(extra), "%s %d", command, wesMode);
Ratnam Rachuri8fe90c62015-08-07 14:03:26 +05304338 len = VOS_MIN(priv_data.total_len, len + 1);
4339 if (copy_to_user(priv_data.buf, &extra, len)) {
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07004340 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4341 "%s: failed to copy data to user buffer", __func__);
4342 ret = -EFAULT;
4343 goto exit;
4344 }
4345 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004346#endif /* WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_ESE || FEATURE_WLAN_LFR */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004347#ifdef FEATURE_WLAN_LFR
4348 else if (strncmp(command, "SETFASTROAM", 11) == 0)
4349 {
4350 tANI_U8 *value = command;
4351 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
4352
4353 /* Move pointer to ahead of SETFASTROAM<delimiter> */
4354 value = value + 12;
4355 /* Convert the value from ascii to integer */
4356 ret = kstrtou8(value, 10, &lfrMode);
4357 if (ret < 0)
4358 {
4359 /* If the input value is greater than max value of datatype, then also
4360 kstrtou8 fails */
4361 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4362 "%s: kstrtou8 failed range [%d - %d]", __func__,
4363 CFG_LFR_FEATURE_ENABLED_MIN,
4364 CFG_LFR_FEATURE_ENABLED_MAX);
4365 ret = -EINVAL;
4366 goto exit;
4367 }
4368
4369 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
4370 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
4371 {
4372 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4373 "lfr mode value %d is out of range"
4374 " (Min: %d Max: %d)", lfrMode,
4375 CFG_LFR_FEATURE_ENABLED_MIN,
4376 CFG_LFR_FEATURE_ENABLED_MAX);
4377 ret = -EINVAL;
4378 goto exit;
4379 }
4380
4381 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4382 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
4383
4384 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
4385 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
4386 }
4387#endif
4388#ifdef WLAN_FEATURE_VOWIFI_11R
4389 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
4390 {
4391 tANI_U8 *value = command;
4392 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
4393
4394 /* Move pointer to ahead of SETFASTROAM<delimiter> */
4395 value = value + 18;
4396 /* Convert the value from ascii to integer */
4397 ret = kstrtou8(value, 10, &ft);
4398 if (ret < 0)
4399 {
4400 /* If the input value is greater than max value of datatype, then also
4401 kstrtou8 fails */
4402 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4403 "%s: kstrtou8 failed range [%d - %d]", __func__,
4404 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
4405 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
4406 ret = -EINVAL;
4407 goto exit;
4408 }
4409
4410 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
4411 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
4412 {
4413 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4414 "ft mode value %d is out of range"
4415 " (Min: %d Max: %d)", ft,
4416 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
4417 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
4418 ret = -EINVAL;
4419 goto exit;
4420 }
4421
4422 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4423 "%s: Received Command to change ft mode = %d", __func__, ft);
4424
4425 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
4426 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
4427 }
Padma, Santhosh Kumar778d8382015-03-04 17:41:22 +05304428 else if (strncmp(command, "SETDFSSCANMODE", 14) == 0)
4429 {
4430 tANI_U8 *value = command;
4431 tANI_U8 dfsScanMode = DFS_CHNL_SCAN_ENABLED_NORMAL;
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05304432
Padma, Santhosh Kumar778d8382015-03-04 17:41:22 +05304433 /* Move pointer to ahead of SETDFSSCANMODE<delimiter> */
4434 value = value + 15;
4435 /* Convert the value from ascii to integer */
4436 ret = kstrtou8(value, 10, &dfsScanMode);
4437 if (ret < 0)
4438 {
4439 /* If the input value is greater than max value of
4440 datatype, then also kstrtou8 fails
4441 */
4442 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4443 "%s: kstrtou8 failed range [%d - %d]", __func__,
4444 CFG_ENABLE_DFS_CHNL_SCAN_MIN,
4445 CFG_ENABLE_DFS_CHNL_SCAN_MAX);
4446 ret = -EINVAL;
4447 goto exit;
4448 }
4449
4450 if ((dfsScanMode < CFG_ENABLE_DFS_CHNL_SCAN_MIN) ||
4451 (dfsScanMode > CFG_ENABLE_DFS_CHNL_SCAN_MAX))
4452 {
4453 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4454 "dfsScanMode value %d is out of range"
4455 " (Min: %d Max: %d)", dfsScanMode,
4456 CFG_ENABLE_DFS_CHNL_SCAN_MIN,
4457 CFG_ENABLE_DFS_CHNL_SCAN_MAX);
4458 ret = -EINVAL;
4459 goto exit;
4460 }
4461 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4462 "%s: Received Command to Set DFS Scan Mode = %d",
4463 __func__, dfsScanMode);
4464
4465 ret = wlan_hdd_handle_dfs_chan_scan(pHddCtx, dfsScanMode);
4466 }
4467 else if (strncmp(command, "GETDFSSCANMODE", 14) == 0)
4468 {
4469 tANI_U8 dfsScanMode = sme_GetDFSScanMode(pHddCtx->hHal);
4470 char extra[32];
4471 tANI_U8 len = 0;
4472
4473 len = scnprintf(extra, sizeof(extra), "%s %d", command, dfsScanMode);
Ratheesh S P767224e2015-07-16 15:35:51 +05304474 len = VOS_MIN(priv_data.total_len, len + 1);
4475 if (copy_to_user(priv_data.buf, &extra, len))
Padma, Santhosh Kumar778d8382015-03-04 17:41:22 +05304476 {
4477 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4478 "%s: failed to copy data to user buffer", __func__);
4479 ret = -EFAULT;
4480 goto exit;
4481 }
4482 }
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05304483 else if (strncmp(command, "FASTREASSOC", 11) == 0)
4484 {
Selvaraj, Sridhar3714c4d2016-06-22 15:19:12 +05304485 ret = wlan_hdd_handle_fastreassoc(pAdapter, command);
4486 if (!ret)
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05304487 goto exit;
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05304488 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004489#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004490#ifdef FEATURE_WLAN_ESE
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004491 else if (strncmp(command, "SETCCXMODE", 10) == 0)
4492 {
4493 tANI_U8 *value = command;
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004494 tANI_U8 eseMode = CFG_ESE_FEATURE_ENABLED_DEFAULT;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004495
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004496 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07004497 then this operation is not permitted (return FAILURE) */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004498 if (sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07004499 hdd_is_okc_mode_enabled(pHddCtx) &&
4500 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
4501 {
4502 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004503 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07004504 " hence this operation is not permitted!", __func__);
4505 ret = -EPERM;
4506 goto exit;
4507 }
4508
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004509 /* Move pointer to ahead of SETCCXMODE<delimiter> */
4510 value = value + 11;
4511 /* Convert the value from ascii to integer */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004512 ret = kstrtou8(value, 10, &eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004513 if (ret < 0)
4514 {
4515 /* If the input value is greater than max value of datatype, then also
4516 kstrtou8 fails */
4517 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4518 "%s: kstrtou8 failed range [%d - %d]", __func__,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004519 CFG_ESE_FEATURE_ENABLED_MIN,
4520 CFG_ESE_FEATURE_ENABLED_MAX);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004521 ret = -EINVAL;
4522 goto exit;
4523 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004524 if ((eseMode < CFG_ESE_FEATURE_ENABLED_MIN) ||
4525 (eseMode > CFG_ESE_FEATURE_ENABLED_MAX))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004526 {
4527 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004528 "Ese mode value %d is out of range"
4529 " (Min: %d Max: %d)", eseMode,
4530 CFG_ESE_FEATURE_ENABLED_MIN,
4531 CFG_ESE_FEATURE_ENABLED_MAX);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004532 ret = -EINVAL;
4533 goto exit;
4534 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004535 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004536 "%s: Received Command to change ese mode = %d", __func__, eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004537
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004538 pHddCtx->cfg_ini->isEseIniFeatureEnabled = eseMode;
4539 sme_UpdateIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal), eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004540 }
4541#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004542 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
4543 {
4544 tANI_U8 *value = command;
4545 tANI_BOOLEAN roamScanControl = 0;
4546
4547 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
4548 value = value + 19;
4549 /* Convert the value from ascii to integer */
4550 ret = kstrtou8(value, 10, &roamScanControl);
4551 if (ret < 0)
4552 {
4553 /* If the input value is greater than max value of datatype, then also
4554 kstrtou8 fails */
4555 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4556 "%s: kstrtou8 failed ", __func__);
4557 ret = -EINVAL;
4558 goto exit;
4559 }
4560
4561 if (0 != roamScanControl)
4562 {
4563 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4564 "roam scan control invalid value = %d",
4565 roamScanControl);
4566 ret = -EINVAL;
4567 goto exit;
4568 }
4569 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4570 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
4571
4572 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
4573 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004574#ifdef FEATURE_WLAN_OKC
4575 else if (strncmp(command, "SETOKCMODE", 10) == 0)
4576 {
4577 tANI_U8 *value = command;
4578 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
4579
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004580 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07004581 then this operation is not permitted (return FAILURE) */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004582 if (sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07004583 hdd_is_okc_mode_enabled(pHddCtx) &&
4584 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
4585 {
4586 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004587 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07004588 " hence this operation is not permitted!", __func__);
4589 ret = -EPERM;
4590 goto exit;
4591 }
4592
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07004593 /* Move pointer to ahead of SETOKCMODE<delimiter> */
4594 value = value + 11;
4595 /* Convert the value from ascii to integer */
4596 ret = kstrtou8(value, 10, &okcMode);
4597 if (ret < 0)
4598 {
4599 /* If the input value is greater than max value of datatype, then also
4600 kstrtou8 fails */
4601 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4602 "%s: kstrtou8 failed range [%d - %d]", __func__,
4603 CFG_OKC_FEATURE_ENABLED_MIN,
4604 CFG_OKC_FEATURE_ENABLED_MAX);
4605 ret = -EINVAL;
4606 goto exit;
4607 }
4608
4609 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
4610 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
4611 {
4612 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4613 "Okc mode value %d is out of range"
4614 " (Min: %d Max: %d)", okcMode,
4615 CFG_OKC_FEATURE_ENABLED_MIN,
4616 CFG_OKC_FEATURE_ENABLED_MAX);
4617 ret = -EINVAL;
4618 goto exit;
4619 }
4620
4621 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4622 "%s: Received Command to change okc mode = %d", __func__, okcMode);
4623
4624 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
4625 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07004626#endif /* FEATURE_WLAN_OKC */
Mahesh A Saptasagarec7d1092015-04-02 13:41:34 +05304627 else if (strncmp(command, "GETROAMSCANCONTROL", 18) == 0)
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004628 {
4629 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
4630 char extra[32];
4631 tANI_U8 len = 0;
4632
Sameer Thalappilb0a30232013-09-27 15:37:48 -07004633 len = scnprintf(extra, sizeof(extra), "%s %d",
4634 command, roamScanControl);
Ratnam Rachuri083ada82015-08-07 14:01:05 +05304635 len = VOS_MIN(priv_data.total_len, len + 1);
4636 if (copy_to_user(priv_data.buf, &extra, len)) {
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004637 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4638 "%s: failed to copy data to user buffer", __func__);
4639 ret = -EFAULT;
4640 goto exit;
4641 }
4642 }
Gopichand Nakkala227c7f32013-06-26 22:44:57 +05304643#ifdef WLAN_FEATURE_PACKET_FILTERING
4644 else if (strncmp(command, "ENABLE_PKTFILTER_IPV6", 21) == 0)
4645 {
4646 tANI_U8 filterType = 0;
4647 tANI_U8 *value = command;
4648
4649 /* Move pointer to ahead of ENABLE_PKTFILTER_IPV6<delimiter> */
4650 value = value + 22;
4651
4652 /* Convert the value from ascii to integer */
4653 ret = kstrtou8(value, 10, &filterType);
4654 if (ret < 0)
4655 {
4656 /* If the input value is greater than max value of datatype,
4657 * then also kstrtou8 fails
4658 */
4659 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4660 "%s: kstrtou8 failed range ", __func__);
4661 ret = -EINVAL;
4662 goto exit;
4663 }
4664
4665 if (filterType != 0 && filterType != 1)
4666 {
4667 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4668 "%s: Accepted Values are 0 and 1 ", __func__);
4669 ret = -EINVAL;
4670 goto exit;
4671 }
4672 wlan_hdd_setIPv6Filter(WLAN_HDD_GET_CTX(pAdapter), filterType,
4673 pAdapter->sessionId);
4674 }
4675#endif
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05304676 else if (strncmp(command, "BTCOEXMODE", 10) == 0 )
4677 {
Kiet Lamad161252014-07-22 11:23:32 -07004678 char *dhcpPhase;
Satyanarayana Dash1faea4f2014-09-22 16:21:04 +05304679 int ret;
4680
Kiet Lamad161252014-07-22 11:23:32 -07004681 dhcpPhase = command + 11;
4682 if ('1' == *dhcpPhase)
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05304683 {
Deepthi Gowribfd17132014-11-14 17:59:04 +05304684 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Kiet Lamad161252014-07-22 11:23:32 -07004685 FL("send DHCP START indication"));
c_hpothu9b781ba2013-12-30 20:57:45 +05304686
4687 pHddCtx->btCoexModeSet = TRUE;
Kiet Lamad161252014-07-22 11:23:32 -07004688
Satyanarayana Dash1faea4f2014-09-22 16:21:04 +05304689 ret = wlan_hdd_scan_abort(pAdapter);
4690 if (ret < 0)
4691 {
4692 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4693 FL("failed to abort existing scan %d"), ret);
4694 }
4695
Kiet Lamad161252014-07-22 11:23:32 -07004696 sme_DHCPStartInd(pHddCtx->hHal, pAdapter->device_mode,
4697 pAdapter->sessionId);
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05304698 }
Kiet Lamad161252014-07-22 11:23:32 -07004699 else if ('2' == *dhcpPhase)
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05304700 {
Deepthi Gowribfd17132014-11-14 17:59:04 +05304701 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Kiet Lamad161252014-07-22 11:23:32 -07004702 FL("send DHCP STOP indication"));
c_hpothu9b781ba2013-12-30 20:57:45 +05304703
4704 pHddCtx->btCoexModeSet = FALSE;
Kiet Lamad161252014-07-22 11:23:32 -07004705
4706 sme_DHCPStopInd(pHddCtx->hHal, pAdapter->device_mode,
4707 pAdapter->sessionId);
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05304708 }
4709 }
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07004710 else if (strncmp(command, "SCAN-ACTIVE", 11) == 0)
4711 {
Abhishek Singh58749d62016-02-03 15:27:20 +05304712 hddLog(LOG1,
4713 FL("making default scan to ACTIVE"));
c_hpothudbefd3e2014-04-28 15:59:47 +05304714 pHddCtx->scan_info.scan_mode = eSIR_ACTIVE_SCAN;
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07004715 }
4716 else if (strncmp(command, "SCAN-PASSIVE", 12) == 0)
4717 {
Abhishek Singh58749d62016-02-03 15:27:20 +05304718 hddLog(LOG1,
4719 FL("making default scan to PASSIVE"));
c_hpothudbefd3e2014-04-28 15:59:47 +05304720 pHddCtx->scan_info.scan_mode = eSIR_PASSIVE_SCAN;
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07004721 }
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05304722 else if (strncmp(command, "GETDWELLTIME", 12) == 0)
4723 {
4724 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
4725 char extra[32];
4726 tANI_U8 len = 0;
4727
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05304728 memset(extra, 0, sizeof(extra));
4729 ret = hdd_get_dwell_time(pCfg, command, extra, sizeof(extra), &len);
Ratnam Rachuri12d5d462015-08-07 14:10:23 +05304730 len = VOS_MIN(priv_data.total_len, len + 1);
4731 if (ret != 0 || copy_to_user(priv_data.buf, &extra, len)) {
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05304732 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4733 "%s: failed to copy data to user buffer", __func__);
4734 ret = -EFAULT;
4735 goto exit;
4736 }
4737 ret = len;
4738 }
4739 else if (strncmp(command, "SETDWELLTIME", 12) == 0)
4740 {
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05304741 ret = hdd_set_dwell_time(pAdapter, command);
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05304742 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07004743 else if ( strncasecmp(command, "MIRACAST", 8) == 0 )
4744 {
4745 tANI_U8 filterType = 0;
4746 tANI_U8 *value;
4747 value = command + 9;
4748
4749 /* Convert the value from ascii to integer */
4750 ret = kstrtou8(value, 10, &filterType);
4751 if (ret < 0)
4752 {
4753 /* If the input value is greater than max value of datatype,
4754 * then also kstrtou8 fails
4755 */
4756 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4757 "%s: kstrtou8 failed range ", __func__);
4758 ret = -EINVAL;
4759 goto exit;
4760 }
4761 if ((filterType < WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL ) ||
4762 (filterType > WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL))
4763 {
4764 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4765 "%s: Accepted Values are 0 to 2. 0-Disabled, 1-Source,"
4766 " 2-Sink ", __func__);
4767 ret = -EINVAL;
4768 goto exit;
4769 }
4770 //Filtertype value should be either 0-Disabled, 1-Source, 2-sink
4771 pHddCtx->drvr_miracast = filterType;
Kaushik, Sushant96122442014-10-21 16:40:18 +05304772 pScanInfo = &pHddCtx->scan_info;
4773 if (filterType && pScanInfo != NULL &&
4774 pHddCtx->scan_info.mScanPending)
4775 {
4776 /*Miracast Session started. Abort Scan */
4777 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4778 "%s, Aborting Scan For Miracast",__func__);
4779 hdd_abort_mac_scan(pHddCtx, pScanInfo->sessionId,
4780 eCSR_SCAN_ABORT_DEFAULT);
4781 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07004782 hdd_tx_rx_pkt_cnt_stat_timer_handler(pHddCtx);
Ganesh Kondabattini8f6e3b32014-08-25 16:07:54 +05304783 sme_SetMiracastMode(pHddCtx->hHal, pHddCtx->drvr_miracast);
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07004784 }
Leo Chang614d2072013-08-22 14:59:44 -07004785 else if (strncmp(command, "SETMCRATE", 9) == 0)
4786 {
Leo Chang614d2072013-08-22 14:59:44 -07004787 tANI_U8 *value = command;
4788 int targetRate;
Leo Chang1f98cbd2013-10-17 15:03:52 -07004789 tSirRateUpdateInd *rateUpdate;
4790 eHalStatus status;
Leo Chang614d2072013-08-22 14:59:44 -07004791
4792 /* Only valid for SAP mode */
4793 if (WLAN_HDD_SOFTAP != pAdapter->device_mode)
4794 {
4795 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4796 "%s: SAP mode is not running", __func__);
4797 ret = -EFAULT;
4798 goto exit;
4799 }
4800
4801 /* Move pointer to ahead of SETMCRATE<delimiter> */
4802 /* input value is in units of hundred kbps */
4803 value = value + 10;
4804 /* Convert the value from ascii to integer, decimal base */
4805 ret = kstrtouint(value, 10, &targetRate);
4806
Leo Chang1f98cbd2013-10-17 15:03:52 -07004807 rateUpdate = (tSirRateUpdateInd *)vos_mem_malloc(sizeof(tSirRateUpdateInd));
4808 if (NULL == rateUpdate)
Leo Chang614d2072013-08-22 14:59:44 -07004809 {
Leo Chang1f98cbd2013-10-17 15:03:52 -07004810 hddLog(VOS_TRACE_LEVEL_ERROR,
4811 "%s: SETMCRATE indication alloc fail", __func__);
4812 ret = -EFAULT;
4813 goto exit;
4814 }
4815 vos_mem_zero(rateUpdate, sizeof(tSirRateUpdateInd ));
4816
4817 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4818 "MC Target rate %d", targetRate);
4819 /* Ignore unicast */
4820 rateUpdate->ucastDataRate = -1;
4821 rateUpdate->mcastDataRate24GHz = targetRate;
4822 rateUpdate->mcastDataRate5GHz = targetRate;
4823 rateUpdate->mcastDataRate24GHzTxFlag = 0;
4824 rateUpdate->mcastDataRate5GHzTxFlag = 0;
4825 status = sme_SendRateUpdateInd(pHddCtx->hHal, rateUpdate);
4826 if (eHAL_STATUS_SUCCESS != status)
4827 {
4828 hddLog(VOS_TRACE_LEVEL_ERROR,
4829 "%s: SET_MC_RATE failed", __func__);
4830 vos_mem_free(rateUpdate);
4831 ret = -EFAULT;
4832 goto exit;
Leo Chang614d2072013-08-22 14:59:44 -07004833 }
4834 }
Rajeev79dbe4c2013-10-05 11:03:42 +05304835#ifdef FEATURE_WLAN_BATCH_SCAN
Rajeev Kumar8b373292014-01-08 20:36:55 -08004836 else if (strncmp(command, "WLS_BATCHING", 12) == 0)
Rajeev79dbe4c2013-10-05 11:03:42 +05304837 {
Rajeev Kumar8b373292014-01-08 20:36:55 -08004838 ret = hdd_handle_batch_scan_ioctl(pAdapter, &priv_data, command);
Rajeev79dbe4c2013-10-05 11:03:42 +05304839 }
4840#endif
Abhishek Singh00b71972016-01-07 10:51:04 +05304841#ifdef WLAN_FEATURE_RMC
4842 else if ((strncasecmp(command, "SETIBSSBEACONOUIDATA", 20) == 0) &&
4843 (WLAN_HDD_IBSS == pAdapter->device_mode))
4844 {
4845 int i = 0;
4846 tANI_U8 *ibss_ie;
4847 tANI_U32 command_len;
4848 tANI_U8 *value = command;
4849 tHalHandle hHal = pHddCtx->hHal;
4850 tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
4851 tANI_U32 ibss_ie_length;
4852 tANI_U32 len, present;
4853 tANI_U8 *addIE;
4854 tANI_U8 *addIEData;
4855
4856 hddLog(LOG1,
4857 FL(" received command %s"),((char *) value));
4858 /* validate argument of command */
4859 if (strlen(value) <= 21)
4860 {
4861 hddLog(LOGE,
4862 FL("No arguements in command length %zu"), strlen(value));
4863 ret = -EFAULT;
4864 goto exit;
4865 }
4866
4867 /* moving to arguments of commands */
4868 value = value + 21;
4869 command_len = strlen(value);
4870
4871 /* oui_data can't be less than 3 bytes */
4872 if (command_len <= (2 * WLAN_HDD_IBSS_MIN_OUI_DATA_LENGTH))
4873 {
4874 hddLog(LOGE,
4875 FL("Invalid SETIBSSBEACONOUIDATA command length %d"),
4876 command_len);
4877 ret = -EFAULT;
4878 goto exit;
4879 }
4880 ibss_ie = vos_mem_malloc(command_len);
4881 if (!ibss_ie) {
4882 hddLog(LOGE,
4883 FL("Could not allocate memory for command length %d"),
4884 command_len);
4885 ret = -ENOMEM;
4886 goto exit;
4887 }
4888 vos_mem_zero(ibss_ie, command_len);
4889
4890 ibss_ie_length = hdd_parse_set_ibss_oui_data_command(value, ibss_ie,
4891 command_len);
4892 if (ibss_ie_length < (2 * WLAN_HDD_IBSS_MIN_OUI_DATA_LENGTH)) {
4893 hddLog(LOGE, FL("Could not parse command %s return length %d"),
4894 value, ibss_ie_length);
4895 ret = -EFAULT;
4896 vos_mem_free(ibss_ie);
4897 goto exit;
4898 }
4899
4900 hddLog(LOG1, FL("ibss_ie length %d ibss_ie:"), ibss_ie_length);
4901 while (i < ibss_ie_length)
4902 hddLog(LOG1, FL("0x%x"), ibss_ie[i++]);
4903
4904 /* Populate Vendor IE in Beacon */
4905 if ((ccmCfgGetInt(hHal,
4906 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
4907 &present)) != eHAL_STATUS_SUCCESS)
4908 {
4909 hddLog(LOGE,
4910 FL("unable to ftch WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG"));
4911 ret = -EFAULT;
4912 vos_mem_free(ibss_ie);
4913 goto exit;
4914 }
4915
4916 addIE = vos_mem_malloc(WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN);
4917 if (!addIE) {
4918 hddLog(LOGE,
4919 FL("Could not allocate memory for command length %d"),
4920 command_len);
4921 vos_mem_free(ibss_ie);
4922 ret = -ENOMEM;
4923 goto exit;
4924 }
4925 vos_mem_zero(addIE, WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN);
4926
4927 if (present)
4928 {
4929 if ((wlan_cfgGetStrLen(pMac,
4930 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, &len)) != eSIR_SUCCESS)
4931 {
4932 hddLog(LOGE,
4933 FL("unable to fetch WNI_CFG_PROBE_RSP_BCN_ADDNIE_LEN"));
4934 ret = -EFAULT;
4935 vos_mem_free(ibss_ie);
4936 vos_mem_free(addIE);
4937 goto exit;
4938 }
4939
4940 if (len <= WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN && len &&
4941 ((len + ibss_ie_length) <=
4942 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN))
4943 {
4944 if ((ccmCfgGetStr(hHal,
4945 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, addIE, &len))
4946 != eHAL_STATUS_SUCCESS)
4947 {
4948 hddLog(LOGE,
4949 FL("unable to fetch WNI_PROBE_RSP_BCN_ADDNIE_DATA"));
4950 ret = -EFAULT;
4951 vos_mem_free(ibss_ie);
4952 vos_mem_free(addIE);
4953 goto exit;
4954 }
4955 else
4956 {
4957 /* Curruntly only WPA IE is added before Vendor IE
4958 * so we can blindly place the Vendor IE after WPA
4959 * IE. If no WPA IE found replace all with Vendor IE.
4960 */
4961 len = hdd_find_ibss_wpa_ie_pos(addIE, len);
4962 }
4963 }
4964 else
4965 {
4966 hddLog(LOGE,
4967 FL("IE len exceed limit len %d,ibss_ie_length %d "),
4968 len, ibss_ie_length);
4969 ret = -EFAULT;
4970 vos_mem_free(addIE);
4971 vos_mem_free(ibss_ie);
4972 goto exit;
4973 }
4974 }
4975 else {
4976 len = 0;
4977 }
4978
4979 vos_mem_copy (addIE + len , ibss_ie, ibss_ie_length);
4980 len += ibss_ie_length;
4981
4982 if (ccmCfgSetStr(hHal,
4983 WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA, addIE, len, NULL,
4984 eANI_BOOLEAN_FALSE) != eHAL_STATUS_SUCCESS)
4985 {
4986 hddLog(LOGE,
4987 FL("unable to set WNI_CFG_PRBE_RSP_BCN_ADDNIE_DATA"));
4988 ret = -EFAULT;
4989 vos_mem_free(ibss_ie);
4990 vos_mem_free(addIE);
4991 goto exit;
4992 }
4993 vos_mem_free(addIE);
4994 if (ccmCfgSetInt(hHal,
4995 WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG, 1,NULL,
4996 eANI_BOOLEAN_FALSE) != eHAL_STATUS_SUCCESS)
4997 {
4998 hddLog(LOGE,
4999 FL("unble to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG"));
5000 ret = -EFAULT;
5001 vos_mem_free(ibss_ie);
5002 goto exit;
5003 }
5004
5005 /* Populate Vendor IE in probe resp */
5006 if ((ccmCfgGetInt(hHal,
5007 WNI_CFG_PROBE_RSP_ADDNIE_FLAG,
5008 &present)) != eHAL_STATUS_SUCCESS)
5009 {
5010 hddLog(LOGE,
5011 FL("unable to fetch WNI_CFG_PROBE_RSP_ADDNIE_FLAG"));
5012 ret = -EFAULT;
5013 vos_mem_free(ibss_ie);
5014 goto exit;
5015 }
5016
5017 addIEData = vos_mem_malloc(WNI_CFG_PROBE_RSP_ADDNIE_DATA1_LEN);
5018 if (!addIEData) {
5019 hddLog(LOGE,
5020 FL("Could not allocate memory for command length %d"),
5021 command_len);
5022 vos_mem_free(ibss_ie);
5023 ret = -ENOMEM;
5024 goto exit;
5025 }
5026 vos_mem_zero(addIEData, WNI_CFG_PROBE_RSP_ADDNIE_DATA1_LEN);
5027
5028 if (present) {
5029 if (eSIR_SUCCESS != wlan_cfgGetStrLen(pMac,
5030 WNI_CFG_PROBE_RSP_ADDNIE_DATA1, &len)) {
5031 hddLog(LOGE,
5032 FL("unable to fetch WNI_CFG_PROBE_RSP_ADDNIE_DATA1"));
5033 ret = -EFAULT;
5034 vos_mem_free(ibss_ie);
5035 vos_mem_free(addIEData);
5036 goto exit;
5037 }
5038 if (len < WNI_CFG_PROBE_RSP_ADDNIE_DATA1_LEN && len &&
5039 (ibss_ie_length + len) <=
5040 WNI_CFG_PROBE_RSP_ADDNIE_DATA1_LEN) {
5041
5042 if ((ccmCfgGetStr(hHal,
5043 WNI_CFG_PROBE_RSP_ADDNIE_DATA1, addIEData, &len))
5044 != eHAL_STATUS_SUCCESS) {
5045 hddLog(LOGE,
5046 FL("unable fetch WNI_CFG_PROBE_RSP_ADDNIE_DATA1"));
5047 ret = -EFAULT;
5048 vos_mem_free(ibss_ie);
5049 vos_mem_free(addIEData);
5050 goto exit;
5051 }
5052 else {
5053 /* Curruntly only WPA IE is added before Vendor IE
5054 * so we can blindly place the Vendor IE after WPA
5055 * IE. If no WPA IE found replace all with Vendor IE.
5056 */
5057 len = hdd_find_ibss_wpa_ie_pos(addIEData, len);
5058 }
5059 }
5060 else
5061 {
5062 hddLog(LOGE,
5063 FL("IE len exceed limit len %d,ibss_ie_length %d "),
5064 len, ibss_ie_length);
5065 ret = -EFAULT;
5066 vos_mem_free(addIEData);
5067 vos_mem_free(ibss_ie);
5068 goto exit;
5069 }
5070 } /* probe rsp ADD IE present */
5071 else {
5072 /* probe rsp add IE is not present */
5073 len = 0;
5074 }
5075
5076 vos_mem_copy(addIEData +len , ibss_ie, ibss_ie_length);
5077 len += ibss_ie_length;
5078
5079 vos_mem_free(ibss_ie);
5080
5081 if (ccmCfgSetStr(hHal,
5082 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,
5083 (tANI_U8*)(addIEData),
5084 len, NULL,
5085 eANI_BOOLEAN_FALSE)
5086 == eHAL_STATUS_FAILURE) {
5087 hddLog(LOGE,
5088 FL("unable to copy to WNI_CFG_PROBE_RSP_ADDNIE_DATA1"));
5089 ret = -EFAULT;
5090 vos_mem_free(addIEData);
5091 goto exit;
5092 }
5093 vos_mem_free(addIEData);
5094 if (ccmCfgSetInt(WLAN_HDD_GET_HAL_CTX(pAdapter),
5095 WNI_CFG_PROBE_RSP_ADDNIE_FLAG, 1,NULL,
5096 eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
5097 {
5098 hddLog(LOGE,
5099 FL("unable to copy WNI_CFG_PROBE_RSP_ADDNIE_FLAG"));
5100 ret = -EFAULT;
5101 goto exit;
5102 }
5103 }
5104 else if (strncasecmp(command, "SETRMCENABLE", 12) == 0)
5105 {
5106 tANI_U8 *value = command;
5107 tANI_U8 ucRmcEnable = 0;
5108 int status;
5109
5110 if ((WLAN_HDD_IBSS != pAdapter->device_mode) &&
5111 (WLAN_HDD_SOFTAP != pAdapter->device_mode))
5112 {
5113 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5114 "Received SETRMCENABLE command in invalid mode %d "
5115 "SETRMCENABLE command is only allowed in IBSS or SOFTAP mode",
5116 pAdapter->device_mode);
5117 ret = -EINVAL;
5118 goto exit;
5119 }
5120
5121 status = hdd_parse_setrmcenable_command(value, &ucRmcEnable);
5122 if (status)
5123 {
5124 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5125 "Invalid SETRMCENABLE command ");
5126 ret = -EINVAL;
5127 goto exit;
5128 }
5129
5130 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5131 "%s: ucRmcEnable %d ", __func__, ucRmcEnable);
5132
5133 if (TRUE == ucRmcEnable)
5134 {
5135 status = sme_EnableRMC( (tHalHandle)(pHddCtx->hHal),
5136 pAdapter->sessionId );
5137 }
5138 else if(FALSE == ucRmcEnable)
5139 {
5140 status = sme_DisableRMC( (tHalHandle)(pHddCtx->hHal),
5141 pAdapter->sessionId );
5142 }
5143 else
5144 {
5145 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5146 "Invalid SETRMCENABLE command %d", ucRmcEnable);
5147 ret = -EINVAL;
5148 goto exit;
5149 }
5150
5151 if (VOS_STATUS_SUCCESS != status)
5152 {
5153 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5154 "%s: SETRMC %d failed status %d", __func__, ucRmcEnable,
5155 status);
5156 ret = -EINVAL;
5157 goto exit;
5158 }
5159 }
5160 else if (strncasecmp(command, "SETRMCACTIONPERIOD", 18) == 0)
5161 {
5162 tANI_U8 *value = command;
5163 tANI_U32 uActionPeriod = 0;
5164 int status;
5165
5166 if ((WLAN_HDD_IBSS != pAdapter->device_mode) &&
5167 (WLAN_HDD_SOFTAP != pAdapter->device_mode))
5168 {
5169 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5170 "Received SETRMC command in invalid mode %d "
5171 "SETRMC command is only allowed in IBSS or SOFTAP mode",
5172 pAdapter->device_mode);
5173 ret = -EINVAL;
5174 goto exit;
5175 }
5176
5177 status = hdd_parse_setrmcactionperiod_command(value, &uActionPeriod);
5178 if (status)
5179 {
5180 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5181 "Invalid SETRMCACTIONPERIOD command ");
5182 ret = -EINVAL;
5183 goto exit;
5184 }
5185
5186 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5187 "%s: uActionPeriod %d ", __func__, uActionPeriod);
5188
5189 if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY,
5190 uActionPeriod, NULL, eANI_BOOLEAN_FALSE))
5191 {
5192 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5193 "%s: Could not set SETRMCACTIONPERIOD %d", __func__, uActionPeriod);
5194 ret = -EINVAL;
5195 goto exit;
5196 }
5197
5198 }
5199 else if (strncasecmp(command, "GETIBSSPEERINFOALL", 18) == 0)
5200 {
5201 /* Peer Info All Command */
5202 int status = eHAL_STATUS_SUCCESS;
5203 hdd_station_ctx_t *pHddStaCtx = NULL;
5204 char *extra = NULL;
5205 int idx = 0, length = 0;
5206 v_MACADDR_t *macAddr;
5207 v_U32_t txRateMbps = 0, numOfBytestoPrint = 0;
5208
5209 if (WLAN_HDD_IBSS == pAdapter->device_mode)
5210 {
5211 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5212 }
5213 else
5214 {
5215 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5216 "%s: pAdapter is not valid for this device mode",
5217 __func__);
5218 ret = -EINVAL;
5219 goto exit;
5220 }
5221
5222 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5223 "%s: Received GETIBSSPEERINFOALL Command", __func__);
5224
5225
5226 /* Handle the command */
5227 status = hdd_cfg80211_get_ibss_peer_info_all(pAdapter);
5228 if (VOS_STATUS_SUCCESS == status)
5229 {
5230 /* The variable extra needed to be allocated on the heap since
5231 * amount of memory required to copy the data for 32 devices
5232 * exceeds the size of 1024 bytes of default stack size. On
5233 * 64 bit devices, the default max stack size of 2048 bytes
5234 */
5235 extra = kmalloc(WLAN_MAX_BUF_SIZE, GFP_KERNEL);
5236
5237 if (NULL == extra)
5238 {
5239 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5240 "%s:kmalloc failed", __func__);
5241 ret = -EINVAL;
5242 goto exit;
5243 }
5244
5245 /* Copy number of stations */
5246 length = scnprintf( extra, WLAN_MAX_BUF_SIZE, "%d ",
5247 pHddStaCtx->ibss_peer_info.numIBSSPeers);
5248 numOfBytestoPrint = length;
5249 for (idx = 0; idx < pHddStaCtx->ibss_peer_info.numIBSSPeers; idx++)
5250 {
5251 macAddr =
5252 hdd_wlan_get_ibss_mac_addr_from_staid(pAdapter,
5253 pHddStaCtx->ibss_peer_info.ibssPeerList[idx].staIdx);
5254 if (NULL != macAddr)
5255 {
5256 txRateMbps =
5257 ((pHddStaCtx->ibss_peer_info.ibssPeerList[idx].txRate)*500*1000)/1000000;
5258
5259 length += scnprintf( (extra + length), WLAN_MAX_BUF_SIZE - length,
5260 "%02x:%02x:%02x:%02x:%02x:%02x %d %d ",
5261 macAddr->bytes[0], macAddr->bytes[1], macAddr->bytes[2],
5262 macAddr->bytes[3], macAddr->bytes[4], macAddr->bytes[5],
5263 (int)txRateMbps,
5264 (int)pHddStaCtx->ibss_peer_info.ibssPeerList[idx].rssi);
5265 }
5266 else
5267 {
5268 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5269 "%s: MAC ADDR is NULL for staIdx: %d", __func__,
5270 pHddStaCtx->ibss_peer_info.ibssPeerList[idx].staIdx);
5271 }
5272
5273 /*
5274 * VOS_TRACE() macro has limitation of 512 bytes for the print
5275 * buffer. Hence printing the data in two chunks. The first chunk
5276 * will have the data for 16 devices and the second chunk will
5277 * have the rest.
5278 */
5279 if (idx < NUM_OF_STA_DATA_TO_PRINT)
5280 {
5281 numOfBytestoPrint = length;
5282 }
5283 }
5284
5285 /*
5286 * Copy the data back into buffer, if the data to copy is
5287 * morethan 512 bytes than we will split the data and do
5288 * it in two shots
5289 */
5290 if (copy_to_user(priv_data.buf, extra, numOfBytestoPrint))
5291 {
5292 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5293 "%s: Copy into user data buffer failed ", __func__);
5294 ret = -EFAULT;
5295 kfree(extra);
5296 goto exit;
5297 }
5298 priv_data.buf[numOfBytestoPrint] = '\0';
5299 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED,
5300 "%s", priv_data.buf);
5301
5302 if (length > numOfBytestoPrint)
5303 {
5304 if (copy_to_user(priv_data.buf + numOfBytestoPrint,
5305 extra + numOfBytestoPrint,
5306 length - numOfBytestoPrint + 1))
5307 {
5308 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5309 "%s: Copy into user data buffer failed ", __func__);
5310 ret = -EFAULT;
5311 kfree(extra);
5312 goto exit;
5313 }
5314 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED,
5315 "%s", &priv_data.buf[numOfBytestoPrint]);
5316 }
5317
5318 /* Free temporary buffer */
5319 kfree(extra);
5320 }
5321
5322 else
5323 {
5324 /* Command failed, log error */
5325 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5326 "%s: GETIBSSPEERINFOALL command failed with status code %d",
5327 __func__, status);
5328 ret = -EINVAL;
5329 goto exit;
5330 }
5331 ret = 0;
5332 }
5333 else if(strncasecmp(command, "GETIBSSPEERINFO", 15) == 0)
5334 {
5335 /* Peer Info <Peer Addr> command */
5336 tANI_U8 *value = command;
5337 VOS_STATUS status;
5338 hdd_station_ctx_t *pHddStaCtx = NULL;
5339 char extra[128] = { 0 };
5340 v_U32_t length = 0;
5341 v_U8_t staIdx = 0;
5342 v_U32_t txRateMbps = 0;
5343 v_MACADDR_t peerMacAddr;
5344
5345 if (WLAN_HDD_IBSS == pAdapter->device_mode)
5346 {
5347 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5348 }
5349 else
5350 {
5351 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5352 "%s: pAdapter is not valid for this device mode",
5353 __func__);
5354 ret = -EINVAL;
5355 goto exit;
5356 }
5357
5358 /* if there are no peers, no need to continue with the command */
5359 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5360 "%s: Received GETIBSSPEERINFO Command", __func__);
5361
5362 if (eConnectionState_IbssConnected != pHddStaCtx->conn_info.connState)
5363 {
5364 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5365 "%s:No IBSS Peers coalesced", __func__);
5366 ret = -EINVAL;
5367 goto exit;
5368 }
5369
5370 /* Parse the incoming command buffer */
5371 status = hdd_parse_get_ibss_peer_info(value, &peerMacAddr);
5372 if (VOS_STATUS_SUCCESS != status)
5373 {
5374 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5375 "%s: Invalid GETIBSSPEERINFO command", __func__);
5376 ret = -EINVAL;
5377 goto exit;
5378 }
5379
5380 /* Get station index for the peer mac address */
5381 hdd_Ibss_GetStaId(pHddStaCtx, &peerMacAddr, &staIdx);
5382
5383 if (staIdx > HDD_MAX_NUM_IBSS_STA)
5384 {
5385 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5386 "%s: Invalid StaIdx %d returned", __func__, staIdx);
5387 ret = -EINVAL;
5388 goto exit;
5389 }
5390
5391 /* Handle the command */
5392 status = hdd_cfg80211_get_ibss_peer_info(pAdapter, staIdx);
5393 if (VOS_STATUS_SUCCESS == status)
5394 {
5395 v_U32_t txRate = pHddStaCtx->ibss_peer_info.ibssPeerList[0].txRate;
5396 txRateMbps = (txRate * 500 * 1000)/1000000;
5397
5398 length = scnprintf( extra, sizeof(extra), "%d %d", (int)txRateMbps,
5399 (int)pHddStaCtx->ibss_peer_info.ibssPeerList[0].rssi);
5400
5401 /* Copy the data back into buffer */
5402 if (copy_to_user(priv_data.buf, &extra, length+ 1))
5403 {
5404 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5405 "%s: copy data to user buffer failed GETIBSSPEERINFO command",
5406 __func__);
5407 ret = -EFAULT;
5408 goto exit;
5409 }
5410 }
5411 else
5412 {
5413 /* Command failed, log error */
5414 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5415 "%s: GETIBSSPEERINFO command failed with status code %d",
5416 __func__, status);
5417 ret = -EINVAL;
5418 goto exit;
5419 }
5420
5421 /* Success ! */
5422 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED,
5423 "%s", priv_data.buf);
5424 ret = 0;
5425 }
5426 else if (strncasecmp(command, "SETRMCTXRATE", 12) == 0)
5427 {
5428 tANI_U8 *value = command;
5429 tANI_U32 uRate = 0;
5430 tTxrateinfoflags txFlags = 0;
5431 tSirRateUpdateInd *rateUpdateParams;
5432 int status;
5433
5434 if ((WLAN_HDD_IBSS != pAdapter->device_mode) &&
5435 (WLAN_HDD_SOFTAP != pAdapter->device_mode))
5436 {
5437 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5438 "Received SETRMCTXRATE command in invalid mode %d "
5439 "SETRMC command is only allowed in IBSS or SOFTAP mode",
5440 pAdapter->device_mode);
5441 ret = -EINVAL;
5442 goto exit;
5443 }
5444
5445 status = hdd_parse_setrmcrate_command(value, &uRate, &txFlags);
5446 if (status)
5447 {
5448 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5449 "Invalid SETRMCTXRATE command ");
5450 ret = -EINVAL;
5451 goto exit;
5452 }
5453
5454 rateUpdateParams = vos_mem_malloc(sizeof(tSirRateUpdateInd));
5455 if (NULL == rateUpdateParams)
5456 {
5457 ret = -EINVAL;
5458 goto exit;
5459 }
5460
5461 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5462 "%s: uRate %d ", __func__, uRate);
5463
5464 vos_mem_zero(rateUpdateParams, sizeof(tSirRateUpdateInd ));
5465
5466 /* -1 implies ignore this param */
5467 rateUpdateParams->ucastDataRate = -1;
5468
5469 /*
5470 * Fill the user specifieed RMC rate param
5471 * and the derived tx flags.
5472 */
5473 rateUpdateParams->rmcDataRate = uRate;
5474 rateUpdateParams->rmcDataRateTxFlag = txFlags;
5475
5476 status = sme_SendRateUpdateInd((tHalHandle)(pHddCtx->hHal), rateUpdateParams);
5477 }
5478 else if (strncasecmp(command, "SETIBSSTXFAILEVENT", 18) == 0 )
5479 {
5480 char *value;
5481 tANI_U8 tx_fail_count = 0;
5482 tANI_U16 pid = 0;
5483
5484 value = command;
5485
5486 ret = hdd_ParseIBSSTXFailEventParams(value, &tx_fail_count, &pid);
5487
5488 if (0 != ret)
5489 {
5490 hddLog(VOS_TRACE_LEVEL_INFO,
5491 "%s: Failed to parse SETIBSSTXFAILEVENT arguments",
5492 __func__);
5493 goto exit;
5494 }
5495
5496 hddLog(VOS_TRACE_LEVEL_INFO, "%s: tx_fail_cnt=%hhu, pid=%hu",
5497 __func__, tx_fail_count, pid);
5498
5499 if (0 == tx_fail_count)
5500 {
5501 // Disable TX Fail Indication
5502 if (eHAL_STATUS_SUCCESS ==
5503 sme_TXFailMonitorStartStopInd(pHddCtx->hHal,
5504 tx_fail_count,
5505 NULL))
5506 {
5507 cesium_pid = 0;
5508 }
5509 else
5510 {
5511 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5512 "%s: failed to disable TX Fail Event ", __func__);
5513 ret = -EINVAL;
5514 }
5515 }
5516 else
5517 {
5518 if (eHAL_STATUS_SUCCESS ==
5519 sme_TXFailMonitorStartStopInd(pHddCtx->hHal,
5520 tx_fail_count,
5521 (void*)hdd_tx_fail_ind_callback))
5522 {
5523 cesium_pid = pid;
5524 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5525 "%s: Registered Cesium pid %u", __func__,
5526 cesium_pid);
5527 }
5528 else
5529 {
5530 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5531 "%s: Failed to enable TX Fail Monitoring", __func__);
5532 ret = -EINVAL;
5533 }
5534 }
5535 }
5536
5537#endif /* WLAN_FEATURE_RMC */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08005538#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07005539 else if (strncmp(command, "SETCCXROAMSCANCHANNELS", 22) == 0)
5540 {
5541 tANI_U8 *value = command;
5542 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
5543 tANI_U8 numChannels = 0;
5544 eHalStatus status = eHAL_STATUS_SUCCESS;
5545
5546 status = hdd_parse_channellist(value, ChannelList, &numChannels);
5547 if (eHAL_STATUS_SUCCESS != status)
5548 {
5549 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5550 "%s: Failed to parse channel list information", __func__);
5551 ret = -EINVAL;
5552 goto exit;
5553 }
5554
5555 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
5556 {
5557 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5558 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
5559 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
5560 ret = -EINVAL;
5561 goto exit;
5562 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08005563 status = sme_SetEseRoamScanChannelList((tHalHandle)(pHddCtx->hHal),
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07005564 ChannelList,
5565 numChannels);
5566 if (eHAL_STATUS_SUCCESS != status)
5567 {
5568 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5569 "%s: Failed to update channel list information", __func__);
5570 ret = -EINVAL;
5571 goto exit;
5572 }
5573 }
5574 else if (strncmp(command, "GETTSMSTATS", 11) == 0)
5575 {
5576 tANI_U8 *value = command;
5577 char extra[128] = {0};
5578 int len = 0;
5579 tANI_U8 tid = 0;
5580 hdd_station_ctx_t *pHddStaCtx = NULL;
5581 tAniTrafStrmMetrics tsmMetrics;
5582 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5583
5584 /* if not associated, return error */
5585 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
5586 {
5587 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:Not associated!",__func__);
5588 ret = -EINVAL;
5589 goto exit;
5590 }
5591
5592 /* Move pointer to ahead of GETTSMSTATS<delimiter> */
5593 value = value + 12;
5594 /* Convert the value from ascii to integer */
5595 ret = kstrtou8(value, 10, &tid);
5596 if (ret < 0)
5597 {
5598 /* If the input value is greater than max value of datatype, then also
5599 kstrtou8 fails */
5600 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5601 "%s: kstrtou8 failed range [%d - %d]", __func__,
5602 TID_MIN_VALUE,
5603 TID_MAX_VALUE);
5604 ret = -EINVAL;
5605 goto exit;
5606 }
5607
5608 if ((tid < TID_MIN_VALUE) || (tid > TID_MAX_VALUE))
5609 {
5610 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5611 "tid value %d is out of range"
5612 " (Min: %d Max: %d)", tid,
5613 TID_MIN_VALUE,
5614 TID_MAX_VALUE);
5615 ret = -EINVAL;
5616 goto exit;
5617 }
5618
5619 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5620 "%s: Received Command to get tsm stats tid = %d", __func__, tid);
5621
5622 if (VOS_STATUS_SUCCESS != hdd_get_tsm_stats(pAdapter, tid, &tsmMetrics))
5623 {
5624 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5625 "%s: failed to get tsm stats", __func__);
5626 ret = -EFAULT;
5627 goto exit;
5628 }
5629
5630 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5631 "UplinkPktQueueDly(%d)\n"
5632 "UplinkPktQueueDlyHist[0](%d)\n"
5633 "UplinkPktQueueDlyHist[1](%d)\n"
5634 "UplinkPktQueueDlyHist[2](%d)\n"
5635 "UplinkPktQueueDlyHist[3](%d)\n"
Arun Kumar Khandavallie8768212014-02-17 16:43:34 +05305636 "UplinkPktTxDly(%u)\n"
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07005637 "UplinkPktLoss(%d)\n"
5638 "UplinkPktCount(%d)\n"
5639 "RoamingCount(%d)\n"
5640 "RoamingDly(%d)", tsmMetrics.UplinkPktQueueDly,
5641 tsmMetrics.UplinkPktQueueDlyHist[0],
5642 tsmMetrics.UplinkPktQueueDlyHist[1],
5643 tsmMetrics.UplinkPktQueueDlyHist[2],
5644 tsmMetrics.UplinkPktQueueDlyHist[3],
5645 tsmMetrics.UplinkPktTxDly, tsmMetrics.UplinkPktLoss,
5646 tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount, tsmMetrics.RoamingDly);
5647
5648 /* Output TSM stats is of the format
5649 GETTSMSTATS [PktQueueDly] [PktQueueDlyHist[0]]:[PktQueueDlyHist[1]] ...[RoamingDly]
5650 eg., GETTSMSTATS 10 1:0:0:161 20 1 17 8 39800 */
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08005651 len = scnprintf(extra, sizeof(extra), "%s %d %d:%d:%d:%d %u %d %d %d %d", command,
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07005652 tsmMetrics.UplinkPktQueueDly, tsmMetrics.UplinkPktQueueDlyHist[0],
5653 tsmMetrics.UplinkPktQueueDlyHist[1], tsmMetrics.UplinkPktQueueDlyHist[2],
5654 tsmMetrics.UplinkPktQueueDlyHist[3], tsmMetrics.UplinkPktTxDly,
5655 tsmMetrics.UplinkPktLoss, tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount,
5656 tsmMetrics.RoamingDly);
5657
Ratnam Rachurid53009c2015-08-07 13:59:00 +05305658 len = VOS_MIN(priv_data.total_len, len + 1);
5659 if (copy_to_user(priv_data.buf, &extra, len)) {
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07005660 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5661 "%s: failed to copy data to user buffer", __func__);
5662 ret = -EFAULT;
5663 goto exit;
5664 }
5665 }
5666 else if (strncmp(command, "SETCCKMIE", 9) == 0)
5667 {
5668 tANI_U8 *value = command;
5669 tANI_U8 *cckmIe = NULL;
5670 tANI_U8 cckmIeLen = 0;
5671 eHalStatus status = eHAL_STATUS_SUCCESS;
5672
5673 status = hdd_parse_get_cckm_ie(value, &cckmIe, &cckmIeLen);
5674 if (eHAL_STATUS_SUCCESS != status)
5675 {
5676 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5677 "%s: Failed to parse cckm ie data", __func__);
5678 ret = -EINVAL;
5679 goto exit;
5680 }
5681
5682 if (cckmIeLen > DOT11F_IE_RSN_MAX_LEN)
5683 {
5684 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5685 "%s: CCKM Ie input length is more than max[%d]", __func__,
5686 DOT11F_IE_RSN_MAX_LEN);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08005687 vos_mem_free(cckmIe);
5688 cckmIe = NULL;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07005689 ret = -EINVAL;
5690 goto exit;
5691 }
5692 sme_SetCCKMIe((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, cckmIe, cckmIeLen);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08005693 vos_mem_free(cckmIe);
5694 cckmIe = NULL;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07005695 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08005696 else if (strncmp(command, "CCXBEACONREQ", 12) == 0)
5697 {
5698 tANI_U8 *value = command;
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08005699 tCsrEseBeaconReq eseBcnReq;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08005700 eHalStatus status = eHAL_STATUS_SUCCESS;
Srinivas Girigowda0c6d7fe2014-05-28 18:18:10 -07005701
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08005702 status = hdd_parse_ese_beacon_req(value, &eseBcnReq);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08005703 if (eHAL_STATUS_SUCCESS != status)
5704 {
5705 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08005706 "%s: Failed to parse ese beacon req", __func__);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08005707 ret = -EINVAL;
5708 goto exit;
5709 }
Srinivas Girigowda0c6d7fe2014-05-28 18:18:10 -07005710 if (!hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))) {
5711 hddLog(VOS_TRACE_LEVEL_INFO, FL("Not associated"));
5712 hdd_indicateEseBcnReportNoResults (pAdapter,
5713 eseBcnReq.bcnReq[0].measurementToken,
5714 0x02, //BIT(1) set for measurement done
5715 0); // no BSS
5716 goto exit;
5717 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08005718
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08005719 status = sme_SetEseBeaconRequest((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, &eseBcnReq);
5720 if (eHAL_STATUS_SUCCESS != status)
5721 {
5722 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5723 "%s: sme_SetEseBeaconRequest failed (%d)", __func__, status);
5724 ret = -EINVAL;
5725 goto exit;
5726 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08005727 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08005728#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
c_hpothu92367912014-05-01 15:18:17 +05305729 else if (strncmp(command, "GETBCNMISSRATE", 14) == 0)
5730 {
5731 eHalStatus status;
5732 char buf[32], len;
5733 long waitRet;
5734 bcnMissRateContext_t getBcnMissRateCtx;
5735
5736 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5737
5738 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
5739 {
5740 hddLog(VOS_TRACE_LEVEL_WARN,
5741 FL("GETBCNMISSRATE: STA is not in connected state"));
5742 ret = -1;
5743 goto exit;
5744 }
5745
5746 init_completion(&(getBcnMissRateCtx.completion));
5747 getBcnMissRateCtx.magic = BCN_MISS_RATE_CONTEXT_MAGIC;
5748
5749 status = sme_getBcnMissRate((tHalHandle)(pHddCtx->hHal),
5750 pAdapter->sessionId,
5751 (void *)getBcnMissRateCB,
5752 (void *)(&getBcnMissRateCtx));
5753 if( eHAL_STATUS_SUCCESS != status)
5754 {
5755 hddLog(VOS_TRACE_LEVEL_INFO,
5756 FL("GETBCNMISSRATE: fail to post WDA cmd"));
5757 ret = -EINVAL;
5758 goto exit;
5759 }
5760
5761 waitRet = wait_for_completion_interruptible_timeout
5762 (&getBcnMissRateCtx.completion, BCN_MISS_RATE_TIME);
5763 if(waitRet <= 0)
5764 {
5765 hddLog(VOS_TRACE_LEVEL_ERROR,
5766 FL("failed to wait on bcnMissRateComp %d"), ret);
5767
5768 //Make magic number to zero so that callback is not called.
5769 spin_lock(&hdd_context_lock);
5770 getBcnMissRateCtx.magic = 0x0;
5771 spin_unlock(&hdd_context_lock);
5772 ret = -EINVAL;
5773 goto exit;
5774 }
5775
5776 hddLog(VOS_TRACE_LEVEL_INFO,
5777 FL("GETBCNMISSRATE: bcnMissRate: %d"), gbcnMissRate);
5778
5779 len = snprintf(buf, sizeof(buf), "GETBCNMISSRATE %d", gbcnMissRate);
5780 if (copy_to_user(priv_data.buf, &buf, len + 1))
5781 {
5782 hddLog(VOS_TRACE_LEVEL_ERROR,
5783 "%s: failed to copy data to user buffer", __func__);
5784 ret = -EFAULT;
5785 goto exit;
5786 }
5787 ret = len;
5788 }
Atul Mittal87ec2422014-09-24 13:12:50 +05305789#ifdef FEATURE_WLAN_TDLS
5790 else if (strncmp(command, "TDLSSECONDARYCHANNELOFFSET", 26) == 0) {
5791 tANI_U8 *value = command;
5792 int set_value;
5793 /* Move pointer to ahead of TDLSOFFCH*/
5794 value += 26;
c_manjeebbc40212015-12-08 13:52:59 +05305795 if (!(sscanf(value, "%d", &set_value))) {
5796 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5797 FL("No input identified"));
5798 ret = -EINVAL;
5799 goto exit;
5800 }
5801
Atul Mittal87ec2422014-09-24 13:12:50 +05305802 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5803 "%s: Tdls offchannel offset:%d",
5804 __func__, set_value);
5805 ret = iw_set_tdlssecoffchanneloffset(pHddCtx, set_value);
5806 if (ret < 0)
5807 {
5808 ret = -EINVAL;
5809 goto exit;
5810 }
5811
5812 } else if (strncmp(command, "TDLSOFFCHANNELMODE", 18) == 0) {
5813 tANI_U8 *value = command;
5814 int set_value;
5815 /* Move pointer to ahead of tdlsoffchnmode*/
5816 value += 18;
c_manjee82323892015-12-08 12:40:34 +05305817 ret = sscanf(value, "%d", &set_value);
5818 if (ret != 1) {
5819 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5820 FL("No input identified"));
5821 ret = -EINVAL;
5822 goto exit;
5823 }
Atul Mittal87ec2422014-09-24 13:12:50 +05305824 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5825 "%s: Tdls offchannel mode:%d",
5826 __func__, set_value);
5827 ret = iw_set_tdlsoffchannelmode(pAdapter, set_value);
5828 if (ret < 0)
5829 {
5830 ret = -EINVAL;
5831 goto exit;
5832 }
5833 } else if (strncmp(command, "TDLSOFFCHANNEL", 14) == 0) {
5834 tANI_U8 *value = command;
5835 int set_value;
5836 /* Move pointer to ahead of TDLSOFFCH*/
5837 value += 14;
c_manjeef6ccaf52015-12-08 11:52:11 +05305838 ret = sscanf(value, "%d", &set_value);
5839 if (ret != 1) {
5840 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5841 "Wrong value is given for hdd_set_tdls_offchannel");
5842 ret = -EINVAL;
5843 goto exit;
5844 }
5845
Atul Mittal87ec2422014-09-24 13:12:50 +05305846 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5847 "%s: Tdls offchannel num: %d",
5848 __func__, set_value);
5849 ret = iw_set_tdlsoffchannel(pHddCtx, set_value);
5850 if (ret < 0)
5851 {
5852 ret = -EINVAL;
5853 goto exit;
5854 }
5855 }
5856#endif
Satyanarayana Dash72806012014-12-02 14:30:08 +05305857 else if (strncmp(command, "GETFWSTATS", 10) == 0)
5858 {
5859 eHalStatus status;
5860 char *buf = NULL;
5861 char len;
5862 long waitRet;
5863 fwStatsContext_t fwStatsCtx;
Abhishek Singh08aa7762014-12-16 13:59:03 +05305864 tSirFwStatsResult *fwStatsRsp = &(pAdapter->fwStatsRsp);
Satyanarayana Dash72806012014-12-02 14:30:08 +05305865 tANI_U8 *ptr = command;
5866 int stats = *(ptr + 11) - '0';
5867
5868 hddLog(VOS_TRACE_LEVEL_INFO, FL("stats = %d "),stats);
5869 if (!IS_FEATURE_FW_STATS_ENABLE)
5870 {
5871 hddLog(VOS_TRACE_LEVEL_INFO,
5872 FL("Get Firmware stats feature not supported"));
5873 ret = -EINVAL;
5874 goto exit;
5875 }
5876
5877 if (FW_STATS_MAX <= stats || 0 >= stats)
5878 {
5879 hddLog(VOS_TRACE_LEVEL_INFO,
5880 FL(" stats %d not supported"),stats);
5881 ret = -EINVAL;
5882 goto exit;
5883 }
5884
5885 init_completion(&(fwStatsCtx.completion));
5886 fwStatsCtx.magic = FW_STATS_CONTEXT_MAGIC;
5887 fwStatsCtx.pAdapter = pAdapter;
5888 fwStatsRsp->type = 0;
5889 status = sme_GetFwStats( (tHalHandle)pHddCtx->hHal, stats,
Abhishek Singh08aa7762014-12-16 13:59:03 +05305890 &fwStatsCtx, hdd_FWStatisCB);
Satyanarayana Dash72806012014-12-02 14:30:08 +05305891 if (eHAL_STATUS_SUCCESS != status)
5892 {
5893 hddLog(VOS_TRACE_LEVEL_ERROR,
5894 FL(" fail to post WDA cmd status = %d"), status);
5895 ret = -EINVAL;
5896 goto exit;
5897 }
5898 waitRet = wait_for_completion_timeout
5899 (&(fwStatsCtx.completion), FW_STATE_WAIT_TIME);
5900 if (waitRet <= 0)
5901 {
5902 hddLog(VOS_TRACE_LEVEL_ERROR,
5903 FL("failed to wait on GwtFwstats"));
5904 //Make magic number to zero so that callback is not executed.
5905 spin_lock(&hdd_context_lock);
5906 fwStatsCtx.magic = 0x0;
5907 spin_unlock(&hdd_context_lock);
5908 ret = -EINVAL;
5909 goto exit;
5910 }
5911 if (fwStatsRsp->type)
5912 {
5913 buf = kmalloc(FW_STATE_RSP_LEN, GFP_KERNEL);
5914 if (!buf)
5915 {
5916 hddLog(VOS_TRACE_LEVEL_ERROR,
5917 FL(" failed to allocate memory"));
5918 ret = -ENOMEM;
5919 goto exit;
5920 }
5921 switch( fwStatsRsp->type )
5922 {
5923 case FW_UBSP_STATS:
5924 {
5925 len = snprintf(buf, FW_STATE_RSP_LEN,
5926 "GETFWSTATS: ubsp_enter_cnt %d ubsp_jump_ddr_cnt %d",
Abhishek Singh08aa7762014-12-16 13:59:03 +05305927 fwStatsRsp->fwStatsData.ubspStats.ubsp_enter_cnt,
5928 fwStatsRsp->fwStatsData.ubspStats.ubsp_jump_ddr_cnt);
Satyanarayana Dash72806012014-12-02 14:30:08 +05305929 }
5930 break;
5931 default:
5932 {
5933 hddLog(VOS_TRACE_LEVEL_ERROR, FL( "No handling for stats type %d"),fwStatsRsp->type);
5934 ret = -EFAULT;
5935 kfree(buf);
5936 goto exit;
5937 }
5938 }
5939 if (copy_to_user(priv_data.buf, buf, len + 1))
5940 {
5941 hddLog(VOS_TRACE_LEVEL_ERROR,
5942 FL(" failed to copy data to user buffer"));
5943 ret = -EFAULT;
5944 kfree(buf);
5945 goto exit;
5946 }
5947 ret = len;
5948 kfree(buf);
5949 }
5950 else
5951 {
5952 hddLog(VOS_TRACE_LEVEL_ERROR,
5953 FL("failed to fetch the stats"));
5954 ret = -EFAULT;
5955 goto exit;
5956 }
5957
5958 }
Agarwal Ashish8bd53ae2015-06-12 18:03:45 +05305959 else if (strncasecmp(command, "SET_FCC_CHANNEL", 15) == 0)
5960 {
5961 /*
5962 * this command wld be called by user-space when it detects WLAN
5963 * ON after airplane mode is set. When APM is set, WLAN turns off.
5964 * But it can be turned back on. Otherwise; when APM is turned back
5965 * off, WLAN wld turn back on. So at that point the command is
5966 * expected to come down. 0 means disable, 1 means enable. The
5967 * constraint is removed when parameter 1 is set or different
5968 * country code is set
5969 */
5970 ret = hdd_cmd_setFccChannel(pHddCtx, command, 15);
5971 }
Mahesh A Saptasagarbeca12c2015-09-07 16:21:06 +05305972 else if (strncasecmp(command, "DISABLE_CA_EVENT", 16) == 0)
5973 {
5974 ret = hdd_enable_disable_ca_event(pHddCtx, command, 16);
5975 }
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07005976 else {
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05305977 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
5978 TRACE_CODE_HDD_UNSUPPORTED_IOCTL,
5979 pAdapter->sessionId, 0));
Satyanarayana Dash72806012014-12-02 14:30:08 +05305980 hddLog( VOS_TRACE_LEVEL_WARN, FL("Unsupported GUI command %s"),
5981 command);
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07005982 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005983 }
5984exit:
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05305985 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07005986 if (command)
5987 {
5988 kfree(command);
5989 }
5990 return ret;
5991}
5992
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07005993#ifdef CONFIG_COMPAT
5994static int hdd_driver_compat_ioctl(hdd_adapter_t *pAdapter, struct ifreq *ifr)
5995{
5996 struct {
5997 compat_uptr_t buf;
5998 int used_len;
5999 int total_len;
6000 } compat_priv_data;
6001 hdd_priv_data_t priv_data;
6002 int ret = 0;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006003
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07006004 /*
6005 * Note that pAdapter and ifr have already been verified by caller,
6006 * and HDD context has also been validated
6007 */
6008 if (copy_from_user(&compat_priv_data, ifr->ifr_data,
6009 sizeof(compat_priv_data))) {
6010 ret = -EFAULT;
6011 goto exit;
6012 }
6013 priv_data.buf = compat_ptr(compat_priv_data.buf);
6014 priv_data.used_len = compat_priv_data.used_len;
6015 priv_data.total_len = compat_priv_data.total_len;
6016 ret = hdd_driver_command(pAdapter, &priv_data);
6017 exit:
6018 return ret;
6019}
6020#else /* CONFIG_COMPAT */
6021static int hdd_driver_compat_ioctl(hdd_adapter_t *pAdapter, struct ifreq *ifr)
6022{
6023 /* will never be invoked */
6024 return 0;
6025}
6026#endif /* CONFIG_COMPAT */
6027
6028static int hdd_driver_ioctl(hdd_adapter_t *pAdapter, struct ifreq *ifr)
6029{
6030 hdd_priv_data_t priv_data;
6031 int ret = 0;
6032
6033 /*
6034 * Note that pAdapter and ifr have already been verified by caller,
6035 * and HDD context has also been validated
6036 */
6037 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(priv_data))) {
6038 ret = -EFAULT;
6039 } else {
6040 ret = hdd_driver_command(pAdapter, &priv_data);
6041 }
6042 return ret;
6043}
6044
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05306045int __hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07006046{
6047 hdd_adapter_t *pAdapter;
6048 hdd_context_t *pHddCtx;
6049 int ret;
6050
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05306051 ENTER();
6052
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07006053 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6054 if (NULL == pAdapter) {
6055 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6056 "%s: HDD adapter context is Null", __func__);
6057 ret = -ENODEV;
6058 goto exit;
6059 }
6060 if (dev != pAdapter->dev) {
6061 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6062 "%s: HDD adapter/dev inconsistency", __func__);
6063 ret = -ENODEV;
6064 goto exit;
6065 }
6066
6067 if ((!ifr) || (!ifr->ifr_data)) {
6068 ret = -EINVAL;
6069 goto exit;
6070 }
6071
6072 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6073 ret = wlan_hdd_validate_context(pHddCtx);
6074 if (ret) {
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07006075 ret = -EBUSY;
6076 goto exit;
6077 }
6078
6079 switch (cmd) {
6080 case (SIOCDEVPRIVATE + 1):
6081 if (is_compat_task())
6082 ret = hdd_driver_compat_ioctl(pAdapter, ifr);
6083 else
6084 ret = hdd_driver_ioctl(pAdapter, ifr);
6085 break;
6086 default:
6087 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unknown ioctl %d",
6088 __func__, cmd);
6089 ret = -EINVAL;
6090 break;
6091 }
6092 exit:
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05306093 EXIT();
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07006094 return ret;
6095}
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006096
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05306097int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
6098{
6099 int ret;
6100
6101 vos_ssr_protect(__func__);
6102 ret = __hdd_ioctl(dev, ifr, cmd);
6103 vos_ssr_unprotect(__func__);
6104
6105 return ret;
6106}
6107
Katya Nigame7b69a82015-04-28 15:24:06 +05306108int hdd_mon_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
6109{
6110 return 0;
6111}
6112
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006113#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006114/**---------------------------------------------------------------------------
6115
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006116 \brief hdd_parse_ese_beacon_req() - Parse ese beacon request
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006117
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006118 This function parses the ese beacon request passed in the format
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006119 CCXBEACONREQ<space><Number of fields><space><Measurement token>
6120 <space>Channel 1<space>Scan Mode <space>Meas Duration<space>Channel N
6121 <space>Scan Mode N<space>Meas Duration N
6122 if the Number of bcn req fields (N) does not match with the actual number of fields passed
6123 then take N.
6124 <Meas Token><Channel><Scan Mode> and <Meas Duration> are treated as one pair
6125 For example, CCXBEACONREQ 2 1 1 1 30 2 44 0 40.
6126 This function does not take care of removing duplicate channels from the list
6127
6128 \param - pValue Pointer to data
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006129 \param - pEseBcnReq output pointer to store parsed ie information
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006130
6131 \return - 0 for success non-zero for failure
6132
6133 --------------------------------------------------------------------------*/
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006134static VOS_STATUS hdd_parse_ese_beacon_req(tANI_U8 *pValue,
6135 tCsrEseBeaconReq *pEseBcnReq)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006136{
6137 tANI_U8 *inPtr = pValue;
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306138 uint8_t input = 0;
6139 uint32_t tempInt = 0;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006140 int j = 0, i = 0, v = 0;
6141 char buf[32];
6142
6143 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
6144 /*no argument after the command*/
6145 if (NULL == inPtr)
6146 {
6147 return -EINVAL;
6148 }
6149 /*no space after the command*/
6150 else if (SPACE_ASCII_VALUE != *inPtr)
6151 {
6152 return -EINVAL;
6153 }
6154
6155 /*removing empty spaces*/
6156 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
6157
6158 /*no argument followed by spaces*/
6159 if ('\0' == *inPtr) return -EINVAL;
6160
6161 /*getting the first argument ie measurement token*/
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08006162 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006163 if (1 != v) return -EINVAL;
6164
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306165 v = kstrtos8(buf, 10, &input);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006166 if ( v < 0) return -EINVAL;
6167
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306168 input = VOS_MIN(input, SIR_ESE_MAX_MEAS_IE_REQS);
6169 pEseBcnReq->numBcnReqIe = input;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006170
Srinivas Girigowda725a88e2016-03-31 19:24:25 +05306171 hddLog(LOG1, "Number of Bcn Req Ie fields: %d", pEseBcnReq->numBcnReqIe);
6172
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006173
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006174 for (j = 0; j < (pEseBcnReq->numBcnReqIe); j++)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006175 {
6176 for (i = 0; i < 4; i++)
6177 {
6178 /*inPtr pointing to the beginning of first space after number of ie fields*/
6179 inPtr = strpbrk( inPtr, " " );
6180 /*no ie data after the number of ie fields argument*/
6181 if (NULL == inPtr) return -EINVAL;
6182
6183 /*removing empty space*/
6184 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
6185
6186 /*no ie data after the number of ie fields argument and spaces*/
6187 if ( '\0' == *inPtr ) return -EINVAL;
6188
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08006189 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006190 if (1 != v) return -EINVAL;
6191
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306192 v = kstrtou32(buf, 10, &tempInt);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006193 if (v < 0) return -EINVAL;
6194
6195 switch (i)
6196 {
6197 case 0: /* Measurement token */
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306198 if (!tempInt)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006199 {
6200 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306201 "Invalid Measurement Token: %u", tempInt);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006202 return -EINVAL;
6203 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006204 pEseBcnReq->bcnReq[j].measurementToken = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006205 break;
6206
6207 case 1: /* Channel number */
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306208 if ((!tempInt) ||
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006209 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
6210 {
6211 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306212 "Invalid Channel Number: %u", tempInt);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006213 return -EINVAL;
6214 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006215 pEseBcnReq->bcnReq[j].channel = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006216 break;
6217
6218 case 2: /* Scan mode */
Varun Reddy Yeturu0b18d5a2013-12-04 11:42:23 -08006219 if ((tempInt < eSIR_PASSIVE_SCAN) || (tempInt > eSIR_BEACON_TABLE))
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006220 {
6221 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306222 "Invalid Scan Mode(%u) Expected{0|1|2}", tempInt);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006223 return -EINVAL;
6224 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006225 pEseBcnReq->bcnReq[j].scanMode= tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006226 break;
6227
6228 case 3: /* Measurement duration */
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306229 if (((!tempInt) && (pEseBcnReq->bcnReq[j].scanMode != eSIR_BEACON_TABLE)) ||
6230 ((pEseBcnReq->bcnReq[j].scanMode == eSIR_BEACON_TABLE)))
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006231 {
6232 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Arun Khandavalli9f3b4832016-06-30 16:58:38 +05306233 "Invalid Measurement Duration: %u", tempInt);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006234 return -EINVAL;
6235 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006236 pEseBcnReq->bcnReq[j].measurementDuration = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006237 break;
6238 }
6239 }
6240 }
6241
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006242 for (j = 0; j < pEseBcnReq->numBcnReqIe; j++)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006243 {
6244 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arun Kumar Khandavallie8768212014-02-17 16:43:34 +05306245 "Index(%d) Measurement Token(%u)Channel(%u) Scan Mode(%u) Measurement Duration(%u)\n",
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006246 j,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006247 pEseBcnReq->bcnReq[j].measurementToken,
6248 pEseBcnReq->bcnReq[j].channel,
6249 pEseBcnReq->bcnReq[j].scanMode,
6250 pEseBcnReq->bcnReq[j].measurementDuration);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08006251 }
6252
6253 return VOS_STATUS_SUCCESS;
6254}
6255
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006256static void hdd_GetTsmStatsCB( tAniTrafStrmMetrics tsmMetrics, const tANI_U32 staId, void *pContext )
6257{
6258 struct statsContext *pStatsContext = NULL;
6259 hdd_adapter_t *pAdapter = NULL;
6260
6261 if (NULL == pContext)
6262 {
6263 hddLog(VOS_TRACE_LEVEL_ERROR,
6264 "%s: Bad param, pContext [%p]",
6265 __func__, pContext);
6266 return;
6267 }
6268
Jeff Johnson72a40512013-12-19 10:14:15 -08006269 /* there is a race condition that exists between this callback
6270 function and the caller since the caller could time out either
6271 before or while this code is executing. we use a spinlock to
6272 serialize these actions */
6273 spin_lock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006274
6275 pStatsContext = pContext;
6276 pAdapter = pStatsContext->pAdapter;
6277 if ((NULL == pAdapter) || (STATS_CONTEXT_MAGIC != pStatsContext->magic))
6278 {
6279 /* the caller presumably timed out so there is nothing we can do */
Jeff Johnson72a40512013-12-19 10:14:15 -08006280 spin_unlock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006281 hddLog(VOS_TRACE_LEVEL_WARN,
6282 "%s: Invalid context, pAdapter [%p] magic [%08x]",
6283 __func__, pAdapter, pStatsContext->magic);
6284 return;
6285 }
6286
Jeff Johnson72a40512013-12-19 10:14:15 -08006287 /* context is valid so caller is still waiting */
6288
6289 /* paranoia: invalidate the magic */
6290 pStatsContext->magic = 0;
6291
6292 /* copy over the tsm stats */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006293 pAdapter->tsmStats.UplinkPktQueueDly = tsmMetrics.UplinkPktQueueDly;
6294 vos_mem_copy(pAdapter->tsmStats.UplinkPktQueueDlyHist,
6295 tsmMetrics.UplinkPktQueueDlyHist,
6296 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
6297 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
6298 pAdapter->tsmStats.UplinkPktTxDly = tsmMetrics.UplinkPktTxDly;
6299 pAdapter->tsmStats.UplinkPktLoss = tsmMetrics.UplinkPktLoss;
6300 pAdapter->tsmStats.UplinkPktCount = tsmMetrics.UplinkPktCount;
6301 pAdapter->tsmStats.RoamingCount = tsmMetrics.RoamingCount;
6302 pAdapter->tsmStats.RoamingDly = tsmMetrics.RoamingDly;
6303
Jeff Johnson72a40512013-12-19 10:14:15 -08006304 /* notify the caller */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006305 complete(&pStatsContext->completion);
Jeff Johnson72a40512013-12-19 10:14:15 -08006306
6307 /* serialization is complete */
6308 spin_unlock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006309}
6310
6311
6312
6313static VOS_STATUS hdd_get_tsm_stats(hdd_adapter_t *pAdapter, const tANI_U8 tid,
6314 tAniTrafStrmMetrics* pTsmMetrics)
6315{
6316 hdd_station_ctx_t *pHddStaCtx = NULL;
6317 eHalStatus hstatus;
Jeff Johnson72a40512013-12-19 10:14:15 -08006318 VOS_STATUS vstatus = VOS_STATUS_SUCCESS;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006319 long lrc;
6320 struct statsContext context;
6321 hdd_context_t *pHddCtx = NULL;
6322
6323 if (NULL == pAdapter)
6324 {
6325 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: pAdapter is NULL", __func__);
6326 return VOS_STATUS_E_FAULT;
6327 }
6328
6329 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6330 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6331
6332 /* we are connected prepare our callback context */
6333 init_completion(&context.completion);
6334 context.pAdapter = pAdapter;
6335 context.magic = STATS_CONTEXT_MAGIC;
6336
6337 /* query tsm stats */
6338 hstatus = sme_GetTsmStats(pHddCtx->hHal, hdd_GetTsmStatsCB,
6339 pHddStaCtx->conn_info.staId[ 0 ],
6340 pHddStaCtx->conn_info.bssId,
6341 &context, pHddCtx->pvosContext, tid);
6342
6343 if (eHAL_STATUS_SUCCESS != hstatus)
6344 {
Jeff Johnson72a40512013-12-19 10:14:15 -08006345 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unable to retrieve statistics",
6346 __func__);
6347 vstatus = VOS_STATUS_E_FAULT;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006348 }
6349 else
6350 {
6351 /* request was sent -- wait for the response */
6352 lrc = wait_for_completion_interruptible_timeout(&context.completion,
6353 msecs_to_jiffies(WLAN_WAIT_TIME_STATS));
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006354 if (lrc <= 0)
6355 {
6356 hddLog(VOS_TRACE_LEVEL_ERROR,
6357 "%s: SME %s while retrieving statistics",
6358 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson72a40512013-12-19 10:14:15 -08006359 vstatus = VOS_STATUS_E_TIMEOUT;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006360 }
6361 }
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006362
Jeff Johnson72a40512013-12-19 10:14:15 -08006363 /* either we never sent a request, we sent a request and received a
6364 response or we sent a request and timed out. if we never sent a
6365 request or if we sent a request and got a response, we want to
6366 clear the magic out of paranoia. if we timed out there is a
6367 race condition such that the callback function could be
6368 executing at the same time we are. of primary concern is if the
6369 callback function had already verified the "magic" but had not
6370 yet set the completion variable when a timeout occurred. we
6371 serialize these activities by invalidating the magic while
6372 holding a shared spinlock which will cause us to block if the
6373 callback is currently executing */
6374 spin_lock(&hdd_context_lock);
6375 context.magic = 0;
6376 spin_unlock(&hdd_context_lock);
6377
6378 if (VOS_STATUS_SUCCESS == vstatus)
6379 {
6380 pTsmMetrics->UplinkPktQueueDly = pAdapter->tsmStats.UplinkPktQueueDly;
6381 vos_mem_copy(pTsmMetrics->UplinkPktQueueDlyHist,
6382 pAdapter->tsmStats.UplinkPktQueueDlyHist,
6383 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
6384 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
6385 pTsmMetrics->UplinkPktTxDly = pAdapter->tsmStats.UplinkPktTxDly;
6386 pTsmMetrics->UplinkPktLoss = pAdapter->tsmStats.UplinkPktLoss;
6387 pTsmMetrics->UplinkPktCount = pAdapter->tsmStats.UplinkPktCount;
6388 pTsmMetrics->RoamingCount = pAdapter->tsmStats.RoamingCount;
6389 pTsmMetrics->RoamingDly = pAdapter->tsmStats.RoamingDly;
6390 }
6391 return vstatus;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006392}
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006393#endif /*FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006394
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006395#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -08006396void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
6397{
6398 eCsrBand band = -1;
6399 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
6400 switch (band)
6401 {
6402 case eCSR_BAND_ALL:
6403 *pBand = WLAN_HDD_UI_BAND_AUTO;
6404 break;
6405
6406 case eCSR_BAND_24:
6407 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
6408 break;
6409
6410 case eCSR_BAND_5G:
6411 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
6412 break;
6413
6414 default:
6415 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
6416 *pBand = -1;
6417 break;
6418 }
6419}
6420
6421/**---------------------------------------------------------------------------
6422
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006423 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
6424
6425 This function parses the send action frame data passed in the format
6426 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
6427
Srinivas Girigowda56076852013-08-20 14:00:50 -07006428 \param - pValue Pointer to input data
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006429 \param - pTargetApBssid Pointer to target Ap bssid
6430 \param - pChannel Pointer to the Target AP channel
6431 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
6432 \param - pBuf Pointer to data
6433 \param - pBufLen Pointer to data length
6434
6435 \return - 0 for success non-zero for failure
6436
6437 --------------------------------------------------------------------------*/
6438VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
6439 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
6440{
6441 tANI_U8 *inPtr = pValue;
6442 tANI_U8 *dataEnd;
6443 int tempInt;
6444 int j = 0;
6445 int i = 0;
6446 int v = 0;
6447 tANI_U8 tempBuf[32];
6448 tANI_U8 tempByte = 0;
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08006449 /* 12 hexa decimal digits, 5 ':' and '\0' */
6450 tANI_U8 macAddress[18];
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006451
6452 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
6453 /*no argument after the command*/
6454 if (NULL == inPtr)
6455 {
6456 return -EINVAL;
6457 }
6458
6459 /*no space after the command*/
6460 else if (SPACE_ASCII_VALUE != *inPtr)
6461 {
6462 return -EINVAL;
6463 }
6464
6465 /*removing empty spaces*/
6466 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
6467
6468 /*no argument followed by spaces*/
6469 if ('\0' == *inPtr)
6470 {
6471 return -EINVAL;
6472 }
6473
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07006474 v = sscanf(inPtr, "%17s", macAddress);
6475 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006476 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07006477 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6478 "Invalid MAC address or All hex inputs are not read (%d)", v);
6479 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006480 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07006481
6482 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
6483 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
6484 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
6485 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
6486 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
6487 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006488
6489 /* point to the next argument */
6490 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
6491 /*no argument after the command*/
6492 if (NULL == inPtr) return -EINVAL;
6493
6494 /*removing empty spaces*/
6495 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
6496
6497 /*no argument followed by spaces*/
6498 if ('\0' == *inPtr)
6499 {
6500 return -EINVAL;
6501 }
6502
6503 /*getting the next argument ie the channel number */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08006504 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07006505 if (1 != v) return -EINVAL;
6506
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006507 v = kstrtos32(tempBuf, 10, &tempInt);
Agarwal Ashish353b3a82014-04-08 14:55:11 +05306508 if ( v < 0 || tempInt <= 0 || tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX )
Kiet Lambe150c22013-11-21 16:30:32 +05306509 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006510
6511 *pChannel = tempInt;
6512
6513 /* point to the next argument */
6514 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
6515 /*no argument after the command*/
6516 if (NULL == inPtr) return -EINVAL;
6517 /*removing empty spaces*/
6518 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
6519
6520 /*no argument followed by spaces*/
6521 if ('\0' == *inPtr)
6522 {
6523 return -EINVAL;
6524 }
6525
6526 /*getting the next argument ie the dwell time */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08006527 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07006528 if (1 != v) return -EINVAL;
6529
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006530 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda5a6e0672014-01-09 14:42:57 -08006531 if ( v < 0 || tempInt < 0) return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006532
6533 *pDwellTime = tempInt;
6534
6535 /* point to the next argument */
6536 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
6537 /*no argument after the command*/
6538 if (NULL == inPtr) return -EINVAL;
6539 /*removing empty spaces*/
6540 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
6541
6542 /*no argument followed by spaces*/
6543 if ('\0' == *inPtr)
6544 {
6545 return -EINVAL;
6546 }
6547
6548 /* find the length of data */
6549 dataEnd = inPtr;
6550 while(('\0' != *dataEnd) )
6551 {
6552 dataEnd++;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006553 }
Kiet Lambe150c22013-11-21 16:30:32 +05306554 *pBufLen = dataEnd - inPtr ;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006555 if ( *pBufLen <= 0) return -EINVAL;
6556
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07006557 /* Allocate the number of bytes based on the number of input characters
6558 whether it is even or odd.
6559 if the number of input characters are even, then we need N/2 byte.
6560 if the number of input characters are odd, then we need do (N+1)/2 to
6561 compensate rounding off.
6562 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
6563 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
6564 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006565 if (NULL == *pBuf)
6566 {
6567 hddLog(VOS_TRACE_LEVEL_FATAL,
6568 "%s: vos_mem_alloc failed ", __func__);
6569 return -EINVAL;
6570 }
6571
6572 /* the buffer received from the upper layer is character buffer,
6573 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
6574 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
6575 and f0 in 3rd location */
6576 for (i = 0, j = 0; j < *pBufLen; j += 2)
6577 {
Kiet Lambe150c22013-11-21 16:30:32 +05306578 if( j+1 == *pBufLen)
6579 {
6580 tempByte = hdd_parse_hex(inPtr[j]);
6581 }
6582 else
6583 {
6584 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
6585 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006586 (*pBuf)[i++] = tempByte;
6587 }
6588 *pBufLen = i;
6589 return VOS_STATUS_SUCCESS;
6590}
6591
Srinivas Girigowda100eb322013-03-15 16:48:20 -07006592/**---------------------------------------------------------------------------
6593
Srinivas Girigowdade697412013-02-14 16:31:48 -08006594 \brief hdd_parse_channellist() - HDD Parse channel list
6595
6596 This function parses the channel list passed in the format
6597 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07006598 if the Number of channels (N) does not match with the actual number of channels passed
6599 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
6600 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
6601 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
6602 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08006603
6604 \param - pValue Pointer to input channel list
6605 \param - ChannelList Pointer to local output array to record channel list
6606 \param - pNumChannels Pointer to number of roam scan channels
6607
6608 \return - 0 for success non-zero for failure
6609
6610 --------------------------------------------------------------------------*/
6611VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
6612{
6613 tANI_U8 *inPtr = pValue;
6614 int tempInt;
6615 int j = 0;
6616 int v = 0;
6617 char buf[32];
6618
6619 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
6620 /*no argument after the command*/
6621 if (NULL == inPtr)
6622 {
6623 return -EINVAL;
6624 }
6625
6626 /*no space after the command*/
6627 else if (SPACE_ASCII_VALUE != *inPtr)
6628 {
6629 return -EINVAL;
6630 }
6631
6632 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07006633 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08006634
6635 /*no argument followed by spaces*/
6636 if ('\0' == *inPtr)
6637 {
6638 return -EINVAL;
6639 }
6640
6641 /*getting the first argument ie the number of channels*/
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08006642 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07006643 if (1 != v) return -EINVAL;
6644
Srinivas Girigowdade697412013-02-14 16:31:48 -08006645 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07006646 if ((v < 0) ||
6647 (tempInt <= 0) ||
6648 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
6649 {
6650 return -EINVAL;
6651 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08006652
6653 *pNumChannels = tempInt;
6654
6655 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
6656 "Number of channels are: %d", *pNumChannels);
6657
6658 for (j = 0; j < (*pNumChannels); j++)
6659 {
6660 /*inPtr pointing to the beginning of first space after number of channels*/
6661 inPtr = strpbrk( inPtr, " " );
6662 /*no channel list after the number of channels argument*/
6663 if (NULL == inPtr)
6664 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07006665 if (0 != j)
6666 {
6667 *pNumChannels = j;
6668 return VOS_STATUS_SUCCESS;
6669 }
6670 else
6671 {
6672 return -EINVAL;
6673 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08006674 }
6675
6676 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07006677 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08006678
6679 /*no channel list after the number of channels argument and spaces*/
6680 if ( '\0' == *inPtr )
6681 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07006682 if (0 != j)
6683 {
6684 *pNumChannels = j;
6685 return VOS_STATUS_SUCCESS;
6686 }
6687 else
6688 {
6689 return -EINVAL;
6690 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08006691 }
6692
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08006693 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07006694 if (1 != v) return -EINVAL;
6695
Srinivas Girigowdade697412013-02-14 16:31:48 -08006696 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07006697 if ((v < 0) ||
6698 (tempInt <= 0) ||
6699 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
6700 {
6701 return -EINVAL;
6702 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08006703 pChannelList[j] = tempInt;
6704
6705 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
6706 "Channel %d added to preferred channel list",
6707 pChannelList[j] );
6708 }
6709
Srinivas Girigowdade697412013-02-14 16:31:48 -08006710 return VOS_STATUS_SUCCESS;
6711}
6712
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07006713
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05306714/**
6715 * hdd_parse_reassoc_command_v1_data() - HDD Parse reassoc command data
6716 * This function parses the reasoc command data passed in the format
6717 * REASSOC<space><bssid><space><channel>
6718 *
6719 * @pValue: Pointer to input data (its a NUL terminated string)
6720 * @pTargetApBssid: Pointer to target Ap bssid
6721 * @pChannel: Pointer to the Target AP channel
6722 *
6723 * Return: 0 for success non-zero for failure
6724 */
6725static int hdd_parse_reassoc_command_v1_data(const tANI_U8 *pValue,
6726 tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07006727{
Selvaraj, Sridhar5aff1ed2016-06-18 01:26:23 +05306728 const tANI_U8 *inPtr = pValue;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07006729 int tempInt;
6730 int v = 0;
6731 tANI_U8 tempBuf[32];
Kiet Lamaa8e15a2014-02-11 23:30:06 -08006732 /* 12 hexa decimal digits, 5 ':' and '\0' */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08006733 tANI_U8 macAddress[18];
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07006734
6735 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
6736 /*no argument after the command*/
6737 if (NULL == inPtr)
6738 {
6739 return -EINVAL;
6740 }
6741
6742 /*no space after the command*/
6743 else if (SPACE_ASCII_VALUE != *inPtr)
6744 {
6745 return -EINVAL;
6746 }
6747
6748 /*removing empty spaces*/
6749 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
6750
6751 /*no argument followed by spaces*/
6752 if ('\0' == *inPtr)
6753 {
6754 return -EINVAL;
6755 }
6756
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07006757 v = sscanf(inPtr, "%17s", macAddress);
6758 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07006759 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07006760 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6761 "Invalid MAC address or All hex inputs are not read (%d)", v);
6762 return -EINVAL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07006763 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07006764
6765 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
6766 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
6767 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
6768 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
6769 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
6770 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07006771
6772 /* point to the next argument */
6773 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
6774 /*no argument after the command*/
6775 if (NULL == inPtr) return -EINVAL;
6776
6777 /*removing empty spaces*/
6778 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
6779
6780 /*no argument followed by spaces*/
6781 if ('\0' == *inPtr)
6782 {
6783 return -EINVAL;
6784 }
6785
6786 /*getting the next argument ie the channel number */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08006787 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07006788 if (1 != v) return -EINVAL;
6789
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07006790 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07006791 if ((v < 0) ||
Padma, Santhosh Kumar0fa809b2014-11-13 14:56:56 +05306792 (tempInt < 0) ||
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07006793 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
6794 {
6795 return -EINVAL;
6796 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07006797
6798 *pChannel = tempInt;
6799 return VOS_STATUS_SUCCESS;
6800}
6801
6802#endif
6803
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006804#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006805/**---------------------------------------------------------------------------
6806
6807 \brief hdd_parse_get_cckm_ie() - HDD Parse and fetch the CCKM IE
6808
6809 This function parses the SETCCKM IE command
6810 SETCCKMIE<space><ie data>
6811
6812 \param - pValue Pointer to input data
6813 \param - pCckmIe Pointer to output cckm Ie
6814 \param - pCckmIeLen Pointer to output cckm ie length
6815
6816 \return - 0 for success non-zero for failure
6817
6818 --------------------------------------------------------------------------*/
6819VOS_STATUS hdd_parse_get_cckm_ie(tANI_U8 *pValue, tANI_U8 **pCckmIe,
6820 tANI_U8 *pCckmIeLen)
6821{
6822 tANI_U8 *inPtr = pValue;
6823 tANI_U8 *dataEnd;
6824 int j = 0;
6825 int i = 0;
6826 tANI_U8 tempByte = 0;
6827
6828 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
6829 /*no argument after the command*/
6830 if (NULL == inPtr)
6831 {
6832 return -EINVAL;
6833 }
6834
6835 /*no space after the command*/
6836 else if (SPACE_ASCII_VALUE != *inPtr)
6837 {
6838 return -EINVAL;
6839 }
6840
6841 /*removing empty spaces*/
6842 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
6843
6844 /*no argument followed by spaces*/
6845 if ('\0' == *inPtr)
6846 {
6847 return -EINVAL;
6848 }
6849
6850 /* find the length of data */
6851 dataEnd = inPtr;
6852 while(('\0' != *dataEnd) )
6853 {
6854 dataEnd++;
6855 ++(*pCckmIeLen);
6856 }
6857 if ( *pCckmIeLen <= 0) return -EINVAL;
6858
6859 /* Allocate the number of bytes based on the number of input characters
6860 whether it is even or odd.
6861 if the number of input characters are even, then we need N/2 byte.
6862 if the number of input characters are odd, then we need do (N+1)/2 to
6863 compensate rounding off.
6864 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
6865 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
6866 *pCckmIe = vos_mem_malloc((*pCckmIeLen + 1)/2);
6867 if (NULL == *pCckmIe)
6868 {
6869 hddLog(VOS_TRACE_LEVEL_FATAL,
6870 "%s: vos_mem_alloc failed ", __func__);
6871 return -EINVAL;
6872 }
6873 vos_mem_zero(*pCckmIe, (*pCckmIeLen + 1)/2);
6874 /* the buffer received from the upper layer is character buffer,
6875 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
6876 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
6877 and f0 in 3rd location */
6878 for (i = 0, j = 0; j < *pCckmIeLen; j += 2)
6879 {
6880 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
6881 (*pCckmIe)[i++] = tempByte;
6882 }
6883 *pCckmIeLen = i;
6884
6885 return VOS_STATUS_SUCCESS;
6886}
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08006887#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07006888
Jeff Johnson295189b2012-06-20 16:38:30 -07006889/**---------------------------------------------------------------------------
6890
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07006891 \brief hdd_is_valid_mac_address() - Validate MAC address
6892
6893 This function validates whether the given MAC address is valid or not
6894 Expected MAC address is of the format XX:XX:XX:XX:XX:XX
6895 where X is the hexa decimal digit character and separated by ':'
6896 This algorithm works even if MAC address is not separated by ':'
6897
6898 This code checks given input string mac contains exactly 12 hexadecimal digits.
6899 and a separator colon : appears in the input string only after
6900 an even number of hex digits.
6901
6902 \param - pMacAddr pointer to the input MAC address
6903 \return - 1 for valid and 0 for invalid
6904
6905 --------------------------------------------------------------------------*/
6906
6907v_BOOL_t hdd_is_valid_mac_address(const tANI_U8 *pMacAddr)
6908{
6909 int xdigit = 0;
6910 int separator = 0;
6911 while (*pMacAddr)
6912 {
6913 if (isxdigit(*pMacAddr))
6914 {
6915 xdigit++;
6916 }
6917 else if (':' == *pMacAddr)
6918 {
6919 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
6920 break;
6921
6922 ++separator;
6923 }
6924 else
6925 {
6926 separator = -1;
6927 /* Invalid MAC found */
6928 return 0;
6929 }
6930 ++pMacAddr;
6931 }
6932 return (xdigit == 12 && (separator == 5 || separator == 0));
6933}
6934
6935/**---------------------------------------------------------------------------
6936
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05306937 \brief __hdd_open() - HDD Open function
Jeff Johnson295189b2012-06-20 16:38:30 -07006938
6939 \param - dev Pointer to net_device structure
6940
6941 \return - 0 for success non-zero for failure
6942
6943 --------------------------------------------------------------------------*/
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05306944int __hdd_open(struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07006945{
6946 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6947 hdd_context_t *pHddCtx;
6948 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6949 VOS_STATUS status;
6950 v_BOOL_t in_standby = TRUE;
6951
6952 if (NULL == pAdapter)
6953 {
6954 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Agarwal Ashish971c2882013-10-30 20:11:12 +05306955 "%s: pAdapter is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006956 return -ENODEV;
6957 }
6958
6959 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05306960 MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_OPEN_REQUEST,
6961 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson295189b2012-06-20 16:38:30 -07006962 if (NULL == pHddCtx)
6963 {
6964 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006965 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006966 return -ENODEV;
6967 }
6968
6969 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6970 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
6971 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07006972 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
6973 {
6974 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306975 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07006976 in_standby = FALSE;
6977 break;
6978 }
6979 else
6980 {
6981 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6982 pAdapterNode = pNext;
6983 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006984 }
6985
6986 if (TRUE == in_standby)
6987 {
6988 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
6989 {
6990 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
6991 "wlan out of power save", __func__);
6992 return -EINVAL;
6993 }
6994 }
6995
Jeff Johnson6a81ca42013-04-05 10:37:08 -07006996 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07006997 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
6998 {
6999 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007000 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007001 /* Enable TX queues only when we are connected */
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05307002 hddLog(VOS_TRACE_LEVEL_INFO, FL("Enabling queues"));
Jeff Johnson295189b2012-06-20 16:38:30 -07007003 netif_tx_start_all_queues(dev);
7004 }
7005
7006 return 0;
7007}
7008
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307009/**---------------------------------------------------------------------------
7010
7011 \brief hdd_open() - Wrapper function for __hdd_open to protect it from SSR
7012
7013 This is called in response to ifconfig up
7014
7015 \param - dev Pointer to net_device structure
7016
7017 \return - 0 for success non-zero for failure
7018
7019 --------------------------------------------------------------------------*/
7020int hdd_open(struct net_device *dev)
7021{
7022 int ret;
7023
7024 vos_ssr_protect(__func__);
7025 ret = __hdd_open(dev);
7026 vos_ssr_unprotect(__func__);
7027
7028 return ret;
7029}
7030
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +05307031int __hdd_mon_open (struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07007032{
7033 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7034
7035 if(pAdapter == NULL) {
7036 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007037 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007038 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007039 }
7040
Jeff Johnson295189b2012-06-20 16:38:30 -07007041 return 0;
7042}
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +05307043
7044int hdd_mon_open (struct net_device *dev)
7045{
7046 int ret;
7047
7048 vos_ssr_protect(__func__);
7049 ret = __hdd_mon_open(dev);
7050 vos_ssr_unprotect(__func__);
7051
7052 return ret;
7053}
7054
Katya Nigame7b69a82015-04-28 15:24:06 +05307055int hdd_mon_stop(struct net_device *dev)
7056{
7057 return 0;
7058}
7059
Jeff Johnson295189b2012-06-20 16:38:30 -07007060/**---------------------------------------------------------------------------
7061
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307062 \brief __hdd_stop() - HDD stop function
Jeff Johnson295189b2012-06-20 16:38:30 -07007063
7064 \param - dev Pointer to net_device structure
7065
7066 \return - 0 for success non-zero for failure
7067
7068 --------------------------------------------------------------------------*/
7069
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307070int __hdd_stop (struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07007071{
Vinay Krishna Eranna90f43532014-10-27 16:45:54 +05307072 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07007073 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7074 hdd_context_t *pHddCtx;
7075 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7076 VOS_STATUS status;
7077 v_BOOL_t enter_standby = TRUE;
7078
7079 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07007080 if (NULL == pAdapter)
7081 {
7082 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Agarwal Ashish971c2882013-10-30 20:11:12 +05307083 "%s: pAdapter is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007084 return -ENODEV;
7085 }
Sachin Ahuja9b4958f2015-01-15 21:37:00 +05307086 MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_STOP_REQUEST,
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05307087 pAdapter->sessionId, pAdapter->device_mode));
Vinay Krishna Eranna90f43532014-10-27 16:45:54 +05307088
7089 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7090 ret = wlan_hdd_validate_context(pHddCtx);
7091 if (ret)
Jeff Johnson295189b2012-06-20 16:38:30 -07007092 {
Vinay Krishna Eranna90f43532014-10-27 16:45:54 +05307093 return ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07007094 }
7095
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307096 /* Nothing to be done if the interface is not opened */
7097 if (VOS_FALSE == test_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags))
7098 {
7099 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7100 "%s: NETDEV Interface is not OPENED", __func__);
7101 return -ENODEV;
7102 }
7103
7104 /* Make sure the interface is marked as closed */
Jeff Johnson6a81ca42013-04-05 10:37:08 -07007105 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07007106 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307107
7108 /* Disable TX on the interface, after this hard_start_xmit() will not
7109 * be called on that interface
7110 */
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05307111 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
Jeff Johnson295189b2012-06-20 16:38:30 -07007112 netif_tx_disable(pAdapter->dev);
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307113
7114 /* Mark the interface status as "down" for outside world */
Jeff Johnson295189b2012-06-20 16:38:30 -07007115 netif_carrier_off(pAdapter->dev);
7116
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307117 /* The interface is marked as down for outside world (aka kernel)
7118 * But the driver is pretty much alive inside. The driver needs to
7119 * tear down the existing connection on the netdev (session)
7120 * cleanup the data pipes and wait until the control plane is stabilized
7121 * for this interface. The call also needs to wait until the above
7122 * mentioned actions are completed before returning to the caller.
7123 * Notice that the hdd_stop_adapter is requested not to close the session
7124 * That is intentional to be able to scan if it is a STA/P2P interface
7125 */
7126 hdd_stop_adapter(pHddCtx, pAdapter, VOS_FALSE);
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05307127#ifdef FEATURE_WLAN_TDLS
7128 mutex_lock(&pHddCtx->tdls_lock);
7129#endif
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307130 /* DeInit the adapter. This ensures datapath cleanup as well */
c_hpothu002231a2015-02-05 14:58:51 +05307131 hdd_deinit_adapter(pHddCtx, pAdapter, TRUE);
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05307132#ifdef FEATURE_WLAN_TDLS
7133 mutex_unlock(&pHddCtx->tdls_lock);
7134#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007135 /* SoftAP ifaces should never go in power save mode
7136 making sure same here. */
7137 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
7138 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07007139 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07007140 )
7141 {
7142 /* SoftAP mode, so return from here */
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307143 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
7144 "%s: In SAP MODE", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007145 EXIT();
7146 return 0;
7147 }
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307148 /* Find if any iface is up. If any iface is up then can't put device to
7149 * sleep/power save mode
7150 */
Jeff Johnson295189b2012-06-20 16:38:30 -07007151 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7152 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
7153 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07007154 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
7155 {
7156 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307157 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07007158 enter_standby = FALSE;
7159 break;
7160 }
7161 else
7162 {
7163 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7164 pAdapterNode = pNext;
7165 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007166 }
7167
7168 if (TRUE == enter_standby)
7169 {
7170 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
7171 "entering standby", __func__);
7172 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
7173 {
7174 /*log and return success*/
7175 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
7176 "wlan in power save", __func__);
7177 }
7178 }
7179
7180 EXIT();
7181 return 0;
7182}
7183
7184/**---------------------------------------------------------------------------
7185
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307186 \brief hdd_stop() - wrapper_function for __hdd_stop to protect it from SSR
Jeff Johnson295189b2012-06-20 16:38:30 -07007187
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307188 This is called in response to ifconfig down
7189
7190 \param - dev Pointer to net_device structure
7191
7192 \return - 0 for success non-zero for failure
7193-----------------------------------------------------------------------------*/
7194int hdd_stop (struct net_device *dev)
7195{
7196 int ret;
7197
7198 vos_ssr_protect(__func__);
7199 ret = __hdd_stop(dev);
7200 vos_ssr_unprotect(__func__);
7201
7202 return ret;
7203}
7204
7205/**---------------------------------------------------------------------------
7206
7207 \brief __hdd_uninit() - HDD uninit function
Jeff Johnson295189b2012-06-20 16:38:30 -07007208
7209 \param - dev Pointer to net_device structure
7210
7211 \return - void
7212
7213 --------------------------------------------------------------------------*/
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307214static void __hdd_uninit (struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07007215{
7216 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05307217 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07007218 ENTER();
7219
7220 do
7221 {
7222 if (NULL == pAdapter)
7223 {
7224 hddLog(VOS_TRACE_LEVEL_FATAL,
7225 "%s: NULL pAdapter", __func__);
7226 break;
7227 }
7228
7229 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
7230 {
7231 hddLog(VOS_TRACE_LEVEL_FATAL,
7232 "%s: Invalid magic", __func__);
7233 break;
7234 }
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05307235 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7236 if (NULL == pHddCtx)
Jeff Johnson295189b2012-06-20 16:38:30 -07007237 {
7238 hddLog(VOS_TRACE_LEVEL_FATAL,
7239 "%s: NULL pHddCtx", __func__);
7240 break;
7241 }
7242
7243 if (dev != pAdapter->dev)
7244 {
7245 hddLog(VOS_TRACE_LEVEL_FATAL,
7246 "%s: Invalid device reference", __func__);
7247 /* we haven't validated all cases so let this go for now */
7248 }
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05307249#ifdef FEATURE_WLAN_TDLS
7250 mutex_lock(&pHddCtx->tdls_lock);
7251#endif
c_hpothu002231a2015-02-05 14:58:51 +05307252 hdd_deinit_adapter(pHddCtx, pAdapter, TRUE);
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05307253#ifdef FEATURE_WLAN_TDLS
7254 mutex_unlock(&pHddCtx->tdls_lock);
7255#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007256
7257 /* after uninit our adapter structure will no longer be valid */
7258 pAdapter->dev = NULL;
7259 pAdapter->magic = 0;
Manjeet Singh47ee8472016-04-11 11:57:18 +05307260 pAdapter->pHddCtx = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007261 } while (0);
7262
7263 EXIT();
7264}
7265
7266/**---------------------------------------------------------------------------
7267
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307268 \brief hdd_uninit() - Wrapper function to protect __hdd_uninit from SSR
7269
7270 This is called during the netdev unregister to uninitialize all data
7271associated with the device
7272
7273 \param - dev Pointer to net_device structure
7274
7275 \return - void
7276
7277 --------------------------------------------------------------------------*/
7278static void hdd_uninit (struct net_device *dev)
7279{
7280 vos_ssr_protect(__func__);
7281 __hdd_uninit(dev);
7282 vos_ssr_unprotect(__func__);
7283}
7284
7285/**---------------------------------------------------------------------------
7286
Jeff Johnson295189b2012-06-20 16:38:30 -07007287 \brief hdd_release_firmware() -
7288
7289 This function calls the release firmware API to free the firmware buffer.
7290
7291 \param - pFileName Pointer to the File Name.
7292 pCtx - Pointer to the adapter .
7293
7294
7295 \return - 0 for success, non zero for failure
7296
7297 --------------------------------------------------------------------------*/
7298
7299VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
7300{
7301 VOS_STATUS status = VOS_STATUS_SUCCESS;
7302 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
7303 ENTER();
7304
7305
7306 if (!strcmp(WLAN_FW_FILE, pFileName)) {
7307
7308 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
7309
7310 if(pHddCtx->fw) {
7311 release_firmware(pHddCtx->fw);
7312 pHddCtx->fw = NULL;
7313 }
7314 else
7315 status = VOS_STATUS_E_FAILURE;
7316 }
7317 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
7318 if(pHddCtx->nv) {
7319 release_firmware(pHddCtx->nv);
7320 pHddCtx->nv = NULL;
7321 }
7322 else
7323 status = VOS_STATUS_E_FAILURE;
7324
7325 }
7326
7327 EXIT();
7328 return status;
7329}
7330
7331/**---------------------------------------------------------------------------
7332
7333 \brief hdd_request_firmware() -
7334
7335 This function reads the firmware file using the request firmware
7336 API and returns the the firmware data and the firmware file size.
7337
7338 \param - pfileName - Pointer to the file name.
7339 - pCtx - Pointer to the adapter .
7340 - ppfw_data - Pointer to the pointer of the firmware data.
7341 - pSize - Pointer to the file size.
7342
7343 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
7344
7345 --------------------------------------------------------------------------*/
7346
7347
7348VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
7349{
7350 int status;
7351 VOS_STATUS retval = VOS_STATUS_SUCCESS;
7352 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
7353 ENTER();
7354
7355 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
7356
7357 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
7358
7359 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
7360 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
7361 __func__, pfileName);
7362 retval = VOS_STATUS_E_FAILURE;
7363 }
7364
7365 else {
7366 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
7367 *pSize = pHddCtx->fw->size;
7368 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
7369 __func__, *pSize);
7370 }
7371 }
7372 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
7373
7374 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
7375
7376 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
7377 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
7378 __func__, pfileName);
7379 retval = VOS_STATUS_E_FAILURE;
7380 }
7381
7382 else {
7383 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
7384 *pSize = pHddCtx->nv->size;
7385 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
7386 __func__, *pSize);
7387 }
7388 }
7389
7390 EXIT();
7391 return retval;
7392}
7393/**---------------------------------------------------------------------------
7394 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
7395
7396 This is the function invoked by SME to inform the result of a full power
7397 request issued by HDD
7398
7399 \param - callbackcontext - Pointer to cookie
7400 status - result of request
7401
7402 \return - None
7403
7404--------------------------------------------------------------------------*/
7405void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
7406{
7407 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
7408
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07007409 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07007410 if(&pHddCtx->full_pwr_comp_var)
7411 {
7412 complete(&pHddCtx->full_pwr_comp_var);
7413 }
7414}
7415
Abhishek Singh00b71972016-01-07 10:51:04 +05307416#ifdef WLAN_FEATURE_RMC
7417static void hdd_tx_fail_ind_callback(v_U8_t *MacAddr, v_U8_t seqNo)
7418{
7419 int payload_len;
7420 struct sk_buff *skb;
7421 struct nlmsghdr *nlh;
7422 v_U8_t *data;
7423
7424 payload_len = ETH_ALEN;
7425
7426 if (0 == cesium_pid)
7427 {
7428 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: cesium process not registered",
7429 __func__);
7430 return;
7431 }
7432
7433 if ((skb = nlmsg_new(payload_len,GFP_ATOMIC)) == NULL)
7434 {
7435 hddLog(VOS_TRACE_LEVEL_ERROR,
7436 "%s: nlmsg_new() failed for msg size[%d]",
7437 __func__, NLMSG_SPACE(payload_len));
7438 return;
7439 }
7440
7441 nlh = nlmsg_put(skb, cesium_pid, seqNo, 0, payload_len, NLM_F_REQUEST);
7442
7443 if (NULL == nlh)
7444 {
7445 hddLog(VOS_TRACE_LEVEL_ERROR,
7446 "%s: nlmsg_put() failed for msg size[%d]",
7447 __func__, NLMSG_SPACE(payload_len));
7448
7449 kfree_skb(skb);
7450 return;
7451 }
7452
7453 data = nlmsg_data(nlh);
7454 memcpy(data, MacAddr, ETH_ALEN);
7455
7456 if (nlmsg_unicast(cesium_nl_srv_sock, skb, cesium_pid) < 0)
7457 {
7458 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: nlmsg_unicast() failed for msg size[%d]",
7459 __func__, NLMSG_SPACE(payload_len));
7460 }
7461
7462 return;
7463}
7464
7465/**---------------------------------------------------------------------------
7466 \brief hdd_ParseuserParams - return a pointer to the next argument
7467
7468 \return - status
7469
7470--------------------------------------------------------------------------*/
7471static int hdd_ParseUserParams(tANI_U8 *pValue, tANI_U8 **ppArg)
7472{
7473 tANI_U8 *pVal;
7474
7475 pVal = strchr(pValue, ' ');
7476
7477 if (NULL == pVal)
7478 {
7479 /* no argument remains */
7480 return -EINVAL;
7481 }
7482 else if (SPACE_ASCII_VALUE != *pVal)
7483 {
7484 /* no space after the current argument */
7485 return -EINVAL;
7486 }
7487
7488 pVal++;
7489
7490 /* remove empty spaces */
7491 while ((SPACE_ASCII_VALUE == *pVal) && ('\0' != *pVal))
7492 {
7493 pVal++;
7494 }
7495
7496 /* no argument followed by spaces */
7497 if ('\0' == *pVal)
7498 {
7499 return -EINVAL;
7500 }
7501
7502 *ppArg = pVal;
7503
7504 return 0;
7505}
7506
7507/**----------------------------------------------------------------------------
7508 \brief hdd_ParseIBSSTXFailEventParams - Parse params for SETIBSSTXFAILEVENT
7509
7510 \return - status
7511
7512------------------------------------------------------------------------------*/
7513static int hdd_ParseIBSSTXFailEventParams(tANI_U8 *pValue,
7514 tANI_U8 *tx_fail_count,
7515 tANI_U16 *pid)
7516{
7517 tANI_U8 *param = NULL;
7518 int ret;
7519
7520 ret = hdd_ParseUserParams(pValue, &param);
7521
7522 if (0 == ret && NULL != param)
7523 {
7524 if (1 != sscanf(param, "%hhu", tx_fail_count))
7525 {
7526 ret = -EINVAL;
7527 goto done;
7528 }
7529 }
7530 else
7531 {
7532 goto done;
7533 }
7534
7535 if (0 == *tx_fail_count)
7536 {
7537 *pid = 0;
7538 goto done;
7539 }
7540
7541 pValue = param;
7542 pValue++;
7543
7544 ret = hdd_ParseUserParams(pValue, &param);
7545
7546 if (0 == ret)
7547 {
7548 if (1 != sscanf(param, "%hu", pid))
7549 {
7550 ret = -EINVAL;
7551 goto done;
7552 }
7553 }
7554 else
7555 {
7556 goto done;
7557 }
7558
7559done:
7560 return ret;
7561}
7562
7563static int hdd_open_cesium_nl_sock()
7564{
7565#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
7566 struct netlink_kernel_cfg cfg = {
7567 .groups = WLAN_NLINK_MCAST_GRP_ID,
7568 .input = NULL
7569 };
7570#endif
7571 int ret = 0;
7572
7573#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
7574 cesium_nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_CESIUM,
7575#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0))
7576 THIS_MODULE,
7577#endif
7578 &cfg);
7579#else
7580 cesium_nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_CESIUM,
7581 WLAN_NLINK_MCAST_GRP_ID, NULL, NULL, THIS_MODULE);
7582#endif
7583
7584 if (cesium_nl_srv_sock == NULL)
7585 {
7586 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7587 "NLINK: cesium netlink_kernel_create failed");
7588 ret = -ECONNREFUSED;
7589 }
7590
7591 return ret;
7592}
7593
7594static void hdd_close_cesium_nl_sock()
7595{
7596 if (NULL != cesium_nl_srv_sock)
7597 {
7598 netlink_kernel_release(cesium_nl_srv_sock);
7599 cesium_nl_srv_sock = NULL;
7600 }
7601}
7602#endif /* WLAN_FEATURE_RMC */
Jeff Johnson295189b2012-06-20 16:38:30 -07007603/**---------------------------------------------------------------------------
7604
7605 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
7606
7607 This is the function invoked by SME to inform the result of BMPS
7608 request issued by HDD
7609
7610 \param - callbackcontext - Pointer to cookie
7611 status - result of request
7612
7613 \return - None
7614
7615--------------------------------------------------------------------------*/
7616void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
7617{
7618
7619 struct completion *completion_var = (struct completion*) callbackContext;
7620
Arif Hussain6d2a3322013-11-17 19:50:10 -08007621 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07007622 if(completion_var != NULL)
7623 {
7624 complete(completion_var);
7625 }
7626}
7627
7628/**---------------------------------------------------------------------------
7629
7630 \brief hdd_get_cfg_file_size() -
7631
7632 This function reads the configuration file using the request firmware
7633 API and returns the configuration file size.
7634
7635 \param - pCtx - Pointer to the adapter .
7636 - pFileName - Pointer to the file name.
7637 - pBufSize - Pointer to the buffer size.
7638
7639 \return - 0 for success, non zero for failure
7640
7641 --------------------------------------------------------------------------*/
7642
7643VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
7644{
7645 int status;
7646 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
7647
7648 ENTER();
7649
7650 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
7651
7652 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
7653 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
7654 status = VOS_STATUS_E_FAILURE;
7655 }
7656 else {
7657 *pBufSize = pHddCtx->fw->size;
7658 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
7659 release_firmware(pHddCtx->fw);
7660 pHddCtx->fw = NULL;
7661 }
7662
7663 EXIT();
7664 return VOS_STATUS_SUCCESS;
7665}
7666
7667/**---------------------------------------------------------------------------
7668
7669 \brief hdd_read_cfg_file() -
7670
7671 This function reads the configuration file using the request firmware
7672 API and returns the cfg data and the buffer size of the configuration file.
7673
7674 \param - pCtx - Pointer to the adapter .
7675 - pFileName - Pointer to the file name.
7676 - pBuffer - Pointer to the data buffer.
7677 - pBufSize - Pointer to the buffer size.
7678
7679 \return - 0 for success, non zero for failure
7680
7681 --------------------------------------------------------------------------*/
7682
7683VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
7684 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
7685{
7686 int status;
7687 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
7688
7689 ENTER();
7690
7691 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
7692
7693 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
7694 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
7695 return VOS_STATUS_E_FAILURE;
7696 }
7697 else {
7698 if(*pBufSize != pHddCtx->fw->size) {
7699 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
7700 "file size", __func__);
7701 release_firmware(pHddCtx->fw);
7702 pHddCtx->fw = NULL;
7703 return VOS_STATUS_E_FAILURE;
7704 }
7705 else {
7706 if(pBuffer) {
7707 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
7708 }
7709 release_firmware(pHddCtx->fw);
7710 pHddCtx->fw = NULL;
7711 }
7712 }
7713
7714 EXIT();
7715
7716 return VOS_STATUS_SUCCESS;
7717}
7718
7719/**---------------------------------------------------------------------------
7720
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307721 \brief __hdd_set_mac_address() -
Jeff Johnson295189b2012-06-20 16:38:30 -07007722
7723 This function sets the user specified mac address using
7724 the command ifconfig wlanX hw ether <mac adress>.
7725
7726 \param - dev - Pointer to the net device.
7727 - addr - Pointer to the sockaddr.
7728 \return - 0 for success, non zero for failure
7729
7730 --------------------------------------------------------------------------*/
7731
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307732static int __hdd_set_mac_address(struct net_device *dev, void *addr)
Jeff Johnson295189b2012-06-20 16:38:30 -07007733{
Mahesh A Saptasagar74088392015-02-05 17:22:09 +05307734 hdd_adapter_t *pAdapter;
7735 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07007736 struct sockaddr *psta_mac_addr = addr;
7737 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
Mahesh A Saptasagar74088392015-02-05 17:22:09 +05307738 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07007739
7740 ENTER();
Mahesh A Saptasagar74088392015-02-05 17:22:09 +05307741 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7742 if (NULL == pAdapter)
7743 {
7744 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
7745 "%s: Adapter is NULL",__func__);
7746 return -EINVAL;
7747 }
7748 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7749 ret = wlan_hdd_validate_context(pHddCtx);
7750 if (0 != ret)
7751 {
Mahesh A Saptasagar74088392015-02-05 17:22:09 +05307752 return ret;
7753 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007754
7755 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
Jeff Johnson295189b2012-06-20 16:38:30 -07007756 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
7757
7758 EXIT();
7759 return halStatus;
7760}
7761
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307762/**---------------------------------------------------------------------------
7763
7764 \brief hdd_set_mac_address() -
7765
7766 Wrapper function to protect __hdd_set_mac_address() function from ssr
7767
7768 \param - dev - Pointer to the net device.
7769 - addr - Pointer to the sockaddr.
7770 \return - 0 for success, non zero for failure
7771
7772 --------------------------------------------------------------------------*/
7773static int hdd_set_mac_address(struct net_device *dev, void *addr)
7774{
7775 int ret;
7776
7777 vos_ssr_protect(__func__);
7778 ret = __hdd_set_mac_address(dev, addr);
7779 vos_ssr_unprotect(__func__);
7780
7781 return ret;
7782}
7783
Jeff Johnson295189b2012-06-20 16:38:30 -07007784tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
7785{
7786 int i;
7787 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
7788 {
Abhishek Singheb183782014-02-06 13:37:21 +05307789 if( 0 == ((pHddCtx->cfg_ini->intfAddrMask) & (1 << i)) )
Jeff Johnson295189b2012-06-20 16:38:30 -07007790 break;
7791 }
7792
7793 if( VOS_MAX_CONCURRENCY_PERSONA == i)
7794 return NULL;
7795
7796 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
7797 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
7798}
7799
7800void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
7801{
7802 int i;
7803 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
7804 {
7805 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
7806 {
7807 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
7808 break;
7809 }
7810 }
7811 return;
7812}
7813
7814#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
7815 static struct net_device_ops wlan_drv_ops = {
7816 .ndo_open = hdd_open,
7817 .ndo_stop = hdd_stop,
7818 .ndo_uninit = hdd_uninit,
7819 .ndo_start_xmit = hdd_hard_start_xmit,
7820 .ndo_tx_timeout = hdd_tx_timeout,
7821 .ndo_get_stats = hdd_stats,
7822 .ndo_do_ioctl = hdd_ioctl,
7823 .ndo_set_mac_address = hdd_set_mac_address,
7824 .ndo_select_queue = hdd_select_queue,
7825#ifdef WLAN_FEATURE_PACKET_FILTERING
7826#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
7827 .ndo_set_rx_mode = hdd_set_multicast_list,
7828#else
7829 .ndo_set_multicast_list = hdd_set_multicast_list,
7830#endif //LINUX_VERSION_CODE
7831#endif
7832 };
Jeff Johnson295189b2012-06-20 16:38:30 -07007833 static struct net_device_ops wlan_mon_drv_ops = {
7834 .ndo_open = hdd_mon_open,
Katya Nigame7b69a82015-04-28 15:24:06 +05307835 .ndo_stop = hdd_mon_stop,
Jeff Johnson295189b2012-06-20 16:38:30 -07007836 .ndo_uninit = hdd_uninit,
7837 .ndo_start_xmit = hdd_mon_hard_start_xmit,
7838 .ndo_tx_timeout = hdd_tx_timeout,
7839 .ndo_get_stats = hdd_stats,
Katya Nigame7b69a82015-04-28 15:24:06 +05307840 .ndo_do_ioctl = hdd_mon_ioctl,
Jeff Johnson295189b2012-06-20 16:38:30 -07007841 .ndo_set_mac_address = hdd_set_mac_address,
7842 };
Mahesh A Saptasagar305e2632015-03-04 12:57:33 +05307843
Jeff Johnson295189b2012-06-20 16:38:30 -07007844#endif
7845
7846void hdd_set_station_ops( struct net_device *pWlanDev )
7847{
7848#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
Jeff Johnson295189b2012-06-20 16:38:30 -07007849 pWlanDev->netdev_ops = &wlan_drv_ops;
7850#else
7851 pWlanDev->open = hdd_open;
7852 pWlanDev->stop = hdd_stop;
7853 pWlanDev->uninit = hdd_uninit;
7854 pWlanDev->hard_start_xmit = NULL;
7855 pWlanDev->tx_timeout = hdd_tx_timeout;
7856 pWlanDev->get_stats = hdd_stats;
7857 pWlanDev->do_ioctl = hdd_ioctl;
Jeff Johnson295189b2012-06-20 16:38:30 -07007858 pWlanDev->set_mac_address = hdd_set_mac_address;
7859#endif
7860}
7861
Katya Nigam1fd24402015-02-16 14:52:19 +05307862void hdd_set_ibss_ops( hdd_adapter_t *pAdapter )
7863{
7864 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
7865 wlan_drv_ops.ndo_start_xmit = hdd_ibss_hard_start_xmit;
7866 #else
7867 pAdapter->dev->hard_start_xmit = hdd_ibss_hard_start_xmit;
7868 #endif
7869}
7870
Jeff Johnsoneed415b2013-01-18 16:11:20 -08007871static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07007872{
7873 struct net_device *pWlanDev = NULL;
7874 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007875 /*
7876 * cfg80211 initialization and registration....
7877 */
Anand N Sunkadc34abbd2015-07-29 09:52:59 +05307878 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name,
7879#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0))
7880 NET_NAME_UNKNOWN,
7881#endif
7882 ether_setup, NUM_TX_QUEUES);
Jeff Johnson295189b2012-06-20 16:38:30 -07007883 if(pWlanDev != NULL)
7884 {
7885
7886 //Save the pointer to the net_device in the HDD adapter
7887 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
7888
Jeff Johnson295189b2012-06-20 16:38:30 -07007889 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
7890
7891 pAdapter->dev = pWlanDev;
7892 pAdapter->pHddCtx = pHddCtx;
7893 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
Agarwal Ashish47d18112014-08-04 19:55:07 +05307894 spin_lock_init(&pAdapter->lock_for_active_session);
Jeff Johnson295189b2012-06-20 16:38:30 -07007895
Rajeev79dbe4c2013-10-05 11:03:42 +05307896#ifdef FEATURE_WLAN_BATCH_SCAN
Rajeev79dbe4c2013-10-05 11:03:42 +05307897 pAdapter->pBatchScanRsp = NULL;
7898 pAdapter->numScanList = 0;
Rajeev Kumar20140c12013-10-21 19:39:02 -07007899 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
Kiet Lamaa8e15a2014-02-11 23:30:06 -08007900 pAdapter->prev_batch_id = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05307901 mutex_init(&pAdapter->hdd_batch_scan_lock);
7902#endif
7903
Jeff Johnson295189b2012-06-20 16:38:30 -07007904 pAdapter->isLinkUpSvcNeeded = FALSE;
7905 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
7906 //Init the net_device structure
7907 strlcpy(pWlanDev->name, name, IFNAMSIZ);
7908
7909 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
7910 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
7911 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
7912 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
7913
7914 hdd_set_station_ops( pAdapter->dev );
7915
7916 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07007917 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
7918 pAdapter->wdev.wiphy = pHddCtx->wiphy;
7919 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07007920 /* set pWlanDev's parent to underlying device */
7921 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
Kumar Anand82c009f2014-05-29 00:29:42 -07007922
7923 hdd_wmm_init( pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07007924 }
7925
7926 return pAdapter;
7927}
7928
7929VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
7930{
7931 struct net_device *pWlanDev = pAdapter->dev;
7932 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
7933 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
7934 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
7935
7936 if( rtnl_lock_held )
7937 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08007938 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07007939 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
7940 {
7941 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
7942 return VOS_STATUS_E_FAILURE;
7943 }
7944 }
7945 if (register_netdevice(pWlanDev))
7946 {
7947 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
7948 return VOS_STATUS_E_FAILURE;
7949 }
7950 }
7951 else
7952 {
7953 if(register_netdev(pWlanDev))
7954 {
7955 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
7956 return VOS_STATUS_E_FAILURE;
7957 }
7958 }
7959 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
7960
7961 return VOS_STATUS_SUCCESS;
7962}
7963
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07007964static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07007965{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07007966 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07007967
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07007968 if (NULL == pAdapter)
7969 {
7970 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
7971 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07007972 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07007973
7974 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
7975 {
7976 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
7977 return eHAL_STATUS_NOT_INITIALIZED;
7978 }
7979
7980 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
7981
Sameer Thalappilbee426e2013-10-30 10:30:30 -07007982#ifndef WLAN_OPEN_SOURCE
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07007983 /* need to make sure all of our scheduled work has completed.
7984 * This callback is called from MC thread context, so it is safe to
7985 * to call below flush workqueue API from here.
Sameer Thalappilbee426e2013-10-30 10:30:30 -07007986 *
7987 * Even though this is called from MC thread context, if there is a faulty
7988 * work item in the system, that can hang this call forever. So flushing
7989 * this global work queue is not safe; and now we make sure that
7990 * individual work queues are stopped correctly. But the cancel work queue
7991 * is a GPL only API, so the proprietary version of the driver would still
7992 * rely on the global work queue flush.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07007993 */
7994 flush_scheduled_work();
Sameer Thalappilbee426e2013-10-30 10:30:30 -07007995#endif
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07007996
7997 /* We can be blocked while waiting for scheduled work to be
7998 * flushed, and the adapter structure can potentially be freed, in
7999 * which case the magic will have been reset. So make sure the
8000 * magic is still good, and hence the adapter structure is still
8001 * valid, before signaling completion */
8002 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
8003 {
8004 complete(&pAdapter->session_close_comp_var);
8005 }
8006
Jeff Johnson295189b2012-06-20 16:38:30 -07008007 return eHAL_STATUS_SUCCESS;
8008}
Manjeet Singh47ee8472016-04-11 11:57:18 +05308009/**
8010 * hdd_close_tx_queues() - close tx queues
8011 * @hdd_ctx: hdd global context
8012 *
8013 * Return: None
8014 */
8015static void hdd_close_tx_queues(hdd_context_t *hdd_ctx)
8016{
8017 VOS_STATUS status;
8018 hdd_adapter_t *adapter;
8019 hdd_adapter_list_node_t *adapter_node = NULL, *next_adapter = NULL;
8020 /* Not validating hdd_ctx as it's already done by the caller */
8021 ENTER();
8022 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
8023 while (NULL != adapter_node && VOS_STATUS_SUCCESS == status) {
8024 adapter = adapter_node->pAdapter;
8025 if (adapter && adapter->dev) {
8026 netif_tx_disable (adapter->dev);
8027 netif_carrier_off(adapter->dev);
8028 }
8029 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
8030 &next_adapter);
8031 adapter_node = next_adapter;
8032 }
8033 EXIT();
8034}
Jeff Johnson295189b2012-06-20 16:38:30 -07008035
8036VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
8037{
8038 struct net_device *pWlanDev = pAdapter->dev;
8039 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
8040 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
8041 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
8042 VOS_STATUS status = VOS_STATUS_E_FAILURE;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308043 long rc = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07008044
Nirav Shah7e3c8132015-06-22 23:51:42 +05308045 spin_lock_init( &pAdapter->sta_hash_lock);
8046 pAdapter->is_sta_id_hash_initialized = VOS_FALSE;
8047
Jeff Johnson295189b2012-06-20 16:38:30 -07008048 INIT_COMPLETION(pAdapter->session_open_comp_var);
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07008049 sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07008050 //Open a SME session for future operation
8051 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07008052 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07008053 if ( !HAL_STATUS_SUCCESS( halStatus ) )
8054 {
8055 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07008056 "sme_OpenSession() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07008057 halStatus, halStatus );
8058 status = VOS_STATUS_E_FAILURE;
8059 goto error_sme_open;
8060 }
8061
8062 //Block on a completion variable. Can't wait forever though.
Vinay Krishna Eranna0fe2e7c2014-04-09 21:32:08 +05308063 rc = wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07008064 &pAdapter->session_open_comp_var,
8065 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308066 if (rc <= 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07008067 {
8068 hddLog(VOS_TRACE_LEVEL_FATAL,
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308069 "Session is not opened within timeout period code %ld", rc );
Jeff Johnson295189b2012-06-20 16:38:30 -07008070 status = VOS_STATUS_E_FAILURE;
8071 goto error_sme_open;
8072 }
8073
8074 // Register wireless extensions
8075 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
8076 {
8077 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07008078 "hdd_register_wext() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07008079 halStatus, halStatus );
8080 status = VOS_STATUS_E_FAILURE;
8081 goto error_register_wext;
8082 }
Katya Nigam1fd24402015-02-16 14:52:19 +05308083
Jeff Johnson295189b2012-06-20 16:38:30 -07008084 //Safe to register the hard_start_xmit function again
Katya Nigam1fd24402015-02-16 14:52:19 +05308085 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
8086 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
8087 #else
8088 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
8089 #endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008090
8091 //Set the Connection State to Not Connected
Abhishek Singhf4669da2014-05-26 15:07:49 +05308092 hddLog(VOS_TRACE_LEVEL_INFO,
8093 "%s: Set HDD connState to eConnectionState_NotConnected",
8094 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008095 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
8096
8097 //Set the default operation channel
8098 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
8099
8100 /* Make the default Auth Type as OPEN*/
8101 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
8102
8103 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
8104 {
8105 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07008106 "hdd_init_tx_rx() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07008107 status, status );
8108 goto error_init_txrx;
8109 }
8110
8111 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
8112
8113 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
8114 {
8115 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07008116 "hdd_wmm_adapter_init() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07008117 status, status );
8118 goto error_wmm_init;
8119 }
8120
8121 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
8122
8123 return VOS_STATUS_SUCCESS;
8124
8125error_wmm_init:
8126 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
8127 hdd_deinit_tx_rx(pAdapter);
8128error_init_txrx:
8129 hdd_UnregisterWext(pWlanDev);
8130error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008131 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07008132 {
8133 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008134 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Agrawal Ashish5a3522c2016-03-02 15:08:28 +05308135 pAdapter->sessionId, FALSE, VOS_TRUE,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008136 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07008137 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308138 unsigned long rc;
8139
Jeff Johnson295189b2012-06-20 16:38:30 -07008140 //Block on a completion variable. Can't wait forever though.
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308141 rc = wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07008142 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07008143 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308144 if (rc <= 0)
8145 hddLog(VOS_TRACE_LEVEL_ERROR,
8146 FL("Session is not opened within timeout period code %ld"), rc);
Jeff Johnson295189b2012-06-20 16:38:30 -07008147 }
8148}
8149error_sme_open:
8150 return status;
8151}
8152
Jeff Johnson295189b2012-06-20 16:38:30 -07008153void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
8154{
8155 hdd_cfg80211_state_t *cfgState;
8156
8157 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
8158
8159 if( NULL != cfgState->buf )
8160 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308161 long rc;
Jeff Johnson295189b2012-06-20 16:38:30 -07008162 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
8163 rc = wait_for_completion_interruptible_timeout(
8164 &pAdapter->tx_action_cnf_event,
8165 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308166 if (rc <= 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07008167 {
Deepthi Gowri91b3e9c2015-08-25 13:14:58 +05308168 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8169 "%s ERROR: HDD Wait for Action Confirmation Failed!! %ld"
8170 , __func__, rc);
8171
8172 // Inform tx status as FAILURE to upper layer and free cfgState->buf
8173 hdd_sendActionCnf( pAdapter, FALSE );
Jeff Johnson295189b2012-06-20 16:38:30 -07008174 }
8175 }
8176 return;
8177}
Jeff Johnson295189b2012-06-20 16:38:30 -07008178
c_hpothu002231a2015-02-05 14:58:51 +05308179void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
Jeff Johnson295189b2012-06-20 16:38:30 -07008180{
8181 ENTER();
8182 switch ( pAdapter->device_mode )
8183 {
Katya Nigam1fd24402015-02-16 14:52:19 +05308184 case WLAN_HDD_IBSS:
8185 {
8186 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
8187 {
8188 hdd_ibss_deinit_tx_rx( pAdapter );
8189 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
8190 }
8191 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008192 case WLAN_HDD_INFRA_STATION:
8193 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07008194 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07008195 {
8196 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
8197 {
8198 hdd_deinit_tx_rx( pAdapter );
8199 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
8200 }
8201
8202 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
8203 {
8204 hdd_wmm_adapter_close( pAdapter );
8205 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
8206 }
8207
Jeff Johnson295189b2012-06-20 16:38:30 -07008208 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07008209 break;
8210 }
8211
8212 case WLAN_HDD_SOFTAP:
8213 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07008214 {
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05308215
8216 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
8217 {
8218 hdd_wmm_adapter_close( pAdapter );
8219 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
8220 }
8221
Jeff Johnson295189b2012-06-20 16:38:30 -07008222 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07008223
c_hpothu002231a2015-02-05 14:58:51 +05308224 hdd_unregister_hostapd(pAdapter, rtnl_held);
Agrawal Ashisha0584d42016-09-29 13:03:45 +05308225 /* set con_mode to STA only when no SAP concurrency mode */
8226 if (!(hdd_get_concurrency_mode() & (VOS_SAP | VOS_P2P_GO)))
8227 hdd_set_conparam(0);
Jeff Johnson295189b2012-06-20 16:38:30 -07008228 break;
8229 }
8230
8231 case WLAN_HDD_MONITOR:
8232 {
Jeff Johnson295189b2012-06-20 16:38:30 -07008233 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
8234 {
8235 hdd_deinit_tx_rx( pAdapter );
8236 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
8237 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008238 break;
8239 }
8240
8241
8242 default:
8243 break;
8244 }
8245
8246 EXIT();
8247}
8248
8249void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
8250{
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -08008251 struct net_device *pWlanDev = NULL;
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05308252
8253 ENTER();
8254 if (NULL == pAdapter)
8255 {
8256 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8257 "%s: HDD adapter is Null", __func__);
8258 return;
8259 }
8260
8261 pWlanDev = pAdapter->dev;
Jeff Johnson295189b2012-06-20 16:38:30 -07008262
Rajeev79dbe4c2013-10-05 11:03:42 +05308263#ifdef FEATURE_WLAN_BATCH_SCAN
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05308264 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
8265 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Rajeev Kumarf999e582014-01-09 17:33:29 -08008266 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05308267 || (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)
8268 )
8269 {
Rajeev Kumarf999e582014-01-09 17:33:29 -08008270 if (pAdapter)
Rajeev79dbe4c2013-10-05 11:03:42 +05308271 {
Rajeev Kumarf999e582014-01-09 17:33:29 -08008272 if (eHDD_BATCH_SCAN_STATE_STARTED == pAdapter->batchScanState)
8273 {
8274 hdd_deinit_batch_scan(pAdapter);
8275 }
Rajeev79dbe4c2013-10-05 11:03:42 +05308276 }
Rajeev Kumarf999e582014-01-09 17:33:29 -08008277 }
Rajeev79dbe4c2013-10-05 11:03:42 +05308278#endif
8279
Jeff Johnson295189b2012-06-20 16:38:30 -07008280 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
8281 if( rtnl_held )
8282 {
8283 unregister_netdevice(pWlanDev);
8284 }
8285 else
8286 {
8287 unregister_netdev(pWlanDev);
8288 }
8289 // note that the pAdapter is no longer valid at this point
8290 // since the memory has been reclaimed
8291 }
8292
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05308293 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07008294}
8295
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008296void hdd_set_pwrparams(hdd_context_t *pHddCtx)
8297{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308298 VOS_STATUS status;
8299 hdd_adapter_t *pAdapter = NULL;
8300 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008301
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308302 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008303
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308304 /*loop through all adapters.*/
8305 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008306 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308307 pAdapter = pAdapterNode->pAdapter;
8308 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
8309 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008310
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308311 { // we skip this registration for modes other than STA and P2P client modes.
8312 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
8313 pAdapterNode = pNext;
8314 continue;
8315 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008316
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308317 //Apply Dynamic DTIM For P2P
8318 //Only if ignoreDynamicDtimInP2pMode is not set in ini
8319 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
8320 pHddCtx->cfg_ini->enableModulatedDTIM) &&
8321 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
8322 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
8323 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
8324 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
8325 (eConnectionState_Associated ==
8326 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
8327 (pHddCtx->cfg_ini->fIsBmpsEnabled))
8328 {
8329 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008330
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308331 powerRequest.uIgnoreDTIM = 1;
8332 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
8333
8334 if (pHddCtx->cfg_ini->enableModulatedDTIM)
8335 {
8336 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
8337 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
8338 }
8339 else
8340 {
8341 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
8342 }
8343
8344 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
8345 * specified during Enter/Exit BMPS when LCD off*/
8346 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
8347 NULL, eANI_BOOLEAN_FALSE);
8348 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
8349 NULL, eANI_BOOLEAN_FALSE);
8350
8351 /* switch to the DTIM specified in cfg.ini */
8352 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Abhishek Singh1e390cf2015-10-27 13:45:17 +05308353 "Switch to DTIM %d Listen interval %d",
8354 powerRequest.uDTIMPeriod,
8355 powerRequest.uListenInterval);
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308356 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
8357 break;
8358
8359 }
8360
8361 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
8362 pAdapterNode = pNext;
8363 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008364}
8365
8366void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
8367{
8368 /*Switch back to DTIM 1*/
8369 tSirSetPowerParamsReq powerRequest = { 0 };
8370
8371 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
8372 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07008373 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08008374
8375 /* Update ignoreDTIM and ListedInterval in CFG with default values */
8376 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
8377 NULL, eANI_BOOLEAN_FALSE);
8378 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
8379 NULL, eANI_BOOLEAN_FALSE);
8380
8381 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8382 "Switch to DTIM%d",powerRequest.uListenInterval);
8383 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
8384
8385}
8386
Jeff Johnson295189b2012-06-20 16:38:30 -07008387VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
8388{
8389 VOS_STATUS status = VOS_STATUS_SUCCESS;
Sushant Kaushik4928e542014-12-29 15:25:54 +05308390 if (WLAN_HDD_IS_UNLOAD_IN_PROGRESS(pHddCtx))
8391 {
8392 hddLog( LOGE, FL("Wlan Unload in progress"));
8393 return VOS_STATUS_E_PERM;
8394 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008395 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
8396 {
8397 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
8398 }
8399
8400 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
8401 {
8402 sme_StartAutoBmpsTimer(pHddCtx->hHal);
8403 }
8404
8405 if (pHddCtx->cfg_ini->fIsImpsEnabled)
8406 {
8407 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
8408 }
8409
8410 return status;
8411}
8412
8413VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
8414{
8415 hdd_adapter_t *pAdapter = NULL;
8416 eHalStatus halStatus;
8417 VOS_STATUS status = VOS_STATUS_E_INVAL;
8418 v_BOOL_t disableBmps = FALSE;
8419 v_BOOL_t disableImps = FALSE;
8420
8421 switch(session_type)
8422 {
8423 case WLAN_HDD_INFRA_STATION:
8424 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07008425 case WLAN_HDD_P2P_CLIENT:
8426 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07008427 //Exit BMPS -> Is Sta/P2P Client is already connected
8428 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
8429 if((NULL != pAdapter)&&
8430 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
8431 {
8432 disableBmps = TRUE;
8433 }
8434
8435 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
8436 if((NULL != pAdapter)&&
8437 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
8438 {
8439 disableBmps = TRUE;
8440 }
8441
8442 //Exit both Bmps and Imps incase of Go/SAP Mode
8443 if((WLAN_HDD_SOFTAP == session_type) ||
8444 (WLAN_HDD_P2P_GO == session_type))
8445 {
8446 disableBmps = TRUE;
8447 disableImps = TRUE;
8448 }
8449
8450 if(TRUE == disableImps)
8451 {
8452 if (pHddCtx->cfg_ini->fIsImpsEnabled)
8453 {
8454 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
8455 }
8456 }
8457
8458 if(TRUE == disableBmps)
8459 {
8460 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
8461 {
8462 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
8463
8464 if(eHAL_STATUS_SUCCESS != halStatus)
8465 {
8466 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08008467 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008468 VOS_ASSERT(0);
8469 return status;
8470 }
8471 }
8472
8473 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
8474 {
8475 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
8476
8477 if(eHAL_STATUS_SUCCESS != halStatus)
8478 {
8479 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08008480 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008481 VOS_ASSERT(0);
8482 return status;
8483 }
8484 }
8485 }
8486
8487 if((TRUE == disableBmps) ||
8488 (TRUE == disableImps))
8489 {
8490 /* Now, get the chip into Full Power now */
8491 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
8492 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
8493 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
8494
8495 if(halStatus != eHAL_STATUS_SUCCESS)
8496 {
8497 if(halStatus == eHAL_STATUS_PMC_PENDING)
8498 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308499 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07008500 //Block on a completion variable. Can't wait forever though
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308501 ret = wait_for_completion_interruptible_timeout(
8502 &pHddCtx->full_pwr_comp_var,
8503 msecs_to_jiffies(1000));
8504 if (ret <= 0)
8505 {
8506 hddLog(VOS_TRACE_LEVEL_ERROR,
8507 "%s: wait on full_pwr_comp_var failed %ld",
8508 __func__, ret);
8509 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008510 }
8511 else
8512 {
8513 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08008514 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008515 VOS_ASSERT(0);
8516 return status;
8517 }
8518 }
8519
8520 status = VOS_STATUS_SUCCESS;
8521 }
8522
8523 break;
8524 }
8525 return status;
8526}
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +05308527
8528void hdd_monPostMsgCb(tANI_U32 *magic, struct completion *cmpVar)
8529{
8530 if (magic == NULL || cmpVar == NULL) {
8531 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8532 FL("invalid arguments %p %p"), magic, cmpVar);
8533 return;
8534 }
8535 if (*magic != MON_MODE_MSG_MAGIC) {
8536 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8537 FL("maic: %x"), *magic);
8538 return;
8539 }
8540
8541 complete(cmpVar);
8542 return;
8543}
8544
Katya Nigame7b69a82015-04-28 15:24:06 +05308545void hdd_init_mon_mode (hdd_adapter_t *pAdapter)
8546 {
8547 hdd_mon_ctx_t *pMonCtx = NULL;
8548 pMonCtx = WLAN_HDD_GET_MONITOR_CTX_PTR(pAdapter);
8549
8550 pMonCtx->state = 0;
8551 pMonCtx->ChannelNo = 1;
8552 pMonCtx->ChannelBW = 20;
Katya Nigamd7d3a1f2015-06-11 14:04:24 +05308553 pMonCtx->crcCheckEnabled = 1;
8554 pMonCtx->typeSubtypeBitmap = 0xFFFF00000000;
8555 pMonCtx->is80211to803ConReq = 1;
Katya Nigame7b69a82015-04-28 15:24:06 +05308556 pMonCtx->numOfMacFilters = 0;
8557 }
8558
Jeff Johnson295189b2012-06-20 16:38:30 -07008559
8560hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08008561 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07008562 tANI_U8 rtnl_held )
8563{
8564 hdd_adapter_t *pAdapter = NULL;
8565 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
8566 VOS_STATUS status = VOS_STATUS_E_FAILURE;
8567 VOS_STATUS exitbmpsStatus;
8568
Arif Hussain6d2a3322013-11-17 19:50:10 -08008569 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d",__func__,iface_name,session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07008570
Nirav Shah436658f2014-02-28 17:05:45 +05308571 if(macAddr == NULL)
8572 {
8573 /* Not received valid macAddr */
8574 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8575 "%s:Unable to add virtual intf: Not able to get"
8576 "valid mac address",__func__);
8577 return NULL;
8578 }
8579
Jeff Johnson295189b2012-06-20 16:38:30 -07008580 //Disable BMPS incase of Concurrency
8581 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
8582
8583 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
8584 {
8585 //Fail to Exit BMPS
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308586 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Exit BMPS", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008587 VOS_ASSERT(0);
8588 return NULL;
8589 }
8590
8591 switch(session_type)
8592 {
8593 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07008594 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07008595 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07008596 {
8597 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
8598
8599 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308600 {
8601 hddLog(VOS_TRACE_LEVEL_FATAL,
8602 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07008603 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308604 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008605
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05308606#ifdef FEATURE_WLAN_TDLS
8607 /* A Mutex Lock is introduced while changing/initializing the mode to
8608 * protect the concurrent access for the Adapters by TDLS module.
8609 */
Rajesh Chauhana34c6e62014-03-25 16:37:58 +05308610 mutex_lock(&pHddCtx->tdls_lock);
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05308611#endif
8612
Jeff Johnsone7245742012-09-05 17:12:55 -07008613 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
8614 NL80211_IFTYPE_P2P_CLIENT:
8615 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07008616
Jeff Johnson295189b2012-06-20 16:38:30 -07008617 pAdapter->device_mode = session_type;
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05308618#ifdef FEATURE_WLAN_TDLS
8619 mutex_unlock(&pHddCtx->tdls_lock);
8620#endif
Sunil Dutt66485cb2013-12-19 19:05:03 +05308621
Mahesh A Saptasagar67ab9222015-10-21 15:38:41 +05308622 hdd_initialize_adapter_common(pAdapter);
Sunil Dutt66485cb2013-12-19 19:05:03 +05308623 status = hdd_init_station_mode( pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07008624 if( VOS_STATUS_SUCCESS != status )
8625 goto err_free_netdev;
8626
8627 status = hdd_register_interface( pAdapter, rtnl_held );
8628 if( VOS_STATUS_SUCCESS != status )
8629 {
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05308630#ifdef FEATURE_WLAN_TDLS
8631 mutex_lock(&pHddCtx->tdls_lock);
8632#endif
c_hpothu002231a2015-02-05 14:58:51 +05308633 hdd_deinit_adapter(pHddCtx, pAdapter, rtnl_held);
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +05308634#ifdef FEATURE_WLAN_TDLS
8635 mutex_unlock(&pHddCtx->tdls_lock);
8636#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008637 goto err_free_netdev;
8638 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05308639
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05308640 // Workqueue which gets scheduled in IPv4 notification callback.
Anand N Sunkaddc63c792015-06-03 14:33:24 +05308641 vos_init_work(&pAdapter->ipv4NotifierWorkQueue, hdd_ipv4_notifier_work_queue);
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05308642
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05308643#ifdef WLAN_NS_OFFLOAD
8644 // Workqueue which gets scheduled in IPv6 notification callback.
Anand N Sunkaddc63c792015-06-03 14:33:24 +05308645 vos_init_work(&pAdapter->ipv6NotifierWorkQueue, hdd_ipv6_notifier_work_queue);
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05308646#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008647 //Stop the Interface TX queue.
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05308648 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
Jeff Johnson295189b2012-06-20 16:38:30 -07008649 netif_tx_disable(pAdapter->dev);
8650 //netif_tx_disable(pWlanDev);
8651 netif_carrier_off(pAdapter->dev);
8652
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +05308653 if (WLAN_HDD_P2P_CLIENT == session_type ||
8654 WLAN_HDD_P2P_DEVICE == session_type)
8655 {
8656 /* Initialize the work queue to defer the
8657 * back to back RoC request */
Anand N Sunkaddc63c792015-06-03 14:33:24 +05308658 vos_init_delayed_work(&pAdapter->roc_work,
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +05308659 hdd_p2p_roc_work_queue);
8660 }
8661
Jeff Johnson295189b2012-06-20 16:38:30 -07008662 break;
8663 }
8664
Jeff Johnson295189b2012-06-20 16:38:30 -07008665 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07008666 case WLAN_HDD_SOFTAP:
8667 {
8668 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
8669 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308670 {
8671 hddLog(VOS_TRACE_LEVEL_FATAL,
8672 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07008673 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308674 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008675
Jeff Johnson295189b2012-06-20 16:38:30 -07008676 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
8677 NL80211_IFTYPE_AP:
8678 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07008679 pAdapter->device_mode = session_type;
8680
Mahesh A Saptasagar67ab9222015-10-21 15:38:41 +05308681 hdd_initialize_adapter_common(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07008682 status = hdd_init_ap_mode(pAdapter);
8683 if( VOS_STATUS_SUCCESS != status )
8684 goto err_free_netdev;
8685
Nirav Shah7e3c8132015-06-22 23:51:42 +05308686 status = hdd_sta_id_hash_attach(pAdapter);
8687 if (VOS_STATUS_SUCCESS != status)
8688 {
8689 hddLog(VOS_TRACE_LEVEL_FATAL,
8690 FL("failed to attach hash for session %d"), session_type);
8691 hdd_deinit_adapter(pHddCtx, pAdapter, rtnl_held);
8692 goto err_free_netdev;
8693 }
8694
Jeff Johnson295189b2012-06-20 16:38:30 -07008695 status = hdd_register_hostapd( pAdapter, rtnl_held );
8696 if( VOS_STATUS_SUCCESS != status )
8697 {
c_hpothu002231a2015-02-05 14:58:51 +05308698 hdd_deinit_adapter(pHddCtx, pAdapter, rtnl_held);
Jeff Johnson295189b2012-06-20 16:38:30 -07008699 goto err_free_netdev;
8700 }
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05308701 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
Jeff Johnson295189b2012-06-20 16:38:30 -07008702 netif_tx_disable(pAdapter->dev);
8703 netif_carrier_off(pAdapter->dev);
8704
8705 hdd_set_conparam( 1 );
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +05308706
8707 if (WLAN_HDD_P2P_GO == session_type)
8708 {
8709 /* Initialize the work queue to
8710 * defer the back to back RoC request */
8711 INIT_DELAYED_WORK(&pAdapter->roc_work,
8712 hdd_p2p_roc_work_queue);
8713 }
Bhargav Shahd0715912015-10-01 18:17:37 +05308714
Jeff Johnson295189b2012-06-20 16:38:30 -07008715 break;
8716 }
8717 case WLAN_HDD_MONITOR:
8718 {
Jeff Johnson295189b2012-06-20 16:38:30 -07008719 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
8720 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308721 {
8722 hddLog(VOS_TRACE_LEVEL_FATAL,
8723 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07008724 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308725 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008726
Katya Nigame7b69a82015-04-28 15:24:06 +05308727 // Register wireless extensions
8728 if( VOS_STATUS_SUCCESS != (status = hdd_register_wext(pAdapter->dev)))
8729 {
8730 hddLog(VOS_TRACE_LEVEL_FATAL,
8731 "hdd_register_wext() failed with status code %08d [x%08x]",
8732 status, status );
8733 status = VOS_STATUS_E_FAILURE;
8734 }
8735
Jeff Johnson295189b2012-06-20 16:38:30 -07008736 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
8737 pAdapter->device_mode = session_type;
Jeff Johnson295189b2012-06-20 16:38:30 -07008738#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
8739 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
8740#else
8741 pAdapter->dev->open = hdd_mon_open;
8742 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
Katya Nigame7b69a82015-04-28 15:24:06 +05308743 pAdapter->dev->stop = hdd_mon_stop;
8744 pAdapter->dev->do_ioctl = hdd_mon_ioctl;
Jeff Johnson295189b2012-06-20 16:38:30 -07008745#endif
Katya Nigame7b69a82015-04-28 15:24:06 +05308746 status = hdd_register_interface( pAdapter, rtnl_held );
8747 hdd_init_mon_mode( pAdapter );
Mahesh A Saptasagar67ab9222015-10-21 15:38:41 +05308748 hdd_initialize_adapter_common(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07008749 hdd_init_tx_rx( pAdapter );
8750 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
Katya Nigame7b69a82015-04-28 15:24:06 +05308751 //Stop the Interface TX queue.
8752 netif_tx_disable(pAdapter->dev);
8753 netif_carrier_off(pAdapter->dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07008754 }
8755 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07008756 case WLAN_HDD_FTM:
8757 {
8758 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
8759
8760 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308761 {
8762 hddLog(VOS_TRACE_LEVEL_FATAL,
8763 FL("failed to allocate adapter for session %d"), session_type);
8764 return NULL;
8765 }
8766
Jeff Johnson295189b2012-06-20 16:38:30 -07008767 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
8768 * message while loading driver in FTM mode. */
8769 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
8770 pAdapter->device_mode = session_type;
8771 status = hdd_register_interface( pAdapter, rtnl_held );
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05308772
Mahesh A Saptasagar67ab9222015-10-21 15:38:41 +05308773 hdd_initialize_adapter_common(pAdapter);
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05308774 hdd_init_tx_rx( pAdapter );
8775
8776 //Stop the Interface TX queue.
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05308777 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05308778 netif_tx_disable(pAdapter->dev);
8779 netif_carrier_off(pAdapter->dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07008780 }
8781 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07008782 default:
8783 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308784 hddLog(VOS_TRACE_LEVEL_FATAL,"%s Invalid session type %d",
8785 __func__, session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07008786 VOS_ASSERT(0);
8787 return NULL;
8788 }
8789 }
8790
Jeff Johnson295189b2012-06-20 16:38:30 -07008791 if( VOS_STATUS_SUCCESS == status )
8792 {
Mahesh A Saptasagar67ab9222015-10-21 15:38:41 +05308793 //Add it to the hdd's session list.
Jeff Johnson295189b2012-06-20 16:38:30 -07008794 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
8795 if( NULL == pHddAdapterNode )
8796 {
8797 status = VOS_STATUS_E_NOMEM;
8798 }
8799 else
8800 {
8801 pHddAdapterNode->pAdapter = pAdapter;
8802 status = hdd_add_adapter_back ( pHddCtx,
8803 pHddAdapterNode );
8804 }
8805 }
8806
8807 if( VOS_STATUS_SUCCESS != status )
8808 {
8809 if( NULL != pAdapter )
8810 {
8811 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
8812 pAdapter = NULL;
8813 }
8814 if( NULL != pHddAdapterNode )
8815 {
8816 vos_mem_free( pHddAdapterNode );
8817 }
8818
8819 goto resume_bmps;
8820 }
8821
8822 if(VOS_STATUS_SUCCESS == status)
8823 {
8824 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
8825
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07008826 //Initialize the WoWL service
8827 if(!hdd_init_wowl(pAdapter))
8828 {
8829 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
8830 goto err_free_netdev;
8831 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008832 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008833 return pAdapter;
8834
8835err_free_netdev:
8836 free_netdev(pAdapter->dev);
8837 wlan_hdd_release_intf_addr( pHddCtx,
8838 pAdapter->macAddressCurrent.bytes );
8839
8840resume_bmps:
8841 //If bmps disabled enable it
8842 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
8843 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308844 if (pHddCtx->hdd_wlan_suspended)
8845 {
8846 hdd_set_pwrparams(pHddCtx);
8847 }
8848 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07008849 }
8850 return NULL;
8851}
8852
8853VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
8854 tANI_U8 rtnl_held )
8855{
8856 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
8857 VOS_STATUS status;
8858
8859 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
8860 if( VOS_STATUS_SUCCESS != status )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308861 {
8862 hddLog(VOS_TRACE_LEVEL_WARN,"%s: adapter list empty %d",
8863 __func__, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07008864 return status;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308865 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008866
8867 while ( pCurrent->pAdapter != pAdapter )
8868 {
8869 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
8870 if( VOS_STATUS_SUCCESS != status )
8871 break;
8872
8873 pCurrent = pNext;
8874 }
8875 pAdapterNode = pCurrent;
8876 if( VOS_STATUS_SUCCESS == status )
8877 {
8878 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
8879 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05308880
8881#ifdef FEATURE_WLAN_TDLS
8882
8883 /* A Mutex Lock is introduced while changing/initializing the mode to
8884 * protect the concurrent access for the Adapters by TDLS module.
8885 */
Rajesh Chauhana34c6e62014-03-25 16:37:58 +05308886 mutex_lock(&pHddCtx->tdls_lock);
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05308887#endif
8888
Jeff Johnson295189b2012-06-20 16:38:30 -07008889 hdd_remove_adapter( pHddCtx, pAdapterNode );
8890 vos_mem_free( pAdapterNode );
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08008891 pAdapterNode = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07008892
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05308893#ifdef FEATURE_WLAN_TDLS
8894 mutex_unlock(&pHddCtx->tdls_lock);
8895#endif
8896
Jeff Johnson295189b2012-06-20 16:38:30 -07008897
8898 /* If there is a single session of STA/P2P client, re-enable BMPS */
Agarwal Ashish51325b52014-06-16 16:50:49 +05308899 if ((!vos_concurrent_open_sessions_running()) &&
8900 ((pHddCtx->no_of_open_sessions[VOS_STA_MODE] >= 1) ||
8901 (pHddCtx->no_of_open_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
Jeff Johnson295189b2012-06-20 16:38:30 -07008902 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308903 if (pHddCtx->hdd_wlan_suspended)
8904 {
8905 hdd_set_pwrparams(pHddCtx);
8906 }
8907 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07008908 }
8909
8910 return VOS_STATUS_SUCCESS;
8911 }
8912
8913 return VOS_STATUS_E_FAILURE;
8914}
8915
8916VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
8917{
8918 hdd_adapter_list_node_t *pHddAdapterNode;
8919 VOS_STATUS status;
8920
8921 ENTER();
8922
8923 do
8924 {
8925 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
8926 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
8927 {
8928 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
8929 vos_mem_free( pHddAdapterNode );
8930 }
8931 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
8932
8933 EXIT();
8934
8935 return VOS_STATUS_SUCCESS;
8936}
8937
8938void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
8939{
8940 v_U8_t addIE[1] = {0};
8941
8942 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
8943 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
8944 eANI_BOOLEAN_FALSE) )
8945 {
8946 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08008947 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07008948 }
8949
8950 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
8951 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
8952 eANI_BOOLEAN_FALSE) )
8953 {
8954 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08008955 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07008956 }
8957
8958 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
8959 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
8960 eANI_BOOLEAN_FALSE) )
8961 {
8962 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08008963 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07008964 }
8965}
8966
Anurag Chouhan83026002016-12-13 22:46:21 +05308967VOS_STATUS hdd_cleanup_ap_events(hdd_adapter_t *adapter)
8968{
8969#ifdef DHCP_SERVER_OFFLOAD
8970 vos_event_destroy(&adapter->dhcp_status.vos_event);
8971#endif
Anurag Chouhan0b29de02016-12-16 13:18:40 +05308972#ifdef MDNS_OFFLOAD
8973 vos_event_destroy(&adapter->mdns_status.vos_event);
8974#endif
Anurag Chouhan83026002016-12-13 22:46:21 +05308975 return VOS_STATUS_SUCCESS;
8976}
8977
8978
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05308979VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
8980 const v_BOOL_t bCloseSession )
Jeff Johnson295189b2012-06-20 16:38:30 -07008981{
8982 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
8983 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
Kaushik, Sushant4975a572014-10-21 16:07:48 +05308984 hdd_scaninfo_t *pScanInfo = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07008985 union iwreq_data wrqu;
Kaushik, Sushant7005e372014-04-08 11:36:54 +05308986 v_U8_t retry = 0;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308987 long ret;
Nirav Shah7e3c8132015-06-22 23:51:42 +05308988 VOS_STATUS status;
Jeff Johnson295189b2012-06-20 16:38:30 -07008989
Anand N Sunkad26d71b92014-12-24 18:08:22 +05308990 if (pHddCtx->isLogpInProgress) {
8991 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
8992 "%s:LOGP in Progress. Ignore!!!",__func__);
8993 return VOS_STATUS_E_FAILURE;
8994 }
8995
Jeff Johnson295189b2012-06-20 16:38:30 -07008996 ENTER();
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +05308997
Kaushik, Sushant4975a572014-10-21 16:07:48 +05308998 pScanInfo = &pHddCtx->scan_info;
Jeff Johnson295189b2012-06-20 16:38:30 -07008999 switch(pAdapter->device_mode)
9000 {
Nirav Shah0cf4d892015-11-05 16:27:27 +05309001 case WLAN_HDD_IBSS:
9002 if ( VOS_TRUE == bCloseSession )
9003 {
9004 status = hdd_sta_id_hash_detach(pAdapter);
9005 if (status != VOS_STATUS_SUCCESS)
9006 hddLog(VOS_TRACE_LEVEL_ERROR,
9007 FL("sta id hash detach failed"));
9008 }
9009
Jeff Johnson295189b2012-06-20 16:38:30 -07009010 case WLAN_HDD_INFRA_STATION:
9011 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07009012 case WLAN_HDD_P2P_DEVICE:
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05309013 {
9014 hdd_station_ctx_t *pstation = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Mahesh A Saptasagare4d05d42015-07-02 16:17:20 +05309015#ifdef FEATURE_WLAN_TDLS
9016 mutex_lock(&pHddCtx->tdls_lock);
9017 wlan_hdd_tdls_exit(pAdapter, TRUE);
9018 mutex_unlock(&pHddCtx->tdls_lock);
9019#endif
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05309020 if( hdd_connIsConnected(pstation) ||
9021 (pstation->conn_info.connState == eConnectionState_Connecting) )
Jeff Johnson295189b2012-06-20 16:38:30 -07009022 {
9023 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
9024 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
9025 pAdapter->sessionId,
9026 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
9027 else
9028 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
9029 pAdapter->sessionId,
9030 eCSR_DISCONNECT_REASON_UNSPECIFIED);
Abhishek Singh7b52ed52016-02-11 17:45:54 +05309031 /* Success implies disconnect command got queued up successfully
9032 * Or cmd not queued as scan for SSID is in progress
9033 */
9034 if((eHAL_STATUS_SUCCESS == halStatus) ||
9035 (eHAL_STATUS_CMD_NOT_QUEUED == halStatus))
Jeff Johnson295189b2012-06-20 16:38:30 -07009036 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309037 ret = wait_for_completion_interruptible_timeout(
9038 &pAdapter->disconnect_comp_var,
9039 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Abhishek Singh7b52ed52016-02-11 17:45:54 +05309040 if (ret <= 0 &&
9041 (eHAL_STATUS_CMD_NOT_QUEUED != halStatus))
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309042 {
9043 hddLog(VOS_TRACE_LEVEL_ERROR,
9044 "%s: wait on disconnect_comp_var failed %ld",
9045 __func__, ret);
9046 }
9047 }
9048 else
9049 {
9050 hddLog(LOGE, "%s: failed to post disconnect event to SME",
9051 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009052 }
9053 memset(&wrqu, '\0', sizeof(wrqu));
9054 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
9055 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
9056 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
9057 }
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05309058 else if(pstation->conn_info.connState ==
9059 eConnectionState_Disconnecting)
9060 {
9061 ret = wait_for_completion_interruptible_timeout(
9062 &pAdapter->disconnect_comp_var,
9063 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
9064 if (ret <= 0)
9065 {
9066 hddLog(VOS_TRACE_LEVEL_ERROR,
9067 FL("wait on disconnect_comp_var failed %ld"), ret);
9068 }
9069 }
Sachin Ahuja27dd2402016-08-01 20:30:31 +05309070 if(pScanInfo != NULL && pHddCtx->scan_info.mScanPending)
Jeff Johnson295189b2012-06-20 16:38:30 -07009071 {
Mahesh A Saptasagar0b61dcc2016-02-15 14:23:38 +05309072 wlan_hdd_scan_abort(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07009073 }
Abhishek Singh3ac179b2015-09-21 10:01:34 +05309074 if ((pAdapter->device_mode != WLAN_HDD_INFRA_STATION) &&
9075 (pAdapter->device_mode != WLAN_HDD_IBSS))
Kaushik, Sushant7005e372014-04-08 11:36:54 +05309076 {
9077 while (pAdapter->is_roc_inprogress)
9078 {
9079 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9080 "%s: ROC in progress for session %d!!!",
9081 __func__, pAdapter->sessionId);
9082 // waiting for ROC to expire
9083 msleep(500);
9084 /* In GO present case , if retry exceeds 3,
9085 it means something went wrong. */
9086 if ( retry++ > MAX_WAIT_FOR_ROC_COMPLETION )
9087 {
9088 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9089 "%s: ROC completion is not received.!!!", __func__);
Deepthi Gowri70498252015-01-20 15:56:45 +05309090 if (eHAL_STATUS_SUCCESS !=
9091 sme_CancelRemainOnChannel( WLAN_HDD_GET_HAL_CTX( pAdapter),
9092 pAdapter->sessionId ))
9093 {
9094 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9095 FL("Failed to Cancel Remain on Channel"));
9096 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +05309097 wait_for_completion_interruptible_timeout(
9098 &pAdapter->cancel_rem_on_chan_var,
9099 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
9100 break;
9101 }
9102 }
Anand N Sunkaddc63c792015-06-03 14:33:24 +05309103 vos_flush_delayed_work(&pAdapter->roc_work);
Kaushik, Sushant7005e372014-04-08 11:36:54 +05309104 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05309105#ifdef WLAN_NS_OFFLOAD
Anand N Sunkaddc63c792015-06-03 14:33:24 +05309106 vos_flush_work(&pAdapter->ipv6NotifierWorkQueue);
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05309107#endif
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +05309108
Anand N Sunkaddc63c792015-06-03 14:33:24 +05309109 vos_flush_work(&pAdapter->ipv4NotifierWorkQueue);
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +05309110
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05309111 /* It is possible that the caller of this function does not
9112 * wish to close the session
9113 */
9114 if (VOS_TRUE == bCloseSession &&
9115 test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07009116 {
9117 INIT_COMPLETION(pAdapter->session_close_comp_var);
9118 if (eHAL_STATUS_SUCCESS ==
Agrawal Ashish5a3522c2016-03-02 15:08:28 +05309119 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId, FALSE,
9120 VOS_FALSE, hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07009121 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309122 unsigned long ret;
9123
Jeff Johnson295189b2012-06-20 16:38:30 -07009124 //Block on a completion variable. Can't wait forever though.
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309125 ret = wait_for_completion_timeout(
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05309126 &pAdapter->session_close_comp_var,
9127 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309128 if ( 0 >= ret)
9129 {
9130 hddLog(LOGE, "%s: failure waiting for session_close_comp_var %ld",
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05309131 __func__, ret);
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309132 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009133 }
9134 }
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05309135 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009136 break;
9137
9138 case WLAN_HDD_SOFTAP:
9139 case WLAN_HDD_P2P_GO:
Nirav Shah0cf4d892015-11-05 16:27:27 +05309140 if ( VOS_TRUE == bCloseSession )
9141 {
9142 status = hdd_sta_id_hash_detach(pAdapter);
9143 if (status != VOS_STATUS_SUCCESS)
9144 hddLog(VOS_TRACE_LEVEL_ERROR,
9145 FL("sta id hash detach failed"));
9146 }
9147
Jeff Johnson295189b2012-06-20 16:38:30 -07009148 //Any softap specific cleanup here...
Anurag Chouhan83026002016-12-13 22:46:21 +05309149 hdd_cleanup_ap_events(pAdapter);
Kaushik, Sushant7005e372014-04-08 11:36:54 +05309150 if (pAdapter->device_mode == WLAN_HDD_P2P_GO) {
9151 while (pAdapter->is_roc_inprogress) {
9152 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9153 "%s: ROC in progress for session %d!!!",
9154 __func__, pAdapter->sessionId);
9155 msleep(500);
9156 if ( retry++ > MAX_WAIT_FOR_ROC_COMPLETION ) {
9157 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9158 "%s: ROC completion is not received.!!!", __func__);
9159 WLANSAP_CancelRemainOnChannel(
9160 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
9161 wait_for_completion_interruptible_timeout(
9162 &pAdapter->cancel_rem_on_chan_var,
9163 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
9164 break;
9165 }
9166 }
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +05309167
Anand N Sunkaddc63c792015-06-03 14:33:24 +05309168 vos_flush_delayed_work(&pAdapter->roc_work);
Kaushik, Sushant7005e372014-04-08 11:36:54 +05309169 }
Agrawal Ashish17ef5082016-10-17 18:33:21 +05309170#ifdef SAP_AUTH_OFFLOAD
9171 if (pHddCtx->cfg_ini->enable_sap_auth_offload)
9172 hdd_set_sap_auth_offload(pAdapter, FALSE);
9173#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009174 mutex_lock(&pHddCtx->sap_lock);
9175 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
9176 {
9177 VOS_STATUS status;
9178 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9179
9180 //Stop Bss.
9181 status = WLANSAP_StopBss(pHddCtx->pvosContext);
9182 if (VOS_IS_STATUS_SUCCESS(status))
9183 {
9184 hdd_hostapd_state_t *pHostapdState =
9185 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
9186
9187 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
9188
9189 if (!VOS_IS_STATUS_SUCCESS(status))
9190 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309191 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss %d",
9192 __func__, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07009193 }
9194 }
9195 else
9196 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07009197 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009198 }
9199 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
Agarwal Ashish51325b52014-06-16 16:50:49 +05309200 wlan_hdd_decr_active_session(pHddCtx, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07009201
9202 if (eHAL_STATUS_FAILURE ==
9203 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
9204 0, NULL, eANI_BOOLEAN_FALSE))
9205 {
9206 hddLog(LOGE,
9207 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07009208 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009209 }
9210
9211 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
9212 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
9213 eANI_BOOLEAN_FALSE) )
9214 {
9215 hddLog(LOGE,
9216 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
9217 }
9218
9219 // Reset WNI_CFG_PROBE_RSP Flags
9220 wlan_hdd_reset_prob_rspies(pAdapter);
9221 kfree(pAdapter->sessionCtx.ap.beacon);
9222 pAdapter->sessionCtx.ap.beacon = NULL;
9223 }
9224 mutex_unlock(&pHddCtx->sap_lock);
9225 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07009226
Jeff Johnson295189b2012-06-20 16:38:30 -07009227 case WLAN_HDD_MONITOR:
9228 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07009229
Jeff Johnson295189b2012-06-20 16:38:30 -07009230 default:
9231 break;
9232 }
9233
9234 EXIT();
9235 return VOS_STATUS_SUCCESS;
9236}
9237
9238VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
9239{
9240 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
9241 VOS_STATUS status;
9242 hdd_adapter_t *pAdapter;
9243
9244 ENTER();
9245
9246 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
9247
9248 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
9249 {
9250 pAdapter = pAdapterNode->pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07009251
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05309252 hdd_stop_adapter( pHddCtx, pAdapter, VOS_TRUE );
Jeff Johnson295189b2012-06-20 16:38:30 -07009253
9254 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
9255 pAdapterNode = pNext;
9256 }
9257
9258 EXIT();
9259
9260 return VOS_STATUS_SUCCESS;
9261}
9262
Rajeev Kumarf999e582014-01-09 17:33:29 -08009263
9264#ifdef FEATURE_WLAN_BATCH_SCAN
9265/**---------------------------------------------------------------------------
9266
9267 \brief hdd_deinit_batch_scan () - This function cleans up batch scan data
9268 structures
9269
9270 \param - pAdapter Pointer to HDD adapter
9271
9272 \return - None
9273
9274 --------------------------------------------------------------------------*/
9275void hdd_deinit_batch_scan(hdd_adapter_t *pAdapter)
9276{
9277 tHddBatchScanRsp *pNode;
9278 tHddBatchScanRsp *pPrev;
9279
Siddharth Bhalb3e9b792014-02-24 15:14:16 +05309280 if (NULL == pAdapter)
Rajeev Kumarf999e582014-01-09 17:33:29 -08009281 {
Siddharth Bhalb3e9b792014-02-24 15:14:16 +05309282 hddLog(VOS_TRACE_LEVEL_ERROR,
9283 "%s: Adapter context is Null", __func__);
9284 return;
9285 }
9286
9287 pNode = pAdapter->pBatchScanRsp;
9288 while (pNode)
9289 {
9290 pPrev = pNode;
9291 pNode = pNode->pNext;
9292 vos_mem_free((v_VOID_t * )pPrev);
Rajeev Kumarf999e582014-01-09 17:33:29 -08009293 }
9294
9295 pAdapter->pBatchScanRsp = NULL;
9296 pAdapter->numScanList = 0;
9297 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
9298 pAdapter->prev_batch_id = 0;
9299
9300 return;
9301}
9302#endif
9303
9304
Jeff Johnson295189b2012-06-20 16:38:30 -07009305VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
9306{
9307 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
9308 VOS_STATUS status;
9309 hdd_adapter_t *pAdapter;
9310
9311 ENTER();
9312
9313 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
9314
9315 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
9316 {
9317 pAdapter = pAdapterNode->pAdapter;
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05309318 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
Jeff Johnson295189b2012-06-20 16:38:30 -07009319 netif_tx_disable(pAdapter->dev);
9320 netif_carrier_off(pAdapter->dev);
9321
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07009322 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
9323
Jeff Johnson295189b2012-06-20 16:38:30 -07009324 hdd_deinit_tx_rx(pAdapter);
Agarwal Ashish6267caa2014-08-06 19:16:21 +05309325
Katya Nigam1fd24402015-02-16 14:52:19 +05309326 if(pAdapter->device_mode == WLAN_HDD_IBSS )
9327 hdd_ibss_deinit_tx_rx(pAdapter);
9328
Nirav Shah7e3c8132015-06-22 23:51:42 +05309329 status = hdd_sta_id_hash_detach(pAdapter);
9330 if (status != VOS_STATUS_SUCCESS)
9331 hddLog(VOS_TRACE_LEVEL_ERROR,
9332 FL("sta id hash detach failed for session id %d"),
9333 pAdapter->sessionId);
9334
Agarwal Ashish6267caa2014-08-06 19:16:21 +05309335 wlan_hdd_decr_active_session(pHddCtx, pAdapter->device_mode);
9336
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05309337 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
9338 {
9339 hdd_wmm_adapter_close( pAdapter );
9340 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
9341 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009342
Siddharth Bhal2db319d2014-12-03 12:37:18 +05309343 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
9344 {
9345 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
9346 }
9347
Rajeev Kumarf999e582014-01-09 17:33:29 -08009348#ifdef FEATURE_WLAN_BATCH_SCAN
9349 if (eHDD_BATCH_SCAN_STATE_STARTED == pAdapter->batchScanState)
9350 {
9351 hdd_deinit_batch_scan(pAdapter);
9352 }
9353#endif
9354
Mahesh A Saptasagarf5b8eff2015-01-31 01:07:07 +05309355#ifdef FEATURE_WLAN_TDLS
9356 mutex_lock(&pHddCtx->tdls_lock);
Pradeep Reddy POTTETI2d4d5c42015-03-03 14:34:19 +05309357 wlan_hdd_tdls_exit(pAdapter, TRUE);
Mahesh A Saptasagarf5b8eff2015-01-31 01:07:07 +05309358 mutex_unlock(&pHddCtx->tdls_lock);
9359#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009360 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
9361 pAdapterNode = pNext;
9362 }
9363
9364 EXIT();
9365
9366 return VOS_STATUS_SUCCESS;
9367}
9368
Abhishek Singhbbe0b2a2016-12-05 11:57:36 +05309369/**
Abhishek Singh5a597e62016-12-05 15:16:30 +05309370 * hdd_get_bss_entry() - Get the bss entry matching the chan, bssid and ssid
9371 * @wiphy: wiphy
9372 * @channel: channel of the BSS to find
9373 * @bssid: bssid of the BSS to find
9374 * @ssid: ssid of the BSS to find
9375 * @ssid_len: ssid len of of the BSS to find
9376 *
9377 * The API is a wrapper to get bss from kernel matching the chan,
9378 * bssid and ssid
9379 *
9380 * Return: Void
9381 */
9382#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) \
9383 && !defined(WITH_BACKPORTS) && !defined(IEEE80211_PRIVACY)
9384
9385struct cfg80211_bss* hdd_get_bss_entry(struct wiphy *wiphy,
9386 struct ieee80211_channel *channel,
9387 const u8 *bssid,
9388 const u8 *ssid, size_t ssid_len)
9389{
9390 return cfg80211_get_bss(wiphy, channel, bssid,
9391 ssid, ssid_len,
9392 WLAN_CAPABILITY_ESS,
9393 WLAN_CAPABILITY_ESS);
9394}
9395#else
9396struct cfg80211_bss* hdd_get_bss_entry(struct wiphy *wiphy,
9397 struct ieee80211_channel *channel,
9398 const u8 *bssid,
9399 const u8 *ssid, size_t ssid_len)
9400{
9401 return cfg80211_get_bss(wiphy, channel, bssid,
9402 ssid, ssid_len,
9403 IEEE80211_BSS_TYPE_ESS,
9404 IEEE80211_PRIVACY_ANY);
9405}
9406#endif
9407
9408/**
Abhishek Singhbbe0b2a2016-12-05 11:57:36 +05309409 * hdd_connect_result() - API to send connection status to supplicant
9410 * @dev: network device
9411 * @bssid: bssid to which we want to associate
9412 * @roam_info: information about connected bss
9413 * @req_ie: Request Information Element
9414 * @req_ie_len: len of the req IE
9415 * @resp_ie: Response IE
9416 * @resp_ie_len: len of ht response IE
9417 * @status: status
9418 * @gfp: Kernel Flag
9419 *
9420 * The API is a wrapper to send connection status to supplicant
9421 *
9422 * Return: Void
9423 */
9424#if defined CFG80211_CONNECT_BSS
9425void hdd_connect_result(struct net_device *dev,
9426 const u8 *bssid,
9427 tCsrRoamInfo *roam_info,
9428 const u8 *req_ie,
9429 size_t req_ie_len,
9430 const u8 *resp_ie,
9431 size_t resp_ie_len,
9432 u16 status,
9433 gfp_t gfp)
9434{
9435 hdd_adapter_t *padapter = (hdd_adapter_t *) netdev_priv(dev);
9436 struct cfg80211_bss *bss = NULL;
9437
9438 if (WLAN_STATUS_SUCCESS == status) {
9439 struct ieee80211_channel *chan;
9440 int freq;
9441 int chan_no = roam_info->pBssDesc->channelId;;
9442
9443 if (chan_no <= 14)
9444 freq = ieee80211_channel_to_frequency(chan_no,
9445 IEEE80211_BAND_2GHZ);
9446 else
9447 freq = ieee80211_channel_to_frequency(chan_no,
9448 IEEE80211_BAND_5GHZ);
9449
9450 chan = ieee80211_get_channel(padapter->wdev.wiphy, freq);
Abhishek Singh5a597e62016-12-05 15:16:30 +05309451 bss = hdd_get_bss_entry(padapter->wdev.wiphy,
9452 chan, bssid,
9453 roam_info->u.pConnectedProfile->SSID.ssId,
9454 roam_info->u.pConnectedProfile->SSID.length);
Abhishek Singhbbe0b2a2016-12-05 11:57:36 +05309455 }
9456
9457 cfg80211_connect_bss(dev, bssid, bss, req_ie, req_ie_len,
9458 resp_ie, resp_ie_len, status, gfp);
9459}
9460#else
9461void hdd_connect_result(struct net_device *dev,
9462 const u8 *bssid,
9463 tCsrRoamInfo *roam_info,
9464 const u8 *req_ie,
9465 size_t req_ie_len,
9466 const u8 * resp_ie,
9467 size_t resp_ie_len,
9468 u16 status,
9469 gfp_t gfp)
9470{
9471 cfg80211_connect_result(dev, bssid, req_ie, req_ie_len,
9472 resp_ie, resp_ie_len, status, gfp);
9473}
9474#endif
9475
Jeff Johnson295189b2012-06-20 16:38:30 -07009476VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
9477{
9478 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
9479 VOS_STATUS status;
9480 hdd_adapter_t *pAdapter;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05309481 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -07009482
9483 ENTER();
9484
9485 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
9486
9487 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
9488 {
9489 pAdapter = pAdapterNode->pAdapter;
9490
Kumar Anand82c009f2014-05-29 00:29:42 -07009491 hdd_wmm_init( pAdapter );
9492
Jeff Johnson295189b2012-06-20 16:38:30 -07009493 switch(pAdapter->device_mode)
9494 {
9495 case WLAN_HDD_INFRA_STATION:
9496 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07009497 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05309498
9499 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
9500
Jeff Johnson295189b2012-06-20 16:38:30 -07009501 hdd_init_station_mode(pAdapter);
9502 /* Open the gates for HDD to receive Wext commands */
9503 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07009504 pHddCtx->scan_info.mScanPending = FALSE;
9505 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07009506
9507 //Trigger the initial scan
Mukul Sharmae74e42c2015-08-06 23:55:49 +05309508 if (!pHddCtx->isLogpInProgress)
9509 hdd_wlan_initial_scan(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07009510
9511 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05309512 if (eConnectionState_Associated == connState ||
9513 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -07009514 {
9515 union iwreq_data wrqu;
9516 memset(&wrqu, '\0', sizeof(wrqu));
9517 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
9518 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
9519 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07009520 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07009521
Jeff Johnson295189b2012-06-20 16:38:30 -07009522 /* indicate disconnected event to nl80211 */
Mahesh A Saptasagar9ff4bcc2016-06-01 17:17:50 +05309523 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, false,
Mahesh A Saptasagarb5a15142016-05-25 11:27:43 +05309524 WLAN_REASON_UNSPECIFIED);
Jeff Johnson295189b2012-06-20 16:38:30 -07009525 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05309526 else if (eConnectionState_Connecting == connState)
9527 {
9528 /*
9529 * Indicate connect failure to supplicant if we were in the
9530 * process of connecting
9531 */
Abhishek Singhbbe0b2a2016-12-05 11:57:36 +05309532 hdd_connect_result(pAdapter->dev, NULL, NULL,
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05309533 NULL, 0, NULL, 0,
9534 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
9535 GFP_KERNEL);
9536 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009537 break;
9538
9539 case WLAN_HDD_SOFTAP:
9540 /* softAP can handle SSR */
9541 break;
9542
9543 case WLAN_HDD_P2P_GO:
Sameer Thalappiledf0d792013-08-09 14:31:03 -07009544 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send stop ap to supplicant",
Jeff Johnson295189b2012-06-20 16:38:30 -07009545 __func__);
Sameer Thalappiledf0d792013-08-09 14:31:03 -07009546 cfg80211_ap_stopped(pAdapter->dev, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07009547 break;
9548
9549 case WLAN_HDD_MONITOR:
9550 /* monitor interface start */
9551 break;
9552 default:
9553 break;
9554 }
9555
9556 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
9557 pAdapterNode = pNext;
9558 }
9559
9560 EXIT();
9561
9562 return VOS_STATUS_SUCCESS;
9563}
9564
9565VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
9566{
9567 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
9568 hdd_adapter_t *pAdapter;
9569 VOS_STATUS status;
9570 v_U32_t roamId;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309571 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07009572
9573 ENTER();
9574
9575 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
9576
9577 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
9578 {
9579 pAdapter = pAdapterNode->pAdapter;
9580
9581 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
9582 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
9583 {
9584 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9585 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
9586
Abhishek Singhf4669da2014-05-26 15:07:49 +05309587 hddLog(VOS_TRACE_LEVEL_INFO,
9588 "%s: Set HDD connState to eConnectionState_NotConnected",
9589 __func__);
Ganesh Kondabattini04338412015-09-14 15:39:09 +05309590 spin_lock_bh(&pAdapter->lock_for_active_session);
9591 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState)
9592 {
9593 wlan_hdd_decr_active_session(pHddCtx, pAdapter->device_mode);
9594 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009595 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
Ganesh Kondabattini04338412015-09-14 15:39:09 +05309596 spin_unlock_bh(&pAdapter->lock_for_active_session);
Jeff Johnson295189b2012-06-20 16:38:30 -07009597 init_completion(&pAdapter->disconnect_comp_var);
9598 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
9599 eCSR_DISCONNECT_REASON_UNSPECIFIED);
9600
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309601 ret = wait_for_completion_interruptible_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07009602 &pAdapter->disconnect_comp_var,
9603 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309604 if (0 >= ret)
9605 hddLog(LOGE, "%s: failure waiting for disconnect_comp_var %ld",
9606 __func__, ret);
Jeff Johnson295189b2012-06-20 16:38:30 -07009607
9608 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
9609 pHddCtx->isAmpAllowed = VOS_FALSE;
9610 sme_RoamConnect(pHddCtx->hHal,
9611 pAdapter->sessionId, &(pWextState->roamProfile),
9612 &roamId);
9613 }
9614
9615 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
9616 pAdapterNode = pNext;
9617 }
9618
9619 EXIT();
9620
9621 return VOS_STATUS_SUCCESS;
9622}
9623
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07009624void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
9625{
9626 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
9627 VOS_STATUS status;
9628 hdd_adapter_t *pAdapter;
9629 hdd_station_ctx_t *pHddStaCtx;
9630 hdd_ap_ctx_t *pHddApCtx;
9631 hdd_hostapd_state_t * pHostapdState;
9632 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
9633 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
9634 const char *p2pMode = "DEV";
9635 const char *ccMode = "Standalone";
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07009636
9637 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
9638 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
9639 {
9640 pAdapter = pAdapterNode->pAdapter;
9641 switch (pAdapter->device_mode) {
9642 case WLAN_HDD_INFRA_STATION:
9643 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9644 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
9645 staChannel = pHddStaCtx->conn_info.operationChannel;
9646 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
9647 }
9648 break;
9649 case WLAN_HDD_P2P_CLIENT:
9650 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9651 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
9652 p2pChannel = pHddStaCtx->conn_info.operationChannel;
9653 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
9654 p2pMode = "CLI";
9655 }
9656 break;
9657 case WLAN_HDD_P2P_GO:
9658 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
9659 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
9660 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
9661 p2pChannel = pHddApCtx->operatingChannel;
9662 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
9663 }
9664 p2pMode = "GO";
9665 break;
9666 case WLAN_HDD_SOFTAP:
9667 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
9668 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
9669 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
9670 apChannel = pHddApCtx->operatingChannel;
9671 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
9672 }
9673 break;
9674 default:
9675 break;
9676 }
9677 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
9678 pAdapterNode = pNext;
9679 }
9680 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
9681 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
9682 }
SaidiReddy Yenugaa8b32f92016-07-27 19:29:18 +05309683 hddLog(VOS_TRACE_LEVEL_INFO, "wlan(%d) " MAC_ADDRESS_STR " %s",
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07009684 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
9685 if (p2pChannel > 0) {
Sushant Kaushikdc3184b2015-10-09 12:00:21 +05309686 hddLog(VOS_TRACE_LEVEL_ERROR, "p2p-%s(%d) " MAC_ADDRESS_STR,
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07009687 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
9688 }
9689 if (apChannel > 0) {
Sushant Kaushikdc3184b2015-10-09 12:00:21 +05309690 hddLog(VOS_TRACE_LEVEL_ERROR, "AP(%d) " MAC_ADDRESS_STR,
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07009691 apChannel, MAC_ADDR_ARRAY(apBssid));
9692 }
9693
9694 if (p2pChannel > 0 && apChannel > 0) {
9695 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
9696 }
9697}
9698
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07009699bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07009700{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07009701 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07009702}
9703
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07009704/* Once SSR is disabled then it cannot be set. */
9705void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07009706{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07009707 if (HDD_SSR_DISABLED == isSsrRequired)
9708 return;
9709
Jeff Johnson295189b2012-06-20 16:38:30 -07009710 isSsrRequired = value;
9711}
9712
Hema Aparna Medicharla6b4d4f32015-06-23 04:09:12 +05309713void hdd_set_pre_close( hdd_context_t *pHddCtx)
9714{
9715 sme_PreClose(pHddCtx->hHal);
9716}
9717
Jeff Johnson295189b2012-06-20 16:38:30 -07009718VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
9719 hdd_adapter_list_node_t** ppAdapterNode)
9720{
9721 VOS_STATUS status;
Mukul Sharmaae1266d2015-06-26 15:29:53 +05309722 spin_lock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07009723 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
9724 (hdd_list_node_t**) ppAdapterNode );
Mukul Sharmaae1266d2015-06-26 15:29:53 +05309725 spin_unlock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07009726 return status;
9727}
9728
9729VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
9730 hdd_adapter_list_node_t* pAdapterNode,
9731 hdd_adapter_list_node_t** pNextAdapterNode)
9732{
9733 VOS_STATUS status;
Mukul Sharmaae1266d2015-06-26 15:29:53 +05309734 spin_lock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07009735 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
9736 (hdd_list_node_t*) pAdapterNode,
9737 (hdd_list_node_t**)pNextAdapterNode );
9738
Mukul Sharmaae1266d2015-06-26 15:29:53 +05309739 spin_unlock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07009740 return status;
9741}
9742
9743VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
9744 hdd_adapter_list_node_t* pAdapterNode)
9745{
9746 VOS_STATUS status;
Mukul Sharmaae1266d2015-06-26 15:29:53 +05309747 spin_lock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07009748 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
9749 &pAdapterNode->node );
Mukul Sharmaae1266d2015-06-26 15:29:53 +05309750 spin_unlock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07009751 return status;
9752}
9753
9754VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
9755 hdd_adapter_list_node_t** ppAdapterNode)
9756{
9757 VOS_STATUS status;
Mukul Sharmaae1266d2015-06-26 15:29:53 +05309758 spin_lock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07009759 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
9760 (hdd_list_node_t**) ppAdapterNode );
Mukul Sharmaae1266d2015-06-26 15:29:53 +05309761 spin_unlock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07009762 return status;
9763}
9764
9765VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
9766 hdd_adapter_list_node_t* pAdapterNode)
9767{
9768 VOS_STATUS status;
Mukul Sharmaae1266d2015-06-26 15:29:53 +05309769 spin_lock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07009770 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
9771 (hdd_list_node_t*) pAdapterNode );
Mukul Sharmaae1266d2015-06-26 15:29:53 +05309772 spin_unlock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07009773 return status;
9774}
9775
9776VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
9777 hdd_adapter_list_node_t* pAdapterNode)
9778{
9779 VOS_STATUS status;
Mukul Sharmaae1266d2015-06-26 15:29:53 +05309780 spin_lock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07009781 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
9782 (hdd_list_node_t*) pAdapterNode );
Mukul Sharmaae1266d2015-06-26 15:29:53 +05309783 spin_unlock_bh(&pHddCtx->hddAdapters.lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07009784 return status;
9785}
9786
9787hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
9788 tSirMacAddr macAddr )
9789{
9790 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
9791 hdd_adapter_t *pAdapter;
9792 VOS_STATUS status;
9793
9794 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
9795
9796 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
9797 {
9798 pAdapter = pAdapterNode->pAdapter;
9799
9800 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
9801 macAddr, sizeof(tSirMacAddr) ) )
9802 {
9803 return pAdapter;
9804 }
9805 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
9806 pAdapterNode = pNext;
9807 }
9808
9809 return NULL;
9810
9811}
9812
9813hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
9814{
9815 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
9816 hdd_adapter_t *pAdapter;
9817 VOS_STATUS status;
9818
9819 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
9820
9821 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
9822 {
9823 pAdapter = pAdapterNode->pAdapter;
9824
9825 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
9826 IFNAMSIZ ) )
9827 {
9828 return pAdapter;
9829 }
9830 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
9831 pAdapterNode = pNext;
9832 }
9833
9834 return NULL;
9835
9836}
9837
Ganesh Kondabattinicbfdc392015-09-11 19:12:59 +05309838hdd_adapter_t *hdd_get_adapter_by_sme_session_id( hdd_context_t *pHddCtx,
9839 tANI_U32 sme_session_id )
9840{
9841 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
9842 hdd_adapter_t *pAdapter;
9843 VOS_STATUS vos_status;
9844
9845
9846 vos_status = hdd_get_front_adapter( pHddCtx, &pAdapterNode);
9847
9848 while ((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == vos_status))
9849 {
9850 pAdapter = pAdapterNode->pAdapter;
9851
9852 if (pAdapter->sessionId == sme_session_id)
9853 return pAdapter;
9854
9855 vos_status = hdd_get_next_adapter(pHddCtx, pAdapterNode, &pNext);
9856 pAdapterNode = pNext;
9857 }
9858
9859 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
9860 "%s: sme_session_id %d does not exist with host",
9861 __func__, sme_session_id);
9862
9863 return NULL;
9864}
9865
Jeff Johnson295189b2012-06-20 16:38:30 -07009866hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
9867{
9868 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
9869 hdd_adapter_t *pAdapter;
9870 VOS_STATUS status;
9871
9872 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
9873
9874 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
9875 {
9876 pAdapter = pAdapterNode->pAdapter;
9877
9878 if( pAdapter && (mode == pAdapter->device_mode) )
9879 {
9880 return pAdapter;
9881 }
9882 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
9883 pAdapterNode = pNext;
9884 }
9885
9886 return NULL;
9887
9888}
9889
9890//Remove this function later
9891hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
9892{
9893 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
9894 hdd_adapter_t *pAdapter;
9895 VOS_STATUS status;
9896
9897 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
9898
9899 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
9900 {
9901 pAdapter = pAdapterNode->pAdapter;
9902
9903 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
9904 {
9905 return pAdapter;
9906 }
9907
9908 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
9909 pAdapterNode = pNext;
9910 }
9911
9912 return NULL;
9913
9914}
9915
Jeff Johnson295189b2012-06-20 16:38:30 -07009916/**---------------------------------------------------------------------------
9917
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05309918 \brief hdd_get_operating_channel() -
Jeff Johnson295189b2012-06-20 16:38:30 -07009919
9920 This API returns the operating channel of the requested device mode
9921
9922 \param - pHddCtx - Pointer to the HDD context.
9923 - mode - Device mode for which operating channel is required
9924 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
9925 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
9926 \return - channel number. "0" id the requested device is not found OR it is not connected.
9927 --------------------------------------------------------------------------*/
9928v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
9929{
9930 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
9931 VOS_STATUS status;
9932 hdd_adapter_t *pAdapter;
9933 v_U8_t operatingChannel = 0;
9934
9935 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
9936
9937 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
9938 {
9939 pAdapter = pAdapterNode->pAdapter;
9940
9941 if( mode == pAdapter->device_mode )
9942 {
9943 switch(pAdapter->device_mode)
9944 {
9945 case WLAN_HDD_INFRA_STATION:
9946 case WLAN_HDD_P2P_CLIENT:
9947 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
9948 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
9949 break;
9950 case WLAN_HDD_SOFTAP:
9951 case WLAN_HDD_P2P_GO:
9952 /*softap connection info */
9953 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
9954 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
9955 break;
9956 default:
9957 break;
9958 }
9959
9960 break; //Found the device of interest. break the loop
9961 }
9962
9963 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
9964 pAdapterNode = pNext;
9965 }
9966 return operatingChannel;
9967}
9968
9969#ifdef WLAN_FEATURE_PACKET_FILTERING
9970/**---------------------------------------------------------------------------
9971
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +05309972 \brief __hdd_set_multicast_list() -
Jeff Johnson295189b2012-06-20 16:38:30 -07009973
9974 This used to set the multicast address list.
9975
9976 \param - dev - Pointer to the WLAN device.
9977 - skb - Pointer to OS packet (sk_buff).
Mahesh A Saptasagar74088392015-02-05 17:22:09 +05309978 \return - success/fail
Jeff Johnson295189b2012-06-20 16:38:30 -07009979
9980 --------------------------------------------------------------------------*/
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +05309981static void __hdd_set_multicast_list(struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07009982{
Mahesh A Saptasagar74088392015-02-05 17:22:09 +05309983 hdd_adapter_t *pAdapter;
9984 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -07009985 int mc_count;
Mahesh A Saptasagar74088392015-02-05 17:22:09 +05309986 int i = 0, ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07009987 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05309988
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05309989 ENTER();
9990
Mahesh A Saptasagar74088392015-02-05 17:22:09 +05309991 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05309992 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07009993 {
9994 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05309995 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009996 return;
9997 }
Mahesh A Saptasagar74088392015-02-05 17:22:09 +05309998 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9999 ret = wlan_hdd_validate_context(pHddCtx);
10000 if (0 != ret)
10001 {
Mahesh A Saptasagar74088392015-02-05 17:22:09 +053010002 return;
10003 }
Jeff Johnson295189b2012-06-20 16:38:30 -070010004 if (dev->flags & IFF_ALLMULTI)
10005 {
10006 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070010007 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +053010008 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -070010009 }
Mahesh A Saptasagar74088392015-02-05 17:22:09 +053010010 else
Jeff Johnson295189b2012-06-20 16:38:30 -070010011 {
10012 mc_count = netdev_mc_count(dev);
10013 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070010014 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -070010015 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
10016 {
10017 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070010018 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +053010019 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -070010020 return;
10021 }
10022
Gopichand Nakkala0f276812013-02-24 14:45:51 +053010023 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -070010024
10025 netdev_for_each_mc_addr(ha, dev) {
10026 if (i == mc_count)
10027 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +053010028 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
10029 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
Arif Hussain6d2a3322013-11-17 19:50:10 -080010030 hddLog(VOS_TRACE_LEVEL_INFO, "%s: mlist[%d] = "MAC_ADDRESS_STR,
Mahesh A Saptasagar74088392015-02-05 17:22:09 +053010031 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +053010032 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -070010033 i++;
10034 }
10035 }
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +053010036
Ganesh Kondabattinifb37e652015-10-09 15:46:47 +053010037 if (pHddCtx->hdd_wlan_suspended)
10038 {
10039 /*
10040 * Configure the Mcast address list to FW
10041 * If wlan is already in suspend mode
10042 */
10043 wlan_hdd_set_mc_addr_list(pAdapter, TRUE);
10044 }
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +053010045 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -070010046 return;
10047}
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +053010048
10049static void hdd_set_multicast_list(struct net_device *dev)
10050{
10051 vos_ssr_protect(__func__);
10052 __hdd_set_multicast_list(dev);
10053 vos_ssr_unprotect(__func__);
10054}
Jeff Johnson295189b2012-06-20 16:38:30 -070010055#endif
10056
10057/**---------------------------------------------------------------------------
10058
10059 \brief hdd_select_queue() -
10060
10061 This function is registered with the Linux OS for network
10062 core to decide which queue to use first.
10063
10064 \param - dev - Pointer to the WLAN device.
10065 - skb - Pointer to OS packet (sk_buff).
10066 \return - ac, Queue Index/access category corresponding to UP in IP header
10067
10068 --------------------------------------------------------------------------*/
10069v_U16_t hdd_select_queue(struct net_device *dev,
Anand N Sunkade9adb1b2015-07-29 09:56:45 +053010070 struct sk_buff *skb
10071#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0))
10072 , void *accel_priv
10073#endif
10074#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0))
10075 , select_queue_fallback_t fallback
10076#endif
10077)
Jeff Johnson295189b2012-06-20 16:38:30 -070010078{
10079 return hdd_wmm_select_queue(dev, skb);
10080}
10081
10082
10083/**---------------------------------------------------------------------------
10084
10085 \brief hdd_wlan_initial_scan() -
10086
10087 This function triggers the initial scan
10088
10089 \param - pAdapter - Pointer to the HDD adapter.
10090
10091 --------------------------------------------------------------------------*/
10092void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
10093{
10094 tCsrScanRequest scanReq;
10095 tCsrChannelInfo channelInfo;
10096 eHalStatus halStatus;
Jeff Johnson02797792013-10-26 19:17:13 -070010097 tANI_U32 scanId;
Jeff Johnson295189b2012-06-20 16:38:30 -070010098 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10099
10100 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
10101 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
10102 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
10103
10104 if(sme_Is11dSupported(pHddCtx->hHal))
10105 {
10106 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
10107 if ( HAL_STATUS_SUCCESS( halStatus ) )
10108 {
10109 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
10110 if( !scanReq.ChannelInfo.ChannelList )
10111 {
10112 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
10113 vos_mem_free(channelInfo.ChannelList);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -080010114 channelInfo.ChannelList = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -070010115 return;
10116 }
10117 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
10118 channelInfo.numOfChannels);
10119 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
10120 vos_mem_free(channelInfo.ChannelList);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -080010121 channelInfo.ChannelList = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -070010122 }
10123
10124 scanReq.scanType = eSIR_PASSIVE_SCAN;
10125 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
10126 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
10127 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
10128 }
10129 else
10130 {
10131 scanReq.scanType = eSIR_ACTIVE_SCAN;
10132 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
10133 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
10134 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
10135 }
10136
10137 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
10138 if ( !HAL_STATUS_SUCCESS( halStatus ) )
10139 {
10140 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
10141 __func__, halStatus );
10142 }
10143
10144 if(sme_Is11dSupported(pHddCtx->hHal))
10145 vos_mem_free(scanReq.ChannelInfo.ChannelList);
10146}
10147
Jeff Johnson295189b2012-06-20 16:38:30 -070010148/**---------------------------------------------------------------------------
10149
10150 \brief hdd_full_power_callback() - HDD full power callback function
10151
10152 This is the function invoked by SME to inform the result of a full power
10153 request issued by HDD
10154
10155 \param - callbackcontext - Pointer to cookie
10156 \param - status - result of request
10157
10158 \return - None
10159
10160 --------------------------------------------------------------------------*/
10161static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
10162{
Jeff Johnson72a40512013-12-19 10:14:15 -080010163 struct statsContext *pContext = callbackContext;
Jeff Johnson295189b2012-06-20 16:38:30 -070010164
10165 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +053010166 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -070010167
10168 if (NULL == callbackContext)
10169 {
10170 hddLog(VOS_TRACE_LEVEL_ERROR,
10171 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070010172 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -070010173 return;
10174 }
10175
Jeff Johnson72a40512013-12-19 10:14:15 -080010176 /* there is a race condition that exists between this callback
10177 function and the caller since the caller could time out either
10178 before or while this code is executing. we use a spinlock to
10179 serialize these actions */
10180 spin_lock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010181
10182 if (POWER_CONTEXT_MAGIC != pContext->magic)
10183 {
10184 /* the caller presumably timed out so there is nothing we can do */
Jeff Johnson72a40512013-12-19 10:14:15 -080010185 spin_unlock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010186 hddLog(VOS_TRACE_LEVEL_WARN,
10187 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070010188 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -070010189 return;
10190 }
10191
Jeff Johnson72a40512013-12-19 10:14:15 -080010192 /* context is valid so caller is still waiting */
10193
10194 /* paranoia: invalidate the magic */
10195 pContext->magic = 0;
10196
10197 /* notify the caller */
Jeff Johnson295189b2012-06-20 16:38:30 -070010198 complete(&pContext->completion);
Jeff Johnson72a40512013-12-19 10:14:15 -080010199
10200 /* serialization is complete */
10201 spin_unlock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010202}
10203
Katya Nigamf0511f62015-05-05 16:40:57 +053010204void wlan_hdd_mon_set_typesubtype( hdd_mon_ctx_t *pMonCtx,int type)
10205{
10206 pMonCtx->typeSubtypeBitmap = 0;
10207 if( type%10 ) /* Management Packets */
10208 pMonCtx->typeSubtypeBitmap |= 0xFFFF;
10209 type/=10;
10210 if( type%10 ) /* Control Packets */
10211 pMonCtx->typeSubtypeBitmap |= 0xFFFF0000;
10212 type/=10;
10213 if( type%10 ) /* Data Packets */
10214 pMonCtx->typeSubtypeBitmap |= 0xFFFF00000000;
10215}
10216
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053010217VOS_STATUS wlan_hdd_mon_postMsg(tANI_U32 *magic, struct completion *cmpVar,
10218 hdd_mon_ctx_t *pMonCtx , void* callback)
Katya Nigamf0511f62015-05-05 16:40:57 +053010219{
10220 vos_msg_t monMsg;
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053010221 tSirMonModeReq *pMonModeReq;
Katya Nigamf0511f62015-05-05 16:40:57 +053010222
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053010223 if (MON_MODE_START == pMonCtx->state)
10224 monMsg.type = WDA_MON_START_REQ;
10225 else if (MON_MODE_STOP == pMonCtx->state)
10226 monMsg.type = WDA_MON_STOP_REQ;
10227 else {
10228 hddLog(VOS_TRACE_LEVEL_ERROR,
10229 FL("invalid monitor state %d"), pMonCtx->state);
Katya Nigamf0511f62015-05-05 16:40:57 +053010230 return VOS_STATUS_E_FAILURE;
10231 }
10232
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053010233 pMonModeReq = vos_mem_malloc(sizeof(tSirMonModeReq));
10234 if (pMonModeReq == NULL) {
10235 hddLog(VOS_TRACE_LEVEL_ERROR,
10236 FL("fail to allocate memory for monitor mode req"));
10237 return VOS_STATUS_E_FAILURE;
10238 }
Katya Nigamf0511f62015-05-05 16:40:57 +053010239
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053010240 pMonModeReq->magic = magic;
10241 pMonModeReq->cmpVar = cmpVar;
10242 pMonModeReq->data = pMonCtx;
10243 pMonModeReq->callback = callback;
Katya Nigamf0511f62015-05-05 16:40:57 +053010244
Katya Nigamf0511f62015-05-05 16:40:57 +053010245 monMsg.reserved = 0;
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053010246 monMsg.bodyptr = pMonModeReq;
Katya Nigamf0511f62015-05-05 16:40:57 +053010247 monMsg.bodyval = 0;
10248
10249 if (VOS_STATUS_SUCCESS != vos_mq_post_message(
10250 VOS_MODULE_ID_WDA,(vos_msg_t *)&monMsg)) {
10251 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: : Failed to post Msg to HAL",__func__);
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053010252 vos_mem_free(pMonModeReq);
Katya Nigamf0511f62015-05-05 16:40:57 +053010253 }
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053010254 return VOS_STATUS_SUCCESS;
Katya Nigamf0511f62015-05-05 16:40:57 +053010255}
10256
Katya Nigame7b69a82015-04-28 15:24:06 +053010257void wlan_hdd_mon_close(hdd_context_t *pHddCtx)
10258{
10259 VOS_STATUS vosStatus;
10260 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053010261 long ret;
10262 hdd_mon_ctx_t *pMonCtx = NULL;
10263 v_U32_t magic;
10264 struct completion cmpVar;
Hanumantha Reddy Pothulac99bc062015-09-08 14:59:26 +053010265
Katya Nigame7b69a82015-04-28 15:24:06 +053010266 hdd_adapter_t *pAdapter = hdd_get_adapter(pHddCtx,WLAN_HDD_MONITOR);
10267 if(pAdapter == NULL || pVosContext == NULL)
10268 {
10269 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:pAdapter is NULL",__func__);
10270 return ;
10271 }
Katya Nigamf0511f62015-05-05 16:40:57 +053010272
Hanumantha Reddy Pothula91cdd7f2015-09-03 21:25:16 +053010273 pMonCtx = WLAN_HDD_GET_MONITOR_CTX_PTR(pAdapter);
10274 if (pMonCtx!= NULL && pMonCtx->state == MON_MODE_START) {
10275 pMonCtx->state = MON_MODE_STOP;
10276 magic = MON_MODE_MSG_MAGIC;
10277 init_completion(&cmpVar);
10278 if (VOS_STATUS_SUCCESS !=
10279 wlan_hdd_mon_postMsg(&magic, &cmpVar,
10280 pMonCtx, hdd_monPostMsgCb)) {
10281 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
10282 FL("failed to post MON MODE REQ"));
10283 pMonCtx->state = MON_MODE_START;
10284 magic = 0;
10285 return;
10286 }
10287 ret = wait_for_completion_timeout(&cmpVar, MON_MODE_MSG_TIMEOUT);
10288 magic = 0;
10289 if (ret <= 0 ) {
10290 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
10291 FL("timeout on monitor mode completion %ld"), ret);
10292 }
10293 }
10294
Katya Nigame7b69a82015-04-28 15:24:06 +053010295 hdd_UnregisterWext(pAdapter->dev);
10296
10297 vos_mon_stop( pVosContext );
10298
10299 vosStatus = vos_sched_close( pVosContext );
10300 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
10301 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
10302 "%s: Failed to close VOSS Scheduler",__func__);
10303 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
10304 }
10305
10306 vosStatus = vos_nv_close();
10307 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
10308 {
10309 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
10310 "%s: Failed to close NV", __func__);
10311 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
10312 }
10313
10314 vos_close(pVosContext);
10315
10316 #ifdef WLAN_KD_READY_NOTIFIER
10317 nl_srv_exit(pHddCtx->ptt_pid);
10318 #else
10319 nl_srv_exit();
10320 #endif
10321
Katya Nigame7b69a82015-04-28 15:24:06 +053010322 hdd_close_all_adapters( pHddCtx );
Katya Nigame7b69a82015-04-28 15:24:06 +053010323}
Agrawal Ashish33ec71e2015-11-26 20:20:58 +053010324/**
10325 * hdd_wlan_free_wiphy_channels - free Channel pointer for wiphy
10326 * @ wiphy: the wiphy to validate against
10327 *
10328 * Return: void
10329 */
10330void hdd_wlan_free_wiphy_channels(struct wiphy *wiphy)
10331{
10332 int i =0;
10333 for (i = 0; i < IEEE80211_NUM_BANDS; i++)
10334 {
10335 if (NULL != wiphy->bands[i] &&
10336 (NULL != wiphy->bands[i]->channels))
10337 {
10338 vos_mem_free(wiphy->bands[i]->channels);
10339 wiphy->bands[i]->channels = NULL;
10340 }
10341 }
10342}
Jeff Johnson295189b2012-06-20 16:38:30 -070010343/**---------------------------------------------------------------------------
10344
10345 \brief hdd_wlan_exit() - HDD WLAN exit function
10346
10347 This is the driver exit point (invoked during rmmod)
10348
10349 \param - pHddCtx - Pointer to the HDD Context
10350
10351 \return - None
10352
10353 --------------------------------------------------------------------------*/
10354void hdd_wlan_exit(hdd_context_t *pHddCtx)
10355{
10356 eHalStatus halStatus;
10357 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
10358 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +053010359 struct wiphy *wiphy = pHddCtx->wiphy;
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -080010360 hdd_adapter_t* pAdapter = NULL;
Jeff Johnson72a40512013-12-19 10:14:15 -080010361 struct statsContext powerContext;
Jeff Johnson295189b2012-06-20 16:38:30 -070010362 long lrc;
c_hpothu5ab05e92014-06-13 17:34:05 +053010363 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -070010364
10365 ENTER();
10366
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053010367
Katya Nigame7b69a82015-04-28 15:24:06 +053010368 if (VOS_MONITOR_MODE == hdd_get_conparam())
10369 {
10370 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: MONITOR MODE",__func__);
10371 wlan_hdd_mon_close(pHddCtx);
Hanumantha Reddy Pothulac99bc062015-09-08 14:59:26 +053010372 goto free_hdd_ctx;
Katya Nigame7b69a82015-04-28 15:24:06 +053010373 }
10374 else if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -080010375 {
10376 // Unloading, restart logic is no more required.
10377 wlan_hdd_restart_deinit(pHddCtx);
Jeff Johnsone7245742012-09-05 17:12:55 -070010378
Agarwal Ashishb20e0ff2014-12-17 22:50:19 +053010379#ifdef FEATURE_WLAN_TDLS
10380 /* At the time of driver unloading; if tdls connection is present;
10381 * hdd_rx_packet_cbk calls wlan_hdd_tdls_find_peer.
10382 * wlan_hdd_tdls_find_peer always checks for valid context;
10383 * as load/unload in progress there can be a race condition.
10384 * hdd_rx_packet_cbk calls wlan_hdd_tdls_find_peer only
10385 * when tdls state is enabled.
10386 * As soon as driver set load/unload flag; tdls flag also needs
10387 * to be disabled so that hdd_rx_packet_cbk won't call
10388 * wlan_hdd_tdls_find_peer.
10389 */
Masti, Narayanraddi20494af2015-12-17 20:56:42 +053010390 wlan_hdd_tdls_set_mode(pHddCtx, eTDLS_SUPPORT_DISABLED, FALSE,
10391 HDD_SET_TDLS_MODE_SOURCE_USER);
Agarwal Ashishb20e0ff2014-12-17 22:50:19 +053010392#endif
10393
c_hpothu5ab05e92014-06-13 17:34:05 +053010394 vosStatus = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10395 while (NULL != pAdapterNode && VOS_STATUS_E_EMPTY != vosStatus)
Jeff Johnson295189b2012-06-20 16:38:30 -070010396 {
c_hpothu5ab05e92014-06-13 17:34:05 +053010397 pAdapter = pAdapterNode->pAdapter;
10398 if (NULL != pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -070010399 {
Mahesh A Saptasagar305e2632015-03-04 12:57:33 +053010400 /* Disable TX on the interface, after this hard_start_xmit() will
10401 * not be called on that interface
10402 */
10403 hddLog(VOS_TRACE_LEVEL_INFO, FL("Disabling queues"));
10404 netif_tx_disable(pAdapter->dev);
10405
10406 /* Mark the interface status as "down" for outside world */
10407 netif_carrier_off(pAdapter->dev);
10408
Agarwal Ashish9ffa5b92014-11-18 21:07:02 +053010409 /* DeInit the adapter. This ensures that all data packets
10410 * are freed.
10411 */
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +053010412#ifdef FEATURE_WLAN_TDLS
10413 mutex_lock(&pHddCtx->tdls_lock);
10414#endif
c_hpothu002231a2015-02-05 14:58:51 +053010415 hdd_deinit_adapter(pHddCtx, pAdapter, FALSE);
Mahesh A Saptasagar02e36e82015-01-14 20:39:19 +053010416#ifdef FEATURE_WLAN_TDLS
10417 mutex_unlock(&pHddCtx->tdls_lock);
10418#endif
Masti, Narayanraddi26378462016-01-05 18:20:28 +053010419 vos_flush_delayed_work(&pHddCtx->scan_ctxt.scan_work);
10420
10421 wlan_hdd_init_deinit_defer_scan_context(&pHddCtx->scan_ctxt);
Agarwal Ashish9ffa5b92014-11-18 21:07:02 +053010422
c_hpothu5ab05e92014-06-13 17:34:05 +053010423 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode ||
10424 WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)
10425 {
10426 wlan_hdd_cfg80211_deregister_frames(pAdapter);
10427 hdd_UnregisterWext(pAdapter->dev);
10428 }
Kaushik, Sushant4975a572014-10-21 16:07:48 +053010429
Jeff Johnson295189b2012-06-20 16:38:30 -070010430 }
c_hpothu5ab05e92014-06-13 17:34:05 +053010431 vosStatus = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10432 pAdapterNode = pNext;
Jeff Johnson295189b2012-06-20 16:38:30 -070010433 }
mukul sharmabab477d2015-06-11 17:14:55 +053010434
Kaushik, Sushant4975a572014-10-21 16:07:48 +053010435 // Cancel any outstanding scan requests. We are about to close all
10436 // of our adapters, but an adapter structure is what SME passes back
10437 // to our callback function. Hence if there are any outstanding scan
10438 // requests then there is a race condition between when the adapter
10439 // is closed and when the callback is invoked.We try to resolve that
10440 // race condition here by canceling any outstanding scans before we
10441 // close the adapters.
10442 // Note that the scans may be cancelled in an asynchronous manner,
10443 // so ideally there needs to be some kind of synchronization. Rather
10444 // than introduce a new synchronization here, we will utilize the
10445 // fact that we are about to Request Full Power, and since that is
10446 // synchronized, the expectation is that by the time Request Full
10447 // Power has completed all scans will be cancelled.
10448 if (pHddCtx->scan_info.mScanPending)
10449 {
Hema Aparna Medicharlaf05f6cd2015-01-21 14:44:19 +053010450 if(NULL != pAdapter)
10451 {
10452 hddLog(VOS_TRACE_LEVEL_INFO,
10453 FL("abort scan mode: %d sessionId: %d"),
10454 pAdapter->device_mode,
10455 pAdapter->sessionId);
10456 }
10457 hdd_abort_mac_scan(pHddCtx,
10458 pHddCtx->scan_info.sessionId,
10459 eCSR_SCAN_ABORT_DEFAULT);
Kaushik, Sushant4975a572014-10-21 16:07:48 +053010460 }
Jeff Johnson295189b2012-06-20 16:38:30 -070010461 }
c_hpothu5ab05e92014-06-13 17:34:05 +053010462 else
Jeff Johnson88ba7742013-02-27 14:36:02 -080010463 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +053010464 hddLog(VOS_TRACE_LEVEL_INFO,"%s: FTM MODE",__func__);
Hanumantha Reddy Pothula45af96b2015-02-12 16:07:58 +053010465 if (pHddCtx->ftm.ftm_state == WLAN_FTM_STARTING)
10466 {
10467 INIT_COMPLETION(pHddCtx->ftm.startCmpVar);
10468 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
10469 "%s: in middle of FTM START", __func__);
10470 lrc = wait_for_completion_timeout(&pHddCtx->ftm.startCmpVar,
10471 msecs_to_jiffies(20000));
10472 if(!lrc)
10473 {
10474 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
10475 "%s: timedout on ftmStartCmpVar fatal error", __func__);
10476 }
10477 }
Jeff Johnson88ba7742013-02-27 14:36:02 -080010478 wlan_hdd_ftm_close(pHddCtx);
10479 goto free_hdd_ctx;
10480 }
c_hpothu6ff1c3c2013-10-01 19:01:57 +053010481
Jeff Johnson295189b2012-06-20 16:38:30 -070010482 /* DeRegister with platform driver as client for Suspend/Resume */
10483 vosStatus = hddDeregisterPmOps(pHddCtx);
10484 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
10485 {
10486 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
10487 VOS_ASSERT(0);
10488 }
10489
10490 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
10491 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
10492 {
10493 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
10494 }
Jeff Johnson295189b2012-06-20 16:38:30 -070010495
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -070010496 //Stop the traffic monitor timer
Mahesh A Saptasagard461e432016-07-20 15:01:40 +053010497 if ((pHddCtx->cfg_ini->dynSplitscan) && (VOS_TIMER_STATE_RUNNING ==
10498 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr)))
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -070010499 {
10500 vos_timer_stop(&pHddCtx->tx_rx_trafficTmr);
10501 }
10502
10503 // Destroy the traffic monitor timer
Mahesh A Saptasagard461e432016-07-20 15:01:40 +053010504 if ((pHddCtx->cfg_ini->dynSplitscan) &&
10505 (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
10506 &pHddCtx->tx_rx_trafficTmr))))
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -070010507 {
10508 hddLog(VOS_TRACE_LEVEL_ERROR,
10509 "%s: Cannot deallocate Traffic monitor timer", __func__);
10510 }
10511
Bhargav Shahd0715912015-10-01 18:17:37 +053010512 if (VOS_TIMER_STATE_RUNNING ==
10513 vos_timer_getCurrentState(&pHddCtx->delack_timer)) {
10514 vos_timer_stop(&pHddCtx->delack_timer);
10515 }
10516
10517 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
10518 &pHddCtx->delack_timer))) {
10519 hddLog(VOS_TRACE_LEVEL_ERROR,
10520 "%s: Cannot deallocate Bus bandwidth timer", __func__);
10521 }
10522
Masti, Narayanraddi44b0db02015-12-22 11:54:35 +053010523 if (VOS_TIMER_STATE_RUNNING ==
10524 vos_timer_getCurrentState(&pHddCtx->tdls_source_timer)) {
10525 vos_timer_stop(&pHddCtx->tdls_source_timer);
10526 }
10527
10528 vos_timer_destroy(&pHddCtx->tdls_source_timer);
10529
Jeff Johnson295189b2012-06-20 16:38:30 -070010530 //Disable IMPS/BMPS as we do not want the device to enter any power
10531 //save mode during shutdown
10532 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
10533 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
10534 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
10535
10536 //Ensure that device is in full power as we will touch H/W during vos_Stop
10537 init_completion(&powerContext.completion);
10538 powerContext.magic = POWER_CONTEXT_MAGIC;
10539
10540 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
10541 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
10542
10543 if (eHAL_STATUS_SUCCESS != halStatus)
10544 {
10545 if (eHAL_STATUS_PMC_PENDING == halStatus)
10546 {
10547 /* request was sent -- wait for the response */
10548 lrc = wait_for_completion_interruptible_timeout(
10549 &powerContext.completion,
10550 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
Jeff Johnson295189b2012-06-20 16:38:30 -070010551 if (lrc <= 0)
10552 {
10553 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070010554 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -070010555 }
10556 }
10557 else
10558 {
10559 hddLog(VOS_TRACE_LEVEL_ERROR,
10560 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070010561 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -070010562 /* continue -- need to clean up as much as possible */
10563 }
10564 }
Hanumantha Reddy Pothula81b42b22015-05-12 13:52:00 +053010565 if ((eHAL_STATUS_SUCCESS == halStatus) ||
10566 (eHAL_STATUS_PMC_PENDING == halStatus && lrc > 0))
10567 {
10568 /* This will issue a dump command which will clean up
10569 BTQM queues and unblock MC thread */
10570 vos_fwDumpReq(274, 0, 0, 0, 0, 1);
10571 }
Jeff Johnson295189b2012-06-20 16:38:30 -070010572
Jeff Johnson72a40512013-12-19 10:14:15 -080010573 /* either we never sent a request, we sent a request and received a
10574 response or we sent a request and timed out. if we never sent a
10575 request or if we sent a request and got a response, we want to
10576 clear the magic out of paranoia. if we timed out there is a
10577 race condition such that the callback function could be
10578 executing at the same time we are. of primary concern is if the
10579 callback function had already verified the "magic" but had not
10580 yet set the completion variable when a timeout occurred. we
10581 serialize these activities by invalidating the magic while
10582 holding a shared spinlock which will cause us to block if the
10583 callback is currently executing */
10584 spin_lock(&hdd_context_lock);
10585 powerContext.magic = 0;
10586 spin_unlock(&hdd_context_lock);
10587
Hema Aparna Medicharlaa6cf65e2015-06-01 16:23:28 +053010588 /* If Device is shutdown, no point for SME to wait for responses
10589 from device. Pre Close SME */
10590 if(wcnss_device_is_shutdown())
10591 {
10592 sme_PreClose(pHddCtx->hHal);
10593 }
Yue Ma0d4891e2013-08-06 17:01:45 -070010594 hdd_debugfs_exit(pHddCtx);
10595
Ratheesh S P35ed8b12015-04-27 14:01:07 +053010596#ifdef WLAN_NS_OFFLOAD
Ratheesh S P36dbc932015-08-07 14:28:57 +053010597 hddLog(LOG1, FL("Unregister IPv6 notifier"));
Ratheesh S P35ed8b12015-04-27 14:01:07 +053010598 unregister_inet6addr_notifier(&pHddCtx->ipv6_notifier);
10599#endif
Ratheesh S P36dbc932015-08-07 14:28:57 +053010600 hddLog(LOG1, FL("Unregister IPv4 notifier"));
Ratheesh S P35ed8b12015-04-27 14:01:07 +053010601 unregister_inetaddr_notifier(&pHddCtx->ipv4_notifier);
10602
Jeff Johnson295189b2012-06-20 16:38:30 -070010603 // Unregister the Net Device Notifier
10604 unregister_netdevice_notifier(&hdd_netdev_notifier);
10605
Jeff Johnson295189b2012-06-20 16:38:30 -070010606 hdd_stop_all_adapters( pHddCtx );
10607
Jeff Johnson295189b2012-06-20 16:38:30 -070010608#ifdef WLAN_BTAMP_FEATURE
10609 vosStatus = WLANBAP_Stop(pVosContext);
10610 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
10611 {
10612 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
10613 "%s: Failed to stop BAP",__func__);
10614 }
10615#endif //WLAN_BTAMP_FEATURE
10616
10617 //Stop all the modules
10618 vosStatus = vos_stop( pVosContext );
10619 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
10620 {
10621 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
10622 "%s: Failed to stop VOSS",__func__);
10623 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
Hanumantha Reddy Pothulabd9601a2016-02-12 13:22:27 +053010624 if (isSsrPanicOnFailure())
10625 VOS_BUG(0);
Jeff Johnson295189b2012-06-20 16:38:30 -070010626 }
10627
Jeff Johnson295189b2012-06-20 16:38:30 -070010628 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -070010629 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -070010630
10631 //Close the scheduler before calling vos_close to make sure no thread is
10632 // scheduled after the each module close is called i.e after all the data
10633 // structures are freed.
10634 vosStatus = vos_sched_close( pVosContext );
10635 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
10636 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
10637 "%s: Failed to close VOSS Scheduler",__func__);
10638 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
10639 }
Jeff Johnsone7245742012-09-05 17:12:55 -070010640#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
10641 /* Destroy the wake lock */
Sushant Kaushik83392fa2015-05-05 17:44:40 +053010642 vos_wake_lock_destroy(&pHddCtx->rx_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -070010643#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -080010644 /* Destroy the wake lock */
Sushant Kaushik83392fa2015-05-05 17:44:40 +053010645 vos_wake_lock_destroy(&pHddCtx->sap_wake_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070010646
Mihir Shete7a24b5f2013-12-21 12:18:31 +053010647#ifdef CONFIG_ENABLE_LINUX_REG
10648 vosStatus = vos_nv_close();
10649 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
10650 {
10651 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
10652 "%s: Failed to close NV", __func__);
10653 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
10654 }
10655#endif
10656
Jeff Johnson295189b2012-06-20 16:38:30 -070010657 //Close VOSS
10658 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
10659 vos_close(pVosContext);
10660
Jeff Johnson295189b2012-06-20 16:38:30 -070010661 //Close Watchdog
10662 if(pHddCtx->cfg_ini->fIsLogpEnabled)
10663 vos_watchdog_close(pVosContext);
10664
Gopichand Nakkalaa0358482013-06-12 17:05:47 +053010665 //Clean up HDD Nlink Service
10666 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Gopichand Nakkalaa0358482013-06-12 17:05:47 +053010667
Manjeet Singh47ee8472016-04-11 11:57:18 +053010668 hdd_close_tx_queues(pHddCtx);
c_manjeecfd1efb2015-09-25 19:32:34 +053010669 wlan_free_fwr_mem_dump_buffer();
10670 memdump_deinit();
10671
Vinay Krishna Erannad938c422014-03-10 17:14:21 +053010672#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +053010673 if (pHddCtx->cfg_ini->wlanLoggingEnable)
Vinay Krishna Erannad938c422014-03-10 17:14:21 +053010674 {
10675 wlan_logging_sock_deactivate_svc();
10676 }
10677#endif
10678
Vinay Krishna Erannaef30b522014-08-26 17:48:16 +053010679#ifdef WLAN_KD_READY_NOTIFIER
10680 nl_srv_exit(pHddCtx->ptt_pid);
10681#else
10682 nl_srv_exit();
10683#endif /* WLAN_KD_READY_NOTIFIER */
10684
Abhishek Singh00b71972016-01-07 10:51:04 +053010685#ifdef WLAN_FEATURE_RMC
10686 hdd_close_cesium_nl_sock();
10687#endif /* WLAN_FEATURE_RMC */
Vinay Krishna Erannaef30b522014-08-26 17:48:16 +053010688
Jeff Johnson295189b2012-06-20 16:38:30 -070010689 hdd_close_all_adapters( pHddCtx );
10690
Padma, Santhosh Kumar9cd38332015-11-17 12:18:10 +053010691 vos_flush_delayed_work(&pHddCtx->spoof_mac_addr_work);
10692
Hanumantha Reddy Pothula97f9bc92015-08-10 17:21:20 +053010693free_hdd_ctx:
Jeff Johnson295189b2012-06-20 16:38:30 -070010694 /* free the power on lock from platform driver */
10695 if (free_riva_power_on_lock("wlan"))
10696 {
10697 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
10698 __func__);
10699 }
10700
c_hpothu78c7b602014-05-17 17:35:49 +053010701 //Free up dynamically allocated members inside HDD Adapter
10702 if (pHddCtx->cfg_ini)
10703 {
10704 kfree(pHddCtx->cfg_ini);
10705 pHddCtx->cfg_ini= NULL;
10706 }
10707
Hanumantha Reddy Pothula6fe221c2016-01-28 15:01:09 +053010708 /* FTM/MONITOR mode, WIPHY did not registered
Leo Changf04ddad2013-09-18 13:46:38 -070010709 If un-register here, system crash will happen */
Hanumantha Reddy Pothula6fe221c2016-01-28 15:01:09 +053010710 if (!(VOS_FTM_MODE == hdd_get_conparam() ||
10711 VOS_MONITOR_MODE == hdd_get_conparam()))
Leo Changf04ddad2013-09-18 13:46:38 -070010712 {
10713 wiphy_unregister(wiphy) ;
Agrawal Ashish33ec71e2015-11-26 20:20:58 +053010714 hdd_wlan_free_wiphy_channels(wiphy);
Leo Changf04ddad2013-09-18 13:46:38 -070010715 }
Jeff Johnson295189b2012-06-20 16:38:30 -070010716 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -070010717 if (hdd_is_ssr_required())
10718 {
10719 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -070010720 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -070010721 msleep(5000);
10722 }
10723 hdd_set_ssr_required (VOS_FALSE);
10724}
10725
10726
10727/**---------------------------------------------------------------------------
10728
10729 \brief hdd_update_config_from_nv() - Function to update the contents of
10730 the running configuration with parameters taken from NV storage
10731
10732 \param - pHddCtx - Pointer to the HDD global context
10733
10734 \return - VOS_STATUS_SUCCESS if successful
10735
10736 --------------------------------------------------------------------------*/
10737static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
10738{
Jeff Johnson295189b2012-06-20 16:38:30 -070010739 v_BOOL_t itemIsValid = VOS_FALSE;
10740 VOS_STATUS status;
10741 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
10742 v_U8_t macLoop;
10743
10744 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
10745 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
10746 if(status != VOS_STATUS_SUCCESS)
10747 {
Arif Hussain6d2a3322013-11-17 19:50:10 -080010748 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed");
Jeff Johnson295189b2012-06-20 16:38:30 -070010749 return VOS_STATUS_E_FAILURE;
10750 }
10751
10752 if (itemIsValid == VOS_TRUE)
10753 {
Arif Hussain6d2a3322013-11-17 19:50:10 -080010754 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV");
Jeff Johnson295189b2012-06-20 16:38:30 -070010755 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
10756 VOS_MAX_CONCURRENCY_PERSONA);
10757 if(status != VOS_STATUS_SUCCESS)
10758 {
10759 /* Get MAC from NV fail, not update CFG info
10760 * INI MAC value will be used for MAC setting */
Arif Hussain6d2a3322013-11-17 19:50:10 -080010761 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed");
Jeff Johnson295189b2012-06-20 16:38:30 -070010762 return VOS_STATUS_E_FAILURE;
10763 }
10764
10765 /* If first MAC is not valid, treat all others are not valid
10766 * Then all MACs will be got from ini file */
10767 if(vos_is_macaddr_zero(&macFromNV[0]))
10768 {
10769 /* MAC address in NV file is not configured yet */
10770 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
10771 return VOS_STATUS_E_INVAL;
10772 }
10773
10774 /* Get MAC address from NV, update CFG info */
10775 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
10776 {
10777 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
10778 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +053010779 hddLog(VOS_TRACE_LEVEL_ERROR,"not valid MAC from NV for %d", macLoop);
Jeff Johnson295189b2012-06-20 16:38:30 -070010780 /* This MAC is not valid, skip it
10781 * This MAC will be got from ini file */
10782 }
10783 else
10784 {
10785 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
10786 (v_U8_t *)&macFromNV[macLoop].bytes[0],
10787 VOS_MAC_ADDR_SIZE);
10788 }
10789 }
10790 }
10791 else
10792 {
10793 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
10794 return VOS_STATUS_E_FAILURE;
10795 }
Jeff Johnson295189b2012-06-20 16:38:30 -070010796
Jeff Johnson295189b2012-06-20 16:38:30 -070010797
10798 return VOS_STATUS_SUCCESS;
10799}
10800
10801/**---------------------------------------------------------------------------
10802
10803 \brief hdd_post_voss_start_config() - HDD post voss start config helper
10804
10805 \param - pAdapter - Pointer to the HDD
10806
10807 \return - None
10808
10809 --------------------------------------------------------------------------*/
10810VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
10811{
10812 eHalStatus halStatus;
10813 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +053010814 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -070010815
Jeff Johnson295189b2012-06-20 16:38:30 -070010816
10817 // Send ready indication to the HDD. This will kick off the MAC
10818 // into a 'running' state and should kick off an initial scan.
10819 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
10820 if ( !HAL_STATUS_SUCCESS( halStatus ) )
10821 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +053010822 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -070010823 "code %08d [x%08x]",__func__, halStatus, halStatus );
10824 return VOS_STATUS_E_FAILURE;
10825 }
10826
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +053010827 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -070010828 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
10829 // And RIVA will crash
10830 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
10831 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +053010832 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
10833 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
10834
10835
Jeff Johnson295189b2012-06-20 16:38:30 -070010836 return VOS_STATUS_SUCCESS;
10837}
10838
Jeff Johnson295189b2012-06-20 16:38:30 -070010839/* wake lock APIs for HDD */
Sushant Kaushik83392fa2015-05-05 17:44:40 +053010840void hdd_prevent_suspend(uint32_t reason)
Jeff Johnson295189b2012-06-20 16:38:30 -070010841{
Sushant Kaushik83392fa2015-05-05 17:44:40 +053010842
10843 vos_wake_lock_acquire(&wlan_wake_lock, reason);
10844
Jeff Johnson295189b2012-06-20 16:38:30 -070010845}
10846
Sushant Kaushik83392fa2015-05-05 17:44:40 +053010847void hdd_allow_suspend(uint32_t reason)
Jeff Johnson295189b2012-06-20 16:38:30 -070010848{
Sushant Kaushik83392fa2015-05-05 17:44:40 +053010849
10850 vos_wake_lock_release(&wlan_wake_lock, reason);
10851
Jeff Johnson295189b2012-06-20 16:38:30 -070010852}
10853
Sushant Kaushik83392fa2015-05-05 17:44:40 +053010854void hdd_prevent_suspend_timeout(v_U32_t timeout, uint32_t reason)
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -070010855{
Sushant Kaushik83392fa2015-05-05 17:44:40 +053010856
10857 vos_wake_lock_timeout_release(&wlan_wake_lock, timeout,
10858 reason);
10859
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -070010860}
10861
Jeff Johnson295189b2012-06-20 16:38:30 -070010862/**---------------------------------------------------------------------------
10863
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070010864 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
10865 information between Host and Riva
10866
10867 This function gets reported version of FW
10868 It also finds the version of Riva headers used to compile the host
10869 It compares the above two and prints a warning if they are different
10870 It gets the SW and HW version string
10871 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
10872 indicating the features they support through a bitmap
10873
10874 \param - pHddCtx - Pointer to HDD context
10875
10876 \return - void
10877
10878 --------------------------------------------------------------------------*/
10879
10880void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
10881{
10882
10883 tSirVersionType versionCompiled;
10884 tSirVersionType versionReported;
10885 tSirVersionString versionString;
10886 tANI_U8 fwFeatCapsMsgSupported = 0;
10887 VOS_STATUS vstatus;
10888
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -080010889 memset(&versionCompiled, 0, sizeof(versionCompiled));
10890 memset(&versionReported, 0, sizeof(versionReported));
10891
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070010892 /* retrieve and display WCNSS version information */
10893 do {
10894
10895 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
10896 &versionCompiled);
10897 if (!VOS_IS_STATUS_SUCCESS(vstatus))
10898 {
10899 hddLog(VOS_TRACE_LEVEL_FATAL,
10900 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070010901 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070010902 break;
10903 }
10904
10905 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
10906 &versionReported);
10907 if (!VOS_IS_STATUS_SUCCESS(vstatus))
10908 {
10909 hddLog(VOS_TRACE_LEVEL_FATAL,
10910 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070010911 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070010912 break;
10913 }
10914
10915 if ((versionCompiled.major != versionReported.major) ||
10916 (versionCompiled.minor != versionReported.minor) ||
10917 (versionCompiled.version != versionReported.version) ||
10918 (versionCompiled.revision != versionReported.revision))
10919 {
10920 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
10921 "Host expected %u.%u.%u.%u\n",
10922 WLAN_MODULE_NAME,
10923 (int)versionReported.major,
10924 (int)versionReported.minor,
10925 (int)versionReported.version,
10926 (int)versionReported.revision,
10927 (int)versionCompiled.major,
10928 (int)versionCompiled.minor,
10929 (int)versionCompiled.version,
10930 (int)versionCompiled.revision);
10931 }
10932 else
10933 {
10934 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
10935 WLAN_MODULE_NAME,
10936 (int)versionReported.major,
10937 (int)versionReported.minor,
10938 (int)versionReported.version,
10939 (int)versionReported.revision);
10940 }
10941
10942 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
10943 versionString,
10944 sizeof(versionString));
10945 if (!VOS_IS_STATUS_SUCCESS(vstatus))
10946 {
10947 hddLog(VOS_TRACE_LEVEL_FATAL,
10948 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070010949 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070010950 break;
10951 }
10952
10953 pr_info("%s: WCNSS software version %s\n",
10954 WLAN_MODULE_NAME, versionString);
Sushant Kaushik084f6592015-09-10 13:11:56 +053010955 vos_mem_copy(pHddCtx->fw_Version, versionString, sizeof(versionString));
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070010956
10957 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
10958 versionString,
10959 sizeof(versionString));
10960 if (!VOS_IS_STATUS_SUCCESS(vstatus))
10961 {
10962 hddLog(VOS_TRACE_LEVEL_FATAL,
10963 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070010964 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070010965 break;
10966 }
10967
10968 pr_info("%s: WCNSS hardware version %s\n",
10969 WLAN_MODULE_NAME, versionString);
10970
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -070010971 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
10972 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070010973 send the message only if it the riva is 1.1
10974 minor numbers for different riva branches:
10975 0 -> (1.0)Mainline Build
10976 1 -> (1.1)Mainline Build
10977 2->(1.04) Stability Build
10978 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -070010979 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070010980 ((versionReported.minor>=1) && (versionReported.version>=1)))
10981 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
10982 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -070010983
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070010984 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -080010985 {
10986#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
10987 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
10988 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
10989#endif
Ravi Joshid2ca7c42013-07-23 08:37:49 -070010990 /* Indicate if IBSS heartbeat monitoring needs to be offloaded */
10991 if (!pHddCtx->cfg_ini->enableIbssHeartBeatOffload)
10992 {
10993 sme_disableFeatureCapablity(IBSS_HEARTBEAT_OFFLOAD);
10994 }
10995
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070010996 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -080010997 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070010998
10999 } while (0);
11000
11001}
Neelansh Mittaledafed22014-09-04 18:54:39 +053011002void wlan_hdd_send_svc_nlink_msg(int type, void *data, int len)
11003{
11004 struct sk_buff *skb;
11005 struct nlmsghdr *nlh;
11006 tAniMsgHdr *ani_hdr;
Hanumantha Reddy Pothulacf2c7ea2015-04-27 14:50:47 +053011007 int flags = GFP_KERNEL;
Bhargav shah23c94942015-10-13 12:48:35 +053011008 void *nl_data = NULL;
Neelansh Mittaledafed22014-09-04 18:54:39 +053011009
Hanumantha Reddy Pothulacf2c7ea2015-04-27 14:50:47 +053011010 if (in_interrupt() || irqs_disabled() || in_atomic())
11011 flags = GFP_ATOMIC;
11012
11013 skb = alloc_skb(NLMSG_SPACE(WLAN_NL_MAX_PAYLOAD), flags);
Neelansh Mittaledafed22014-09-04 18:54:39 +053011014
11015 if(skb == NULL) {
11016 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
11017 "%s: alloc_skb failed", __func__);
11018 return;
11019 }
11020
11021 nlh = (struct nlmsghdr *)skb->data;
11022 nlh->nlmsg_pid = 0; /* from kernel */
11023 nlh->nlmsg_flags = 0;
11024 nlh->nlmsg_seq = 0;
11025 nlh->nlmsg_type = WLAN_NL_MSG_SVC;
11026
11027 ani_hdr = NLMSG_DATA(nlh);
11028 ani_hdr->type = type;
11029
11030 switch(type) {
11031 case WLAN_SVC_SAP_RESTART_IND:
11032 ani_hdr->length = 0;
11033 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr)));
11034 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr)));
11035 break;
Bhargav Shahd0715912015-10-01 18:17:37 +053011036 case WLAN_SVC_WLAN_TP_IND:
11037 ani_hdr->length = len;
11038 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr)
11039 + len));
11040 nl_data = (char *)ani_hdr + sizeof(tAniMsgHdr);
11041 memcpy(nl_data, data, len);
11042 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + len));
11043 break;
Bhargav shah23c94942015-10-13 12:48:35 +053011044 case WLAN_MSG_RPS_ENABLE_IND:
11045 ani_hdr->length = len;
11046 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + len));
11047 nl_data = (char *)ani_hdr + sizeof(tAniMsgHdr);
11048 memcpy(nl_data, data, len);
11049 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + len));
11050 break;
Neelansh Mittaledafed22014-09-04 18:54:39 +053011051 default:
11052 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
11053 "Attempt to send unknown nlink message %d", type);
11054 kfree_skb(skb);
11055 return;
11056 }
11057
11058 nl_srv_bcast(skb);
11059
11060 return;
11061}
11062
Bhargav Shahd0715912015-10-01 18:17:37 +053011063/**
11064 * hdd_request_tcp_delack() - Find the Delack value based on RX packet
11065 * @pHddCtx: Valid Global HDD context pointer
11066 * @rx_packets: Number of RX packet in perticular time
11067 *
11068 * Based on the RX packet this function calculate next value of tcp delack.
11069 * This function compare rx packet value to high and low threshold limit.
11070 *
11071 * Return: void
11072 */
11073void hdd_request_tcp_delack(hdd_context_t *pHddCtx, uint64_t rx_packets)
11074{
11075 /* average of rx_packets and prev_rx is taken so that
11076 bus width doesnot fluctuate much */
11077 uint64_t temp_rx = (rx_packets + pHddCtx->prev_rx)/2;
11078 TP_IND_TYPE next_rx_level = pHddCtx->cur_rx_level;
Neelansh Mittaledafed22014-09-04 18:54:39 +053011079
Bhargav Shahd0715912015-10-01 18:17:37 +053011080 pHddCtx->prev_rx = rx_packets;
11081 if (temp_rx > pHddCtx->cfg_ini->tcpDelAckThresholdHigh)
11082 next_rx_level = TP_IND_HIGH;
11083 else if (temp_rx <= pHddCtx->cfg_ini->tcpDelAckThresholdLow)
11084 next_rx_level = TP_IND_LOW;
11085
11086 hdd_set_delack_value(pHddCtx, next_rx_level);
11087}
11088
11089#define HDD_BW_GET_DIFF(x, y) ((x) >= (y) ? (x) - (y) : (ULONG_MAX - (y) + (x)))
11090
11091/**
11092 * hdd_tcp_delack_compute_function() - get link status
11093 * @priv: Valid Global HDD context pointer
11094 *
11095 * This function find number of RX packet during timer life span.
11096 * It request tcp delack with number of RX packet and re-configure delack timer
11097 * for tcpDelAckComputeInterval timer interval.
11098 *
11099 * Return: void
11100 */
11101void hdd_tcp_delack_compute_function(void *priv)
11102{
11103 hdd_context_t *pHddCtx = (hdd_context_t *)priv;
11104 hdd_adapter_t *pAdapter = NULL;
11105 v_U32_t rx_packets = 0;
11106 hdd_adapter_list_node_t *pAdapterNode = NULL;
11107 VOS_STATUS status = 0;
11108
11109 for (status = hdd_get_front_adapter(pHddCtx, &pAdapterNode);
11110 NULL != pAdapterNode && VOS_STATUS_SUCCESS == status;
11111 status = hdd_get_next_adapter(pHddCtx, pAdapterNode, &pAdapterNode)) {
11112 if ((pAdapter = pAdapterNode->pAdapter) == NULL)
11113 continue;
11114
11115 rx_packets += HDD_BW_GET_DIFF(pAdapter->stats.rx_packets,
11116 pAdapter->prev_rx_packets);
11117 pAdapter->prev_rx_packets = pAdapter->stats.rx_packets;
11118 }
11119
11120 hdd_request_tcp_delack(pHddCtx, rx_packets);
11121
11122 vos_timer_start(&pHddCtx->delack_timer,
11123 pHddCtx->cfg_ini->tcpDelAckComputeInterval);
11124}
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070011125
11126/**---------------------------------------------------------------------------
11127
Gopichand Nakkalafce506f2013-07-03 23:55:16 +053011128 \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
11129
11130 \param - pHddCtx - Pointer to the hdd context
11131
11132 \return - true if hardware supports 5GHz
11133
11134 --------------------------------------------------------------------------*/
Vinay Krishna Erannafacf5e22014-02-24 13:16:25 +053011135boolean hdd_is_5g_supported(hdd_context_t * pHddCtx)
Gopichand Nakkalafce506f2013-07-03 23:55:16 +053011136{
11137 /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
11138 * then hardware support 5Ghz.
11139 */
11140 if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode())
11141 {
Ratheesh S P36dbc932015-08-07 14:28:57 +053011142 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware supports 5Ghz", __func__);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +053011143 return true;
11144 }
11145 else
11146 {
Ratheesh S P36dbc932015-08-07 14:28:57 +053011147 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware doesn't supports 5Ghz",
Gopichand Nakkalafce506f2013-07-03 23:55:16 +053011148 __func__);
11149 return false;
11150 }
11151}
11152
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053011153/**---------------------------------------------------------------------------
11154
11155 \brief hdd_generate_iface_mac_addr_auto() - HDD Mac Interface Auto
11156 generate function
11157
11158 This is generate the random mac address for WLAN interface
11159
11160 \param - pHddCtx - Pointer to HDD context
11161 idx - Start interface index to get auto
11162 generated mac addr.
11163 mac_addr - Mac address
11164
11165 \return - 0 for success, < 0 for failure
11166
11167 --------------------------------------------------------------------------*/
11168
11169static int hdd_generate_iface_mac_addr_auto(hdd_context_t *pHddCtx,
11170 int idx, v_MACADDR_t mac_addr)
11171{
11172 int i;
11173 unsigned int serialno;
11174 serialno = wcnss_get_serial_number();
11175
11176 if (0 != serialno)
11177 {
11178 /* MAC address has 3 bytes of OUI so we have a maximum of 3
11179 bytes of the serial number that can be used to generate
11180 the other 3 bytes of the MAC address. Mask off all but
11181 the lower 3 bytes (this will also make sure we don't
11182 overflow in the next step) */
11183 serialno &= 0x00FFFFFF;
11184
11185 /* we need a unique address for each session */
11186 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
11187
11188 /* autogen other Mac addresses */
11189 for (i = idx; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
11190 {
11191 /* start with the entire default address */
11192 pHddCtx->cfg_ini->intfMacAddr[i] = mac_addr;
11193 /* then replace the lower 3 bytes */
11194 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
11195 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
11196 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
11197
11198 serialno++;
11199 hddLog(VOS_TRACE_LEVEL_ERROR,
11200 "%s: Derived Mac Addr: "
11201 MAC_ADDRESS_STR, __func__,
11202 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[i].bytes));
11203 }
11204
11205 }
11206 else
11207 {
11208 hddLog(LOGE, FL("Failed to Get Serial NO"));
11209 return -1;
11210 }
11211 return 0;
11212}
Gopichand Nakkalafce506f2013-07-03 23:55:16 +053011213
Katya Nigame7b69a82015-04-28 15:24:06 +053011214int wlan_hdd_mon_open(hdd_context_t *pHddCtx)
11215{
11216 VOS_STATUS status;
11217 v_CONTEXT_t pVosContext= NULL;
11218 hdd_adapter_t *pAdapter= NULL;
11219
11220 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
11221
11222 if (NULL == pVosContext)
11223 {
11224 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
11225 "%s: Trying to open VOSS without a PreOpen", __func__);
11226 VOS_ASSERT(0);
11227 return VOS_STATUS_E_FAILURE;
11228 }
11229
11230 status = vos_nv_open();
11231 if (!VOS_IS_STATUS_SUCCESS(status))
11232 {
11233 /* NV module cannot be initialized */
11234 hddLog( VOS_TRACE_LEVEL_FATAL,
11235 "%s: vos_nv_open failed", __func__);
11236 return VOS_STATUS_E_FAILURE;
11237 }
11238
11239 status = vos_init_wiphy_from_nv_bin();
11240 if (!VOS_IS_STATUS_SUCCESS(status))
11241 {
11242 /* NV module cannot be initialized */
11243 hddLog( VOS_TRACE_LEVEL_FATAL,
11244 "%s: vos_init_wiphy failed", __func__);
11245 goto err_vos_nv_close;
11246 }
11247
11248 status = vos_open( &pVosContext, pHddCtx->parent_dev);
11249 if ( !VOS_IS_STATUS_SUCCESS( status ))
11250 {
11251 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
11252 goto err_vos_nv_close;
11253 }
11254
11255 status = vos_mon_start( pVosContext );
11256 if ( !VOS_IS_STATUS_SUCCESS( status ) )
11257 {
11258 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
11259 goto err_vosclose;
11260 }
11261
11262 WLANTL_SetMonRxCbk( pVosContext, hdd_rx_packet_monitor_cbk );
11263 WDA_featureCapsExchange(pVosContext);
11264 wcnss_wlan_set_drvdata(pHddCtx->parent_dev, pHddCtx);
11265
11266 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_MONITOR, "wlan%d",
11267 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
11268 if( pAdapter == NULL )
11269 {
11270 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
11271 goto err_close_adapter;
11272 }
11273
11274 //Initialize the nlink service
11275 if(nl_srv_init() != 0)
11276 {
11277 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
11278 goto err_close_adapter;
11279 }
11280 return VOS_STATUS_SUCCESS;
11281
11282err_close_adapter:
11283 hdd_close_all_adapters( pHddCtx );
11284 vos_mon_stop( pVosContext );
11285err_vosclose:
11286 status = vos_sched_close( pVosContext );
11287 if (!VOS_IS_STATUS_SUCCESS(status)) {
11288 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
11289 "%s: Failed to close VOSS Scheduler", __func__);
11290 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
11291 }
11292 vos_close(pVosContext );
11293
11294err_vos_nv_close:
11295 vos_nv_close();
11296
11297return status;
11298}
Gopichand Nakkalafce506f2013-07-03 23:55:16 +053011299/**---------------------------------------------------------------------------
11300
Mihir Shetefc7ff5b2014-01-27 11:30:05 +053011301 \brief hdd_11d_scan_done - callback to be executed when 11d scan is
11302 completed to flush out the scan results
11303
11304 11d scan is done during driver load and is a passive scan on all
11305 channels supported by the device, 11d scans may find some APs on
11306 frequencies which are forbidden to be used in the regulatory domain
11307 the device is operating in. If these APs are notified to the supplicant
11308 it may try to connect to these APs, thus flush out all the scan results
11309 which are present in SME after 11d scan is done.
11310
11311 \return - eHalStatus
11312
11313 --------------------------------------------------------------------------*/
11314static eHalStatus hdd_11d_scan_done(tHalHandle halHandle, void *pContext,
11315 tANI_U32 scanId, eCsrScanStatus status)
11316{
11317 ENTER();
11318
11319 sme_ScanFlushResult(halHandle, 0);
11320
11321 EXIT();
11322
11323 return eHAL_STATUS_SUCCESS;
11324}
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011325/**---------------------------------------------------------------------------
11326
11327 \brief hdd_init_frame_logging_done - callback to be executed when mgmt frame
11328 logging is completed successfully.
11329
11330 \return - None
11331
11332 --------------------------------------------------------------------------*/
c_manjeecfd1efb2015-09-25 19:32:34 +053011333void hdd_init_frame_logging_done(void *fwlogInitCbContext, tAniLoggingInitRsp *pRsp)
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011334{
Siddharth Bhald1be97f2015-05-27 22:39:59 +053011335 hdd_context_t* pHddCtx = (hdd_context_t*)fwlogInitCbContext;
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011336
11337 if (NULL == pHddCtx)
11338 {
11339 hddLog(VOS_TRACE_LEVEL_ERROR,
11340 "%s: HDD context is NULL",__func__);
11341 return;
11342 }
11343
c_manjeecfd1efb2015-09-25 19:32:34 +053011344 if ((pRsp->status == VOS_STATUS_SUCCESS) &&
Mahesh A Saptasagarfabb1a02015-06-29 12:17:04 +053011345 (TRUE == pHddCtx->cfg_ini->enableMgmtLogging))
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011346 {
11347 hddLog(VOS_TRACE_LEVEL_INFO, FL("Mgmt Frame Logging init successful"));
11348 pHddCtx->mgmt_frame_logging = TRUE;
11349 }
11350 else
11351 {
11352 hddLog(VOS_TRACE_LEVEL_INFO, FL("Mgmt Frame Logging init not success"));
11353 pHddCtx->mgmt_frame_logging = FALSE;
c_manjeecfd1efb2015-09-25 19:32:34 +053011354 return;
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011355 }
11356
c_manjeecfd1efb2015-09-25 19:32:34 +053011357 /*Check feature supported by FW*/
11358 if(TRUE == sme_IsFeatureSupportedByFW(MEMORY_DUMP_SUPPORTED))
11359 {
11360 //Store fwr mem dump size given by firmware.
11361 wlan_store_fwr_mem_dump_size(pRsp->fw_mem_dump_max_size);
11362 }
11363 else
11364 {
11365 wlan_store_fwr_mem_dump_size(0);
11366 }
11367
11368
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011369}
11370/**---------------------------------------------------------------------------
11371
11372 \brief hdd_init_frame_logging - function to initialize frame logging.
11373 Currently only Mgmt Frames are logged in both TX
11374 and Rx direction and are sent to userspace
11375 application using logger thread when queried.
11376
11377 \return - None
11378
11379 --------------------------------------------------------------------------*/
Siddharth Bhald1be97f2015-05-27 22:39:59 +053011380void hdd_init_frame_logging(hdd_context_t* pHddCtx)
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011381{
11382 eHalStatus halStatus = eHAL_STATUS_FAILURE;
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053011383 tSirFWLoggingInitParam wlanFWLoggingInitParam = {0};
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011384
Siddharth Bhald1be97f2015-05-27 22:39:59 +053011385 if (TRUE != sme_IsFeatureSupportedByFW(MGMT_FRAME_LOGGING) &&
11386 TRUE != sme_IsFeatureSupportedByFW(LOGGING_ENHANCEMENT))
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011387 {
11388 hddLog(VOS_TRACE_LEVEL_INFO, FL("MGMT_FRAME_LOGGING not supp by FW"));
11389 return;
11390 }
11391
c_manjeecfd1efb2015-09-25 19:32:34 +053011392 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Configuring %s %s %s %s Logging",__func__,
Siddharth Bhald1be97f2015-05-27 22:39:59 +053011393 pHddCtx->cfg_ini->enableFWLogging?"FW Log,":"",
11394 pHddCtx->cfg_ini->enableContFWLogging ? "Cont FW log,":"",
c_manjeecfd1efb2015-09-25 19:32:34 +053011395 pHddCtx->cfg_ini->enableMgmtLogging ? "Mgmt Pkt Log":"",
11396 pHddCtx->cfg_ini->enableFwrMemDump ? "Fw Mem dump":"");
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011397
Siddharth Bhald1be97f2015-05-27 22:39:59 +053011398 if (pHddCtx->cfg_ini->enableFWLogging ||
11399 pHddCtx->cfg_ini->enableContFWLogging)
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011400 {
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053011401 wlanFWLoggingInitParam.enableFlag |= WLAN_QXDM_LOG_EN;
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011402 }
11403
Sushant Kaushik46804902015-07-08 14:46:03 +053011404 if (pHddCtx->cfg_ini->enableMgmtLogging)
11405 {
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053011406 wlanFWLoggingInitParam.enableFlag |= WLAN_FRAME_LOG_EN;
Sushant Kaushik46804902015-07-08 14:46:03 +053011407 }
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011408 if (pHddCtx->cfg_ini->enableBMUHWtracing)
11409 {
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053011410 wlanFWLoggingInitParam.enableFlag |= WLAN_BMUHW_TRACE_LOG_EN;
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011411 }
c_manjeecfd1efb2015-09-25 19:32:34 +053011412 if(pHddCtx->cfg_ini->enableFwrMemDump &&
11413 (TRUE == sme_IsFeatureSupportedByFW(MEMORY_DUMP_SUPPORTED)))
11414 {
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053011415 wlanFWLoggingInitParam.enableFlag |= WLAN_FW_MEM_DUMP_EN;
c_manjeecfd1efb2015-09-25 19:32:34 +053011416 }
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053011417 if( wlanFWLoggingInitParam.enableFlag == 0 )
c_manjeecfd1efb2015-09-25 19:32:34 +053011418 {
11419 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Logging not enabled", __func__);
11420 return;
11421 }
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053011422 wlanFWLoggingInitParam.frameType = WLAN_FRAME_LOGGING_FRAMETYPE_MGMT;
11423 wlanFWLoggingInitParam.frameSize = WLAN_MGMT_LOGGING_FRAMESIZE_128BYTES;
11424 wlanFWLoggingInitParam.bufferMode = WLAN_FRAME_LOGGING_BUFFERMODE_CIRCULAR;
11425 wlanFWLoggingInitParam.continuousFrameLogging =
Siddharth Bhald1be97f2015-05-27 22:39:59 +053011426 pHddCtx->cfg_ini->enableContFWLogging;
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011427
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053011428 wlanFWLoggingInitParam.enableFlag &= ~WLAN_DPU_TXP_LOG_EN;
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011429
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053011430 wlanFWLoggingInitParam.minLogBufferSize =
Siddharth Bhald1be97f2015-05-27 22:39:59 +053011431 pHddCtx->cfg_ini->minLoggingBufferSize;
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053011432 wlanFWLoggingInitParam.maxLogBufferSize =
Siddharth Bhald1be97f2015-05-27 22:39:59 +053011433 pHddCtx->cfg_ini->maxLoggingBufferSize;
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053011434 wlanFWLoggingInitParam.fwlogInitCallback = hdd_init_frame_logging_done;
11435 wlanFWLoggingInitParam.fwlogInitCbContext= pHddCtx;
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011436
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053011437 halStatus = sme_InitMgmtFrameLogging(pHddCtx->hHal, &wlanFWLoggingInitParam);
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011438
11439 if (eHAL_STATUS_SUCCESS != halStatus)
11440 {
Sreelakshmi Konamkid8784d92016-04-14 14:59:13 +053011441 hddLog(LOGE, FL("sme_InitMgmtFrameLogging failed, returned %d"),
11442 halStatus);
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053011443 }
11444
11445 return;
11446}
Mihir Shetefc7ff5b2014-01-27 11:30:05 +053011447
Bhargav shah23c94942015-10-13 12:48:35 +053011448static void hdd_dp_util_send_rps_ind(hdd_context_t *hdd_ctxt)
11449{
11450 hdd_adapter_t *adapter;
11451 hdd_adapter_list_node_t *adapter_node, *next;
11452 VOS_STATUS status = VOS_STATUS_SUCCESS;
11453 struct wlan_rps_data rps_data;
11454 int count;
11455
11456 if(!hdd_ctxt->cfg_ini->rps_mask)
11457 {
11458 return;
11459 }
11460
11461 for (count=0; count < WLAN_SVC_IFACE_NUM_QUEUES; count++)
11462 {
11463 rps_data.cpu_map[count] = hdd_ctxt->cfg_ini->rps_mask;
11464 }
11465
11466 rps_data.num_queues = WLAN_SVC_IFACE_NUM_QUEUES;
11467
11468 hddLog(LOG1, FL("0x%x 0x%x 0x%x 0x%x 0x%x 0x%x"),
11469 rps_data.cpu_map[0], rps_data.cpu_map[1],rps_data.cpu_map[2],
11470 rps_data.cpu_map[3], rps_data.cpu_map[4], rps_data.cpu_map[5]);
11471
11472 status = hdd_get_front_adapter (hdd_ctxt, &adapter_node);
11473
11474 while (NULL != adapter_node && VOS_STATUS_SUCCESS == status)
11475 {
11476 adapter = adapter_node->pAdapter;
11477 if (NULL != adapter) {
11478 strlcpy(rps_data.ifname, adapter->dev->name,
11479 sizeof(rps_data.ifname));
11480 wlan_hdd_send_svc_nlink_msg(WLAN_MSG_RPS_ENABLE_IND,
11481 (void *)&rps_data,sizeof(rps_data));
11482 }
11483 status = hdd_get_next_adapter (hdd_ctxt, adapter_node, &next);
11484 adapter_node = next;
11485 }
11486}
11487
Masti, Narayanraddi26378462016-01-05 18:20:28 +053011488void wlan_hdd_schedule_defer_scan(struct work_struct *work)
11489{
11490 scan_context_t *scan_ctx =
11491 container_of(work, scan_context_t, scan_work.work);
11492
11493 if (NULL == scan_ctx)
11494 {
11495 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
11496 FL("scan_ctx is NULL"));
11497 return;
11498 }
11499
11500 if (unlikely(TDLS_CTX_MAGIC != scan_ctx->magic))
11501 return;
11502
11503 scan_ctx->attempt++;
11504
11505 wlan_hdd_cfg80211_scan(scan_ctx->wiphy,
11506#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
11507 scan_ctx->dev,
11508#endif
11509 scan_ctx->scan_request);
11510}
11511
11512int wlan_hdd_copy_defer_scan_context(hdd_context_t *pHddCtx,
11513 struct wiphy *wiphy,
11514#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
11515 struct net_device *dev,
11516#endif
11517 struct cfg80211_scan_request *request)
11518{
11519 scan_context_t *scan_ctx;
11520
11521 ENTER();
11522 if (0 != (wlan_hdd_validate_context(pHddCtx)))
11523 {
11524 return -1;
11525 }
11526
11527 scan_ctx = &pHddCtx->scan_ctxt;
11528
11529 scan_ctx->wiphy = wiphy;
11530#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
11531 scan_ctx->dev = dev;
11532#endif
11533
11534 scan_ctx->scan_request = request;
11535
11536 EXIT();
11537 return 0;
11538}
11539
11540void wlan_hdd_defer_scan_init_work(hdd_context_t *pHddCtx,
11541 struct wiphy *wiphy,
11542#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
11543 struct net_device *dev,
11544#endif
11545 struct cfg80211_scan_request *request,
11546 unsigned long delay)
11547{
11548 if (TDLS_CTX_MAGIC != pHddCtx->scan_ctxt.magic)
11549 {
11550#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))
11551 wlan_hdd_copy_defer_scan_context(pHddCtx, wiphy, dev, request);
11552#else
11553 wlan_hdd_copy_defer_scan_context(pHddCtx, wiphy, request);
11554#endif
11555 pHddCtx->scan_ctxt.attempt = 0;
11556 pHddCtx->scan_ctxt.magic = TDLS_CTX_MAGIC;
11557 }
11558 schedule_delayed_work(&pHddCtx->scan_ctxt.scan_work, delay);
11559}
11560
11561void wlan_hdd_init_deinit_defer_scan_context(scan_context_t *scan_ctx)
11562{
11563 scan_ctx->magic = 0;
11564 scan_ctx->attempt = 0;
11565 scan_ctx->reject = 0;
11566 scan_ctx->scan_request = NULL;
11567
11568 return;
11569}
11570
Mihir Shetefc7ff5b2014-01-27 11:30:05 +053011571/**---------------------------------------------------------------------------
11572
Jeff Johnson295189b2012-06-20 16:38:30 -070011573 \brief hdd_wlan_startup() - HDD init function
11574
11575 This is the driver startup code executed once a WLAN device has been detected
11576
11577 \param - dev - Pointer to the underlying device
11578
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -080011579 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -070011580
11581 --------------------------------------------------------------------------*/
11582
11583int hdd_wlan_startup(struct device *dev )
11584{
11585 VOS_STATUS status;
11586 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -070011587 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -070011588 hdd_context_t *pHddCtx = NULL;
11589 v_CONTEXT_t pVosContext= NULL;
11590#ifdef WLAN_BTAMP_FEATURE
11591 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
11592 WLANBAP_ConfigType btAmpConfig;
11593 hdd_config_t *pConfig;
11594#endif
11595 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -070011596 struct wiphy *wiphy;
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053011597 v_MACADDR_t mac_addr;
Jeff Johnson295189b2012-06-20 16:38:30 -070011598
11599 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -070011600 /*
11601 * cfg80211: wiphy allocation
11602 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +053011603 wiphy = wlan_hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t)) ;
Jeff Johnson295189b2012-06-20 16:38:30 -070011604
11605 if(wiphy == NULL)
11606 {
11607 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -080011608 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -070011609 }
Jeff Johnson295189b2012-06-20 16:38:30 -070011610 pHddCtx = wiphy_priv(wiphy);
11611
Jeff Johnson295189b2012-06-20 16:38:30 -070011612 //Initialize the adapter context to zeros.
11613 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
11614
Jeff Johnson295189b2012-06-20 16:38:30 -070011615 pHddCtx->wiphy = wiphy;
Sushant Kaushik83392fa2015-05-05 17:44:40 +053011616 hdd_prevent_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_INIT);
Mihir Shete18156292014-03-11 15:38:30 +053011617 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_LOAD_IN_PROGRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -070011618
11619 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
11620
Siddharth Bhalcd92b782015-06-29 12:25:40 +053011621 /* register for riva power on lock to platform driver
11622 * Locking power early to ensure FW doesn't reset by kernel while
11623 * host driver is busy initializing itself */
11624 if (req_riva_power_on_lock("wlan"))
11625 {
11626 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
11627 __func__);
11628 goto err_free_hdd_context;
11629 }
11630
Jeff Johnson295189b2012-06-20 16:38:30 -070011631 /*Get vos context here bcoz vos_open requires it*/
11632 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
11633
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -080011634 if(pVosContext == NULL)
11635 {
11636 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
11637 goto err_free_hdd_context;
11638 }
11639
Jeff Johnson295189b2012-06-20 16:38:30 -070011640 //Save the Global VOSS context in adapter context for future.
11641 pHddCtx->pvosContext = pVosContext;
11642
11643 //Save the adapter context in global context for future.
11644 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
11645
Jeff Johnson295189b2012-06-20 16:38:30 -070011646 pHddCtx->parent_dev = dev;
Sreelakshmi Konamkif0646d52016-12-09 12:35:31 +053011647 pHddCtx->last_scan_reject_session_id = 0xFF;
11648 pHddCtx->last_scan_reject_reason = 0;
Sreelakshmi Konamki20ebed92016-10-27 12:13:30 +053011649 pHddCtx->last_scan_reject_timestamp = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -070011650
11651 init_completion(&pHddCtx->full_pwr_comp_var);
11652 init_completion(&pHddCtx->standby_comp_var);
11653 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -070011654 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -080011655 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Kiet Lam46b8e4e2013-11-06 21:49:53 +053011656 init_completion(&pHddCtx->wiphy_channel_update_event);
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +053011657 init_completion(&pHddCtx->ssr_comp_var);
Mahesh A Saptasagar67ab9222015-10-21 15:38:41 +053011658 init_completion(&pHddCtx->mc_sus_event_var);
11659 init_completion(&pHddCtx->tx_sus_event_var);
11660 init_completion(&pHddCtx->rx_sus_event_var);
11661
Amar Singhala49cbc52013-10-08 18:37:44 -070011662
mukul sharma4bd8d2e2015-08-13 20:33:25 +053011663 hdd_init_ll_stats_ctx(pHddCtx);
11664
Amar Singhala49cbc52013-10-08 18:37:44 -070011665#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhalfddc28c2013-09-05 13:03:40 -070011666 init_completion(&pHddCtx->linux_reg_req);
Amar Singhala49cbc52013-10-08 18:37:44 -070011667#else
11668 init_completion(&pHddCtx->driver_crda_req);
11669#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070011670
Padma, Santhosh Kumara1aa4a32015-06-19 19:00:46 +053011671#ifdef WLAN_FEATURE_EXTSCAN
11672 init_completion(&pHddCtx->ext_scan_context.response_event);
11673#endif /* WLAN_FEATURE_EXTSCAN */
11674
Kamath Vinayak4000c9a2013-08-23 14:24:27 +053011675 spin_lock_init(&pHddCtx->schedScan_lock);
11676
Jeff Johnson295189b2012-06-20 16:38:30 -070011677 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
11678
Padma, Santhosh Kumar9cd38332015-11-17 12:18:10 +053011679 vos_init_delayed_work(&pHddCtx->spoof_mac_addr_work,
11680 hdd_processSpoofMacAddrRequest);
11681
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +053011682#ifdef FEATURE_WLAN_TDLS
11683 /* tdls_lock is initialized before an hdd_open_adapter ( which is
11684 * invoked by other instances also) to protect the concurrent
11685 * access for the Adapters by TDLS module.
11686 */
11687 mutex_init(&pHddCtx->tdls_lock);
11688#endif
Siddharth Bhal76972212014-10-15 16:22:51 +053011689 mutex_init(&pHddCtx->spoofMacAddr.macSpoofingLock);
Mukul Sharma1fd6efd2015-02-14 00:29:14 +053011690 mutex_init(&pHddCtx->wmmLock);
11691
Srinivas Girigowda8bf64cb2015-09-30 19:50:09 +053011692 hdd_init_offloaded_packets_ctx(pHddCtx);
Agarwal Ashish1f422872014-07-22 00:11:55 +053011693 /* By default Strict Regulatory For FCC should be false */
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +053011694
Agarwal Ashish1f422872014-07-22 00:11:55 +053011695 pHddCtx->nEnableStrictRegulatoryForFCC = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -070011696 // Load all config first as TL config is needed during vos_open
11697 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
11698 if(pHddCtx->cfg_ini == NULL)
11699 {
11700 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
11701 goto err_free_hdd_context;
11702 }
11703
11704 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
11705
11706 // Read and parse the qcom_cfg.ini file
11707 status = hdd_parse_config_ini( pHddCtx );
11708 if ( VOS_STATUS_SUCCESS != status )
11709 {
11710 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
11711 __func__, WLAN_INI_FILE);
11712 goto err_config;
11713 }
Arif Hussaind5218912013-12-05 01:10:55 -080011714#ifdef MEMORY_DEBUG
11715 if (pHddCtx->cfg_ini->IsMemoryDebugSupportEnabled)
11716 vos_mem_init();
11717
11718 hddLog(VOS_TRACE_LEVEL_INFO, "%s: gEnableMemoryDebug=%d",
11719 __func__, pHddCtx->cfg_ini->IsMemoryDebugSupportEnabled);
11720#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070011721
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +053011722 /* INI has been read, initialise the configuredMcastBcastFilter with
11723 * INI value as this will serve as the default value
11724 */
11725 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
11726 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
11727 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +053011728
11729 if (false == hdd_is_5g_supported(pHddCtx))
11730 {
11731 //5Ghz is not supported.
11732 if (1 != pHddCtx->cfg_ini->nBandCapability)
11733 {
11734 hddLog(VOS_TRACE_LEVEL_INFO,
11735 "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__);
11736 pHddCtx->cfg_ini->nBandCapability = 1;
11737 }
11738 }
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +053011739
11740 /* If SNR Monitoring is enabled, FW has to parse all beacons
11741 * for calcaluting and storing the average SNR, so set Nth beacon
11742 * filter to 1 to enable FW to parse all the beaocons
11743 */
11744 if (1 == pHddCtx->cfg_ini->fEnableSNRMonitoring)
11745 {
11746 /* The log level is deliberately set to WARN as overriding
11747 * nthBeaconFilter to 1 will increase power cosumption and this
11748 * might just prove helpful to detect the power issue.
11749 */
11750 hddLog(VOS_TRACE_LEVEL_WARN,
11751 "%s: Setting pHddCtx->cfg_ini->nthBeaconFilter = 1", __func__);
11752 pHddCtx->cfg_ini->nthBeaconFilter = 1;
11753 }
Jeff Johnson295189b2012-06-20 16:38:30 -070011754 /*
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +053011755 * cfg80211: Initialization ...
Jeff Johnson295189b2012-06-20 16:38:30 -070011756 */
Manjeet Singh61016fa2016-12-02 11:10:19 +053011757 if (0 < wlan_hdd_cfg80211_init(dev, wiphy, pHddCtx->cfg_ini))
Jeff Johnson295189b2012-06-20 16:38:30 -070011758 {
Manjeet Singh61016fa2016-12-02 11:10:19 +053011759 hddLog(VOS_TRACE_LEVEL_FATAL,
11760 "%s: wlan_hdd_cfg80211_init return failure", __func__);
11761 goto err_config;
Jeff Johnson295189b2012-06-20 16:38:30 -070011762 }
Jeff Johnson295189b2012-06-20 16:38:30 -070011763
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -080011764 // Update VOS trace levels based upon the cfg.ini
11765 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
11766 pHddCtx->cfg_ini->vosTraceEnableBAP);
11767 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
11768 pHddCtx->cfg_ini->vosTraceEnableTL);
11769 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
11770 pHddCtx->cfg_ini->vosTraceEnableWDI);
11771 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
11772 pHddCtx->cfg_ini->vosTraceEnableHDD);
11773 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
11774 pHddCtx->cfg_ini->vosTraceEnableSME);
11775 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
11776 pHddCtx->cfg_ini->vosTraceEnablePE);
Katya Nigam70d68332013-09-16 16:49:45 +053011777 hdd_vos_trace_enable(VOS_MODULE_ID_PMC,
11778 pHddCtx->cfg_ini->vosTraceEnablePMC);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -080011779 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
11780 pHddCtx->cfg_ini->vosTraceEnableWDA);
11781 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
11782 pHddCtx->cfg_ini->vosTraceEnableSYS);
11783 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
11784 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -080011785 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
11786 pHddCtx->cfg_ini->vosTraceEnableSAP);
11787 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
11788 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -080011789
Jeff Johnson295189b2012-06-20 16:38:30 -070011790 // Update WDI trace levels based upon the cfg.ini
11791 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
11792 pHddCtx->cfg_ini->wdiTraceEnableDAL);
11793 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
11794 pHddCtx->cfg_ini->wdiTraceEnableCTL);
11795 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
11796 pHddCtx->cfg_ini->wdiTraceEnableDAT);
11797 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
11798 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -070011799
Jeff Johnson88ba7742013-02-27 14:36:02 -080011800 if (VOS_FTM_MODE == hdd_get_conparam())
11801 {
Jeff Johnson295189b2012-06-20 16:38:30 -070011802 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
11803 {
11804 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
11805 goto err_free_hdd_context;
11806 }
11807 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
Sachin Ahuja38ef5e02015-03-13 17:31:16 +053011808 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_NO_LOAD_UNLOAD_IN_PROGRESS;
c_hpothu2de0ef62014-04-15 16:16:15 +053011809 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -070011810 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -080011811 }
Jeff Johnson295189b2012-06-20 16:38:30 -070011812
Katya Nigame7b69a82015-04-28 15:24:06 +053011813 if( VOS_MONITOR_MODE == hdd_get_conparam())
11814 {
11815 if ( VOS_STATUS_SUCCESS != wlan_hdd_mon_open(pHddCtx))
11816 {
11817 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_mon_open Failed",__func__);
11818 goto err_free_hdd_context;
11819 }
11820 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Driver loaded in Monitor Mode",__func__);
11821 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_NO_LOAD_UNLOAD_IN_PROGRESS;
11822 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
11823 return VOS_STATUS_SUCCESS;
11824 }
11825
Jeff Johnson88ba7742013-02-27 14:36:02 -080011826 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -070011827 if(pHddCtx->cfg_ini->fIsLogpEnabled)
11828 {
11829 status = vos_watchdog_open(pVosContext,
11830 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
11831
11832 if(!VOS_IS_STATUS_SUCCESS( status ))
11833 {
11834 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +053011835 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -070011836 }
11837 }
11838
11839 pHddCtx->isLogpInProgress = FALSE;
11840 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
11841
Amar Singhala49cbc52013-10-08 18:37:44 -070011842#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -070011843 /* initialize the NV module. This is required so that
11844 we can initialize the channel information in wiphy
11845 from the NV.bin data. The channel information in
11846 wiphy needs to be initialized before wiphy registration */
11847
11848 status = vos_nv_open();
11849 if (!VOS_IS_STATUS_SUCCESS(status))
11850 {
11851 /* NV module cannot be initialized */
11852 hddLog( VOS_TRACE_LEVEL_FATAL,
11853 "%s: vos_nv_open failed", __func__);
Vinay Krishna Eranna2025d892014-09-18 16:51:42 +053011854 goto err_wdclose;
Amar Singhal0a402232013-10-11 20:57:16 -070011855 }
11856
11857 status = vos_init_wiphy_from_nv_bin();
11858 if (!VOS_IS_STATUS_SUCCESS(status))
11859 {
11860 /* NV module cannot be initialized */
11861 hddLog( VOS_TRACE_LEVEL_FATAL,
11862 "%s: vos_init_wiphy failed", __func__);
11863 goto err_vos_nv_close;
11864 }
11865
Amar Singhala49cbc52013-10-08 18:37:44 -070011866#endif
Mahesh A Saptasagarc3ed0122016-01-19 16:45:11 +053011867 //Initialize the nlink service
11868 if(nl_srv_init() != 0)
11869 {
11870 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
11871 goto err_vos_nv_close;
11872 }
11873
11874#ifdef WLAN_KD_READY_NOTIFIER
11875 pHddCtx->kd_nl_init = 1;
11876#endif /* WLAN_KD_READY_NOTIFIER */
11877
Girish Gowlibf0e1ab2015-01-19 16:05:16 +053011878 vos_set_roam_delay_stats_enabled(pHddCtx->cfg_ini->gEnableRoamDelayStats);
Arun Kumar Khandavalliebb19482014-03-25 13:56:53 +053011879 status = vos_open( &pVosContext, pHddCtx->parent_dev);
Jeff Johnson295189b2012-06-20 16:38:30 -070011880 if ( !VOS_IS_STATUS_SUCCESS( status ))
11881 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -080011882 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
Mahesh A Saptasagarc3ed0122016-01-19 16:45:11 +053011883 goto err_nl_srv;
Jeff Johnson295189b2012-06-20 16:38:30 -070011884 }
11885
Jeff Johnson295189b2012-06-20 16:38:30 -070011886 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
11887
11888 if ( NULL == pHddCtx->hHal )
11889 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -080011890 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -070011891 goto err_vosclose;
11892 }
11893
Jeff Johnsonbc676b42013-02-14 16:04:08 -080011894 status = vos_preStart( pHddCtx->pvosContext );
11895 if ( !VOS_IS_STATUS_SUCCESS( status ) )
11896 {
11897 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053011898 goto err_vosclose;
Jeff Johnsonbc676b42013-02-14 16:04:08 -080011899 }
Jeff Johnsone7245742012-09-05 17:12:55 -070011900
Arif Hussaineaf68602013-12-30 23:10:44 -080011901 if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan)
11902 {
11903 pHddCtx->cfg_ini->enableDFSChnlScan = enable_dfs_chan_scan;
11904 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_dfs_chan_scan set to %d",
11905 __func__, enable_dfs_chan_scan);
11906 }
11907 if (0 == enable_11d || 1 == enable_11d)
11908 {
11909 pHddCtx->cfg_ini->Is11dSupportEnabled = enable_11d;
11910 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_11d set to %d",
11911 __func__, enable_11d);
11912 }
11913
Jeff Johnsonbc676b42013-02-14 16:04:08 -080011914 /* Note that the vos_preStart() sequence triggers the cfg download.
11915 The cfg download must occur before we update the SME config
11916 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -070011917 status = hdd_set_sme_config( pHddCtx );
11918
11919 if ( VOS_STATUS_SUCCESS != status )
11920 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -080011921 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053011922 goto err_vosclose;
Jeff Johnsonbc676b42013-02-14 16:04:08 -080011923 }
Jeff Johnson295189b2012-06-20 16:38:30 -070011924
Jeff Johnson295189b2012-06-20 16:38:30 -070011925 /* In the integrated architecture we update the configuration from
11926 the INI file and from NV before vOSS has been started so that
11927 the final contents are available to send down to the cCPU */
11928
11929 // Apply the cfg.ini to cfg.dat
11930 if (FALSE == hdd_update_config_dat(pHddCtx))
11931 {
11932 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053011933 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -070011934 }
11935
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053011936 // Get mac addr from platform driver
11937 ret = wcnss_get_wlan_mac_address((char*)&mac_addr.bytes);
11938
11939 if ((0 == ret) && (!vos_is_macaddr_zero(&mac_addr)))
Jeff Johnson295189b2012-06-20 16:38:30 -070011940 {
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053011941 /* Store the mac addr for first interface */
11942 pHddCtx->cfg_ini->intfMacAddr[0] = mac_addr;
11943
11944 hddLog(VOS_TRACE_LEVEL_ERROR,
11945 "%s: WLAN Mac Addr: "
11946 MAC_ADDRESS_STR, __func__,
11947 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
11948
11949 /* Here, passing Arg2 as 1 because we do not want to change the
11950 last 3 bytes (means non OUI bytes) of first interface mac
11951 addr.
11952 */
11953 if (0 != hdd_generate_iface_mac_addr_auto(pHddCtx, 1, mac_addr))
11954 {
11955 hddLog(VOS_TRACE_LEVEL_ERROR,
11956 "%s: Failed to generate wlan interface mac addr "
11957 "using MAC from ini file ", __func__);
11958 }
11959 }
11960 else if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
11961 {
11962 // Apply the NV to cfg.dat
11963 /* Prima Update MAC address only at here */
Jeff Johnson295189b2012-06-20 16:38:30 -070011964#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
11965 /* There was not a valid set of MAC Addresses in NV. See if the
11966 default addresses were modified by the cfg.ini settings. If so,
11967 we'll use them, but if not, we'll autogenerate a set of MAC
11968 addresses based upon the device serial number */
11969
11970 static const v_MACADDR_t default_address =
11971 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
Jeff Johnson295189b2012-06-20 16:38:30 -070011972
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053011973 if (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
11974 sizeof(default_address)))
Jeff Johnson295189b2012-06-20 16:38:30 -070011975 {
11976 /* cfg.ini has the default address, invoke autogen logic */
11977
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053011978 /* Here, passing Arg2 as 0 because we want to change the
11979 last 3 bytes (means non OUI bytes) of all the interfaces
11980 mac addr.
11981 */
11982 if (0 != hdd_generate_iface_mac_addr_auto(pHddCtx, 0,
11983 default_address))
Jeff Johnson295189b2012-06-20 16:38:30 -070011984 {
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053011985 hddLog(VOS_TRACE_LEVEL_ERROR,
11986 "%s: Failed to generate wlan interface mac addr "
11987 "using MAC from ini file " MAC_ADDRESS_STR, __func__,
11988 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
Jeff Johnson295189b2012-06-20 16:38:30 -070011989 }
Jeff Johnson295189b2012-06-20 16:38:30 -070011990 }
11991 else
11992#endif //WLAN_AUTOGEN_MACADDR_FEATURE
11993 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -080011994 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -070011995 "%s: Invalid MAC address in NV, using MAC from ini file "
11996 MAC_ADDRESS_STR, __func__,
11997 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
11998 }
11999 }
12000 {
12001 eHalStatus halStatus;
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053012002
12003 /* Set the MAC Address Currently this is used by HAL to
12004 * add self sta. Remove this once self sta is added as
12005 * part of session open.
12006 */
Jeff Johnson295189b2012-06-20 16:38:30 -070012007 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
12008 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
12009 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +053012010
Jeff Johnson295189b2012-06-20 16:38:30 -070012011 if (!HAL_STATUS_SUCCESS( halStatus ))
12012 {
12013 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
12014 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053012015 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -070012016 }
12017 }
Jeff Johnson295189b2012-06-20 16:38:30 -070012018
12019 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
12020 Note: Firmware image will be read and downloaded inside vos_start API */
12021 status = vos_start( pHddCtx->pvosContext );
12022 if ( !VOS_IS_STATUS_SUCCESS( status ) )
12023 {
12024 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
Hanumantha Reddy Pothulabd9601a2016-02-12 13:22:27 +053012025 if (isSsrPanicOnFailure())
12026 VOS_BUG(0);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053012027 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -070012028 }
12029
Leo Chang6cec3e22014-01-21 15:33:49 -080012030#ifdef FEATURE_WLAN_CH_AVOID
12031 /* Plug in avoid channel notification callback
12032 * This should happen before ADD_SELF_STA
12033 * FW will send first IND with ADD_SELF_STA REQ from host */
Pradeep Reddy POTTETI5c2e16d2014-06-27 16:47:38 +053012034
12035 /* check the Channel Avoidance is enabled */
12036 if (TRUE == pHddCtx->cfg_ini->fenableCHAvoidance)
12037 {
12038 sme_AddChAvoidCallback(pHddCtx->hHal,
12039 hdd_hostapd_ch_avoid_cb);
12040 }
Leo Chang6cec3e22014-01-21 15:33:49 -080012041#endif /* FEATURE_WLAN_CH_AVOID */
12042
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -070012043 /* Exchange capability info between Host and FW and also get versioning info from FW */
12044 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -070012045
Agarwal Ashishad9281b2014-06-10 14:57:30 +053012046#ifdef CONFIG_ENABLE_LINUX_REG
12047 status = wlan_hdd_init_channels(pHddCtx);
12048 if ( !VOS_IS_STATUS_SUCCESS( status ) )
12049 {
12050 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: wlan_hdd_init_channels failed",
12051 __func__);
12052 goto err_vosstop;
12053 }
12054#endif
12055
Jeff Johnson295189b2012-06-20 16:38:30 -070012056 status = hdd_post_voss_start_config( pHddCtx );
12057 if ( !VOS_IS_STATUS_SUCCESS( status ) )
12058 {
12059 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
12060 __func__);
12061 goto err_vosstop;
12062 }
Amar Singhala49cbc52013-10-08 18:37:44 -070012063
12064#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +053012065 wlan_hdd_cfg80211_update_reg_info( wiphy );
12066
12067 /* registration of wiphy dev with cfg80211 */
12068 if (0 > wlan_hdd_cfg80211_register(wiphy))
12069 {
12070 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
12071 goto err_vosstop;
12072 }
Amar Singhala49cbc52013-10-08 18:37:44 -070012073#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070012074
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053012075#ifdef CONFIG_ENABLE_LINUX_REG
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053012076 /* registration of wiphy dev with cfg80211 */
12077 if (0 > wlan_hdd_cfg80211_register(wiphy))
12078 {
12079 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
12080 goto err_vosstop;
12081 }
12082
Agarwal Ashish6db9d532014-09-30 18:19:10 +053012083 status = wlan_hdd_init_channels_for_cc(pHddCtx, INIT);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053012084 if ( !VOS_IS_STATUS_SUCCESS( status ) )
12085 {
12086 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: wlan_hdd_init_channels_for_cc failed",
12087 __func__);
12088 goto err_unregister_wiphy;
12089 }
12090#endif
12091
c_hpothu4a298be2014-12-22 21:12:51 +053012092 wcnss_wlan_set_drvdata(pHddCtx->parent_dev, pHddCtx);
12093
Jeff Johnson295189b2012-06-20 16:38:30 -070012094 if (VOS_STA_SAP_MODE == hdd_get_conparam())
12095 {
12096 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
12097 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
12098 }
12099 else
12100 {
Jeff Johnson295189b2012-06-20 16:38:30 -070012101 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
12102 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
12103 if (pAdapter != NULL)
12104 {
Katya Nigama7d81d72014-11-12 12:44:34 +053012105 if (pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated && !(pHddCtx->cfg_ini->intfMacAddr[0].bytes[0] & 0x02))
Jeff Johnson295189b2012-06-20 16:38:30 -070012106 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +053012107 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
12108 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
12109 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -070012110
Gopichand Nakkala49f96f62013-02-06 14:38:17 +053012111 /* Generate the P2P Device Address. This consists of the device's
12112 * primary MAC address with the locally administered bit set.
12113 */
12114 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -070012115 }
12116 else
12117 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +053012118 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
12119 if (p2p_dev_addr != NULL)
12120 {
12121 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
12122 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
12123 }
12124 else
12125 {
12126 hddLog(VOS_TRACE_LEVEL_FATAL,
12127 "%s: Failed to allocate mac_address for p2p_device",
12128 __func__);
12129 goto err_close_adapter;
12130 }
Jeff Johnson295189b2012-06-20 16:38:30 -070012131 }
Jeff Johnsone7245742012-09-05 17:12:55 -070012132
12133 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
12134 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
12135 if ( NULL == pP2pAdapter )
12136 {
12137 hddLog(VOS_TRACE_LEVEL_FATAL,
12138 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070012139 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -070012140 goto err_close_adapter;
12141 }
Jeff Johnsone7245742012-09-05 17:12:55 -070012142 }
Jeff Johnson295189b2012-06-20 16:38:30 -070012143 }
Jeff Johnson295189b2012-06-20 16:38:30 -070012144
12145 if( pAdapter == NULL )
12146 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -080012147 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
12148 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -070012149 }
Jeff Johnsone7245742012-09-05 17:12:55 -070012150
Arif Hussain66559122013-11-21 10:11:40 -080012151 if (country_code)
12152 {
12153 eHalStatus ret;
Arif Hussaincb607082013-12-20 11:57:42 -080012154 INIT_COMPLETION(pAdapter->change_country_code);
Arif Hussain66559122013-11-21 10:11:40 -080012155 hdd_checkandupdate_dfssetting(pAdapter, country_code);
12156#ifndef CONFIG_ENABLE_LINUX_REG
12157 hdd_checkandupdate_phymode(pAdapter, country_code);
12158#endif
Arif Hussaineaf68602013-12-30 23:10:44 -080012159 ret = sme_ChangeCountryCode(pHddCtx->hHal,
12160 (void *)(tSmeChangeCountryCallback)
12161 wlan_hdd_change_country_code_callback,
Arif Hussain66559122013-11-21 10:11:40 -080012162 country_code,
12163 pAdapter, pHddCtx->pvosContext,
Abhishek Singha306a442013-11-07 18:39:01 +053012164 eSIR_TRUE, eSIR_TRUE);
Arif Hussain66559122013-11-21 10:11:40 -080012165 if (eHAL_STATUS_SUCCESS == ret)
12166 {
Arif Hussaincb607082013-12-20 11:57:42 -080012167 ret = wait_for_completion_interruptible_timeout(
12168 &pAdapter->change_country_code,
12169 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
12170
12171 if (0 >= ret)
12172 {
12173 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
12174 "%s: SME while setting country code timed out", __func__);
12175 }
Arif Hussain66559122013-11-21 10:11:40 -080012176 }
12177 else
12178 {
Arif Hussaincb607082013-12-20 11:57:42 -080012179 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
12180 "%s: SME Change Country code from module param fail ret=%d",
12181 __func__, ret);
Arif Hussain66559122013-11-21 10:11:40 -080012182 }
12183 }
12184
Jeff Johnson295189b2012-06-20 16:38:30 -070012185#ifdef WLAN_BTAMP_FEATURE
12186 vStatus = WLANBAP_Open(pVosContext);
12187 if(!VOS_IS_STATUS_SUCCESS(vStatus))
12188 {
12189 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
12190 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -070012191 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -070012192 }
12193
12194 vStatus = BSL_Init(pVosContext);
12195 if(!VOS_IS_STATUS_SUCCESS(vStatus))
12196 {
12197 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
12198 "%s: Failed to Init BSL",__func__);
12199 goto err_bap_close;
12200 }
12201 vStatus = WLANBAP_Start(pVosContext);
12202 if (!VOS_IS_STATUS_SUCCESS(vStatus))
12203 {
12204 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
12205 "%s: Failed to start TL",__func__);
12206 goto err_bap_close;
12207 }
12208
12209 pConfig = pHddCtx->cfg_ini;
12210 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
12211 status = WLANBAP_SetConfig(&btAmpConfig);
12212
12213#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -070012214
Mihir Shete9c238772014-10-15 14:35:16 +053012215 /*
12216 * UapsdMask is 0xf if U-APSD is enbaled for all AC's...
12217 * The value of CFG_QOS_WMM_UAPSD_MASK_DEFAULT is 0xaa(Magic Value)
12218 * which is greater than 0xf. So the below check is safe to make
12219 * sure that there is no entry for UapsdMask in the ini
12220 */
12221 if (CFG_QOS_WMM_UAPSD_MASK_DEFAULT == pHddCtx->cfg_ini->UapsdMask)
12222 {
12223 if(IS_DYNAMIC_WMM_PS_ENABLED)
12224 {
12225 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: Enable UAPSD for VI & VO",
12226 __func__);
12227 pHddCtx->cfg_ini->UapsdMask =
12228 CFG_QOS_WMM_UAPSD_MASK_DYMANIC_WMM_PS_DEFAULT;
12229 }
12230 else
12231 {
12232 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: Do not enable UAPSD",
12233 __func__);
12234 pHddCtx->cfg_ini->UapsdMask =
12235 CFG_QOS_WMM_UAPSD_MASK_LEGACY_WMM_PS_DEFAULT;
12236 }
12237 }
12238
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -070012239#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
12240 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
12241 {
12242 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
12243 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
12244 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
12245 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
12246 }
12247#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070012248
Agarwal Ashish4b87f922014-06-18 03:03:21 +053012249 wlan_hdd_tdls_init(pHddCtx);
12250
Masti, Narayanraddi26378462016-01-05 18:20:28 +053012251 wlan_hdd_init_deinit_defer_scan_context(&pHddCtx->scan_ctxt);
12252
12253 vos_init_delayed_work(&pHddCtx->scan_ctxt.scan_work,
12254 wlan_hdd_schedule_defer_scan);
12255
Mihir Shetefc7ff5b2014-01-27 11:30:05 +053012256 sme_Register11dScanDoneCallback(pHddCtx->hHal, hdd_11d_scan_done);
12257
Jeff Johnson295189b2012-06-20 16:38:30 -070012258 /* Register with platform driver as client for Suspend/Resume */
12259 status = hddRegisterPmOps(pHddCtx);
12260 if ( !VOS_IS_STATUS_SUCCESS( status ) )
12261 {
12262 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
12263#ifdef WLAN_BTAMP_FEATURE
12264 goto err_bap_stop;
12265#else
Jeff Johnsone7245742012-09-05 17:12:55 -070012266 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -070012267#endif //WLAN_BTAMP_FEATURE
12268 }
12269
Yue Ma0d4891e2013-08-06 17:01:45 -070012270 /* Open debugfs interface */
12271 if (VOS_STATUS_SUCCESS != hdd_debugfs_init(pAdapter))
12272 {
12273 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
12274 "%s: hdd_debugfs_init failed!", __func__);
Yue Ma0d4891e2013-08-06 17:01:45 -070012275 }
12276
Jeff Johnson295189b2012-06-20 16:38:30 -070012277 /* Register TM level change handler function to the platform */
12278 status = hddDevTmRegisterNotifyCallback(pHddCtx);
12279 if ( !VOS_IS_STATUS_SUCCESS( status ) )
12280 {
12281 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
12282 goto err_unregister_pmops;
12283 }
Jeff Johnson295189b2012-06-20 16:38:30 -070012284
Jeff Johnson295189b2012-06-20 16:38:30 -070012285 // register net device notifier for device change notification
12286 ret = register_netdevice_notifier(&hdd_netdev_notifier);
12287
12288 if(ret < 0)
12289 {
12290 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
Siddharth Bhalcd92b782015-06-29 12:25:40 +053012291 goto err_unregister_pmops;
Jeff Johnson295189b2012-06-20 16:38:30 -070012292 }
12293
Jeff Johnson295189b2012-06-20 16:38:30 -070012294 //Initialize the BTC service
12295 if(btc_activate_service(pHddCtx) != 0)
12296 {
12297 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
Mahesh A Saptasagarc3ed0122016-01-19 16:45:11 +053012298 goto err_reg_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -070012299 }
12300
Padma, Santhosh Kumar2762e9d2015-10-20 15:02:57 +053012301#ifdef FEATURE_OEM_DATA_SUPPORT
12302 //Initialize the OEM service
12303 if (oem_activate_service(pHddCtx) != 0)
12304 {
12305 hddLog(VOS_TRACE_LEVEL_FATAL,
12306 "%s: oem_activate_service failed", __func__);
Mahesh A Saptasagarc3ed0122016-01-19 16:45:11 +053012307 goto err_reg_netdev;
Padma, Santhosh Kumar2762e9d2015-10-20 15:02:57 +053012308 }
12309#endif
12310
Jeff Johnson295189b2012-06-20 16:38:30 -070012311#ifdef PTT_SOCK_SVC_ENABLE
12312 //Initialize the PTT service
12313 if(ptt_sock_activate_svc(pHddCtx) != 0)
12314 {
12315 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
Mahesh A Saptasagarc3ed0122016-01-19 16:45:11 +053012316 goto err_reg_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -070012317 }
12318#endif
12319
Abhishek Singh00b71972016-01-07 10:51:04 +053012320#ifdef WLAN_FEATURE_RMC
12321 if (hdd_open_cesium_nl_sock() < 0)
12322 {
12323 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_open_cesium_nl_sock failed", __func__);
12324 goto err_reg_netdev;
12325 }
12326#endif
12327
Vinay Krishna Erannad938c422014-03-10 17:14:21 +053012328#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
12329 if(pHddCtx->cfg_ini && pHddCtx->cfg_ini->wlanLoggingEnable)
12330 {
Deepthi Gowri78083a32014-11-04 12:55:51 +053012331 if(wlan_logging_sock_activate_svc(
12332 pHddCtx->cfg_ini->wlanLoggingFEToConsole,
Sushant Kaushik33200572015-08-05 16:46:20 +053012333 pHddCtx->cfg_ini->wlanLoggingNumBuf,
12334 pHddCtx->cfg_ini->wlanPerPktStatsLogEnable,
12335 pHddCtx->cfg_ini->wlanPerPktStatsNumBuf))
Deepthi Gowri78083a32014-11-04 12:55:51 +053012336 {
12337 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wlan_logging_sock_activate_svc"
12338 " failed", __func__);
Mahesh A Saptasagarc3ed0122016-01-19 16:45:11 +053012339 goto err_reg_netdev;
Deepthi Gowri78083a32014-11-04 12:55:51 +053012340 }
12341 //TODO: To Remove enableDhcpDebug and use gEnableDebugLog for
12342 //EAPOL and DHCP
Sachin Ahuja8c65f382014-12-12 15:34:21 +053012343 if (!pHddCtx->cfg_ini->gEnableDebugLog)
12344 pHddCtx->cfg_ini->gEnableDebugLog =
Sushant Kaushik6e4e2bc2015-10-05 17:23:07 +053012345 VOS_PKT_PROTO_TYPE_EAPOL | VOS_PKT_PROTO_TYPE_DHCP |
12346 VOS_PKT_PROTO_TYPE_ARP;
Vinay Krishna Erannad938c422014-03-10 17:14:21 +053012347 }
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012348
Siddharth Bhald1be97f2015-05-27 22:39:59 +053012349 if (pHddCtx->cfg_ini->wlanLoggingEnable &&
12350 (pHddCtx->cfg_ini->enableFWLogging ||
Siddharth Bhaldb963232015-06-25 19:34:35 +053012351 pHddCtx->cfg_ini->enableMgmtLogging ||
c_manjeecfd1efb2015-09-25 19:32:34 +053012352 pHddCtx->cfg_ini->enableContFWLogging ||
12353 pHddCtx->cfg_ini->enableFwrMemDump )
12354 )
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012355 {
Siddharth Bhald1be97f2015-05-27 22:39:59 +053012356 hdd_init_frame_logging(pHddCtx);
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012357 }
12358 else
12359 {
Siddharth Bhald1be97f2015-05-27 22:39:59 +053012360 hddLog(VOS_TRACE_LEVEL_INFO, FL("Logging disabled in ini"));
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012361 }
12362
Vinay Krishna Erannad938c422014-03-10 17:14:21 +053012363#endif
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012364
Agrawal Ashish17ef5082016-10-17 18:33:21 +053012365#ifdef SAP_AUTH_OFFLOAD
12366 if (!sme_IsFeatureSupportedByFW(SAP_OFFLOADS))
12367 {
12368 hddLog(VOS_TRACE_LEVEL_INFO, FL(" SAP AUTH OFFLOAD not supp by FW"));
12369 pHddCtx->cfg_ini->enable_sap_auth_offload = 0;
12370 }
12371#endif
Siddharth Bhalb7c421c2015-02-27 00:26:09 +053012372
Sushant Kaushik215778f2015-05-21 14:05:36 +053012373 if (vos_is_multicast_logging())
12374 wlan_logging_set_log_level();
12375
Jeff Johnson295189b2012-06-20 16:38:30 -070012376 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -070012377 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -070012378 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -070012379 /* Action frame registered in one adapter which will
12380 * applicable to all interfaces
12381 */
Agarwal Ashish8fa0e9a2014-05-23 00:40:12 +053012382 wlan_hdd_cfg80211_register_frames(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -070012383 }
Jeff Johnson295189b2012-06-20 16:38:30 -070012384
12385 mutex_init(&pHddCtx->sap_lock);
Mahesh A Saptasagar60627942014-10-13 13:55:14 +053012386 mutex_init(&pHddCtx->roc_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -070012387
Jeff Johnsone7245742012-09-05 17:12:55 -070012388#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
12389 /* Initialize the wake lcok */
Sushant Kaushik83392fa2015-05-05 17:44:40 +053012390 vos_wake_lock_init(&pHddCtx->rx_wake_lock,
Jeff Johnsone7245742012-09-05 17:12:55 -070012391 "qcom_rx_wakelock");
Sushant Kaushik83392fa2015-05-05 17:44:40 +053012392
Jeff Johnsone7245742012-09-05 17:12:55 -070012393#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -080012394 /* Initialize the wake lcok */
Sushant Kaushik83392fa2015-05-05 17:44:40 +053012395 vos_wake_lock_init(&pHddCtx->sap_wake_lock,
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -080012396 "qcom_sap_wakelock");
Sushant Kaushik83392fa2015-05-05 17:44:40 +053012397
Jeff Johnsone7245742012-09-05 17:12:55 -070012398
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -070012399 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
12400 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -070012401
Katya Nigam5c306ea2014-06-19 15:39:54 +053012402 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_NO_LOAD_UNLOAD_IN_PROGRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -070012403 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
Sushant Kaushik83392fa2015-05-05 17:44:40 +053012404 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_INIT);
Katya Nigam5c306ea2014-06-19 15:39:54 +053012405
12406#ifdef FEATURE_WLAN_SCAN_PNO
12407 /*SME must send channel update configuration to RIVA*/
12408 sme_UpdateChannelConfig(pHddCtx->hHal);
12409#endif
Abhishek Singhf644b272014-08-21 02:59:39 +053012410 /* Send the update default channel list to the FW*/
12411 sme_UpdateChannelList(pHddCtx->hHal);
Mukul Sharma45063942015-04-01 20:07:59 +053012412
12413 /* Fwr capabilities received, Set the Dot11 mode */
Abhishek Singh41ebce12016-02-03 10:43:21 +053012414 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter),
12415 hdd_cfg_xlate_to_csr_phy_mode(pHddCtx->cfg_ini->dot11Mode));
Mukul Sharma45063942015-04-01 20:07:59 +053012416 sme_SetDefDot11Mode(pHddCtx->hHal);
12417
Abhishek Singha306a442013-11-07 18:39:01 +053012418#ifndef CONFIG_ENABLE_LINUX_REG
12419 /*updating wiphy so that regulatory user hints can be processed*/
12420 if (wiphy)
12421 {
12422 regulatory_hint(wiphy, "00");
12423 }
12424#endif
Jeff Johnsone7245742012-09-05 17:12:55 -070012425 // Initialize the restart logic
12426 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +053012427
Hanumanth Reddy Pothula146bca42016-11-08 12:01:07 +053012428 if (pHddCtx->cfg_ini->fIsLogpEnabled) {
12429 vos_wdthread_init_timer_work(vos_process_wd_timer);
12430 /* Initialize the timer to detect thread stuck issues */
12431 vos_thread_stuck_timer_init(
12432 &((VosContextType*)pVosContext)->vosWatchdog);
12433 }
12434
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -070012435 //Register the traffic monitor timer now
12436 if ( pHddCtx->cfg_ini->dynSplitscan)
12437 {
12438 vos_timer_init(&pHddCtx->tx_rx_trafficTmr,
12439 VOS_TIMER_TYPE_SW,
12440 hdd_tx_rx_pkt_cnt_stat_timer_handler,
12441 (void *)pHddCtx);
12442 }
Srinivas Dasari030bad32015-02-18 23:23:54 +053012443 wlan_hdd_cfg80211_nan_init(pHddCtx);
12444
Bhargav Shahd0715912015-10-01 18:17:37 +053012445 mutex_init(&pHddCtx->cur_rx_level_lock);
12446 vos_timer_init(&pHddCtx->delack_timer, VOS_TIMER_TYPE_SW,
12447 hdd_tcp_delack_compute_function,(void *)pHddCtx);
Masti, Narayanraddi44b0db02015-12-22 11:54:35 +053012448 vos_timer_init(&pHddCtx->tdls_source_timer, VOS_TIMER_TYPE_SW,
12449 wlan_hdd_change_tdls_mode, (void *)pHddCtx);
Bhargav Shahd0715912015-10-01 18:17:37 +053012450
Dino Mycle6fb96c12014-06-10 11:52:40 +053012451#ifdef WLAN_FEATURE_EXTSCAN
12452 sme_EXTScanRegisterCallback(pHddCtx->hHal,
12453 wlan_hdd_cfg80211_extscan_callback,
12454 pHddCtx);
12455#endif /* WLAN_FEATURE_EXTSCAN */
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053012456
Padma, Santhosh Kumar2ccac212015-10-20 17:27:27 +053012457#ifdef FEATURE_OEM_DATA_SUPPORT
12458 sme_OemDataRegisterCallback(pHddCtx->hHal,
12459 wlan_hdd_cfg80211_oemdata_callback,
12460 pHddCtx);
12461#endif /* FEATURE_OEM_DATA_SUPPORT */
12462
Gupta, Kapil7c34b322015-09-30 13:12:35 +053012463 sme_set_rssi_threshold_breached_cb(pHddCtx->hHal, hdd_rssi_threshold_breached_cb);
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053012464#ifdef WLAN_NS_OFFLOAD
12465 // Register IPv6 notifier to notify if any change in IP
12466 // So that we can reconfigure the offload parameters
12467 pHddCtx->ipv6_notifier.notifier_call = wlan_hdd_ipv6_changed;
12468 ret = register_inet6addr_notifier(&pHddCtx->ipv6_notifier);
12469 if (ret)
12470 {
Ratheesh S P36dbc932015-08-07 14:28:57 +053012471 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Failed to register IPv6 notifier"));
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053012472 }
12473 else
12474 {
Ratheesh S P36dbc932015-08-07 14:28:57 +053012475 hddLog(VOS_TRACE_LEVEL_INFO, FL("Registered IPv6 notifier"));
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053012476 }
12477#endif
12478
Sravan Kumar Kairamb0edc612016-10-26 13:55:24 +053012479 vos_mem_set((uint8_t *)&pHddCtx->bad_sta, HDD_MAX_STA_COUNT, 0);
12480
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053012481 // Register IPv4 notifier to notify if any change in IP
12482 // So that we can reconfigure the offload parameters
12483 pHddCtx->ipv4_notifier.notifier_call = wlan_hdd_ipv4_changed;
12484 ret = register_inetaddr_notifier(&pHddCtx->ipv4_notifier);
12485 if (ret)
12486 {
Ratheesh S P36dbc932015-08-07 14:28:57 +053012487 hddLog(VOS_TRACE_LEVEL_ERROR, FL("Failed to register IPv4 notifier"));
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053012488 }
12489 else
12490 {
Ratheesh S P36dbc932015-08-07 14:28:57 +053012491 hddLog(VOS_TRACE_LEVEL_INFO, FL("Registered IPv4 notifier"));
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053012492 }
c_manjeecfd1efb2015-09-25 19:32:34 +053012493 /*Fw mem dump procfs initialization*/
12494 memdump_init();
Bhargav shah23c94942015-10-13 12:48:35 +053012495 hdd_dp_util_send_rps_ind(pHddCtx);
Vinay Krishna Erannaf97ef5c2014-12-26 17:47:19 +053012496
Jeff Johnson295189b2012-06-20 16:38:30 -070012497 goto success;
12498
Jeff Johnson295189b2012-06-20 16:38:30 -070012499err_reg_netdev:
12500 unregister_netdevice_notifier(&hdd_netdev_notifier);
12501
Jeff Johnson295189b2012-06-20 16:38:30 -070012502err_unregister_pmops:
12503 hddDevTmUnregisterNotifyCallback(pHddCtx);
12504 hddDeregisterPmOps(pHddCtx);
12505
Yue Ma0d4891e2013-08-06 17:01:45 -070012506 hdd_debugfs_exit(pHddCtx);
12507
Jeff Johnson295189b2012-06-20 16:38:30 -070012508#ifdef WLAN_BTAMP_FEATURE
12509err_bap_stop:
12510 WLANBAP_Stop(pVosContext);
12511#endif
12512
12513#ifdef WLAN_BTAMP_FEATURE
12514err_bap_close:
12515 WLANBAP_Close(pVosContext);
12516#endif
12517
Jeff Johnson295189b2012-06-20 16:38:30 -070012518err_close_adapter:
12519 hdd_close_all_adapters( pHddCtx );
Mahesh A Saptasagar9ecefe42014-07-15 18:43:49 +053012520#ifdef CONFIG_ENABLE_LINUX_REG
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053012521err_unregister_wiphy:
Mahesh A Saptasagar9ecefe42014-07-15 18:43:49 +053012522#endif
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +053012523 wiphy_unregister(wiphy) ;
Agrawal Ashish33ec71e2015-11-26 20:20:58 +053012524 hdd_wlan_free_wiphy_channels(wiphy);
12525
Jeff Johnson295189b2012-06-20 16:38:30 -070012526err_vosstop:
12527 vos_stop(pVosContext);
12528
Amar Singhala49cbc52013-10-08 18:37:44 -070012529err_vosclose:
Jeff Johnson295189b2012-06-20 16:38:30 -070012530 status = vos_sched_close( pVosContext );
12531 if (!VOS_IS_STATUS_SUCCESS(status)) {
12532 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
12533 "%s: Failed to close VOSS Scheduler", __func__);
12534 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
12535 }
Amar Singhala49cbc52013-10-08 18:37:44 -070012536 vos_close(pVosContext );
12537
Mahesh A Saptasagarc3ed0122016-01-19 16:45:11 +053012538err_nl_srv:
12539#ifdef WLAN_KD_READY_NOTIFIER
12540 nl_srv_exit(pHddCtx->ptt_pid);
12541#else
12542 nl_srv_exit();
12543#endif /* WLAN_KD_READY_NOTIFIER */
Amar Singhal0a402232013-10-11 20:57:16 -070012544err_vos_nv_close:
12545
c_hpothue6a36282014-03-19 12:27:38 +053012546#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -070012547 vos_nv_close();
12548
c_hpothu70f8d812014-03-22 22:59:23 +053012549#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070012550
12551err_wdclose:
12552 if(pHddCtx->cfg_ini->fIsLogpEnabled)
12553 vos_watchdog_close(pVosContext);
12554
Jeff Johnson295189b2012-06-20 16:38:30 -070012555err_config:
12556 kfree(pHddCtx->cfg_ini);
12557 pHddCtx->cfg_ini= NULL;
12558
12559err_free_hdd_context:
Sushant Kaushik83392fa2015-05-05 17:44:40 +053012560 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_INIT);
Siddharth Bhalcd92b782015-06-29 12:25:40 +053012561 free_riva_power_on_lock("wlan");
Jeff Johnson295189b2012-06-20 16:38:30 -070012562 wiphy_free(wiphy) ;
12563 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -070012564 VOS_BUG(1);
12565
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -080012566 if (hdd_is_ssr_required())
12567 {
12568 /* WDI timeout had happened during load, so SSR is needed here */
12569 subsystem_restart("wcnss");
12570 msleep(5000);
12571 }
12572 hdd_set_ssr_required (VOS_FALSE);
12573
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -080012574 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -070012575
12576success:
12577 EXIT();
12578 return 0;
12579}
12580
12581/**---------------------------------------------------------------------------
12582
Jeff Johnson32d95a32012-09-10 13:15:23 -070012583 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -070012584
Jeff Johnson32d95a32012-09-10 13:15:23 -070012585 This is the driver entry point - called in different timeline depending
12586 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -070012587
12588 \param - None
12589
12590 \return - 0 for success, non zero for failure
12591
12592 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -070012593static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -070012594{
12595 VOS_STATUS status;
12596 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -070012597 struct device *dev = NULL;
12598 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -070012599#ifdef HAVE_WCNSS_CAL_DOWNLOAD
12600 int max_retries = 0;
12601#endif
Siddharth Bhalc7e79b62014-10-10 22:37:38 +053012602#ifdef HAVE_CBC_DONE
12603 int max_cbc_retries = 0;
12604#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070012605
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +053012606#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
12607 wlan_logging_sock_init_svc();
12608#endif
12609
Jeff Johnson295189b2012-06-20 16:38:30 -070012610 ENTER();
12611
Sushant Kaushik83392fa2015-05-05 17:44:40 +053012612 vos_wake_lock_init(&wlan_wake_lock, "wlan");
Jeff Johnson295189b2012-06-20 16:38:30 -070012613
12614 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
12615 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
12616
Jeff Johnson295189b2012-06-20 16:38:30 -070012617#ifdef ANI_BUS_TYPE_PCI
12618
12619 dev = wcnss_wlan_get_device();
12620
12621#endif // ANI_BUS_TYPE_PCI
12622
12623#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -070012624
12625#ifdef HAVE_WCNSS_CAL_DOWNLOAD
12626 /* wait until WCNSS driver downloads NV */
Ravi Kumar Bokka7a139e62016-11-17 21:32:55 +053012627 while (!wcnss_device_ready() && 10 >= ++max_retries) {
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -070012628 msleep(1000);
12629 }
Siddharth Bhalc7e79b62014-10-10 22:37:38 +053012630
Ravi Kumar Bokka7a139e62016-11-17 21:32:55 +053012631 if (max_retries >= 10) {
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -070012632 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
Sushant Kaushik83392fa2015-05-05 17:44:40 +053012633 vos_wake_lock_destroy(&wlan_wake_lock);
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +053012634#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
12635 wlan_logging_sock_deinit_svc();
12636#endif
12637
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -070012638 return -ENODEV;
12639 }
12640#endif
12641
Siddharth Bhalc7e79b62014-10-10 22:37:38 +053012642#ifdef HAVE_CBC_DONE
12643 while (!wcnss_cbc_complete() && 10 >= ++max_cbc_retries) {
12644 msleep(1000);
12645 }
12646 if (max_cbc_retries >= 10) {
12647 hddLog(VOS_TRACE_LEVEL_FATAL, "%s:CBC not completed", __func__);
12648 }
12649#endif
12650
Jeff Johnson295189b2012-06-20 16:38:30 -070012651 dev = wcnss_wlan_get_device();
12652#endif // ANI_BUS_TYPE_PLATFORM
12653
12654
12655 do {
12656 if (NULL == dev) {
12657 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
12658 ret_status = -1;
12659 break;
12660 }
12661
Jeff Johnson295189b2012-06-20 16:38:30 -070012662#ifdef TIMER_MANAGER
12663 vos_timer_manager_init();
12664#endif
12665
12666 /* Preopen VOSS so that it is ready to start at least SAL */
12667 status = vos_preOpen(&pVosContext);
12668
12669 if (!VOS_IS_STATUS_SUCCESS(status))
12670 {
12671 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
12672 ret_status = -1;
12673 break;
12674 }
12675
Sushant Kaushik02beb352015-06-04 15:15:01 +053012676 hddTraceInit();
Padma, Santhosh Kumar9093b202015-07-21 15:37:38 +053012677 hdd_register_debug_callback();
12678
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070012679#ifndef MODULE
12680 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
12681 */
12682 hdd_set_conparam((v_UINT_t)con_mode);
12683#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070012684
12685 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -080012686 if (hdd_wlan_startup(dev))
12687 {
Jeff Johnson295189b2012-06-20 16:38:30 -070012688 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -080012689 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -070012690 vos_preClose( &pVosContext );
12691 ret_status = -1;
12692 break;
12693 }
12694
Jeff Johnson295189b2012-06-20 16:38:30 -070012695 } while (0);
12696
12697 if (0 != ret_status)
12698 {
Jeff Johnson295189b2012-06-20 16:38:30 -070012699#ifdef TIMER_MANAGER
12700 vos_timer_exit();
12701#endif
12702#ifdef MEMORY_DEBUG
12703 vos_mem_exit();
12704#endif
Sushant Kaushik83392fa2015-05-05 17:44:40 +053012705 vos_wake_lock_destroy(&wlan_wake_lock);
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +053012706#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
12707 wlan_logging_sock_deinit_svc();
12708#endif
12709
Jeff Johnson295189b2012-06-20 16:38:30 -070012710 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
12711 }
12712 else
12713 {
12714 //Send WLAN UP indication to Nlink Service
12715 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
12716
12717 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Jeff Johnson295189b2012-06-20 16:38:30 -070012718 }
12719
12720 EXIT();
12721
12722 return ret_status;
12723}
12724
Jeff Johnson32d95a32012-09-10 13:15:23 -070012725/**---------------------------------------------------------------------------
12726
12727 \brief hdd_module_init() - Init Function
12728
12729 This is the driver entry point (invoked when module is loaded using insmod)
12730
12731 \param - None
12732
12733 \return - 0 for success, non zero for failure
12734
12735 --------------------------------------------------------------------------*/
12736#ifdef MODULE
12737static int __init hdd_module_init ( void)
12738{
12739 return hdd_driver_init();
12740}
Jeff Johnson32d95a32012-09-10 13:15:23 -070012741#else /* #ifdef MODULE */
12742static int __init hdd_module_init ( void)
12743{
12744 /* Driver initialization is delayed to fwpath_changed_handler */
12745 return 0;
12746}
Jeff Johnson32d95a32012-09-10 13:15:23 -070012747#endif /* #ifdef MODULE */
12748
Jeff Johnson295189b2012-06-20 16:38:30 -070012749
12750/**---------------------------------------------------------------------------
12751
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070012752 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -070012753
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070012754 This is the driver exit point (invoked when module is unloaded using rmmod
12755 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -070012756
12757 \param - None
12758
12759 \return - None
12760
12761 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070012762static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -070012763{
12764 hdd_context_t *pHddCtx = NULL;
12765 v_CONTEXT_t pVosContext = NULL;
Agarwal Ashish5e414792014-06-08 15:25:23 +053012766 v_REGDOMAIN_t regId;
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +053012767 unsigned long rc = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -070012768
12769 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
12770
12771 //Get the global vos context
12772 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
12773
12774 if(!pVosContext)
12775 {
12776 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
12777 goto done;
12778 }
12779
12780 //Get the HDD context.
12781 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
12782
12783 if(!pHddCtx)
12784 {
12785 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
12786 }
Katya Nigame7b69a82015-04-28 15:24:06 +053012787 else if (VOS_MONITOR_MODE == hdd_get_conparam())
12788 {
12789 hddLog(VOS_TRACE_LEVEL_INFO,"%s: MONITOR MODE",__func__);
12790 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_UNLOAD_IN_PROGRESS;
12791 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
12792 hdd_wlan_exit(pHddCtx);
12793 vos_preClose( &pVosContext );
12794 goto done;
12795 }
Jeff Johnson295189b2012-06-20 16:38:30 -070012796 else
12797 {
Siddharth Bhal2e5871b2015-03-24 16:20:51 +053012798 /* We wait for active entry threads to exit from driver
12799 * by waiting until rtnl_lock is available.
12800 */
12801 rtnl_lock();
12802 rtnl_unlock();
12803
Siddharth Bhal3c29dca2015-02-19 00:41:40 +053012804 INIT_COMPLETION(pHddCtx->ssr_comp_var);
12805 if ((pHddCtx->isLogpInProgress) && (FALSE ==
12806 vos_is_wlan_in_badState(VOS_MODULE_ID_HDD, NULL)))
12807 {
Siddharth Bhala204f572015-01-17 02:03:36 +053012808 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Siddharth Bhal3c29dca2015-02-19 00:41:40 +053012809 "%s:SSR in Progress; block rmmod !!!", __func__);
Siddharth Bhala204f572015-01-17 02:03:36 +053012810 rc = wait_for_completion_timeout(&pHddCtx->ssr_comp_var,
12811 msecs_to_jiffies(30000));
12812 if(!rc)
12813 {
12814 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
12815 "%s:SSR timedout, fatal error", __func__);
12816 VOS_BUG(0);
12817 }
12818 }
12819
Siddharth Bhal3c29dca2015-02-19 00:41:40 +053012820 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_UNLOAD_IN_PROGRESS;
12821 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
Jeff Johnson295189b2012-06-20 16:38:30 -070012822
c_hpothu8adb97b2014-12-08 19:38:20 +053012823 /* Driver Need to send country code 00 in below condition
12824 * 1) If gCountryCodePriority is set to 1; and last country
12825 * code set is through 11d. This needs to be done in case
12826 * when NV country code is 00.
12827 * This Needs to be done as when kernel store last country
12828 * code and if stored country code is not through 11d,
12829 * in sme_HandleChangeCountryCodeByUser we will disable 11d
12830 * in next load/unload as soon as we get any country through
12831 * 11d. In sme_HandleChangeCountryCodeByUser
12832 * pMsg->countryCode will be last countryCode and
12833 * pMac->scan.countryCode11d will be country through 11d so
12834 * due to mismatch driver will disable 11d.
12835 *
12836 */
Agarwal Ashish8db39882014-07-30 21:56:07 +053012837
c_hpothu8adb97b2014-12-08 19:38:20 +053012838 if ((eANI_BOOLEAN_TRUE == sme_Is11dCountrycode(pHddCtx->hHal) &&
Agarwal Ashish8dcd2862014-07-25 11:58:52 +053012839 pHddCtx->cfg_ini->fSupplicantCountryCodeHasPriority &&
Abhishek Singh2a705962014-10-30 14:47:28 +053012840 sme_Is11dSupported(pHddCtx->hHal)))
c_hpothu8adb97b2014-12-08 19:38:20 +053012841 {
12842 hddLog(VOS_TRACE_LEVEL_INFO,
Agarwal Ashish8dcd2862014-07-25 11:58:52 +053012843 FL("CountryCode 00 is being set while unloading driver"));
c_hpothu8adb97b2014-12-08 19:38:20 +053012844 vos_nv_getRegDomainFromCountryCode(&regId , "00", COUNTRY_USER);
12845 }
Agarwal Ashish5e414792014-06-08 15:25:23 +053012846
c_hpothu8adb97b2014-12-08 19:38:20 +053012847 //Do all the cleanup before deregistering the driver
12848 hdd_wlan_exit(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -070012849 }
12850
Jeff Johnson295189b2012-06-20 16:38:30 -070012851 vos_preClose( &pVosContext );
12852
12853#ifdef TIMER_MANAGER
12854 vos_timer_exit();
12855#endif
12856#ifdef MEMORY_DEBUG
12857 vos_mem_exit();
12858#endif
12859
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +053012860#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
12861 wlan_logging_sock_deinit_svc();
12862#endif
12863
Jeff Johnson295189b2012-06-20 16:38:30 -070012864done:
Sushant Kaushik83392fa2015-05-05 17:44:40 +053012865 vos_wake_lock_destroy(&wlan_wake_lock);
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +053012866
Jeff Johnson295189b2012-06-20 16:38:30 -070012867 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
12868}
12869
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070012870/**---------------------------------------------------------------------------
12871
12872 \brief hdd_module_exit() - Exit function
12873
12874 This is the driver exit point (invoked when module is unloaded using rmmod)
12875
12876 \param - None
12877
12878 \return - None
12879
12880 --------------------------------------------------------------------------*/
12881static void __exit hdd_module_exit(void)
12882{
12883 hdd_driver_exit();
12884}
12885
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070012886#ifdef MODULE
12887static int fwpath_changed_handler(const char *kmessage,
12888 struct kernel_param *kp)
12889{
Jeff Johnson76052702013-04-16 13:55:05 -070012890 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070012891}
12892
12893static int con_mode_handler(const char *kmessage,
12894 struct kernel_param *kp)
12895{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -070012896 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070012897}
12898#else /* #ifdef MODULE */
12899/**---------------------------------------------------------------------------
12900
Jeff Johnson76052702013-04-16 13:55:05 -070012901 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070012902
Jeff Johnson76052702013-04-16 13:55:05 -070012903 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070012904 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -070012905 - invoked when module parameter fwpath is modified from userspace to signal
12906 initializing the WLAN driver or when con_mode is modified from userspace
12907 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070012908
12909 \return - 0 for success, non zero for failure
12910
12911 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -070012912static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070012913{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -070012914 int ret_status;
12915
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070012916 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -070012917 ret_status = hdd_driver_init();
12918 wlan_hdd_inited = ret_status ? 0 : 1;
12919 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070012920 }
12921
12922 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -070012923
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070012924 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -070012925
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -070012926 ret_status = hdd_driver_init();
12927 wlan_hdd_inited = ret_status ? 0 : 1;
12928 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -070012929}
12930
Jeff Johnson295189b2012-06-20 16:38:30 -070012931/**---------------------------------------------------------------------------
12932
Jeff Johnson76052702013-04-16 13:55:05 -070012933 \brief fwpath_changed_handler() - Handler Function
12934
12935 Handle changes to the fwpath parameter
12936
12937 \return - 0 for success, non zero for failure
12938
12939 --------------------------------------------------------------------------*/
12940static int fwpath_changed_handler(const char *kmessage,
12941 struct kernel_param *kp)
12942{
12943 int ret;
12944
12945 ret = param_set_copystring(kmessage, kp);
12946 if (0 == ret)
12947 ret = kickstart_driver();
12948 return ret;
12949}
12950
12951/**---------------------------------------------------------------------------
12952
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070012953 \brief con_mode_handler() -
12954
12955 Handler function for module param con_mode when it is changed by userspace
12956 Dynamically linked - do nothing
12957 Statically linked - exit and init driver, as in rmmod and insmod
12958
Jeff Johnson76052702013-04-16 13:55:05 -070012959 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070012960
Jeff Johnson76052702013-04-16 13:55:05 -070012961 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070012962
12963 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -070012964static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070012965{
Jeff Johnson76052702013-04-16 13:55:05 -070012966 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070012967
Jeff Johnson76052702013-04-16 13:55:05 -070012968 ret = param_set_int(kmessage, kp);
12969 if (0 == ret)
12970 ret = kickstart_driver();
12971 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070012972}
12973#endif /* #ifdef MODULE */
12974
12975/**---------------------------------------------------------------------------
12976
Jeff Johnson295189b2012-06-20 16:38:30 -070012977 \brief hdd_get_conparam() -
12978
12979 This is the driver exit point (invoked when module is unloaded using rmmod)
12980
12981 \param - None
12982
12983 \return - tVOS_CON_MODE
12984
12985 --------------------------------------------------------------------------*/
12986tVOS_CON_MODE hdd_get_conparam ( void )
12987{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070012988#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -070012989 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070012990#else
12991 return (tVOS_CON_MODE)curr_con_mode;
12992#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070012993}
12994void hdd_set_conparam ( v_UINT_t newParam )
12995{
12996 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070012997#ifndef MODULE
12998 curr_con_mode = con_mode;
12999#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070013000}
13001/**---------------------------------------------------------------------------
13002
13003 \brief hdd_softap_sta_deauth() - function
13004
13005 This to take counter measure to handle deauth req from HDD
13006
13007 \param - pAdapter - Pointer to the HDD
13008
13009 \param - enable - boolean value
13010
13011 \return - None
13012
13013 --------------------------------------------------------------------------*/
13014
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +053013015VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter,
13016 struct tagCsrDelStaParams *pDelStaParams)
Jeff Johnson295189b2012-06-20 16:38:30 -070013017{
Jeff Johnson295189b2012-06-20 16:38:30 -070013018 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -080013019 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -070013020
13021 ENTER();
13022
Rajesh Chauhan18488fc2013-08-22 10:15:03 -070013023 hddLog(LOG1, "hdd_softap_sta_deauth:(%p, false)",
13024 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -070013025
13026 //Ignore request to deauth bcmc station
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +053013027 if (pDelStaParams->peerMacAddr[0] & 0x1)
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -080013028 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -070013029
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +053013030 vosStatus = WLANSAP_DeauthSta(pVosContext, pDelStaParams);
Jeff Johnson295189b2012-06-20 16:38:30 -070013031
13032 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -080013033 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -070013034}
13035
13036/**---------------------------------------------------------------------------
13037
Rashmi Ramanna1f0948d2014-08-28 15:33:48 +053013038 \brief hdd_del_all_sta() - function
13039
13040 This function removes all the stations associated on stopping AP/P2P GO.
13041
13042 \param - pAdapter - Pointer to the HDD
13043
13044 \return - None
13045
13046 --------------------------------------------------------------------------*/
13047
13048int hdd_del_all_sta(hdd_adapter_t *pAdapter)
13049{
13050 v_U16_t i;
13051 VOS_STATUS vos_status;
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +053013052 v_CONTEXT_t pVosContext = ( WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
13053 ptSapContext pSapCtx = NULL;
13054 pSapCtx = VOS_GET_SAP_CB(pVosContext);
13055 if(pSapCtx == NULL){
13056 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
13057 FL("psapCtx is NULL"));
13058 return 1;
13059 }
Rashmi Ramanna1f0948d2014-08-28 15:33:48 +053013060 ENTER();
13061
13062 hddLog(VOS_TRACE_LEVEL_INFO,
13063 "%s: Delete all STAs associated.",__func__);
13064 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
13065 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
13066 )
13067 {
13068 for(i = 0; i < WLAN_MAX_STA_COUNT; i++)
13069 {
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +053013070 if ((pSapCtx->aStaInfo[i].isUsed) &&
13071 (!pSapCtx->aStaInfo[i].isDeauthInProgress))
Rashmi Ramanna1f0948d2014-08-28 15:33:48 +053013072 {
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +053013073 struct tagCsrDelStaParams delStaParams;
13074
13075 WLANSAP_PopulateDelStaParams(
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +053013076 pSapCtx->aStaInfo[i].macAddrSTA.bytes,
Sushant Kaushik4cd28f62014-12-26 14:23:50 +053013077 eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
13078 SIR_MAC_MGMT_DEAUTH >> 4,
Hanumantha Reddy Pothulabfd06f72014-10-31 14:03:37 +053013079 &delStaParams);
13080 vos_status = hdd_softap_sta_deauth(pAdapter, &delStaParams);
Rashmi Ramanna1f0948d2014-08-28 15:33:48 +053013081 if (VOS_IS_STATUS_SUCCESS(vos_status))
Sachin Ahujabcb0b7e2014-11-07 13:01:24 +053013082 pSapCtx->aStaInfo[i].isDeauthInProgress = TRUE;
Rashmi Ramanna1f0948d2014-08-28 15:33:48 +053013083 }
13084 }
13085 }
13086
13087 EXIT();
13088 return 0;
13089}
13090
13091/**---------------------------------------------------------------------------
13092
Jeff Johnson295189b2012-06-20 16:38:30 -070013093 \brief hdd_softap_sta_disassoc() - function
13094
13095 This to take counter measure to handle deauth req from HDD
13096
13097 \param - pAdapter - Pointer to the HDD
13098
13099 \param - enable - boolean value
13100
13101 \return - None
13102
13103 --------------------------------------------------------------------------*/
13104
13105void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
13106{
13107 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
13108
13109 ENTER();
13110
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +053013111 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -070013112
13113 //Ignore request to disassoc bcmc station
13114 if( pDestMacAddress[0] & 0x1 )
13115 return;
13116
13117 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
13118}
13119
13120void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
13121{
13122 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
13123
13124 ENTER();
13125
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +053013126 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -070013127
13128 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
13129}
13130
Jeff Johnson295189b2012-06-20 16:38:30 -070013131/**---------------------------------------------------------------------------
13132 *
13133 * \brief hdd_get__concurrency_mode() -
13134 *
13135 *
13136 * \param - None
13137 *
13138 * \return - CONCURRENCY MODE
13139 *
13140 * --------------------------------------------------------------------------*/
13141tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
13142{
13143 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
13144 hdd_context_t *pHddCtx;
13145
13146 if (NULL != pVosContext)
13147 {
13148 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
13149 if (NULL != pHddCtx)
13150 {
13151 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
13152 }
13153 }
13154
13155 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -070013156 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -070013157 return VOS_STA;
13158}
Sushant Kaushikabb7ee62014-07-18 16:20:12 +053013159v_BOOL_t
13160wlan_hdd_is_GO_power_collapse_allowed (hdd_context_t* pHddCtx)
13161{
13162 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -070013163
Sushant Kaushikabb7ee62014-07-18 16:20:12 +053013164 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_GO);
13165 if (pAdapter == NULL)
13166 {
13167 hddLog(VOS_TRACE_LEVEL_INFO,
13168 FL("GO doesn't exist"));
13169 return TRUE;
13170 }
13171 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
13172 {
13173 hddLog(VOS_TRACE_LEVEL_INFO,
13174 FL("GO started"));
13175 return TRUE;
13176 }
13177 else
13178 /* wait till GO changes its interface to p2p device */
13179 hddLog(VOS_TRACE_LEVEL_INFO,
13180 FL("Del_bss called, avoid apps suspend"));
13181 return FALSE;
13182
13183}
Jeff Johnson295189b2012-06-20 16:38:30 -070013184/* Decide whether to allow/not the apps power collapse.
13185 * Allow apps power collapse if we are in connected state.
13186 * if not, allow only if we are in IMPS */
13187v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
13188{
13189 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -080013190 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -080013191 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -070013192 hdd_config_t *pConfig = pHddCtx->cfg_ini;
13193 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
13194 hdd_adapter_t *pAdapter = NULL;
13195 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -080013196 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -070013197
Jeff Johnson295189b2012-06-20 16:38:30 -070013198 if (VOS_STA_SAP_MODE == hdd_get_conparam())
13199 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -070013200
Yathish9f22e662012-12-10 14:21:35 -080013201 concurrent_state = hdd_get_concurrency_mode();
13202
Sushant Kaushikabb7ee62014-07-18 16:20:12 +053013203 if ((concurrent_state == (VOS_STA | VOS_P2P_GO)) &&
13204 !(wlan_hdd_is_GO_power_collapse_allowed(pHddCtx)))
13205 return FALSE;
Yathish9f22e662012-12-10 14:21:35 -080013206#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
Sushant Kaushikabb7ee62014-07-18 16:20:12 +053013207
Yathish9f22e662012-12-10 14:21:35 -080013208 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
Sushant Kaushikabb7ee62014-07-18 16:20:12 +053013209 (concurrent_state == (VOS_STA | VOS_P2P_GO)))&&
Yathish9f22e662012-12-10 14:21:35 -080013210 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
13211 return TRUE;
13212#endif
13213
Jeff Johnson295189b2012-06-20 16:38:30 -070013214 /*loop through all adapters. TBD fix for Concurrency */
13215 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
13216 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
13217 {
13218 pAdapter = pAdapterNode->pAdapter;
13219 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
13220 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
13221 {
Srikant Kuppafef66a72013-01-30 17:32:44 -080013222 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
c_hpothu4e8faac2014-05-16 17:38:44 +053013223 && (pmcState != IMPS && pmcState != BMPS && pmcState != UAPSD
c_hpothu1c6957d2015-01-06 18:19:47 +053013224 && pmcState != STOPPED && pmcState != STANDBY &&
13225 pmcState != WOWL)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -080013226 (eANI_BOOLEAN_TRUE == scanRspPending) ||
13227 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -070013228 {
Mukul Sharma4be88422015-03-09 20:29:07 +053013229 if(pmcState == FULL_POWER &&
13230 sme_IsCoexScoIndicationSet(pHddCtx->hHal))
13231 {
13232 /*
13233 * When SCO indication comes from Coex module , host will
13234 * enter in to full power mode, but this should not prevent
13235 * apps processor power collapse.
13236 */
13237 hddLog(LOG1,
13238 FL("Allow apps power collapse"
13239 "even when sco indication is set"));
13240 return TRUE;
13241 }
Srikant Kuppafef66a72013-01-30 17:32:44 -080013242 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Deepthi Gowri03a979f2016-11-03 15:20:19 +053013243 "pmcState = %d scanRspPending = %d "
13244 "inMiddleOfRoaming = %d connected = %d",
13245 __func__, pmcState, scanRspPending,
13246 inMiddleOfRoaming, hdd_connIsConnected(
13247 WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )));
13248 wlan_hdd_get_tdls_stats(pAdapter);
13249 return FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -070013250 }
13251 }
13252 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
13253 pAdapterNode = pNext;
13254 }
13255 return TRUE;
13256}
13257
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -080013258/* Decides whether to send suspend notification to Riva
13259 * if any adapter is in BMPS; then it is required */
13260v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
13261{
13262 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
13263 hdd_config_t *pConfig = pHddCtx->cfg_ini;
13264
13265 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
13266 {
13267 return TRUE;
13268 }
13269 return FALSE;
13270}
13271
Jeff Johnson295189b2012-06-20 16:38:30 -070013272void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
13273{
13274 switch(mode)
13275 {
Chilam Ngc4244af2013-04-01 15:37:32 -070013276 case VOS_STA_MODE:
13277 case VOS_P2P_CLIENT_MODE:
13278 case VOS_P2P_GO_MODE:
13279 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -070013280 pHddCtx->concurrency_mode |= (1 << mode);
Agarwal Ashish51325b52014-06-16 16:50:49 +053013281 pHddCtx->no_of_open_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -070013282 break;
13283 default:
13284 break;
Jeff Johnson295189b2012-06-20 16:38:30 -070013285 }
Agarwal Ashish51325b52014-06-16 16:50:49 +053013286 hddLog(VOS_TRACE_LEVEL_INFO, FL("concurrency_mode = 0x%x "
13287 "Number of open sessions for mode %d = %d"),
13288 pHddCtx->concurrency_mode, mode,
13289 pHddCtx->no_of_open_sessions[mode]);
Jeff Johnson295189b2012-06-20 16:38:30 -070013290}
13291
13292
13293void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
13294{
13295 switch(mode)
13296 {
Chilam Ngc4244af2013-04-01 15:37:32 -070013297 case VOS_STA_MODE:
13298 case VOS_P2P_CLIENT_MODE:
13299 case VOS_P2P_GO_MODE:
13300 case VOS_STA_SAP_MODE:
Agarwal Ashish51325b52014-06-16 16:50:49 +053013301 pHddCtx->no_of_open_sessions[mode]--;
13302 if (!(pHddCtx->no_of_open_sessions[mode]))
13303 pHddCtx->concurrency_mode &= (~(1 << mode));
Jeff Johnson295189b2012-06-20 16:38:30 -070013304 break;
13305 default:
13306 break;
13307 }
Agarwal Ashish51325b52014-06-16 16:50:49 +053013308 hddLog(VOS_TRACE_LEVEL_INFO, FL("concurrency_mode = 0x%x "
13309 "Number of open sessions for mode %d = %d"),
13310 pHddCtx->concurrency_mode, mode, pHddCtx->no_of_open_sessions[mode]);
13311
13312}
13313/**---------------------------------------------------------------------------
13314 *
13315 * \brief wlan_hdd_incr_active_session()
13316 *
13317 * This function increments the number of active sessions
13318 * maintained per device mode
13319 * Incase of STA/P2P CLI/IBSS upon connection indication it is incremented
13320 * Incase of SAP/P2P GO upon bss start it is incremented
13321 *
13322 * \param pHddCtx - HDD Context
13323 * \param mode - device mode
13324 *
13325 * \return - None
13326 *
13327 * --------------------------------------------------------------------------*/
13328void wlan_hdd_incr_active_session(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
13329{
13330 switch (mode) {
13331 case VOS_STA_MODE:
13332 case VOS_P2P_CLIENT_MODE:
13333 case VOS_P2P_GO_MODE:
13334 case VOS_STA_SAP_MODE:
13335 pHddCtx->no_of_active_sessions[mode]++;
13336 break;
13337 default:
13338 hddLog(VOS_TRACE_LEVEL_INFO, FL("Not Expected Mode %d"), mode);
13339 break;
13340 }
13341 hddLog(VOS_TRACE_LEVEL_INFO, FL("No.# of active sessions for mode %d = %d"),
13342 mode,
13343 pHddCtx->no_of_active_sessions[mode]);
13344}
13345
13346/**---------------------------------------------------------------------------
13347 *
13348 * \brief wlan_hdd_decr_active_session()
13349 *
13350 * This function decrements the number of active sessions
13351 * maintained per device mode
13352 * Incase of STA/P2P CLI/IBSS upon disconnection it is decremented
13353 * Incase of SAP/P2P GO upon bss stop it is decremented
13354 *
13355 * \param pHddCtx - HDD Context
13356 * \param mode - device mode
13357 *
13358 * \return - None
13359 *
13360 * --------------------------------------------------------------------------*/
13361void wlan_hdd_decr_active_session(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
13362{
Bhargav Shahd0715912015-10-01 18:17:37 +053013363
Agarwal Ashish51325b52014-06-16 16:50:49 +053013364 switch (mode) {
13365 case VOS_STA_MODE:
13366 case VOS_P2P_CLIENT_MODE:
13367 case VOS_P2P_GO_MODE:
13368 case VOS_STA_SAP_MODE:
Agarwal Ashish5325f522014-08-06 00:58:44 +053013369 if (pHddCtx->no_of_active_sessions[mode] > 0)
13370 pHddCtx->no_of_active_sessions[mode]--;
13371 else
13372 hddLog(VOS_TRACE_LEVEL_INFO, FL(" No.# of Active sessions"
13373 "is already Zero"));
Agarwal Ashish51325b52014-06-16 16:50:49 +053013374 break;
13375 default:
13376 hddLog(VOS_TRACE_LEVEL_INFO, FL("Not Expected Mode %d"), mode);
13377 break;
13378 }
13379 hddLog(VOS_TRACE_LEVEL_INFO, FL("No.# of active sessions for mode %d = %d"),
13380 mode,
13381 pHddCtx->no_of_active_sessions[mode]);
Jeff Johnson295189b2012-06-20 16:38:30 -070013382}
13383
Jeff Johnsone7245742012-09-05 17:12:55 -070013384/**---------------------------------------------------------------------------
13385 *
13386 * \brief wlan_hdd_restart_init
13387 *
13388 * This function initalizes restart timer/flag. An internal function.
13389 *
13390 * \param - pHddCtx
13391 *
13392 * \return - None
13393 *
13394 * --------------------------------------------------------------------------*/
13395
13396static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
13397{
13398 /* Initialize */
13399 pHddCtx->hdd_restart_retries = 0;
13400 atomic_set(&pHddCtx->isRestartInProgress, 0);
13401 vos_timer_init(&pHddCtx->hdd_restart_timer,
13402 VOS_TIMER_TYPE_SW,
13403 wlan_hdd_restart_timer_cb,
13404 pHddCtx);
13405}
13406/**---------------------------------------------------------------------------
13407 *
13408 * \brief wlan_hdd_restart_deinit
13409 *
13410 * This function cleans up the resources used. An internal function.
13411 *
13412 * \param - pHddCtx
13413 *
13414 * \return - None
13415 *
13416 * --------------------------------------------------------------------------*/
13417
13418static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
13419{
13420
13421 VOS_STATUS vos_status;
13422 /* Block any further calls */
13423 atomic_set(&pHddCtx->isRestartInProgress, 1);
13424 /* Cleanup */
13425 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
13426 if (!VOS_IS_STATUS_SUCCESS(vos_status))
c_hpothu6ff1c3c2013-10-01 19:01:57 +053013427 hddLog(LOGE, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -070013428 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
13429 if (!VOS_IS_STATUS_SUCCESS(vos_status))
c_hpothu6ff1c3c2013-10-01 19:01:57 +053013430 hddLog(LOGE, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -070013431
13432}
13433
13434/**---------------------------------------------------------------------------
13435 *
13436 * \brief wlan_hdd_framework_restart
13437 *
13438 * This function uses a cfg80211 API to start a framework initiated WLAN
13439 * driver module unload/load.
13440 *
13441 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
13442 *
13443 *
13444 * \param - pHddCtx
13445 *
13446 * \return - VOS_STATUS_SUCCESS: Success
13447 * VOS_STATUS_E_EMPTY: Adapter is Empty
13448 * VOS_STATUS_E_NOMEM: No memory
13449
13450 * --------------------------------------------------------------------------*/
13451
13452static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
13453{
13454 VOS_STATUS status = VOS_STATUS_SUCCESS;
13455 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -070013456 int len = (sizeof (struct ieee80211_mgmt));
13457 struct ieee80211_mgmt *mgmt = NULL;
13458
13459 /* Prepare the DEAUTH managment frame with reason code */
13460 mgmt = kzalloc(len, GFP_KERNEL);
13461 if(mgmt == NULL)
13462 {
13463 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
13464 "%s: memory allocation failed (%d bytes)", __func__, len);
13465 return VOS_STATUS_E_NOMEM;
13466 }
13467 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -070013468
13469 /* Iterate over all adapters/devices */
13470 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Hanumantha Reddy Pothulada0fe362015-02-27 18:37:03 +053013471 if ((NULL == pAdapterNode) || (VOS_STATUS_SUCCESS != status))
13472 {
13473 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
13474 FL("fail to get adapter: %p %d"), pAdapterNode, status);
13475 goto end;
13476 }
13477
Jeff Johnsone7245742012-09-05 17:12:55 -070013478 do
13479 {
Hanumantha Reddy Pothulada0fe362015-02-27 18:37:03 +053013480 if(pAdapterNode->pAdapter &&
13481 WLAN_HDD_ADAPTER_MAGIC == pAdapterNode->pAdapter->magic)
Jeff Johnsone7245742012-09-05 17:12:55 -070013482 {
13483 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
13484 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
13485 pAdapterNode->pAdapter->dev->name,
13486 pAdapterNode->pAdapter->device_mode,
13487 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -070013488 /*
13489 * CFG80211 event to restart the driver
13490 *
13491 * 'cfg80211_send_unprot_deauth' sends a
13492 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
13493 * of SME(Linux Kernel) state machine.
13494 *
13495 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
13496 * the driver.
13497 *
13498 */
Abhishek Singh00b71972016-01-07 10:51:04 +053013499
Anand N Sunkade9adb1b2015-07-29 09:56:45 +053013500#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
13501 cfg80211_rx_unprot_mlme_mgmt(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len);
13502#else
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -070013503 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Anand N Sunkade9adb1b2015-07-29 09:56:45 +053013504#endif
Jeff Johnsone7245742012-09-05 17:12:55 -070013505 }
13506 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
13507 pAdapterNode = pNext;
13508 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
13509
Hanumantha Reddy Pothulada0fe362015-02-27 18:37:03 +053013510 end:
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -070013511 /* Free the allocated management frame */
13512 kfree(mgmt);
13513
Jeff Johnsone7245742012-09-05 17:12:55 -070013514 /* Retry until we unload or reach max count */
13515 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
13516 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
13517
13518 return status;
13519
13520}
13521/**---------------------------------------------------------------------------
13522 *
13523 * \brief wlan_hdd_restart_timer_cb
13524 *
13525 * Restart timer callback. An internal function.
13526 *
13527 * \param - User data:
13528 *
13529 * \return - None
13530 *
13531 * --------------------------------------------------------------------------*/
13532
13533void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
13534{
13535 hdd_context_t *pHddCtx = usrDataForCallback;
13536 wlan_hdd_framework_restart(pHddCtx);
13537 return;
13538
13539}
13540
13541
13542/**---------------------------------------------------------------------------
13543 *
13544 * \brief wlan_hdd_restart_driver
13545 *
13546 * This function sends an event to supplicant to restart the WLAN driver.
13547 *
13548 * This function is called from vos_wlanRestart.
13549 *
13550 * \param - pHddCtx
13551 *
13552 * \return - VOS_STATUS_SUCCESS: Success
13553 * VOS_STATUS_E_EMPTY: Adapter is Empty
13554 * VOS_STATUS_E_ALREADY: Request already in progress
13555
13556 * --------------------------------------------------------------------------*/
13557VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
13558{
13559 VOS_STATUS status = VOS_STATUS_SUCCESS;
13560
13561 /* A tight check to make sure reentrancy */
13562 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
13563 {
Mihir Shetefd528652014-06-23 19:07:50 +053013564 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnsone7245742012-09-05 17:12:55 -070013565 "%s: WLAN restart is already in progress", __func__);
13566
13567 return VOS_STATUS_E_ALREADY;
13568 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -070013569 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -080013570#ifdef HAVE_WCNSS_RESET_INTR
Siddharth Bhal864e7e82015-04-07 20:07:24 +053013571 wcnss_reset_fiq(TRUE);
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -070013572#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -070013573
Jeff Johnsone7245742012-09-05 17:12:55 -070013574 return status;
13575}
13576
Bhargav Shahd0715912015-10-01 18:17:37 +053013577/**
13578 * hdd_get_total_sessions() - provide total number of active sessions
13579 * @pHddCtx: Valid Global HDD context pointer
13580 *
13581 * This function iterates through pAdaptors and find the number of all active
13582 * sessions. This active sessions includes connected sta, p2p client and number
13583 * of client connected to sap/p2p go.
13584 *
13585 * Return: Total number of active sessions.
13586 */
13587v_U8_t hdd_get_total_sessions(hdd_context_t *pHddCtx)
13588{
13589 v_U8_t active_session = 0;
13590 hdd_station_ctx_t *pHddStaCtx;
13591 hdd_adapter_list_node_t *pAdapterNode, *pNext;
13592 hdd_adapter_t *pAdapter;
13593 VOS_STATUS status;
13594
13595 status = hdd_get_front_adapter(pHddCtx, &pAdapterNode);
13596 while (NULL != pAdapterNode && VOS_STATUS_SUCCESS == status) {
13597 pAdapter = pAdapterNode->pAdapter;
13598 switch (pAdapter->device_mode) {
13599 case VOS_STA_MODE:
13600 case VOS_P2P_CLIENT_MODE:
13601 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13602 if(eConnectionState_Associated == pHddStaCtx->conn_info.connState)
13603 active_session += 1;
13604 break;
13605 case VOS_STA_SAP_MODE:
13606 case VOS_P2P_GO_MODE:
13607 active_session += hdd_softap_get_connected_sta(pAdapter);
13608 break;
13609 default:
13610 break;
13611 }
13612
13613 status = hdd_get_next_adapter(pHddCtx, pAdapterNode, &pNext);
13614 pAdapterNode = pNext;
13615 }
13616
13617 return active_session;
13618}
13619
13620/**
13621 * hdd_set_delack_value() - Set delack value
13622 * @pHddCtx: Valid Global HDD context pointer
13623 * @next_rx_level: Value to set for delack
13624 *
13625 * This function compare present value and next value of delack. If the both
13626 * are diffrent then it sets next value .
13627 *
13628 * Return: void.
13629 */
13630void hdd_set_delack_value(hdd_context_t *pHddCtx, v_U32_t next_rx_level)
13631{
13632 if (pHddCtx->cur_rx_level != next_rx_level) {
13633 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_DEBUG,
13634 "%s: TCP DELACK trigger level %d",
13635 __func__, next_rx_level);
13636 mutex_lock(&pHddCtx->cur_rx_level_lock);
13637 pHddCtx->cur_rx_level = next_rx_level;
13638 mutex_unlock(&pHddCtx->cur_rx_level_lock);
13639 wlan_hdd_send_svc_nlink_msg(WLAN_SVC_WLAN_TP_IND, &next_rx_level,
13640 sizeof(next_rx_level));
13641 }
13642}
13643
13644/**
13645 * hdd_set_default_stop_delack_timer() - Start delack timer
13646 * @pHddCtx: Valid Global HDD context pointer
13647 *
13648 * This function stop delack timer and set delack value to default..
13649 *
13650 * Return: void.
13651 */
13652
13653void hdd_set_default_stop_delack_timer(hdd_context_t *pHddCtx)
13654{
13655 if (VOS_TIMER_STATE_RUNNING !=
13656 vos_timer_getCurrentState(&pHddCtx->delack_timer)) {
13657 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_DEBUG,
13658 "%s: Can not stop timer", __func__);
13659 return;
13660 }
13661
13662 vos_timer_stop(&pHddCtx->delack_timer);
13663 hdd_set_delack_value(pHddCtx, TP_IND_LOW);
13664}
13665
13666/**
13667 * hdd_start_delack_timer() - Start delack timer
13668 * @pHddCtx: Valid Global HDD context pointer
13669 *
13670 * This function starts the delack timer for tcpDelAckComputeInterval time
13671 * interval.The default timer value is 2 second.
13672 *
13673 * Return: void.
13674 */
13675void hdd_start_delack_timer(hdd_context_t *pHddCtx)
13676{
13677 if (VOS_TIMER_STATE_RUNNING ==
13678 vos_timer_getCurrentState(&pHddCtx->delack_timer)) {
13679 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_DEBUG,
13680 "%s: Timer is already running", __func__);
13681 return;
13682 }
13683
13684 vos_timer_start(&pHddCtx->delack_timer,
13685 pHddCtx->cfg_ini->tcpDelAckComputeInterval);
13686}
13687
13688/**
13689 * hdd_update_prev_rx_packet_count() - Update previous rx packet count
13690 * @pHddCtx: Valid Global HDD context pointer
13691 *
13692 * This function updates the prev_rx_packets count from the corresponding
13693 * pAdapter states. This prev_rx_packets will diffed with the packet count
13694 * at the end of delack timer. That can give number of RX packet is spacific
13695 * time.
13696 *
13697 * Return: void.
13698 */
13699void hdd_update_prev_rx_packet_count(hdd_context_t *pHddCtx)
13700{
13701 hdd_adapter_list_node_t *pAdapterNode, *pNext;
13702 hdd_adapter_t *pAdapter;
13703 VOS_STATUS status;
13704
13705 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
13706 while (NULL != pAdapterNode && VOS_STATUS_SUCCESS == status) {
13707 pAdapter = pAdapterNode->pAdapter;
13708 pAdapter->prev_rx_packets = pAdapter->stats.rx_packets;
13709 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
13710 pAdapterNode = pNext;
13711 }
13712}
13713
13714/**
13715 * hdd_manage_delack_timer() - start\stop delack timer
13716 * @pHddCtx: Valid Global HDD context pointer
13717 *
13718 * This function check the number of concerent session present, it starts the
13719 * delack timer if only one session is present.
13720 * In the case of BT_COEX and TDLS mode it blindly stop delack functionality.
13721 *
13722 * Return: void.
13723 */
13724void hdd_manage_delack_timer(hdd_context_t *pHddCtx)
13725{
13726 uint8_t sessions;
13727
13728 if (!pHddCtx->cfg_ini->enable_delack) {
13729 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_DEBUG,
13730 "%s: TCP DELACK is not enabled", __func__);
13731 return;
13732 }
13733
13734 /* Blindly stop timer of BTCOEX and TDLS Session is up */
13735 if (pHddCtx->mode != 0) {
13736 hdd_set_default_stop_delack_timer(pHddCtx);
13737 return;
13738 }
13739
13740 sessions = hdd_get_total_sessions(pHddCtx);
13741 if (sessions == 1) {
13742 hdd_update_prev_rx_packet_count(pHddCtx);
13743 hdd_start_delack_timer(pHddCtx);
13744 } else {
13745 hdd_set_default_stop_delack_timer(pHddCtx);
13746 }
13747}
13748
Mihir Shetee1093ba2014-01-21 20:13:32 +053013749/**---------------------------------------------------------------------------
13750 *
13751 * \brief wlan_hdd_init_channels
13752 *
13753 * This function is used to initialize the channel list in CSR
13754 *
13755 * This function is called from hdd_wlan_startup
13756 *
13757 * \param - pHddCtx: HDD context
13758 *
13759 * \return - VOS_STATUS_SUCCESS: Success
13760 * VOS_STATUS_E_FAULT: Failure reported by SME
13761
13762 * --------------------------------------------------------------------------*/
13763static VOS_STATUS wlan_hdd_init_channels(hdd_context_t *pHddCtx)
13764{
13765 eHalStatus status;
13766
13767 status = sme_InitChannels(pHddCtx->hHal);
13768 if (HAL_STATUS_SUCCESS(status))
13769 {
13770 return VOS_STATUS_SUCCESS;
13771 }
13772 else
13773 {
13774 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Channel initialization failed(%d)",
13775 __func__, status);
13776 return VOS_STATUS_E_FAULT;
13777 }
13778}
13779
Mihir Shete04206452014-11-20 17:50:58 +053013780#ifdef CONFIG_ENABLE_LINUX_REG
Agarwal Ashish6db9d532014-09-30 18:19:10 +053013781VOS_STATUS wlan_hdd_init_channels_for_cc(hdd_context_t *pHddCtx, driver_load_type init )
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053013782{
13783 eHalStatus status;
13784
Agarwal Ashish6db9d532014-09-30 18:19:10 +053013785 status = sme_InitChannelsForCC(pHddCtx->hHal, init);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053013786 if (HAL_STATUS_SUCCESS(status))
13787 {
13788 return VOS_STATUS_SUCCESS;
13789 }
13790 else
13791 {
13792 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Issue reg hint failed(%d)",
13793 __func__, status);
13794 return VOS_STATUS_E_FAULT;
13795 }
13796}
Mihir Shete04206452014-11-20 17:50:58 +053013797#endif
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -070013798/*
13799 * API to find if there is any STA or P2P-Client is connected
13800 */
13801VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
13802{
13803 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
13804}
Jeff Johnsone7245742012-09-05 17:12:55 -070013805
Mihir Shetee2ae82a2015-03-16 14:08:49 +053013806
13807/*
13808 * API to find if the firmware will send logs using DXE channel
13809 */
13810v_U8_t hdd_is_fw_logging_enabled(void)
13811{
13812 hdd_context_t *pHddCtx;
13813
13814 pHddCtx = vos_get_context(VOS_MODULE_ID_HDD,
13815 vos_get_global_context(VOS_MODULE_ID_HDD, NULL));
13816
Sachin Ahuja084313e2015-05-21 17:57:10 +053013817 return (pHddCtx && pHddCtx->cfg_ini->enableMgmtLogging);
Mihir Shetee2ae82a2015-03-16 14:08:49 +053013818}
13819
Agarwal Ashish57e84372014-12-05 18:26:53 +053013820/*
Mihir Shetebe94ebb2015-05-26 12:07:14 +053013821 * API to find if the firmware will send trace logs using DXE channel
13822 */
13823v_U8_t hdd_is_fw_ev_logging_enabled(void)
13824{
13825 hdd_context_t *pHddCtx;
13826
13827 pHddCtx = vos_get_context(VOS_MODULE_ID_HDD,
13828 vos_get_global_context(VOS_MODULE_ID_HDD, NULL));
13829
13830 return (pHddCtx && pHddCtx->cfg_ini->enableFWLogging);
13831}
13832/*
Agarwal Ashish57e84372014-12-05 18:26:53 +053013833 * API to find if there is any session connected
13834 */
13835VOS_STATUS hdd_is_any_session_connected(hdd_context_t *pHddCtx)
13836{
13837 return sme_is_any_session_connected(pHddCtx->hHal);
13838}
13839
13840
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053013841int wlan_hdd_scan_abort(hdd_adapter_t *pAdapter)
13842{
13843 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13844 hdd_scaninfo_t *pScanInfo = NULL;
Girish Gowli4bf7a632014-06-12 13:42:11 +053013845 long status = 0;
c_hpothua3d45d52015-01-05 14:11:17 +053013846 tSirAbortScanStatus abortScanStatus;
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053013847
13848 pScanInfo = &pHddCtx->scan_info;
Ratnam Rachuric7681132015-06-30 10:35:13 +053013849 INIT_COMPLETION(pScanInfo->abortscan_event_var);
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053013850 if (pScanInfo->mScanPending)
13851 {
c_hpothua3d45d52015-01-05 14:11:17 +053013852 abortScanStatus = hdd_abort_mac_scan(pHddCtx, pScanInfo->sessionId,
13853 eCSR_SCAN_ABORT_DEFAULT);
13854 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
13855 FL("abortScanStatus: %d"), abortScanStatus);
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053013856
c_hpothua3d45d52015-01-05 14:11:17 +053013857 /* If there is active scan command lets wait for the completion else
13858 * there is no need to wait as scan command might be in the SME pending
13859 * command list.
13860 */
13861 if (abortScanStatus == eSIR_ABORT_ACTIVE_SCAN_LIST_NOT_EMPTY)
13862 {
c_hpothua3d45d52015-01-05 14:11:17 +053013863 status = wait_for_completion_interruptible_timeout(
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053013864 &pScanInfo->abortscan_event_var,
13865 msecs_to_jiffies(5000));
c_hpothua3d45d52015-01-05 14:11:17 +053013866 if (0 >= status)
13867 {
13868 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Girish Gowli4bf7a632014-06-12 13:42:11 +053013869 "%s: Timeout or Interrupt occurred while waiting for abort"
13870 "scan, status- %ld", __func__, status);
c_hpothua3d45d52015-01-05 14:11:17 +053013871 return -ETIMEDOUT;
13872 }
13873 }
13874 else if (abortScanStatus == eSIR_ABORT_SCAN_FAILURE)
13875 {
13876 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
13877 FL("hdd_abort_mac_scan failed"));
13878 return -VOS_STATUS_E_FAILURE;
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053013879 }
13880 }
Girish Gowli4bf7a632014-06-12 13:42:11 +053013881 return 0;
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053013882}
13883
Abhishek Singh7d624e12015-11-30 14:29:27 +053013884/**
13885 * hdd_indicate_mgmt_frame() - Wrapper to indicate management frame to
13886 * user space
13887 * @frame_ind: Management frame data to be informed.
13888 *
13889 * This function is used to indicate management frame to
13890 * user space
13891 *
13892 * Return: None
13893 *
13894 */
13895void hdd_indicate_mgmt_frame(tSirSmeMgmtFrameInd *frame_ind)
13896{
13897 hdd_context_t *hdd_ctx = NULL;
13898 hdd_adapter_t *adapter = NULL;
13899 v_CONTEXT_t vos_context = NULL;
13900
13901 /* Get the global VOSS context.*/
13902 vos_context = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
13903 if (!vos_context) {
13904 hddLog(LOGE, FL("Global VOS context is Null"));
13905 return;
13906 }
13907 /* Get the HDD context.*/
13908 hdd_ctx =
13909 (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, vos_context );
13910
13911 if (0 != wlan_hdd_validate_context(hdd_ctx))
13912 {
13913 return;
13914 }
13915 adapter = hdd_get_adapter_by_sme_session_id(hdd_ctx,
13916 frame_ind->sessionId);
13917
13918 if ((NULL != adapter) &&
13919 (WLAN_HDD_ADAPTER_MAGIC == adapter->magic))
13920 __hdd_indicate_mgmt_frame(adapter,
13921 frame_ind->frameLen,
13922 frame_ind->frameBuf,
13923 frame_ind->frameType,
13924 frame_ind->rxChan,
13925 frame_ind->rxRssi);
13926 return;
13927
13928}
13929
c_hpothu225aa7c2014-10-22 17:45:13 +053013930VOS_STATUS wlan_hdd_cancel_remain_on_channel(hdd_context_t *pHddCtx)
13931{
13932 hdd_adapter_t *pAdapter;
13933 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
13934 VOS_STATUS vosStatus;
13935
13936 vosStatus = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
13937 while (NULL != pAdapterNode && VOS_STATUS_E_EMPTY != vosStatus)
13938 {
13939 pAdapter = pAdapterNode->pAdapter;
13940 if (NULL != pAdapter)
13941 {
13942 if (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode ||
13943 WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ||
13944 WLAN_HDD_P2P_GO == pAdapter->device_mode)
13945 {
13946 hddLog(LOG1, FL("abort ROC deviceMode: %d"),
13947 pAdapter->device_mode);
13948 if (VOS_STATUS_SUCCESS !=
13949 wlan_hdd_cancel_existing_remain_on_channel(pAdapter))
13950 {
13951 hddLog(LOGE, FL("failed to abort ROC"));
13952 return VOS_STATUS_E_FAILURE;
13953 }
13954 }
13955 }
13956 vosStatus = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
13957 pAdapterNode = pNext;
13958 }
13959 return VOS_STATUS_SUCCESS;
13960}
Mahesh A Saptasagard477b092015-02-06 15:12:16 +053013961
Mihir Shete0be28772015-02-17 18:42:14 +053013962hdd_remain_on_chan_ctx_t *hdd_get_remain_on_channel_ctx(hdd_context_t *pHddCtx)
13963{
13964 hdd_adapter_t *pAdapter;
13965 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
13966 hdd_cfg80211_state_t *cfgState;
13967 hdd_remain_on_chan_ctx_t *pRemainChanCtx = NULL;
13968 VOS_STATUS vosStatus;
13969
13970 vosStatus = hdd_get_front_adapter (pHddCtx, &pAdapterNode);
13971 while (NULL != pAdapterNode && VOS_STATUS_E_EMPTY != vosStatus)
13972 {
13973 pAdapter = pAdapterNode->pAdapter;
13974 if (NULL != pAdapter)
13975 {
13976 cfgState = WLAN_HDD_GET_CFG_STATE_PTR(pAdapter);
13977 pRemainChanCtx = cfgState->remain_on_chan_ctx;
13978 if (pRemainChanCtx)
13979 break;
13980 }
13981 vosStatus = hdd_get_next_adapter (pHddCtx, pAdapterNode, &pNext);
13982 pAdapterNode = pNext;
13983 }
13984 return pRemainChanCtx;
13985}
13986
Padma, Santhosh Kumar778d8382015-03-04 17:41:22 +053013987/**
13988 * wlan_hdd_handle_dfs_chan_scan () - handles disable/enable DFS channels
13989 *
13990 * @pHddCtx: HDD context within host driver
13991 * @dfsScanMode: dfsScanMode passed from ioctl
13992 *
13993 */
13994
13995VOS_STATUS wlan_hdd_handle_dfs_chan_scan(hdd_context_t *pHddCtx,
13996 tANI_U8 dfsScanMode)
13997{
13998 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
13999 hdd_adapter_t *pAdapter;
14000 VOS_STATUS vosStatus;
14001 hdd_station_ctx_t *pHddStaCtx;
14002 eHalStatus status = eHAL_STATUS_SUCCESS;
14003
14004 if(!pHddCtx)
14005 {
14006 hddLog(LOGE, FL("HDD context is Null"));
14007 return eHAL_STATUS_FAILURE;
14008 }
14009
14010 if (pHddCtx->scan_info.mScanPending)
14011 {
14012 hddLog(LOG1, FL("Aborting scan for sessionId: %d"),
14013 pHddCtx->scan_info.sessionId);
14014 hdd_abort_mac_scan(pHddCtx,
14015 pHddCtx->scan_info.sessionId,
14016 eCSR_SCAN_ABORT_DEFAULT);
14017 }
14018
14019 if (!dfsScanMode)
14020 {
14021 vosStatus = hdd_get_front_adapter( pHddCtx, &pAdapterNode);
14022 while ((NULL != pAdapterNode) &&
14023 (VOS_STATUS_SUCCESS == vosStatus))
14024 {
14025 pAdapter = pAdapterNode->pAdapter;
14026
14027 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
14028 {
14029 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14030
14031 if(!pHddStaCtx)
14032 {
14033 hddLog(LOGE, FL("HDD STA context is Null"));
14034 return eHAL_STATUS_FAILURE;
14035 }
14036
14037 /* if STA is already connected on DFS channel,
14038 disconnect immediately*/
14039 if (hdd_connIsConnected(pHddStaCtx) &&
14040 (NV_CHANNEL_DFS ==
14041 vos_nv_getChannelEnabledState(
14042 pHddStaCtx->conn_info.operationChannel)))
14043 {
14044 status = sme_RoamDisconnect(pHddCtx->hHal,
14045 pAdapter->sessionId,
14046 eCSR_DISCONNECT_REASON_UNSPECIFIED);
14047 hddLog(LOG1, FL("Client connected on DFS channel %d,"
14048 "sme_RoamDisconnect returned with status: %d"
14049 "for sessionid: %d"), pHddStaCtx->conn_info.
14050 operationChannel, status, pAdapter->sessionId);
14051 }
14052 }
14053
14054 vosStatus = hdd_get_next_adapter(pHddCtx, pAdapterNode,
14055 &pNext);
14056 pAdapterNode = pNext;
14057 }
14058 }
14059
14060 sme_UpdateDFSScanMode(pHddCtx->hHal, dfsScanMode);
14061 sme_UpdateDFSRoamMode(pHddCtx->hHal,
14062 (dfsScanMode != DFS_CHNL_SCAN_DISABLED));
14063
14064 status = sme_HandleDFSChanScan(pHddCtx->hHal);
14065 if (!HAL_STATUS_SUCCESS(status))
14066 {
14067 hddLog(LOGE,
14068 FL("Failed in sme_HandleDFSChanScan (err=%d)"), status);
14069 return status;
14070 }
14071
14072 return status;
14073}
14074
Nirav Shah7e3c8132015-06-22 23:51:42 +053014075static int hdd_log2_ceil(unsigned value)
14076{
14077 /* need to switch to unsigned math so that negative values
14078 * will right-shift towards 0 instead of -1
14079 */
14080 unsigned tmp = value;
14081 int log2 = -1;
14082
14083 if (value == 0)
14084 return 0;
14085
14086 while (tmp) {
14087 log2++;
14088 tmp >>= 1;
14089 }
14090 if (1U << log2 != value)
14091 log2++;
14092
14093 return log2;
14094}
14095
14096/**
14097 * hdd_sta_id_hash_attach() - initialize sta id to macaddr hash
14098 * @pAdapter: adapter handle
14099 *
14100 * Return: vos status
14101 */
14102VOS_STATUS hdd_sta_id_hash_attach(hdd_adapter_t *pAdapter)
14103{
14104 int hash_elem, log2, i;
14105
14106 spin_lock_bh( &pAdapter->sta_hash_lock);
14107 if (pAdapter->is_sta_id_hash_initialized == VOS_TRUE) {
14108 spin_unlock_bh( &pAdapter->sta_hash_lock);
14109 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
14110 "%s: hash already attached for session id %d",
14111 __func__, pAdapter->sessionId);
14112 return VOS_STATUS_SUCCESS;
14113 }
14114 spin_unlock_bh( &pAdapter->sta_hash_lock);
14115
14116 hash_elem = WLAN_MAX_STA_COUNT;
14117 hash_elem *= HDD_STA_ID_HASH_MULTIPLIER;
14118 log2 = hdd_log2_ceil(hash_elem);
14119 hash_elem = 1 << log2;
14120
14121 pAdapter->sta_id_hash.mask = hash_elem - 1;
14122 pAdapter->sta_id_hash.idx_bits = log2;
14123 pAdapter->sta_id_hash.bins =
14124 vos_mem_malloc(hash_elem *sizeof(hdd_list_t));
14125 if (!pAdapter->sta_id_hash.bins) {
14126 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
14127 "%s: malloc failed for session %d",
14128 __func__, pAdapter->sessionId);
14129 return VOS_STATUS_E_NOMEM;
14130 }
14131
14132 for (i = 0; i < hash_elem; i++)
14133 hdd_list_init(&pAdapter->sta_id_hash.bins[i], WLAN_MAX_STA_COUNT);
14134
14135 spin_lock_bh( &pAdapter->sta_hash_lock);
14136 pAdapter->is_sta_id_hash_initialized = VOS_TRUE;
14137 spin_unlock_bh( &pAdapter->sta_hash_lock);
14138 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
14139 "%s: Station ID Hash attached for session id %d",
14140 __func__, pAdapter->sessionId);
14141
14142 return VOS_STATUS_SUCCESS;
14143}
14144
14145/**
14146 * hdd_sta_id_hash_detach() - deinit sta_id to macaddr hash
14147 * @pAdapter: adapter handle
14148 *
14149 * Return: vos status
14150 */
14151VOS_STATUS hdd_sta_id_hash_detach(hdd_adapter_t *pAdapter)
14152{
14153 int hash_elem, i;
14154 v_SIZE_t size;
14155
14156 spin_lock_bh( &pAdapter->sta_hash_lock);
14157 if (pAdapter->is_sta_id_hash_initialized != VOS_TRUE) {
14158 spin_unlock_bh( &pAdapter->sta_hash_lock);
14159 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
14160 "%s: hash not initialized for session id %d",
14161 __func__, pAdapter->sessionId);
14162 return VOS_STATUS_SUCCESS;
14163 }
14164
14165 pAdapter->is_sta_id_hash_initialized = VOS_FALSE;
14166 spin_unlock_bh( &pAdapter->sta_hash_lock);
14167
14168 hash_elem = 1 << pAdapter->sta_id_hash.idx_bits;
14169
14170 /* free all station info*/
14171 for (i = 0; i < hash_elem; i++) {
14172 hdd_list_size(&pAdapter->sta_id_hash.bins[i], &size);
14173 if (size != 0) {
14174 VOS_STATUS status;
14175 hdd_staid_hash_node_t *sta_info_node = NULL;
14176 hdd_staid_hash_node_t *next_node = NULL;
14177 status = hdd_list_peek_front ( &pAdapter->sta_id_hash.bins[i],
14178 (hdd_list_node_t**) &sta_info_node );
14179
14180 while ( NULL != sta_info_node && VOS_STATUS_SUCCESS == status )
14181 {
14182 status = hdd_list_remove_node( &pAdapter->sta_id_hash.bins[i],
14183 &sta_info_node->node);
14184 vos_mem_free(sta_info_node);
14185
14186 status = hdd_list_peek_next (&pAdapter->sta_id_hash.bins[i],
14187 (hdd_list_node_t*)sta_info_node,
14188 (hdd_list_node_t**)&next_node);
14189 sta_info_node = next_node;
14190 }
14191 }
14192 }
14193
14194 vos_mem_free(pAdapter->sta_id_hash.bins);
14195 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
14196 "%s: Station ID Hash detached for session id %d",
14197 __func__, pAdapter->sessionId);
14198 return VOS_STATUS_SUCCESS;
14199}
14200
14201/**
14202 * hdd_sta_id_hash_calculate_index() - derive index from macaddr
14203 * @pAdapter: adapter handle
14204 * @mac_addr_in: input mac address
14205 *
14206 * Return: index derived from mac address
14207 */
14208int hdd_sta_id_hash_calculate_index(hdd_adapter_t *pAdapter,
14209 v_MACADDR_t *mac_addr_in)
14210{
14211 uint16 index;
14212 struct hdd_align_mac_addr_t * mac_addr =
14213 (struct hdd_align_mac_addr_t *)mac_addr_in;
14214
14215 index = mac_addr->bytes_ab ^
14216 mac_addr->bytes_cd ^ mac_addr->bytes_ef;
14217 index ^= index >> pAdapter->sta_id_hash.idx_bits;
14218 index &= pAdapter->sta_id_hash.mask;
14219 return index;
14220}
14221
14222/**
14223 * hdd_sta_id_hash_add_entry() - add entry in hash
14224 * @pAdapter: adapter handle
14225 * @sta_id: station id
14226 * @mac_addr: mac address
14227 *
14228 * Return: vos status
14229 */
14230VOS_STATUS hdd_sta_id_hash_add_entry(hdd_adapter_t *pAdapter,
14231 v_U8_t sta_id, v_MACADDR_t *mac_addr)
14232{
14233 uint16 index;
14234 hdd_staid_hash_node_t *sta_info_node = NULL;
14235
Nirav Shah7e3c8132015-06-22 23:51:42 +053014236 index = hdd_sta_id_hash_calculate_index(pAdapter, mac_addr);
14237 sta_info_node = vos_mem_malloc(sizeof(hdd_staid_hash_node_t));
14238 if (!sta_info_node) {
Nirav Shah7e3c8132015-06-22 23:51:42 +053014239 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
14240 "%s: malloc failed", __func__);
14241 return VOS_STATUS_E_NOMEM;
14242 }
14243
14244 sta_info_node->sta_id = sta_id;
14245 vos_mem_copy(&sta_info_node->mac_addr, mac_addr, sizeof(v_MACADDR_t));
14246
Nirav Shah303ed5c2015-08-24 10:29:25 +053014247 spin_lock_bh( &pAdapter->sta_hash_lock);
14248 if (pAdapter->is_sta_id_hash_initialized != VOS_TRUE) {
14249 spin_unlock_bh( &pAdapter->sta_hash_lock);
14250 vos_mem_free(sta_info_node);
14251 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
14252 "%s: hash is not initialized for session id %d",
14253 __func__, pAdapter->sessionId);
14254 return VOS_STATUS_E_FAILURE;
14255 }
14256
Nirav Shah7e3c8132015-06-22 23:51:42 +053014257 hdd_list_insert_back ( &pAdapter->sta_id_hash.bins[index],
14258 (hdd_list_node_t*) sta_info_node );
14259 spin_unlock_bh( &pAdapter->sta_hash_lock);
14260 return VOS_STATUS_SUCCESS;
14261}
14262
14263/**
14264 * hdd_sta_id_hash_remove_entry() - remove entry from hash
14265 * @pAdapter: adapter handle
14266 * @sta_id: station id
14267 * @mac_addr: mac address
14268 *
14269 * Return: vos status
14270 */
14271VOS_STATUS hdd_sta_id_hash_remove_entry(hdd_adapter_t *pAdapter,
14272 v_U8_t sta_id, v_MACADDR_t *mac_addr)
14273{
14274 uint16 index;
14275 VOS_STATUS status;
14276 hdd_staid_hash_node_t *sta_info_node = NULL;
14277 hdd_staid_hash_node_t *next_node = NULL;
14278
14279 spin_lock_bh( &pAdapter->sta_hash_lock);
14280 if (pAdapter->is_sta_id_hash_initialized != VOS_TRUE) {
14281 spin_unlock_bh( &pAdapter->sta_hash_lock);
14282 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
14283 "%s: hash is not initialized for session id %d",
14284 __func__, pAdapter->sessionId);
14285 return VOS_STATUS_E_FAILURE;
14286 }
14287
14288 index = hdd_sta_id_hash_calculate_index(pAdapter, mac_addr);
14289 status = hdd_list_peek_front ( &pAdapter->sta_id_hash.bins[index],
14290 (hdd_list_node_t**) &sta_info_node );
14291
14292 while ( NULL != sta_info_node && VOS_STATUS_SUCCESS == status )
14293 {
14294 if (sta_info_node->sta_id == sta_id) {
14295 status = hdd_list_remove_node( &pAdapter->sta_id_hash.bins[index],
14296 &sta_info_node->node);
14297 vos_mem_free(sta_info_node);
14298 break;
14299 }
14300 status = hdd_list_peek_next (&pAdapter->sta_id_hash.bins[index],
14301 (hdd_list_node_t*)sta_info_node, (hdd_list_node_t**)&next_node);
14302 sta_info_node = next_node;
14303 }
14304 spin_unlock_bh( &pAdapter->sta_hash_lock);
14305 return status;
14306}
14307
14308/**
14309 * hdd_sta_id_find_from_mac_addr() - find sta id from mac address
14310 * @pAdapter: adapter handle
14311 * @mac_addr_in: mac address
14312 *
14313 * Return: station id
14314 */
14315int hdd_sta_id_find_from_mac_addr(hdd_adapter_t *pAdapter,
14316 v_MACADDR_t *mac_addr_in)
14317{
14318 uint8 is_found = 0;
14319 uint8 sta_id = HDD_WLAN_INVALID_STA_ID;
14320 uint16 index;
14321 VOS_STATUS status;
14322 hdd_staid_hash_node_t *sta_info_node = NULL;
14323 hdd_staid_hash_node_t *next_node = NULL;
14324
14325 spin_lock_bh( &pAdapter->sta_hash_lock);
14326 if (pAdapter->is_sta_id_hash_initialized != VOS_TRUE) {
14327 spin_unlock_bh( &pAdapter->sta_hash_lock);
Bhargav Shahce3b32c2015-08-10 12:29:24 +053014328 hddLog(VOS_TRACE_LEVEL_INFO,
Nirav Shah7e3c8132015-06-22 23:51:42 +053014329 FL("hash is not initialized for session id %d"),
14330 pAdapter->sessionId);
14331 return HDD_WLAN_INVALID_STA_ID;
14332 }
14333
14334 index = hdd_sta_id_hash_calculate_index(pAdapter, mac_addr_in);
14335 status = hdd_list_peek_front ( &pAdapter->sta_id_hash.bins[index],
14336 (hdd_list_node_t**) &sta_info_node );
14337
14338 while ( NULL != sta_info_node && VOS_STATUS_SUCCESS == status )
14339 {
14340 if (vos_mem_compare(&sta_info_node->mac_addr,
14341 mac_addr_in, sizeof(v_MACADDR_t))) {
14342 is_found = 1;
14343 sta_id = sta_info_node->sta_id;
14344 break;
14345 }
14346 status = hdd_list_peek_next (&pAdapter->sta_id_hash.bins[index],
14347 (hdd_list_node_t*)sta_info_node,
14348 (hdd_list_node_t**)&next_node);
14349 sta_info_node = next_node;
14350 }
14351 spin_unlock_bh( &pAdapter->sta_hash_lock);
14352 return sta_id;
14353}
14354
c_manjeecfd1efb2015-09-25 19:32:34 +053014355/*FW memory dump feature*/
14356/**
14357 * This structure hold information about the /proc file
14358 *
14359 */
14360static struct proc_dir_entry *proc_file, *proc_dir;
14361
14362/**
14363 * memdump_read() - perform read operation in memory dump proc file
14364 *
14365 * @file - handle for the proc file.
14366 * @buf - pointer to user space buffer.
14367 * @count - number of bytes to be read.
14368 * @pos - offset in the from buffer.
14369 *
14370 * This function performs read operation for the memory dump proc file.
14371 *
14372 * Return: number of bytes read on success, error code otherwise.
14373 */
14374static ssize_t memdump_read(struct file *file, char __user *buf,
14375 size_t count, loff_t *pos)
14376{
14377 int status;
14378 hdd_context_t *hdd_ctx = (hdd_context_t *)PDE_DATA(file_inode(file));
14379 size_t ret_count;
c_manjeef1495642015-10-13 18:35:01 +053014380 loff_t bytes_left;
c_manjeecfd1efb2015-09-25 19:32:34 +053014381 ENTER();
14382
14383 hddLog(LOG1, FL("Read req for size:%zu pos:%llu"), count, *pos);
14384 status = wlan_hdd_validate_context(hdd_ctx);
14385 if (0 != status) {
14386 return -EINVAL;
14387 }
14388
14389 if (!wlan_fwr_mem_dump_test_and_set_read_allowed_bit()) {
14390 hddLog(LOGE, FL("Current mem dump request timed out/failed"));
14391 return -EINVAL;
14392 }
14393
14394 /* run fs_read_handler in an atomic context*/
14395 vos_ssr_protect(__func__);
c_manjeef1495642015-10-13 18:35:01 +053014396 ret_count = wlan_fwr_mem_dump_fsread_handler( buf, count, pos, &bytes_left);
14397 if(bytes_left == 0)
c_manjeecfd1efb2015-09-25 19:32:34 +053014398 {
14399 /*Free the fwr mem dump buffer */
14400 wlan_free_fwr_mem_dump_buffer();
14401 wlan_set_fwr_mem_dump_state(FW_MEM_DUMP_IDLE);
c_manjeef1495642015-10-13 18:35:01 +053014402 ret_count=0;
c_manjeecfd1efb2015-09-25 19:32:34 +053014403 }
14404 /*if SSR/unload code is waiting for memdump_read to finish,signal it*/
14405 vos_ssr_unprotect(__func__);
14406 EXIT();
14407 return ret_count;
14408}
14409
14410/**
14411 * struct memdump_fops - file operations for memory dump feature
14412 * @read - read function for memory dump operation.
14413 *
14414 * This structure initialize the file operation handle for memory
14415 * dump feature
14416 */
14417static const struct file_operations memdump_fops = {
14418 read: memdump_read
14419};
14420
14421/*
14422* wlan_hdd_fw_mem_dump_cb : callback for Fw mem dump request
14423* To be passed by HDD to WDA and called upon receiving of response
14424* from firmware
14425* @fwMemDumpReqContext : memory dump request context
14426* @dump_rsp : dump response from HAL
14427* Returns none
14428*/
14429void wlan_hdd_fw_mem_dump_cb(void *fwMemDumpReqContext,
14430 tAniFwrDumpRsp *dump_rsp)
14431{
c_manjeef1495642015-10-13 18:35:01 +053014432 struct hdd_fw_mem_dump_req_ctx *pHddFwMemDumpCtx = (struct hdd_fw_mem_dump_req_ctx *)fwMemDumpReqContext;
c_manjeecfd1efb2015-09-25 19:32:34 +053014433
c_manjeef1495642015-10-13 18:35:01 +053014434 ENTER();
14435 spin_lock(&hdd_context_lock);
14436 if(!pHddFwMemDumpCtx || (FW_MEM_DUMP_MAGIC != pHddFwMemDumpCtx->magic)) {
14437 spin_unlock(&hdd_context_lock);
14438 return;
14439 }
14440 /* report the status to requesting function and free mem.*/
c_manjeecfd1efb2015-09-25 19:32:34 +053014441 if (dump_rsp->dump_status != eHAL_STATUS_SUCCESS) {
c_manjeef1495642015-10-13 18:35:01 +053014442 hddLog(LOGE, FL("fw dump request declined by fwr"));
14443 //set the request completion variable
14444 complete(&(pHddFwMemDumpCtx->req_completion));
c_manjeecfd1efb2015-09-25 19:32:34 +053014445 //Free the allocated fwr dump
14446 wlan_free_fwr_mem_dump_buffer();
14447 wlan_set_fwr_mem_dump_state(FW_MEM_DUMP_IDLE);
c_manjeecfd1efb2015-09-25 19:32:34 +053014448 }
c_manjeef1495642015-10-13 18:35:01 +053014449 else {
14450 hddLog(LOG1, FL("fw dump request accepted by fwr"));
14451 /* register the HDD callback which will be called by SVC */
14452 wlan_set_svc_fw_mem_dump_req_cb((void*)wlan_hdd_fw_mem_dump_req_cb,(void*)pHddFwMemDumpCtx);
14453 }
14454 spin_unlock(&hdd_context_lock);
c_manjeecfd1efb2015-09-25 19:32:34 +053014455 EXIT();
14456
14457}
14458
14459/**
14460 * memdump_procfs_remove() - Remove file/dir under procfs for memory dump
14461 *
14462 * This function removes file/dir under proc file system that was
14463 * processing firmware memory dump
14464 *
14465 * Return: None
14466 */
14467static void memdump_procfs_remove(void)
14468{
14469 remove_proc_entry(PROCFS_MEMDUMP_NAME, proc_dir);
14470 hddLog(LOG1 , FL("/proc/%s/%s removed\n"),
14471 PROCFS_MEMDUMP_DIR, PROCFS_MEMDUMP_NAME);
14472 remove_proc_entry(PROCFS_MEMDUMP_DIR, NULL);
14473 hddLog(LOG1 , FL("/proc/%s removed\n"), PROCFS_MEMDUMP_DIR);
14474}
14475
14476/**
14477 * memdump_procfs_init() - Initialize procfs for memory dump
14478 *
14479 * @vos_ctx - Global vos context.
14480 *
14481 * This function create file under proc file system to be used later for
14482 * processing firmware memory dump
14483 *
14484 * Return: 0 on success, error code otherwise.
14485 */
14486static int memdump_procfs_init(void *vos_ctx)
14487{
14488 hdd_context_t *hdd_ctx;
14489
14490 hdd_ctx = vos_get_context(VOS_MODULE_ID_HDD, vos_ctx);
14491 if (!hdd_ctx) {
14492 hddLog(LOGE , FL("Invalid HDD context"));
14493 return -EINVAL;
14494 }
14495
14496 proc_dir = proc_mkdir(PROCFS_MEMDUMP_DIR, NULL);
14497 if (proc_dir == NULL) {
14498 remove_proc_entry(PROCFS_MEMDUMP_DIR, NULL);
14499 hddLog(LOGE , FL("Error: Could not initialize /proc/%s"),
14500 PROCFS_MEMDUMP_DIR);
14501 return -ENOMEM;
14502 }
14503
14504 proc_file = proc_create_data(PROCFS_MEMDUMP_NAME,
14505 S_IRUSR | S_IWUSR, proc_dir,
14506 &memdump_fops, hdd_ctx);
14507 if (proc_file == NULL) {
14508 remove_proc_entry(PROCFS_MEMDUMP_NAME, proc_dir);
14509 hddLog(LOGE , FL("Error: Could not initialize /proc/%s"),
14510 PROCFS_MEMDUMP_NAME);
14511 return -ENOMEM;
14512 }
14513
14514 hddLog(LOG1 , FL("/proc/%s/%s created"),
14515 PROCFS_MEMDUMP_DIR, PROCFS_MEMDUMP_NAME);
14516
14517 return 0;
14518}
14519
14520/**
14521 * memdump_init() - Initialization function for memory dump feature
14522 *
14523 * This function creates proc file for memdump feature and registers
14524 * HDD callback function with SME.
14525 *
14526 * Return - 0 on success, error otherwise
14527 */
14528int memdump_init(void)
14529{
14530 hdd_context_t *hdd_ctx;
14531 void *vos_ctx;
14532 int status = 0;
14533
14534 vos_ctx = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
14535 if (!vos_ctx) {
14536 hddLog(LOGE, FL("Invalid VOS context"));
14537 return -EINVAL;
14538 }
14539
14540 hdd_ctx = vos_get_context(VOS_MODULE_ID_HDD, vos_ctx);
14541 if (!hdd_ctx) {
14542 hddLog(LOGE , FL("Invalid HDD context"));
14543 return -EINVAL;
14544 }
14545
14546 status = memdump_procfs_init(vos_ctx);
14547 if (status) {
14548 hddLog(LOGE , FL("Failed to create proc file"));
14549 return status;
14550 }
14551
14552 return 0;
14553}
14554
14555/**
14556 * memdump_deinit() - De initialize memdump feature
14557 *
14558 * This function removes proc file created for memdump feature.
14559 *
14560 * Return: None
14561 */
14562int memdump_deinit(void)
14563{
14564 hdd_context_t *hdd_ctx;
14565 void *vos_ctx;
14566
14567 vos_ctx = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
14568 if (!vos_ctx) {
14569 hddLog(LOGE, FL("Invalid VOS context"));
14570 return -EINVAL;
14571 }
14572
14573 hdd_ctx = vos_get_context(VOS_MODULE_ID_HDD, vos_ctx);
14574 if(!hdd_ctx) {
14575 hddLog(LOGE , FL("Invalid HDD context"));
14576 return -EINVAL;
14577 }
14578
14579 memdump_procfs_remove();
14580 return 0;
14581}
14582
14583/**
14584 * wlan_hdd_fw_mem_dump_req(pHddCtx) - common API(cfg80211/ioctl) for requesting fw mem dump to SME
14585 * Return: HAL status
14586 */
14587
14588int wlan_hdd_fw_mem_dump_req(hdd_context_t * pHddCtx)
14589{
14590 tAniFwrDumpReq fw_mem_dump_req={0};
c_manjeef1495642015-10-13 18:35:01 +053014591 struct hdd_fw_mem_dump_req_ctx fw_mem_dump_ctx;
c_manjeecfd1efb2015-09-25 19:32:34 +053014592 eHalStatus status = eHAL_STATUS_FAILURE;
Abhishek Singh4eca9822015-12-09 18:07:34 +053014593 int ret=0, result;
c_manjeecfd1efb2015-09-25 19:32:34 +053014594 ENTER();
c_manjeef1495642015-10-13 18:35:01 +053014595
c_manjeecfd1efb2015-09-25 19:32:34 +053014596 /*Check whether a dump request is already going on
14597 *Caution this function will free previously held memory if new dump request is allowed*/
14598 if (!wlan_fwr_mem_dump_test_and_set_write_allowed_bit()) {
14599 hddLog(LOGE, FL("Fw memdump already in progress"));
14600 return -EBUSY;
14601 }
14602 //Allocate memory for fw mem dump buffer
14603 ret = wlan_fwr_mem_dump_buffer_allocation();
14604 if(ret == -EFAULT)
14605 {
14606 hddLog(LOGE, FL("Fwr mem dump not supported by FW"));
14607 return ret;
14608 }
14609 if (0 != ret) {
14610 hddLog(LOGE, FL("Fwr mem Allocation failed"));
14611 return -ENOMEM;
14612 }
c_manjeef1495642015-10-13 18:35:01 +053014613 init_completion(&fw_mem_dump_ctx.req_completion);
14614 fw_mem_dump_ctx.magic = FW_MEM_DUMP_MAGIC;
14615 fw_mem_dump_ctx.status = false;
14616
c_manjeecfd1efb2015-09-25 19:32:34 +053014617 fw_mem_dump_req.fwMemDumpReqCallback = wlan_hdd_fw_mem_dump_cb;
c_manjeef1495642015-10-13 18:35:01 +053014618 fw_mem_dump_req.fwMemDumpReqContext = &fw_mem_dump_ctx;
c_manjeecfd1efb2015-09-25 19:32:34 +053014619 status = sme_FwMemDumpReq(pHddCtx->hHal, &fw_mem_dump_req);
14620 if(eHAL_STATUS_SUCCESS != status)
14621 {
14622 hddLog(VOS_TRACE_LEVEL_ERROR,
14623 "%s: fw_mem_dump_req failed ", __func__);
14624 wlan_free_fwr_mem_dump_buffer();
c_manjeef1495642015-10-13 18:35:01 +053014625 ret = -EFAULT;
14626 goto cleanup;
c_manjeecfd1efb2015-09-25 19:32:34 +053014627 }
c_manjeef1495642015-10-13 18:35:01 +053014628 /*wait for fw mem dump completion to send event to userspace*/
Abhishek Singh4eca9822015-12-09 18:07:34 +053014629 result =
14630 wait_for_completion_timeout(&fw_mem_dump_ctx.req_completion,
14631 msecs_to_jiffies(FW_MEM_DUMP_TIMEOUT_MS));
14632 if (0 >= result )
c_manjeef1495642015-10-13 18:35:01 +053014633 {
14634 hddLog(VOS_TRACE_LEVEL_ERROR,
Abhishek Singh4eca9822015-12-09 18:07:34 +053014635 "%s: fw_mem_dump_req timeout %d ", __func__,result);
14636 ret = -ETIMEDOUT;
c_manjeef1495642015-10-13 18:35:01 +053014637 }
14638cleanup:
14639 spin_lock(&hdd_context_lock);
14640 fw_mem_dump_ctx.magic = 0;
Abhishek Singh4eca9822015-12-09 18:07:34 +053014641 if(!ret && !fw_mem_dump_ctx.status)
14642 ret = -EFAULT;
c_manjeef1495642015-10-13 18:35:01 +053014643 spin_unlock(&hdd_context_lock);
c_manjeecfd1efb2015-09-25 19:32:34 +053014644
c_manjeef1495642015-10-13 18:35:01 +053014645 EXIT();
Abhishek Singh4eca9822015-12-09 18:07:34 +053014646 return ret;
c_manjeef1495642015-10-13 18:35:01 +053014647}
14648
14649/**
14650 * HDD callback which will be called by SVC to indicate mem dump completion.
14651 */
14652void wlan_hdd_fw_mem_dump_req_cb(struct hdd_fw_mem_dump_req_ctx* pHddFwMemDumpCtx)
14653{
14654 if (!pHddFwMemDumpCtx) {
14655 hddLog(VOS_TRACE_LEVEL_ERROR,
14656 "%s: HDD context not valid ", __func__);
14657 return;
14658 }
14659 spin_lock(&hdd_context_lock);
14660 /* check the req magic and set status */
14661 if (pHddFwMemDumpCtx->magic == FW_MEM_DUMP_MAGIC)
14662 {
14663 pHddFwMemDumpCtx->status = true;
14664 //signal the completion
14665 complete(&(pHddFwMemDumpCtx->req_completion));
14666 }
14667 else
14668 {
14669 hddLog(VOS_TRACE_LEVEL_ERROR,
14670 "%s: fw mem dump request possible timeout ", __func__);
14671 }
14672 spin_unlock(&hdd_context_lock);
c_manjeecfd1efb2015-09-25 19:32:34 +053014673}
14674
Mahesh A Saptasagar67ab9222015-10-21 15:38:41 +053014675void hdd_initialize_adapter_common(hdd_adapter_t *pAdapter)
14676{
14677 if (NULL == pAdapter)
14678 {
14679 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: pAdapter is NULL ", __func__);
14680 return;
14681 }
14682 init_completion(&pAdapter->session_open_comp_var);
14683 init_completion(&pAdapter->session_close_comp_var);
14684 init_completion(&pAdapter->disconnect_comp_var);
14685 init_completion(&pAdapter->linkup_event_var);
14686 init_completion(&pAdapter->cancel_rem_on_chan_var);
14687 init_completion(&pAdapter->rem_on_chan_ready_event);
14688 init_completion(&pAdapter->pno_comp_var);
14689#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
14690 init_completion(&pAdapter->offchannel_tx_event);
14691#endif
14692 init_completion(&pAdapter->tx_action_cnf_event);
14693#ifdef FEATURE_WLAN_TDLS
14694 init_completion(&pAdapter->tdls_add_station_comp);
14695 init_completion(&pAdapter->tdls_del_station_comp);
14696 init_completion(&pAdapter->tdls_mgmt_comp);
14697 init_completion(&pAdapter->tdls_link_establish_req_comp);
14698#endif
14699
14700#ifdef WLAN_FEATURE_RMC
14701 init_completion(&pAdapter->ibss_peer_info_comp);
14702#endif /* WLAN_FEATURE_RMC */
14703 init_completion(&pAdapter->ula_complete);
14704 init_completion(&pAdapter->change_country_code);
14705
14706#ifdef FEATURE_WLAN_BATCH_SCAN
14707 init_completion(&pAdapter->hdd_set_batch_scan_req_var);
14708 init_completion(&pAdapter->hdd_get_batch_scan_req_var);
14709#endif
14710
14711 return;
14712}
c_manjeecfd1efb2015-09-25 19:32:34 +053014713
Anurag Chouhan0b29de02016-12-16 13:18:40 +053014714#ifdef MDNS_OFFLOAD
14715
14716/**
14717 * hdd_mdns_enable_offload_done() - mdns enable offload response api
14718 * @padapter: holds adapter
14719 * @status: response status
14720 *
14721 * Return - None
14722 */
14723void hdd_mdns_enable_offload_done(void *padapter, VOS_STATUS status)
14724{
14725 hdd_adapter_t* adapter = (hdd_adapter_t*) padapter;
14726
14727 ENTER();
14728
14729 if (NULL == adapter)
14730 {
14731 hddLog(VOS_TRACE_LEVEL_ERROR,
14732 "%s: adapter is NULL",__func__);
14733 return;
14734 }
14735
14736 adapter->mdns_status.mdns_enable_status = status;
14737 vos_event_set(&adapter->mdns_status.vos_event);
14738 return;
14739}
14740
14741/**
14742 * hdd_mdns_fqdn_offload_done() - mdns fqdn offload response api
14743 * @padapter: holds adapter
14744 * @status: responce status
14745 *
14746 * Return - None
14747 */
14748void hdd_mdns_fqdn_offload_done(void *padapter, VOS_STATUS status)
14749{
14750 hdd_adapter_t* adapter = (hdd_adapter_t*) padapter;
14751
14752 ENTER();
14753
14754 if (NULL == adapter)
14755 {
14756 hddLog(VOS_TRACE_LEVEL_ERROR,
14757 "%s: adapter is NULL",__func__);
14758 return;
14759 }
14760
14761 adapter->mdns_status.mdns_fqdn_status = status;
14762 return;
14763}
14764
14765/**
14766 * hdd_mdns_resp_offload_done() - mdns resp offload response api
14767 * @padapter: holds adapter
14768 * @status: responce status
14769 *
14770 * Return - None
14771 */
14772void hdd_mdns_resp_offload_done(void *padapter, VOS_STATUS status)
14773{
14774 hdd_adapter_t* adapter = (hdd_adapter_t*) padapter;
14775
14776 ENTER();
14777
14778 if (NULL == adapter)
14779 {
14780 hddLog(VOS_TRACE_LEVEL_ERROR,
14781 "%s: adapter is NULL",__func__);
14782 return;
14783 }
14784
14785 adapter->mdns_status.mdns_resp_status = status;
14786 return;
14787}
14788
14789/**
14790 * wlan_hdd_mdns_process_response_dname() - Process mDNS domain name
14791 * @response: Pointer to a struct hdd_mdns_resp_info
14792 * @resp_info: Pointer to a struct tSirMDNSResponseInfo
14793 *
14794 * This function will pack the whole domain name without compression. It will
14795 * add the leading len for each field and add zero length octet to terminate
14796 * the domain name.
14797 *
14798 * Return: Return boolean. TRUE for success, FALSE for fail.
14799 */
14800static bool
14801wlan_hdd_mdns_process_response_dname(struct hdd_mdns_resp_info *response,
14802 sir_mdns_resp_info resp_info)
14803{
14804 uint8_t num;
14805 uint16_t idx;
14806 uint8_t len = 0;
14807
14808 if ((response == NULL) || (response->data == NULL) ||
14809 (response->offset == NULL)) {
14810 hddLog(LOGE, FL("Either data or offset in response is NULL!"));
14811 return FALSE;
14812 }
14813
14814 if ((resp_info == NULL) ||
14815 (resp_info->resp_len >= MAX_MDNS_RESP_LEN)) {
14816 hddLog(LOGE, FL("resp_len exceeds %d!"), MAX_MDNS_RESP_LEN);
14817 return FALSE;
14818 }
14819
14820 for (num = 0; num < response->num_entries; num++) {
14821 response->offset[num] =
14822 resp_info->resp_len + MDNS_HEADER_LEN;
14823 idx = num * MAX_LEN_DOMAINNAME_FIELD;
14824 len = strlen((char *)&response->data[idx]);
14825 if ((resp_info->resp_len + len + 1) >= MAX_MDNS_RESP_LEN) {
14826 hddLog(LOGE, FL("resp_len exceeds %d!"),
14827 MAX_MDNS_RESP_LEN);
14828 return FALSE;
14829 }
14830 resp_info->resp_data[resp_info->resp_len] = len;
14831 resp_info->resp_len++;
14832 vos_mem_copy(&resp_info->resp_data[resp_info->resp_len],
14833 &response->data[idx], len);
14834 resp_info->resp_len += len;
14835 }
14836
14837 /* The domain name terminates with the zero length octet */
14838 if (num == response->num_entries) {
14839 if (resp_info->resp_len >= MAX_MDNS_RESP_LEN) {
14840 hddLog(LOGE, FL("resp_len exceeds %d!"),
14841 MAX_MDNS_RESP_LEN);
14842 return FALSE;
14843 }
14844 resp_info->resp_data[resp_info->resp_len] = 0;
14845 resp_info->resp_len++;
14846 }
14847
14848 return TRUE;
14849}
14850
14851/**
14852 * wlan_hdd_mdns_format_response_u16() - Form uint16_t response data
14853 * @value: The uint16_t value is formed to the struct tSirMDNSResponseInfo
14854 * @resp_info: Pointer to a struct tSirMDNSResponseInfo
14855 *
14856 * Return: None
14857 */
14858static void wlan_hdd_mdns_format_response_u16(uint16_t value,
14859 sir_mdns_resp_info resp_info)
14860{
14861 uint8_t val_u8;
14862
14863 if ((resp_info == NULL) || (resp_info->resp_data == NULL))
14864 return;
14865 val_u8 = (value & 0xff00) >> 8;
14866 resp_info->resp_data[resp_info->resp_len++] = val_u8;
14867 val_u8 = value & 0xff;
14868 resp_info->resp_data[resp_info->resp_len++] = val_u8;
14869}
14870
14871/**
14872 * wlan_hdd_mdns_format_response_u32() - Form uint32_t response data
14873 * @value: The uint32_t value is formed to the struct tSirMDNSResponseInfo
14874 * @resp_info: Pointer to a struct tSirMDNSResponseInfo
14875 *
14876 * Return: None
14877 */
14878static void wlan_hdd_mdns_format_response_u32(uint32_t value,
14879 sir_mdns_resp_info resp_info)
14880{
14881 uint8_t val_u8;
14882
14883 if ((resp_info == NULL) || (resp_info->resp_data == NULL))
14884 return;
14885 val_u8 = (value & 0xff000000) >> 24;
14886 resp_info->resp_data[resp_info->resp_len++] = val_u8;
14887 val_u8 = (value & 0xff0000) >> 16;
14888 resp_info->resp_data[resp_info->resp_len++] = val_u8;
14889 val_u8 = (value & 0xff00) >> 8;
14890 resp_info->resp_data[resp_info->resp_len++] = val_u8;
14891 val_u8 = value & 0xff;
14892 resp_info->resp_data[resp_info->resp_len++] = val_u8;
14893}
14894
14895/**
14896 * wlan_hdd_mdns_process_response_misc() - Process misc info in mDNS response
14897 * @resp_type: Response type for mDNS
14898 * @resp_info: Pointer to a struct tSirMDNSResponseInfo
14899 *
14900 * This function will pack the response type, class and TTL (Time To Live).
14901 *
14902 * Return: Return boolean. TRUE for success, FALSE for fail.
14903 */
14904static bool wlan_hdd_mdns_process_response_misc(uint16_t resp_type,
14905 sir_mdns_resp_info resp_info)
14906{
14907 uint16_t len;
14908
14909 if (resp_info == NULL) {
14910 hddLog(LOGE, FL("resp_info is NULL!"));
14911 return FALSE;
14912 }
14913
14914 len = resp_info->resp_len + (2 * sizeof(uint16_t) + sizeof(uint32_t));
14915 if (len >= MAX_MDNS_RESP_LEN) {
14916 hddLog(LOGE, FL("resp_len exceeds %d!"), MAX_MDNS_RESP_LEN);
14917 return FALSE;
14918 }
14919
14920 /* Fill Type, Class, TTL */
14921 wlan_hdd_mdns_format_response_u16(resp_type, resp_info);
14922 wlan_hdd_mdns_format_response_u16(MDNS_CLASS, resp_info);
14923 wlan_hdd_mdns_format_response_u32(MDNS_TTL, resp_info);
14924
14925 return TRUE;
14926}
14927
14928/**
14929 * wlan_hdd_mdns_compress_data() - Compress the domain name in mDNS response
14930 * @resp_info: Pointer to a struct tSirMDNSResponseInfo
14931 * @response_dst: The response which domain name is compressed.
14932 * @response_src: The response which domain name is matched with response_dst.
14933 * Its offset is used for data compression.
14934 * @num_matched: The number of matched entries between response_dst and
14935 * response_src
14936 *
14937 * This function will form the different fields of domain name in response_dst
14938 * if any. Then use the offset of the matched domain name in response_src to
14939 * compress the matched domain name.
14940 *
14941 * Return: Return boolean. TRUE for success, FALSE for fail.
14942 */
14943static bool
14944wlan_hdd_mdns_compress_data(sir_mdns_resp_info resp_info,
14945 struct hdd_mdns_resp_info *response_dst,
14946 struct hdd_mdns_resp_info *response_src,
14947 uint8_t num_matched)
14948{
14949 uint8_t num, num_diff;
14950 uint16_t value, idx;
14951 uint8_t len = 0;
14952
14953 if ((response_src == NULL) || (response_dst == NULL) ||
14954 (resp_info == NULL)) {
14955 hddLog(LOGE, FL("response info is NULL!"));
14956 return FALSE;
14957 }
14958
14959 if (response_dst->num_entries < num_matched) {
14960 hddLog(LOGE, FL("num_entries is less than num_matched!"));
14961 return FALSE;
14962 }
14963
14964 if (resp_info->resp_len >= MAX_MDNS_RESP_LEN) {
14965 hddLog(LOGE, FL("resp_len exceeds %d!"), MAX_MDNS_RESP_LEN);
14966 return FALSE;
14967 }
14968
14969 num_diff = response_dst->num_entries - num_matched;
14970 if ((num_diff > 0) && (response_dst->data == NULL)) {
14971 hddLog(LOGE, FL("response_dst->data is NULL!"));
14972 return FALSE;
14973 }
14974
14975 /*
14976 * Handle the unmatched string at the beginning
14977 * Store the length of octets and the octets
14978 */
14979 for (num = 0; num < num_diff; num++) {
14980 response_dst->offset[num] =
14981 resp_info->resp_len + MDNS_HEADER_LEN;
14982 idx = num * MAX_LEN_DOMAINNAME_FIELD;
14983 len = strlen((char *)&response_dst->data[idx]);
14984 if ((resp_info->resp_len + len + 1) >= MAX_MDNS_RESP_LEN) {
14985 hddLog(LOGE, FL("resp_len exceeds %d!"),
14986 MAX_MDNS_RESP_LEN);
14987 return FALSE;
14988 }
14989 resp_info->resp_data[resp_info->resp_len] = len;
14990 resp_info->resp_len++;
14991 vos_mem_copy(&resp_info->resp_data[resp_info->resp_len],
14992 &response_dst->data[idx], len);
14993 resp_info->resp_len += len;
14994 }
14995 /*
14996 * Handle the matched string from the end
14997 * Just keep the offset and mask the leading two bit
14998 */
14999 if (response_src->num_entries >= num_matched) {
15000 num_diff = response_src->num_entries - num_matched;
15001 value = response_src->offset[num_diff];
15002 if (value > 0) {
15003 value |= 0xc000;
15004 if ((resp_info->resp_len + sizeof(uint16_t)) >=
15005 MAX_MDNS_RESP_LEN) {
15006 hddLog(LOGE, FL("resp_len exceeds %d!"),
15007 MAX_MDNS_RESP_LEN);
15008 return FALSE;
15009 }
15010 wlan_hdd_mdns_format_response_u16(value, resp_info);
15011 return TRUE;
15012 }
15013 }
15014 return FALSE;
15015}
15016
15017/**
15018 * wlan_hdd_mdns_reset_response() - Reset the response info
15019 * @response: The response which info is reset.
15020 *
15021 * Return: None
15022 */
15023static void wlan_hdd_mdns_reset_response(struct hdd_mdns_resp_info *response)
15024{
15025 if (response == NULL)
15026 return;
15027 response->num_entries = 0;
15028 response->data = NULL;
15029 response->offset = NULL;
15030}
15031
15032/**
15033 * wlan_hdd_mdns_init_response() - Initialize the response info
15034 * @response: The response which info is initiatized.
15035 * @resp_dname: The domain name string which might be tokenized.
15036 *
15037 * This function will allocate the memory for both response->data and
15038 * response->offset. Besides, it will also tokenize the domain name to some
15039 * entries and fill response->num_entries with the num of entries.
15040 *
15041 * Return: Return boolean. TRUE for success, FALSE for fail.
15042 */
15043static bool wlan_hdd_mdns_init_response(struct hdd_mdns_resp_info *response,
15044 uint8_t *resp_dname, char separator)
15045{
15046 uint16_t size;
15047
15048 if ((resp_dname == NULL) || (response == NULL)) {
15049 hddLog(LOGE, FL("resp_dname or response is NULL!"));
15050 return FALSE;
15051 }
15052
15053 size = MAX_NUM_FIELD_DOMAINNAME * MAX_LEN_DOMAINNAME_FIELD;
15054 response->data = vos_mem_malloc(size);
15055 if (response->data) {
15056 vos_mem_zero(response->data, size);
15057 if (VOS_STATUS_SUCCESS !=
15058 hdd_string_to_string_array((char *)resp_dname,
15059 response->data,
15060 separator,
15061 &response->num_entries,
15062 MAX_NUM_FIELD_DOMAINNAME,
15063 MAX_LEN_DOMAINNAME_FIELD)) {
15064 hddLog(LOGE, FL("hdd_string_to_string_array fail!"));
15065 goto err_init_resp;
15066 }
15067
15068 if ((response->num_entries > 0) &&
15069 (strlen((char *)&response->data[0]) > 0)) {
15070 size = sizeof(uint16_t) * response->num_entries;
15071 response->offset = vos_mem_malloc(size);
15072 if (response->offset) {
15073 vos_mem_zero(response->offset, size);
15074 return TRUE;
15075 }
15076 }
15077 }
15078
15079err_init_resp:
15080 if (response->data)
15081 vos_mem_free(response->data);
15082 wlan_hdd_mdns_reset_response(response);
15083 return FALSE;
15084}
15085
15086/**
15087 * wlan_hdd_mdns_find_entries_from_end() - Find the matched entries
15088 * @response1: The response info is used to be compared.
15089 * @response2: The response info is used to be compared.
15090 *
15091 * This function will find the matched entries from the end.
15092 *
15093 * Return: Return the number of the matched entries.
15094 */
15095static uint8_t
15096wlan_hdd_mdns_find_entries_from_end(struct hdd_mdns_resp_info *response1,
15097 struct hdd_mdns_resp_info *response2)
15098{
15099 uint8_t min, len1, i;
15100 uint16_t num1, num2;
15101 uint8_t num_matched = 0;
15102
15103 min = VOS_MIN(response1->num_entries, response2->num_entries);
15104
15105 for (i = 1; i <= min; i++) {
15106 num1 = (response1->num_entries - i);
15107 num1 *= MAX_LEN_DOMAINNAME_FIELD;
15108 num2 = (response2->num_entries - i);
15109 num2 *= MAX_LEN_DOMAINNAME_FIELD;
15110 len1 = strlen((char *)&response1->data[num1]);
15111
15112 if ((len1 == 0) ||
15113 (len1 != strlen((char *)&response2->data[num2])))
15114 break;
15115 if (memcmp(&response1->data[num1],
15116 &response2->data[num2], len1))
15117 break;
15118 else
15119 num_matched++;
15120 }
15121
15122 return num_matched;
15123}
15124
15125/**
15126 * wlan_hdd_mdns_find_max() - Find the maximum number of the matched entries
15127 * @matchedlist: Pointer to the array of struct hdd_mdns_resp_matched
15128 * @numlist: The number of the elements in the array matchedlist.
15129 *
15130 * Find the max number of the matched entries among the array matchedlist.
15131 *
15132 * Return: None
15133 */
15134static void wlan_hdd_mdns_find_max(struct hdd_mdns_resp_matched *matchedlist,
15135 uint8_t numlist)
15136{
15137 int j;
15138 struct hdd_mdns_resp_matched tmp;
15139
15140 /* At least two values are used for sorting */
15141 if ((numlist < 2) || (matchedlist == NULL)) {
15142 hddLog(LOGE, FL("At least two values are used for sorting!"));
15143 return;
15144 }
15145
15146 for (j = 0; j < numlist-1; j++) {
15147 if (matchedlist[j].num_matched >
15148 matchedlist[j+1].num_matched) {
15149 vos_mem_copy(&tmp, &matchedlist[j],
15150 sizeof(struct hdd_mdns_resp_matched));
15151 vos_mem_copy(&matchedlist[j], &matchedlist[j+1],
15152 sizeof(struct hdd_mdns_resp_matched));
15153 vos_mem_copy(&matchedlist[j+1], &tmp,
15154 sizeof(struct hdd_mdns_resp_matched));
15155 }
15156 }
15157}
15158
15159/**
15160 * wlan_hdd_mdns_pack_response_type_a() - Pack Type A response
15161 * @ini_config: Pointer to the struct hdd_config_t
15162 * @resp_info: Pointer to the struct tSirMDNSResponseInfo
15163 * @resptype_a: Pointer to the struct hdd_mdns_resp_info of Type A
15164 *
15165 * Type A response include QName, response type, class, TTL and Ipv4.
15166 *
15167 * Return: Return boolean. TRUE for success, FALSE for fail.
15168 */
15169static bool
15170wlan_hdd_mdns_pack_response_type_a(hdd_config_t *ini_config,
15171 sir_mdns_resp_info resp_info,
15172 struct hdd_mdns_resp_info *resptype_a)
15173{
15174 uint16_t value;
15175 uint32_t len;
15176
15177 ENTER();
15178 if ((ini_config == NULL) || (resp_info == NULL) ||
15179 (resptype_a == NULL)) {
15180 hddLog(LOGE, FL("ini_config or response info is NULL!"));
15181 return FALSE;
15182 }
15183
15184 /* No Type A response */
15185 if (strlen((char *)ini_config->mdns_resp_type_a) <= 0)
15186 return TRUE;
15187
15188 /* Wrong response is assigned, just ignore this response */
15189 if (!wlan_hdd_mdns_init_response(resptype_a,
15190 ini_config->mdns_resp_type_a, '.'))
15191 return TRUE;
15192
15193 /* Process response domain name */
15194 if (!wlan_hdd_mdns_process_response_dname(resptype_a, resp_info)) {
15195 hddLog(LOGE, FL("Fail to process mDNS response (%d)!"),
15196 MDNS_TYPE_A);
15197 return FALSE;
15198 }
15199
15200 /* Process response Type, Class, TTL */
15201 if (!wlan_hdd_mdns_process_response_misc(MDNS_TYPE_A, resp_info)) {
15202 hddLog(LOGE, FL("Fail to process mDNS misc response (%d)!"),
15203 MDNS_TYPE_A);
15204 return FALSE;
15205 }
15206
15207 /* Process response RDLength, RData */
15208 len = sizeof(uint16_t) + sizeof(uint32_t);
15209 len += resp_info->resp_len;
15210 if (len >= MAX_MDNS_RESP_LEN) {
15211 hddLog(LOGE, FL("resp_len exceeds %d!"), MAX_MDNS_RESP_LEN);
15212 return FALSE;
15213 }
15214 value = sizeof(uint32_t);
15215 wlan_hdd_mdns_format_response_u16(value, resp_info);
15216 wlan_hdd_mdns_format_response_u32(ini_config->mdns_resp_type_a_ipv4,
15217 resp_info);
15218
15219 EXIT();
15220 return TRUE;
15221}
15222
15223/**
15224 * wlan_hdd_mdns_pack_response_type_txt() - Pack Type Txt response
15225 * @ini_config: Pointer to the struct hdd_config_t
15226 * @resp_info: Pointer to the struct tSirMDNSResponseInfo
15227 * @resptype_txt: Pointer to the struct hdd_mdns_resp_info of Type txt
15228 * @resptype_a: Pointer to the struct hdd_mdns_resp_info of Type A
15229 *
15230 * Type Txt response include QName, response type, class, TTL and text content.
15231 * Also, it will find the matched QName from resptype_A and compress the data.
15232 *
15233 * Return: Return boolean. TRUE for success, FALSE for fail.
15234 */
15235static bool
15236wlan_hdd_mdns_pack_response_type_txt(hdd_config_t *ini_config,
15237 sir_mdns_resp_info resp_info,
15238 struct hdd_mdns_resp_info *resptype_txt,
15239 struct hdd_mdns_resp_info *resptype_a)
15240{
15241 uint8_t num_matched;
15242 uint8_t num;
15243 uint16_t idx;
15244 uint16_t value = 0;
15245 uint32_t len;
15246 uint32_t total_len;
15247 bool status;
15248 struct hdd_mdns_resp_info resptype_content;
15249
15250 ENTER();
15251
15252 if ((ini_config == NULL) || (resp_info == NULL) ||
15253 (resptype_txt == NULL)) {
15254 hddLog(LOGE, FL("ini_config or response info is NULL!"));
15255 return FALSE;
15256 }
15257
15258 /* No Type Txt response */
15259 if (strlen((char *)ini_config->mdns_resp_type_txt) <= 0)
15260 return TRUE;
15261
15262 /* Wrong response is assigned, just ignore this response */
15263 if (!wlan_hdd_mdns_init_response(resptype_txt,
15264 ini_config->mdns_resp_type_txt, '.'))
15265 return TRUE;
15266
15267 /*
15268 * For data compression
15269 * Check if any strings are matched with Type A response
15270 */
15271 if (resptype_a && (resptype_a->num_entries > 0)) {
15272 num_matched = wlan_hdd_mdns_find_entries_from_end(resptype_txt,
15273 resptype_a);
15274 if (num_matched > 0) {
15275 if (!wlan_hdd_mdns_compress_data(resp_info,
15276 resptype_txt, resptype_a, num_matched)) {
15277 hddLog(LOGE, FL("Fail to compress mDNS "
15278 "response (%d)!"), MDNS_TYPE_TXT);
15279 return FALSE;
15280 }
15281 } else {
15282 /*
15283 * num_matched is zero. Error!
15284 * At least ".local" is needed.
15285 */
15286 hddLog(LOGE, FL("No matched string! Fail to pack mDNS "
15287 "response (%d)!"), MDNS_TYPE_TXT);
15288 return FALSE;
15289 }
15290 } else {
15291 /* no TypeA response, so show the whole data */
15292 if (!wlan_hdd_mdns_process_response_dname(resptype_txt,
15293 resp_info)) {
15294 hddLog(LOGE, FL("Fail to process mDNS response (%d)!"),
15295 MDNS_TYPE_TXT);
15296 return FALSE;
15297 }
15298 }
15299
15300 /* Process response Type, Class, TTL */
15301 if (!wlan_hdd_mdns_process_response_misc(MDNS_TYPE_TXT, resp_info)) {
15302 hddLog(LOGE, FL("Fail to process mDNS misc response (%d)!"),
15303 MDNS_TYPE_TXT);
15304 return FALSE;
15305 }
15306
15307 /*
15308 * Process response RDLength, RData.
15309 * TypeTxt RData include len.
15310 */
15311 status = wlan_hdd_mdns_init_response(&resptype_content,
15312 ini_config->mdns_resp_type_txt_content,
15313 '/');
15314 if (status == FALSE) {
15315 hddLog(LOGE, FL("wlan_hdd_mdns_init_response FAIL"));
15316 return FALSE;
15317 }
15318
15319 for (num = 0; num < resptype_content.num_entries; num++) {
15320 idx = num * MAX_LEN_DOMAINNAME_FIELD;
15321 value += strlen((char *)&resptype_content.data[idx]);
15322 }
15323
15324 /* content len is uint16_t */
15325 total_len = sizeof(uint16_t);
15326 total_len += resp_info->resp_len + value +
15327 resptype_content.num_entries;
15328
15329 if (total_len >= MAX_MDNS_RESP_LEN) {
15330 hddLog(LOGE, FL("resp_len exceeds %d!"), MAX_MDNS_RESP_LEN);
15331 return FALSE;
15332 }
15333 wlan_hdd_mdns_format_response_u16(value + resptype_content.num_entries,
15334 resp_info);
15335
15336 for (num = 0; num < resptype_content.num_entries; num++) {
15337 idx = num * MAX_LEN_DOMAINNAME_FIELD;
15338 len = strlen((char *)&resptype_content.data[idx]);
15339 resp_info->resp_data[resp_info->resp_len] = len;
15340 resp_info->resp_len++;
15341
15342 vos_mem_copy(&resp_info->resp_data[resp_info->resp_len],
15343 &resptype_content.data[idx], len);
15344
15345 resp_info->resp_len += len;
15346 hddLog(LOG1, FL("index = %d, len = %d, str = %s"),
15347 num, len, &resptype_content.data[idx]);
15348 }
15349
15350 EXIT();
15351 return TRUE;
15352}
15353
15354/**
15355 * wlan_hdd_mdns_pack_response_type_ptr_dname() - Pack Type PTR domain name
15356 * @ini_config: Pointer to the struct hdd_config_t
15357 * @resp_info: Pointer to the struct tSirMDNSResponseInfo
15358 * @resptype_ptr_dn: Pointer to the struct hdd_mdns_resp_info of Type Ptr
15359 * domain name
15360 * @resptype_ptr: Pointer to the struct hdd_mdns_resp_info of Type Ptr
15361 * @resptype_txt: Pointer to the struct hdd_mdns_resp_info of Type Txt
15362 * @resptype_a: Pointer to the struct hdd_mdns_resp_info of Type A
15363 *
15364 * The Type Ptr response include Type PTR domain name in its data field.
15365 * Also, it will find the matched QName from the existing resptype_ptr,
15366 * resptype_txt, resptype_a and then compress the data.
15367 *
15368 * Return: Return boolean. TRUE for success, FALSE for fail.
15369 */
15370static bool
15371wlan_hdd_mdns_pack_response_type_ptr_dname(hdd_config_t *ini_config,
15372 sir_mdns_resp_info resp_info,
15373 struct hdd_mdns_resp_info *resptype_ptr_dn,
15374 struct hdd_mdns_resp_info *resptype_ptr,
15375 struct hdd_mdns_resp_info *resptype_txt,
15376 struct hdd_mdns_resp_info *resptype_a)
15377{
15378 uint8_t num_matched, numlist, size;
15379 struct hdd_mdns_resp_matched matchedlist[MAX_MDNS_RESP_TYPE-1];
15380 struct hdd_mdns_resp_info *resp;
15381
15382 if ((ini_config == NULL) || (resp_info == NULL) ||
15383 (resptype_ptr == NULL) || (resptype_ptr_dn == NULL)) {
15384 hddLog(LOGE, FL("ini_config or response info is NULL!"));
15385 return FALSE;
15386 }
15387
15388 /* No Type Ptr domain name response */
15389 if (strlen((char *)ini_config->mdns_resp_type_ptr_dname) <= 0)
15390 return TRUE;
15391
15392 /* Wrong response is assigned, just ignore this response */
15393 if (!wlan_hdd_mdns_init_response(resptype_ptr_dn,
15394 ini_config->mdns_resp_type_ptr_dname, '.'))
15395 return TRUE;
15396
15397 /*
15398 * For data compression
15399 * Check if any strings are matched with previous
15400 * response.
15401 */
15402 numlist = 0;
15403 size = (MAX_MDNS_RESP_TYPE-1);
15404 size *= sizeof(struct hdd_mdns_resp_matched);
15405 vos_mem_zero(matchedlist, size);
15406 num_matched = wlan_hdd_mdns_find_entries_from_end(resptype_ptr_dn,
15407 resptype_ptr);
15408 if (num_matched > 0) {
15409 matchedlist[numlist].num_matched = num_matched;
15410 matchedlist[numlist].type = MDNS_TYPE_PTR;
15411 numlist++;
15412 }
15413 if (resptype_txt && (resptype_txt->num_entries > 0)) {
15414 num_matched = wlan_hdd_mdns_find_entries_from_end(
15415 resptype_ptr_dn, resptype_txt);
15416 if (num_matched > 0) {
15417 matchedlist[numlist].num_matched = num_matched;
15418 matchedlist[numlist].type = MDNS_TYPE_TXT;
15419 numlist++;
15420 }
15421 }
15422 if (resptype_a && (resptype_a->num_entries > 0)) {
15423 num_matched = wlan_hdd_mdns_find_entries_from_end(
15424 resptype_ptr_dn,resptype_a);
15425 if (num_matched > 0) {
15426 matchedlist[numlist].num_matched = num_matched;
15427 matchedlist[numlist].type = MDNS_TYPE_A;
15428 numlist++;
15429 }
15430 }
15431 if (numlist > 0) {
15432 if (numlist > 1)
15433 wlan_hdd_mdns_find_max(matchedlist, numlist);
15434 resp = NULL;
15435 switch (matchedlist[numlist-1].type) {
15436 case MDNS_TYPE_A:
15437 resp = resptype_a;
15438 break;
15439 case MDNS_TYPE_TXT:
15440 resp = resptype_txt;
15441 break;
15442 case MDNS_TYPE_PTR:
15443 resp = resptype_ptr;
15444 break;
15445 default:
15446 hddLog(LOGE, FL("Fail to compress mDNS response "
15447 "(%d)!"), MDNS_TYPE_PTR_DNAME);
15448 return FALSE;
15449 }
15450 num_matched = matchedlist[numlist-1].num_matched;
15451 if (!wlan_hdd_mdns_compress_data(resp_info, resptype_ptr_dn,
15452 resp, num_matched)) {
15453 hddLog(LOGE, FL("Fail to compress mDNS response "
15454 "(%d)!"), MDNS_TYPE_PTR_DNAME);
15455 return FALSE;
15456 }
15457 } else {
15458 /* num = 0 -> no matched string */
15459 if (!wlan_hdd_mdns_process_response_dname(resptype_ptr_dn,
15460 resp_info)) {
15461 hddLog(LOGE, FL("Fail to process mDNS response (%d)!"),
15462 MDNS_TYPE_PTR_DNAME);
15463 return FALSE;
15464 }
15465 }
15466
15467 return TRUE;
15468}
15469
15470/**
15471 * wlan_hdd_mdns_pack_response_type_ptr() - Pack Type PTR response
15472 * @ini_config: Pointer to the struct hdd_config_t
15473 * @resp_info: Pointer to the struct tSirMDNSResponseInfo
15474 * @resptype_ptr: Pointer to the struct hdd_mdns_resp_info of Type Ptr
15475 * @resptype_ptr_dn: Pointer to the struct hdd_mdns_resp_info of Type Ptr
15476 * domain name
15477 * @resptype_txt: Pointer to the struct hdd_mdns_resp_info of Type Txt
15478 * @resptype_a: Pointer to the struct hdd_mdns_resp_info of Type A
15479 *
15480 * The Type Ptr response include QName, response type, class, TTL and
15481 * Type PTR domain name. Also, it will find the matched QName from the
15482 * existing resptype_txt, resptype_a and then compress the data.
15483 *
15484 * Return: Return boolean. TRUE for success, FALSE for fail.
15485 */
15486static bool
15487wlan_hdd_mdns_pack_response_type_ptr(hdd_config_t *ini_config,
15488 sir_mdns_resp_info resp_info,
15489 struct hdd_mdns_resp_info *resptype_ptr,
15490 struct hdd_mdns_resp_info *resptype_ptr_dn,
15491 struct hdd_mdns_resp_info *resptype_txt,
15492 struct hdd_mdns_resp_info *resptype_a)
15493{
15494 uint8_t num_matched, num_matched1;
15495 uint16_t value;
15496 uint8_t val_u8;
15497 uint32_t offset_data_len, len;
15498
15499 ENTER();
15500 if ((ini_config == NULL) || (resp_info == NULL) ||
15501 (resptype_ptr == NULL) || (resptype_ptr_dn == NULL)) {
15502 hddLog(LOGE, FL("ini_config or response info is NULL!"));
15503 return FALSE;
15504 }
15505
15506 /* No Type Ptr response */
15507 if (strlen((char *)ini_config->mdns_resp_type_ptr) <= 0)
15508 return TRUE;
15509
15510 /* Wrong response is assigned, just ignore this response */
15511 if (!wlan_hdd_mdns_init_response(resptype_ptr,
15512 ini_config->mdns_resp_type_ptr, '.'))
15513 return TRUE;
15514
15515 /*
15516 * For data compression
15517 * Check if any strings are matched with Type A response
15518 */
15519 num_matched = 0;
15520 num_matched1 = 0;
15521 if (resptype_a && (resptype_a->num_entries > 0)) {
15522 num_matched = wlan_hdd_mdns_find_entries_from_end(resptype_ptr,
15523 resptype_a);
15524 }
15525 if (resptype_txt && (resptype_txt->num_entries > 0)) {
15526 num_matched1 = wlan_hdd_mdns_find_entries_from_end(
15527 resptype_ptr, resptype_txt);
15528 }
15529 if ((num_matched != num_matched1) ||
15530 ((num_matched > 0) && (num_matched1 > 0))) {
15531 if (num_matched >= num_matched1) {
15532 if (!wlan_hdd_mdns_compress_data(resp_info,
15533 resptype_ptr, resptype_a, num_matched)) {
15534 hddLog(LOGE, FL("Fail to compress mDNS "
15535 "response (%d)!"), MDNS_TYPE_PTR);
15536 return FALSE;
15537 }
15538 } else {
15539 /* num_matched is less than num_matched1 */
15540 if (!wlan_hdd_mdns_compress_data(resp_info,
15541 resptype_ptr, resptype_txt, num_matched1)) {
15542 hddLog(LOGE, FL("Fail to compress mDNS "
15543 "response (%d)!"), MDNS_TYPE_PTR);
15544 return FALSE;
15545 }
15546 }
15547 } else {
15548 /*
15549 * Both num_matched and num_matched1 are zero.
15550 * no TypeA & TypeTxt
15551 */
15552 if (!wlan_hdd_mdns_process_response_dname(resptype_ptr,
15553 resp_info)) {
15554 hddLog(LOGE, FL("Fail to process mDNS response (%d)!"),
15555 MDNS_TYPE_PTR);
15556 return FALSE;
15557 }
15558 }
15559
15560 /* Process response Type, Class, TTL */
15561 if (!wlan_hdd_mdns_process_response_misc(MDNS_TYPE_PTR, resp_info)) {
15562 hddLog(LOGE, FL("Fail to process mDNS misc response (%d)!"),
15563 MDNS_TYPE_PTR);
15564 return FALSE;
15565 }
15566
15567 /*
15568 * Process response RDLength, RData (Ptr domain name)
15569 * Save the offset of RData length
15570 */
15571 offset_data_len = resp_info->resp_len;
15572 resp_info->resp_len += sizeof(uint16_t);
15573
15574 if (!wlan_hdd_mdns_pack_response_type_ptr_dname(ini_config, resp_info,
15575 resptype_ptr_dn, resptype_ptr,
15576 resptype_txt, resptype_a)) {
15577 return FALSE;
15578 }
15579 /* Set the RData length */
15580 len = offset_data_len + sizeof(uint16_t);
15581 if ((resptype_ptr_dn->num_entries > 0) &&
15582 (resp_info->resp_len > len)) {
15583 value = resp_info->resp_len - len;
15584 val_u8 = (value & 0xff00) >> 8;
15585 resp_info->resp_data[offset_data_len] = val_u8;
15586 val_u8 = value & 0xff;
15587 resp_info->resp_data[offset_data_len+1] = val_u8;
15588 } else {
15589 hddLog(LOGE, FL("Fail to process mDNS response (%d)!"),
15590 MDNS_TYPE_PTR);
15591 return FALSE;
15592 }
15593
15594 EXIT();
15595 return TRUE;
15596}
15597
15598/**
15599 * wlan_hdd_mdns_pack_response_type_srv_target()- Pack Type Service Target
15600 * @ini_config: Pointer to the struct hdd_config_t
15601 * @resp_info: Pointer to the struct tSirMDNSResponseInfo
15602 * @resptype_srv_tgt: Pointer to the struct hdd_mdns_resp_info of Type Srv
15603 * target
15604 * @resptype_srv: Pointer to the struct hdd_mdns_resp_info of Type Srv
15605 * @resptype_ptr: Pointer to the struct hdd_mdns_resp_info of Type Ptr
15606 * @resptype_ptr_dn: Pointer to the struct hdd_mdns_resp_info of Type Ptr
15607 * domain name
15608 * @resptype_txt: Pointer to the struct hdd_mdns_resp_info of Type Txt
15609 * @resptype_a: Pointer to the struct hdd_mdns_resp_info of Type A
15610 *
15611 * The Type service target is one of the data field in the Type SRV response.
15612 * Also, it will find the matched QName from the existing resptype_srv,
15613 * resptype_ptr, resptype_ptr_dn, resptype_txt, resptype_a and then compress
15614 * the data.
15615 *
15616 * Return: Return boolean. TRUE for success, FALSE for fail.
15617 */
15618static bool
15619wlan_hdd_mdns_pack_response_type_srv_target(hdd_config_t *ini_config,
15620 sir_mdns_resp_info resp_info,
15621 struct hdd_mdns_resp_info *resptype_srv_tgt,
15622 struct hdd_mdns_resp_info *resptype_srv,
15623 struct hdd_mdns_resp_info *resptype_ptr,
15624 struct hdd_mdns_resp_info *resptype_ptr_dn,
15625 struct hdd_mdns_resp_info *resptype_txt,
15626 struct hdd_mdns_resp_info *resptype_a)
15627{
15628 uint8_t num_matched, num, size;
15629 struct hdd_mdns_resp_matched matchedlist[MAX_MDNS_RESP_TYPE-1];
15630 struct hdd_mdns_resp_info *resp;
15631
15632 if ((ini_config == NULL) || (resp_info == NULL) ||
15633 (resptype_srv == NULL) || (resptype_srv_tgt == NULL)) {
15634 hddLog(LOGE, FL("ini_config or response info is NULL!"));
15635 return FALSE;
15636 }
15637
15638 /* No Type Srv Target response */
15639 if (strlen((char *)ini_config->mdns_resp_type_srv_target) <= 0)
15640 return TRUE;
15641
15642 /* Wrong response is assigned, just ignore this response */
15643 if (!wlan_hdd_mdns_init_response(resptype_srv_tgt,
15644 ini_config->mdns_resp_type_srv_target, '.'))
15645 return TRUE;
15646
15647 /*
15648 * For data compression
15649 * Check if any strings are matched with previous response.
15650 */
15651 num = 0;
15652 size = (MAX_MDNS_RESP_TYPE-1);
15653 size *= sizeof(struct hdd_mdns_resp_matched);
15654 vos_mem_zero(matchedlist, size);
15655 num_matched = wlan_hdd_mdns_find_entries_from_end(resptype_srv_tgt,
15656 resptype_srv);
15657 if (num_matched > 0) {
15658 matchedlist[num].num_matched = num_matched;
15659 matchedlist[num].type = MDNS_TYPE_SRV;
15660 num++;
15661 }
15662 if (resptype_ptr && (resptype_ptr->num_entries > 0)) {
15663 if (resptype_ptr_dn && (resptype_ptr_dn->num_entries > 0)) {
15664 num_matched = wlan_hdd_mdns_find_entries_from_end(
15665 resptype_srv_tgt, resptype_ptr_dn);
15666 if (num_matched > 0) {
15667 matchedlist[num].num_matched = num_matched;
15668 matchedlist[num].type = MDNS_TYPE_PTR_DNAME;
15669 num++;
15670 }
15671 }
15672 num_matched = wlan_hdd_mdns_find_entries_from_end(
15673 resptype_srv_tgt, resptype_ptr);
15674 if (num_matched > 0) {
15675 matchedlist[num].num_matched = num_matched;
15676 matchedlist[num].type = MDNS_TYPE_PTR;
15677 num++;
15678 }
15679 }
15680 if (resptype_txt && (resptype_txt->num_entries > 0)) {
15681 num_matched = wlan_hdd_mdns_find_entries_from_end(
15682 resptype_srv_tgt, resptype_txt);
15683 if (num_matched > 0) {
15684 matchedlist[num].num_matched = num_matched;
15685 matchedlist[num].type = MDNS_TYPE_TXT;
15686 num++;
15687 }
15688 }
15689 if (resptype_a && (resptype_a->num_entries > 0)) {
15690 num_matched = wlan_hdd_mdns_find_entries_from_end(
15691 resptype_srv_tgt, resptype_a);
15692 if (num_matched > 0) {
15693 matchedlist[num].num_matched = num_matched;
15694 matchedlist[num].type = MDNS_TYPE_A;
15695 num++;
15696 }
15697 }
15698 if (num > 0) {
15699 if (num > 1)
15700 wlan_hdd_mdns_find_max(matchedlist, num);
15701 resp = NULL;
15702 switch (matchedlist[num-1].type) {
15703 case MDNS_TYPE_A:
15704 resp = resptype_a;
15705 break;
15706 case MDNS_TYPE_TXT:
15707 resp = resptype_txt;
15708 break;
15709 case MDNS_TYPE_PTR:
15710 resp = resptype_ptr;
15711 break;
15712 case MDNS_TYPE_PTR_DNAME:
15713 resp = resptype_ptr_dn;
15714 break;
15715 case MDNS_TYPE_SRV:
15716 resp = resptype_srv;
15717 break;
15718 default:
15719 hddLog(LOGE, FL("Fail to compress mDNS response "
15720 "(%d)!"), MDNS_TYPE_SRV_TARGET);
15721 return FALSE;
15722 }
15723 num_matched = matchedlist[num-1].num_matched;
15724 if (!wlan_hdd_mdns_compress_data(resp_info, resptype_srv_tgt,
15725 resp, num_matched)) {
15726 hddLog(LOGE, FL("Fail to compress mDNS response "
15727 "(%d)!"), MDNS_TYPE_SRV_TARGET);
15728 return FALSE;
15729 }
15730 } else {
15731 /* num = 0 -> no matched string */
15732 if (!wlan_hdd_mdns_process_response_dname(resptype_srv_tgt,
15733 resp_info)) {
15734 hddLog(LOGE, FL("Fail to process mDNS response (%d)!"),
15735 MDNS_TYPE_SRV_TARGET);
15736 return FALSE;
15737 }
15738 }
15739
15740 return TRUE;
15741}
15742
15743/**
15744 * wlan_hdd_mdns_pack_response_type_srv()- Pack Type Service response
15745 * @ini_config: Pointer to the struct hdd_config_t
15746 * @resp_info: Pointer to the struct tSirMDNSResponseInfo
15747 * @resptype_srv: Pointer to the struct hdd_mdns_resp_info of Type Srv
15748 * @resptype_srv_tgt: Pointer to the struct hdd_mdns_resp_info of Type Srv
15749 * target
15750 * @resptype_ptr: Pointer to the struct hdd_mdns_resp_info of Type Ptr
15751 * @resptype_ptr_dn: Pointer to the struct hdd_mdns_resp_info of Type Ptr
15752 * domain name
15753 * @resptype_txt: Pointer to the struct hdd_mdns_resp_info of Type Txt
15754 * @resptype_a: Pointer to the struct hdd_mdns_resp_info of Type A
15755 *
15756 * The Type SRV (Service) response include QName, response type, class, TTL
15757 * and four kinds of data fields. Also, it will find the matched QName from
15758 * the existing resptype_ptr, resptype_ptr_dn, resptype_txt, resptype_a and
15759 * then compress the data.
15760 *
15761 * Return: Return boolean. TRUE for success, FALSE for fail.
15762 */
15763static bool
15764wlan_hdd_mdns_pack_response_type_srv(hdd_config_t *ini_config,
15765 sir_mdns_resp_info resp_info,
15766 struct hdd_mdns_resp_info *resptype_srv,
15767 struct hdd_mdns_resp_info *resptype_srv_tgt,
15768 struct hdd_mdns_resp_info *resptype_ptr,
15769 struct hdd_mdns_resp_info *resptype_ptr_dn,
15770 struct hdd_mdns_resp_info *resptype_txt,
15771 struct hdd_mdns_resp_info *resptype_a)
15772{
15773 uint8_t num_matched, num, size;
15774 uint16_t value;
15775 uint8_t val_u8;
15776 uint32_t offset_data_len, len;
15777 struct hdd_mdns_resp_info *resp;
15778 struct hdd_mdns_resp_matched matchedlist[MAX_MDNS_RESP_TYPE-1];
15779
15780 ENTER();
15781
15782 if ((ini_config == NULL) || (resp_info == NULL) ||
15783 (resptype_srv == NULL) || (resptype_srv_tgt == NULL)) {
15784 hddLog(LOGE, FL("ini_config or response info is NULL!"));
15785 return FALSE;
15786 }
15787
15788 /* No Type Srv response */
15789 if (strlen((char *)ini_config->mdns_resp_type_srv) <= 0)
15790 return TRUE;
15791
15792 /* Wrong response is assigned, just ignore this response */
15793 if (!wlan_hdd_mdns_init_response(resptype_srv,
15794 ini_config->mdns_resp_type_srv, '.'))
15795 return TRUE;
15796
15797 /*
15798 * For data compression
15799 * Check if any strings are matched with Type A response
15800 */
15801 num = 0;
15802 size = (MAX_MDNS_RESP_TYPE-1);
15803 size *= sizeof(struct hdd_mdns_resp_matched);
15804 vos_mem_zero(matchedlist, size);
15805 if (resptype_ptr && (resptype_ptr->num_entries > 0)) {
15806 if (resptype_ptr_dn && (resptype_ptr_dn->num_entries > 0)) {
15807 num_matched = wlan_hdd_mdns_find_entries_from_end(
15808 resptype_srv,
15809 resptype_ptr_dn);
15810 if (num_matched > 0) {
15811 matchedlist[num].num_matched = num_matched;
15812 matchedlist[num].type = MDNS_TYPE_PTR_DNAME;
15813 num++;
15814 }
15815 }
15816 num_matched = wlan_hdd_mdns_find_entries_from_end(resptype_srv,
15817 resptype_ptr);
15818 if (num_matched > 0) {
15819 matchedlist[num].num_matched = num_matched;
15820 matchedlist[num].type = MDNS_TYPE_PTR;
15821 num++;
15822 }
15823 }
15824 if (resptype_txt && (resptype_txt->num_entries > 0)) {
15825 num_matched = wlan_hdd_mdns_find_entries_from_end(resptype_srv,
15826 resptype_txt);
15827 if (num_matched > 0) {
15828 matchedlist[num].num_matched =num_matched;
15829 matchedlist[num].type = MDNS_TYPE_TXT;
15830 num++;
15831 }
15832 }
15833 if (resptype_a && (resptype_a->num_entries > 0)) {
15834 num_matched = wlan_hdd_mdns_find_entries_from_end(resptype_srv,
15835 resptype_a);
15836 if (num_matched > 0) {
15837 matchedlist[num].num_matched = num_matched;
15838 matchedlist[num].type = MDNS_TYPE_A;
15839 num++;
15840 }
15841 }
15842 if (num > 0) {
15843 if (num > 1)
15844 wlan_hdd_mdns_find_max(matchedlist, num);
15845 resp = NULL;
15846 switch (matchedlist[num-1].type) {
15847 case MDNS_TYPE_A:
15848 resp = resptype_a;
15849 break;
15850 case MDNS_TYPE_TXT:
15851 resp = resptype_txt;
15852 break;
15853 case MDNS_TYPE_PTR:
15854 resp = resptype_ptr;
15855 break;
15856 case MDNS_TYPE_PTR_DNAME:
15857 resp = resptype_ptr_dn;
15858 break;
15859 default:
15860 hddLog(LOGE, FL("Fail to compress mDNS response "
15861 "(%d)!"), MDNS_TYPE_SRV);
15862 return FALSE;
15863 }
15864 num_matched = matchedlist[num-1].num_matched;
15865 if (!wlan_hdd_mdns_compress_data(resp_info, resptype_srv,
15866 resp, num_matched)) {
15867 hddLog(LOGE, FL("Fail to compress mDNS response "
15868 "(%d)!"), MDNS_TYPE_SRV);
15869 return FALSE;
15870 }
15871 } else {
15872 /* num = 0 -> no matched string */
15873 if (!wlan_hdd_mdns_process_response_dname(resptype_srv,
15874 resp_info)) {
15875 hddLog(LOGE, FL("Fail to process mDNS response (%d)!"),
15876 MDNS_TYPE_SRV);
15877 return FALSE;
15878 }
15879 }
15880
15881 /* Process response Type, Class, TTL */
15882 if (!wlan_hdd_mdns_process_response_misc(MDNS_TYPE_SRV, resp_info)) {
15883 hddLog(LOGE, FL("Fail to process mDNS misc response (%d)!"),
15884 MDNS_TYPE_SRV);
15885 return FALSE;
15886 }
15887
15888 /*
15889 * Process response RDLength, RData (Srv target name)
15890 * Save the offset of RData length
15891 */
15892 offset_data_len = resp_info->resp_len;
15893 resp_info->resp_len += sizeof(uint16_t);
15894
15895 len = resp_info->resp_len + (3 * sizeof(uint16_t));
15896 if (len >= MAX_MDNS_RESP_LEN) {
15897 hddLog(LOGE, FL("resp_len exceeds %d!"), MAX_MDNS_RESP_LEN);
15898 return FALSE;
15899 }
15900
15901 /* set Srv Priority */
15902 value = ini_config->mdns_resp_type_srv_priority;
15903 wlan_hdd_mdns_format_response_u16(value, resp_info);
15904 /* set Srv Weight */
15905 value = ini_config->mdns_resp_type_srv_weight;
15906 wlan_hdd_mdns_format_response_u16(value, resp_info);
15907 /* set Srv Port */
15908 value = ini_config->mdns_resp_type_srv_port;
15909 wlan_hdd_mdns_format_response_u16(value, resp_info);
15910
15911 if (!wlan_hdd_mdns_pack_response_type_srv_target(ini_config, resp_info,
15912 resptype_srv_tgt, resptype_srv,
15913 resptype_ptr, resptype_ptr_dn,
15914 resptype_txt, resptype_a)) {
15915 return FALSE;
15916 }
15917 /* Set the RData length */
15918 len = offset_data_len + sizeof(uint16_t);
15919 if ((resptype_srv_tgt->num_entries > 0) &&
15920 (resp_info->resp_len > len)) {
15921 value = resp_info->resp_len - len;
15922 val_u8 = (value & 0xff00) >> 8;
15923 resp_info->resp_data[offset_data_len] = val_u8;
15924 val_u8 = value & 0xff;
15925 resp_info->resp_data[offset_data_len+1] = val_u8;
15926 } else {
15927 hddLog(LOGE, FL("Fail to process mDNS response (%d)!"),
15928 MDNS_TYPE_SRV);
15929 return FALSE;
15930 }
15931
15932 EXIT();
15933 return TRUE;
15934}
15935
15936/**
15937 * wlan_hdd_mdns_free_mem() - Free the allocated memory
15938 * @response: Pointer to the struct hdd_mdns_resp_info
15939 *
15940 * Return: None
15941 */
15942static void wlan_hdd_mdns_free_mem(struct hdd_mdns_resp_info *response)
15943{
15944 if (response && response->data)
15945 vos_mem_free(response->data);
15946 if (response && response->offset)
15947 vos_mem_free(response->offset);
15948}
15949
15950/**
15951 * wlan_hdd_mdns_pack_response() - Pack mDNS response
15952 * @ini_config: Pointer to the struct hdd_config_t
15953 * @resp_info: Pointer to the struct tSirMDNSResponseInfo
15954 *
15955 * This function will pack four types of responses (Type A, Type Txt, Type Ptr
15956 * and Type Service). Each response contains QName, response type, class, TTL
15957 * and data fields.
15958 *
15959 * Return: Return boolean. TRUE for success, FALSE for fail.
15960 */
15961static bool wlan_hdd_mdns_pack_response(hdd_config_t *ini_config,
15962 sir_mdns_resp_info resp_info)
15963{
15964 struct hdd_mdns_resp_info resptype_a, resptype_txt;
15965 struct hdd_mdns_resp_info resptype_ptr, resptype_ptr_dn;
15966 struct hdd_mdns_resp_info resptype_srv, resptype_srv_tgt;
15967 uint32_t num_res_records = 0;
15968 bool status = FALSE;
15969
15970 ENTER();
15971
15972 wlan_hdd_mdns_reset_response(&resptype_a);
15973 wlan_hdd_mdns_reset_response(&resptype_txt);
15974 wlan_hdd_mdns_reset_response(&resptype_ptr);
15975 wlan_hdd_mdns_reset_response(&resptype_ptr_dn);
15976 wlan_hdd_mdns_reset_response(&resptype_srv);
15977 wlan_hdd_mdns_reset_response(&resptype_srv_tgt);
15978
15979 resp_info->resp_len = 0;
15980
15981 /* Process Type A response */
15982 if (!wlan_hdd_mdns_pack_response_type_a(ini_config, resp_info,
15983 &resptype_a))
15984 goto err_resptype_a;
15985
15986 if ((resptype_a.num_entries > 0) &&
15987 (strlen((char *)&resptype_a.data[0]) > 0))
15988 num_res_records++;
15989
15990 /* Process Type TXT response */
15991 if (!wlan_hdd_mdns_pack_response_type_txt(ini_config, resp_info,
15992 &resptype_txt, &resptype_a))
15993 goto err_resptype_txt;
15994
15995 if ((resptype_txt.num_entries > 0) &&
15996 (strlen((char *)&resptype_txt.data[0]) > 0))
15997 num_res_records++;
15998
15999 /* Process Type PTR response */
16000 if (!wlan_hdd_mdns_pack_response_type_ptr(ini_config, resp_info,
16001 &resptype_ptr, &resptype_ptr_dn,
16002 &resptype_txt, &resptype_a))
16003 goto err_resptype_ptr;
16004
16005 if ((resptype_ptr.num_entries > 0) &&
16006 (strlen((char *)&resptype_ptr.data[0]) > 0))
16007 num_res_records++;
16008
16009 /* Process Type SRV response */
16010 if (!wlan_hdd_mdns_pack_response_type_srv(ini_config, resp_info,
16011 &resptype_srv, &resptype_srv_tgt,
16012 &resptype_ptr, &resptype_ptr_dn,
16013 &resptype_txt, &resptype_a))
16014 goto err_resptype_srv;
16015
16016 if ((resptype_srv.num_entries > 0) &&
16017 (strlen((char *)&resptype_srv.data[0]) > 0))
16018 num_res_records++;
16019
16020 resp_info->resourceRecord_count = num_res_records;
16021 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
16022 "%s: Pack mDNS response data successfully!", __func__);
16023 status = TRUE;
16024
16025err_resptype_srv:
16026 wlan_hdd_mdns_free_mem(&resptype_srv);
16027 wlan_hdd_mdns_free_mem(&resptype_srv_tgt);
16028
16029err_resptype_ptr:
16030 wlan_hdd_mdns_free_mem(&resptype_ptr);
16031 wlan_hdd_mdns_free_mem(&resptype_ptr_dn);
16032
16033err_resptype_txt:
16034 wlan_hdd_mdns_free_mem(&resptype_txt);
16035
16036err_resptype_a:
16037 wlan_hdd_mdns_free_mem(&resptype_a);
16038
16039 EXIT();
16040 return status;
16041}
16042
16043/**
16044 * wlan_hdd_set_mdns_offload() - Enable mDNS offload
16045 * @hostapd_adapter: Pointer to the struct hdd_adapter_t
16046 *
16047 * This function will set FQDN/unique FQDN (full qualified domain name)
16048 * and the mDNS response. Then send them to SME.
16049 *
16050 * Return: Return boolean. TRUE for success, FALSE for fail.
16051 */
16052bool wlan_hdd_set_mdns_offload(hdd_adapter_t *hostapd_adapter)
16053{
16054 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(hostapd_adapter);
16055 sir_mdns_offload_info mdns_offload_info;
16056 sir_mdns_fqdn_info mdns_fqdn_info;
16057 sir_mdns_resp_info mdns_resp_info;
16058 uint32_t fqdn_len, ufqdn_len;
16059
16060 ENTER();
16061
16062 /* 1. Prepare the MDNS fqdn request to send to SME */
16063 fqdn_len = strlen(hdd_ctx->cfg_ini->mdns_fqdn);
16064 ufqdn_len = strlen(hdd_ctx->cfg_ini->mdns_uniquefqdn);
16065 if ((fqdn_len == 0) && (ufqdn_len == 0)) {
16066 hddLog(LOGE, FL("No mDNS FQDN or UFQDN is assigned fqdn_len %d,"
16067 "ufqdn_len %d!"), fqdn_len, ufqdn_len);
16068 return FALSE;
16069 }
16070
16071 mdns_fqdn_info = vos_mem_malloc(sizeof(*mdns_fqdn_info));
16072 if (NULL == mdns_fqdn_info) {
16073 hddLog(LOGE, FL("could not allocate tSirMDNSFqdnInfo!"));
16074 return FALSE;
16075 }
16076 /* MDNS fqdn request */
16077 if (fqdn_len > 0) {
16078 vos_mem_zero(mdns_fqdn_info, sizeof(*mdns_fqdn_info));
16079 mdns_fqdn_info->bss_idx = hostapd_adapter->sessionId;
16080 mdns_fqdn_info->fqdn_type = MDNS_FQDN_TYPE_GENERAL;
16081 mdns_fqdn_info->fqdn_len = fqdn_len;
16082 mdns_fqdn_info->mdns_fqdn_callback = hdd_mdns_fqdn_offload_done;
16083 mdns_fqdn_info->mdns_fqdn_cb_context = hostapd_adapter;
16084 vos_mem_copy(mdns_fqdn_info->fqdn_data,
16085 hdd_ctx->cfg_ini->mdns_fqdn,
16086 mdns_fqdn_info->fqdn_len);
16087
16088 if (eHAL_STATUS_SUCCESS !=
16089 sme_set_mdns_fqdn(hdd_ctx->hHal, mdns_fqdn_info)) {
16090 hddLog(LOGE, FL("sme_set_mdns_fqdn fail!"));
16091 vos_mem_free(mdns_fqdn_info);
16092 return FALSE;
16093 }
16094 }
16095 /* MDNS unique fqdn request */
16096 if (ufqdn_len > 0) {
16097 vos_mem_zero(mdns_fqdn_info, sizeof(*mdns_fqdn_info));
16098 mdns_fqdn_info->bss_idx = hostapd_adapter->sessionId;
16099 mdns_fqdn_info->fqdn_type = MDNS_FQDN_TYPE_UNIQUE;
16100 mdns_fqdn_info->fqdn_len = ufqdn_len;
16101 mdns_fqdn_info->mdns_fqdn_callback = hdd_mdns_fqdn_offload_done;
16102 mdns_fqdn_info->mdns_fqdn_cb_context = hostapd_adapter;
16103 vos_mem_copy(mdns_fqdn_info->fqdn_data,
16104 hdd_ctx->cfg_ini->mdns_uniquefqdn,
16105 mdns_fqdn_info->fqdn_len);
16106 if (eHAL_STATUS_SUCCESS !=
16107 sme_set_mdns_fqdn(hdd_ctx->hHal, mdns_fqdn_info)) {
16108 hddLog(LOGE, FL("sme_set_mdns_fqdn fail!"));
16109 vos_mem_free(mdns_fqdn_info);
16110 return FALSE;
16111 }
16112 }
16113 vos_mem_free(mdns_fqdn_info);
16114
16115 /* 2. Prepare the MDNS response request to send to SME */
16116 mdns_resp_info = vos_mem_malloc(sizeof(*mdns_resp_info));
16117 if (NULL == mdns_resp_info) {
16118 hddLog(LOGE, FL("could not allocate tSirMDNSResponseInfo!"));
16119 return FALSE;
16120 }
16121
16122 vos_mem_zero(mdns_resp_info, sizeof(*mdns_resp_info));
16123 mdns_resp_info->bss_idx = hostapd_adapter->sessionId;
16124 mdns_resp_info->mdns_resp_callback = hdd_mdns_resp_offload_done;
16125 mdns_resp_info->mdns_resp_cb_context = hostapd_adapter;
16126 if (!wlan_hdd_mdns_pack_response(hdd_ctx->cfg_ini, mdns_resp_info)) {
16127 hddLog(LOGE, FL("wlan_hdd_pack_mdns_response fail!"));
16128 vos_mem_free(mdns_resp_info);
16129 return FALSE;
16130 }
16131 if (eHAL_STATUS_SUCCESS !=
16132 sme_set_mdns_resp(hdd_ctx->hHal, mdns_resp_info)) {
16133 hddLog(LOGE, FL("sme_set_mdns_resp fail!"));
16134 vos_mem_free(mdns_resp_info);
16135 return FALSE;
16136 }
16137 vos_mem_free(mdns_resp_info);
16138
16139 /* 3. Prepare the MDNS Enable request to send to SME */
16140 mdns_offload_info = vos_mem_malloc(sizeof(*mdns_offload_info));
16141 if (NULL == mdns_offload_info) {
16142 hddLog(LOGE, FL("could not allocate tSirMDNSOffloadInfo!"));
16143 return FALSE;
16144 }
16145
16146 vos_mem_zero(mdns_offload_info, sizeof(*mdns_offload_info));
16147
16148 mdns_offload_info->bss_idx = hostapd_adapter->sessionId;
16149 mdns_offload_info->enable = hdd_ctx->cfg_ini->enable_mdns_offload;
16150 mdns_offload_info->mdns_enable_callback = hdd_mdns_enable_offload_done;
16151 mdns_offload_info->mdns_enable_cb_context = hostapd_adapter;
16152 if (eHAL_STATUS_SUCCESS !=
16153 sme_set_mdns_offload(hdd_ctx->hHal, mdns_offload_info)) {
16154 hddLog(LOGE, FL("sme_set_mdns_offload fail!"));
16155 vos_mem_free(mdns_offload_info);
16156 return FALSE;
16157 }
16158
16159 vos_mem_free(mdns_offload_info);
16160 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
16161 "%s: enable mDNS offload successfully!", __func__);
16162 return TRUE;
16163}
16164#endif /* MDNS_OFFLOAD */
c_manjeecfd1efb2015-09-25 19:32:34 +053016165
Jeff Johnson295189b2012-06-20 16:38:30 -070016166//Register the module init/exit functions
16167module_init(hdd_module_init);
16168module_exit(hdd_module_exit);
16169
16170MODULE_LICENSE("Dual BSD/GPL");
16171MODULE_AUTHOR("Qualcomm Atheros, Inc.");
16172MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
16173
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070016174module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
16175 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -070016176
Jeff Johnson76052702013-04-16 13:55:05 -070016177module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -070016178 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Arif Hussain66559122013-11-21 10:11:40 -080016179
16180module_param(enable_dfs_chan_scan, int,
16181 S_IRUSR | S_IRGRP | S_IROTH);
16182
16183module_param(enable_11d, int,
16184 S_IRUSR | S_IRGRP | S_IROTH);
16185
16186module_param(country_code, charp,
16187 S_IRUSR | S_IRGRP | S_IROTH);