blob: 566c60c8b3144ab56c0b083bfbf52002139c7c38 [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Kiet Lam842dad02014-02-18 18:44:02 -08002 * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved.
3 *
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
37 Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved.
38
39 Qualcomm Confidential and Proprietary.
40
41 ========================================================================*/
42
43/**=========================================================================
44
45 EDIT HISTORY FOR FILE
46
47
48 This section contains comments describing changes made to the module.
49 Notice that changes are listed in reverse chronological order.
50
51
52 $Header:$ $DateTime: $ $Author: $
53
54
55 when who what, where, why
56 -------- --- --------------------------------------------------------
57 04/5/09 Shailender Created module.
58 02/24/10 Sudhir.S.Kohalli Added to support param for SoftAP module
59 06/03/10 js - Added support to hostapd driven deauth/disassoc/mic failure
60 ==========================================================================*/
61
62/*--------------------------------------------------------------------------
63 Include Files
64 ------------------------------------------------------------------------*/
65//#include <wlan_qct_driver.h>
66#include <wlan_hdd_includes.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070067#include <vos_api.h>
68#include <vos_sched.h>
69#include <vos_power.h>
70#include <linux/etherdevice.h>
71#include <linux/firmware.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070072#ifdef ANI_BUS_TYPE_PLATFORM
73#include <linux/wcnss_wlan.h>
74#endif //ANI_BUS_TYPE_PLATFORM
75#ifdef ANI_BUS_TYPE_PCI
76#include "wcnss_wlan.h"
77#endif /* ANI_BUS_TYPE_PCI */
78#include <wlan_hdd_tx_rx.h>
79#include <palTimer.h>
80#include <wniApi.h>
81#include <wlan_nlink_srv.h>
82#include <wlan_btc_svc.h>
83#include <wlan_hdd_cfg.h>
84#include <wlan_ptt_sock_svc.h>
Vinay Krishna Erannad938c422014-03-10 17:14:21 +053085#include <wlan_logging_sock_svc.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070086#include <wlan_hdd_wowl.h>
87#include <wlan_hdd_misc.h>
88#include <wlan_hdd_wext.h>
89#ifdef WLAN_BTAMP_FEATURE
90#include <bap_hdd_main.h>
91#include <bapInternal.h>
92#endif // WLAN_BTAMP_FEATURE
Sushant Kaushik4b7cb302014-01-06 17:45:01 +053093#include "wlan_hdd_trace.h"
94#include "vos_types.h"
95#include "vos_trace.h"
Jeff Johnson295189b2012-06-20 16:38:30 -070096#include <linux/wireless.h>
97#include <net/cfg80211.h>
Vinay Krishna Erannad9cbdb32014-01-16 12:59:10 +053098#include <linux/inetdevice.h>
99#include <net/addrconf.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700100#include "wlan_hdd_cfg80211.h"
101#include "wlan_hdd_p2p.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700102#include <linux/rtnetlink.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700103int wlan_hdd_ftm_start(hdd_context_t *pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700104#include "sapApi.h"
105#include <linux/semaphore.h>
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -0700106#include <linux/ctype.h>
Arun Kumar Khandavalli74fe3032014-03-17 20:35:34 +0530107#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0))
108#include <soc/qcom/subsystem_restart.h>
109#else
Jeff Johnson295189b2012-06-20 16:38:30 -0700110#include <mach/subsystem_restart.h>
Arun Kumar Khandavalli74fe3032014-03-17 20:35:34 +0530111#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700112#include <wlan_hdd_hostapd.h>
113#include <wlan_hdd_softap_tx_rx.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700114#include "cfgApi.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700115#include "wlan_hdd_dev_pwr.h"
116#ifdef WLAN_BTAMP_FEATURE
117#include "bap_hdd_misc.h"
118#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700119#include "wlan_qct_pal_trace.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700120#include "qwlan_version.h"
Yathish9f22e662012-12-10 14:21:35 -0800121#include "wlan_qct_wda.h"
Chilam NG571c65a2013-01-19 12:27:36 +0530122#ifdef FEATURE_WLAN_TDLS
123#include "wlan_hdd_tdls.h"
124#endif
Yue Ma0d4891e2013-08-06 17:01:45 -0700125#include "wlan_hdd_debugfs.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700126
127#ifdef MODULE
128#define WLAN_MODULE_NAME module_name(THIS_MODULE)
129#else
130#define WLAN_MODULE_NAME "wlan"
131#endif
132
133#ifdef TIMER_MANAGER
134#define TIMER_MANAGER_STR " +TIMER_MANAGER"
135#else
136#define TIMER_MANAGER_STR ""
137#endif
138
139#ifdef MEMORY_DEBUG
140#define MEMORY_DEBUG_STR " +MEMORY_DEBUG"
141#else
142#define MEMORY_DEBUG_STR ""
143#endif
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530144#define MAX_WAIT_FOR_ROC_COMPLETION 3
Jeff Johnson295189b2012-06-20 16:38:30 -0700145/* the Android framework expects this param even though we don't use it */
146#define BUF_LEN 20
Jeff Johnson76052702013-04-16 13:55:05 -0700147static char fwpath_buffer[BUF_LEN];
148static struct kparam_string fwpath = {
149 .string = fwpath_buffer,
150 .maxlen = BUF_LEN,
151};
Arif Hussain66559122013-11-21 10:11:40 -0800152
153static char *country_code;
154static int enable_11d = -1;
155static int enable_dfs_chan_scan = -1;
c_hpothu92367912014-05-01 15:18:17 +0530156static int gbcnMissRate = -1;
Arif Hussain66559122013-11-21 10:11:40 -0800157
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700158#ifndef MODULE
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700159static int wlan_hdd_inited;
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700160#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700161
Jeff Johnsone7245742012-09-05 17:12:55 -0700162/*
Jeff Johnson72a40512013-12-19 10:14:15 -0800163 * spinlock for synchronizing asynchronous request/response
164 * (full description of use in wlan_hdd_main.h)
165 */
166DEFINE_SPINLOCK(hdd_context_lock);
167
168/*
Jeff Johnsone7245742012-09-05 17:12:55 -0700169 * The rate at which the driver sends RESTART event to supplicant
170 * once the function 'vos_wlanRestart()' is called
171 *
172 */
173#define WLAN_HDD_RESTART_RETRY_DELAY_MS 5000 /* 5 second */
174#define WLAN_HDD_RESTART_RETRY_MAX_CNT 5 /* 5 retries */
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -0700175
176/*
177 * Size of Driver command strings from upper layer
178 */
179#define SIZE_OF_SETROAMMODE 11 /* size of SETROAMMODE */
180#define SIZE_OF_GETROAMMODE 11 /* size of GETROAMMODE */
181
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -0800182#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda5cecb202013-10-08 09:13:25 -0700183#define TID_MIN_VALUE 0
184#define TID_MAX_VALUE 15
185static VOS_STATUS hdd_get_tsm_stats(hdd_adapter_t *pAdapter, const tANI_U8 tid,
186 tAniTrafStrmMetrics* pTsmMetrics);
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -0800187static VOS_STATUS hdd_parse_ese_beacon_req(tANI_U8 *pValue,
188 tCsrEseBeaconReq *pEseBcnReq);
189#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -0700190
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +0530191static VOS_STATUS wlan_hdd_init_channels_for_cc(hdd_context_t *pHddCtx);
Atul Mittal1d722422014-03-19 11:15:07 +0530192/*
193 * Maximum buffer size used for returning the data back to user space
194 */
195#define WLAN_MAX_BUF_SIZE 1024
196#define WLAN_PRIV_DATA_MAX_LEN 8192
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -0700197
c_hpothu92367912014-05-01 15:18:17 +0530198//wait time for beacon miss rate.
199#define BCN_MISS_RATE_TIME 500
200
Sameer Thalappil50dc0092013-02-19 17:23:33 -0800201#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -0700202static struct wake_lock wlan_wake_lock;
Jeff Johnsone7245742012-09-05 17:12:55 -0700203#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700204/* set when SSR is needed after unload */
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -0700205static e_hdd_ssr_required isSsrRequired = HDD_SSR_NOT_REQUIRED;
Jeff Johnson295189b2012-06-20 16:38:30 -0700206
207//internal function declaration
Jeff Johnsone7245742012-09-05 17:12:55 -0700208static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx);
209static void wlan_hdd_restart_init(hdd_context_t *pHddCtx);
210static void wlan_hdd_restart_deinit(hdd_context_t *pHddCtx);
211void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback);
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800212void hdd_set_wlan_suspend_mode(bool suspend);
Jeff Johnsone7245742012-09-05 17:12:55 -0700213
Jeff Johnson295189b2012-06-20 16:38:30 -0700214v_U16_t hdd_select_queue(struct net_device *dev,
215 struct sk_buff *skb);
216
217#ifdef WLAN_FEATURE_PACKET_FILTERING
218static void hdd_set_multicast_list(struct net_device *dev);
219#endif
220
221void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter);
222
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -0800223#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -0800224void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand);
225static VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels);
Srinivas Girigowda100eb322013-03-15 16:48:20 -0700226static VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid,
227 tANI_U8 *pChannel, tANI_U8 *pDwellTime,
228 tANI_U8 **pBuf, tANI_U8 *pBufLen);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -0700229static VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue,
230 tANI_U8 *pTargetApBssid,
231 tANI_U8 *pChannel);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800232#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -0800233#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda5cecb202013-10-08 09:13:25 -0700234VOS_STATUS hdd_parse_get_cckm_ie(tANI_U8 *pValue, tANI_U8 **pCckmIe, tANI_U8 *pCckmIeLen);
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -0800235#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -0700236
Mihir Shetee1093ba2014-01-21 20:13:32 +0530237static VOS_STATUS wlan_hdd_init_channels(hdd_context_t *pHddCtx);
Sushant Kaushik8bc7df22014-04-09 17:55:29 +0530238const char * hdd_device_modetoString(v_U8_t device_mode)
239{
240 switch(device_mode)
241 {
242 CASE_RETURN_STRING( WLAN_HDD_INFRA_STATION );
243 CASE_RETURN_STRING( WLAN_HDD_SOFTAP );
244 CASE_RETURN_STRING( WLAN_HDD_P2P_CLIENT );
245 CASE_RETURN_STRING( WLAN_HDD_P2P_GO );
246 CASE_RETURN_STRING( WLAN_HDD_MONITOR);
247 CASE_RETURN_STRING( WLAN_HDD_FTM );
248 CASE_RETURN_STRING( WLAN_HDD_IBSS );
249 CASE_RETURN_STRING( WLAN_HDD_P2P_DEVICE );
250 default:
251 return "device_mode Unknown";
252 }
253}
Mihir Shetee1093ba2014-01-21 20:13:32 +0530254
Jeff Johnson295189b2012-06-20 16:38:30 -0700255static int hdd_netdev_notifier_call(struct notifier_block * nb,
256 unsigned long state,
257 void *ndev)
258{
259 struct net_device *dev = ndev;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700260 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson27cee452013-03-27 11:10:24 -0700261 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700262#ifdef WLAN_BTAMP_FEATURE
263 VOS_STATUS status;
Jeff Johnson295189b2012-06-20 16:38:30 -0700264#endif
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +0530265 long result;
Jeff Johnson295189b2012-06-20 16:38:30 -0700266
267 //Make sure that this callback corresponds to our device.
Jeff Johnson27cee452013-03-27 11:10:24 -0700268 if ((strncmp(dev->name, "wlan", 4)) &&
Amar Singhal4c723bd2013-03-25 18:14:15 -0700269 (strncmp(dev->name, "p2p", 3)))
270 return NOTIFY_DONE;
271
Jeff Johnson295189b2012-06-20 16:38:30 -0700272 if (!dev->ieee80211_ptr)
Jeff Johnson27cee452013-03-27 11:10:24 -0700273 return NOTIFY_DONE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700274
Jeff Johnson27cee452013-03-27 11:10:24 -0700275 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -0700276 {
Jeff Johnsona8a1a482012-12-12 16:49:33 -0800277 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Adapter Null Pointer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700278 VOS_ASSERT(0);
279 return NOTIFY_DONE;
280 }
281
Jeff Johnson27cee452013-03-27 11:10:24 -0700282 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
283 if (NULL == pHddCtx)
284 {
285 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Context Null Pointer", __func__);
286 VOS_ASSERT(0);
287 return NOTIFY_DONE;
288 }
Sameer Thalappil14067972014-01-23 14:54:54 -0800289 if (pHddCtx->isLogpInProgress)
290 return NOTIFY_DONE;
291
Jeff Johnson27cee452013-03-27 11:10:24 -0700292
293 hddLog(VOS_TRACE_LEVEL_INFO, "%s: %s New Net Device State = %lu",
294 __func__, dev->name, state);
Jeff Johnson295189b2012-06-20 16:38:30 -0700295
296 switch (state) {
297 case NETDEV_REGISTER:
298 break;
299
300 case NETDEV_UNREGISTER:
301 break;
302
303 case NETDEV_UP:
304 break;
305
306 case NETDEV_DOWN:
307 break;
308
309 case NETDEV_CHANGE:
Jeff Johnsone7245742012-09-05 17:12:55 -0700310 if(TRUE == pAdapter->isLinkUpSvcNeeded)
311 complete(&pAdapter->linkup_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700312 break;
313
314 case NETDEV_GOING_DOWN:
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +0530315 result = wlan_hdd_scan_abort(pAdapter);
Girish Gowli4bf7a632014-06-12 13:42:11 +0530316 if (result < 0)
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +0530317 {
318 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
319 "%s: Timeout occurred while waiting for abortscan %ld",
320 __func__, result);
Jeff Johnson295189b2012-06-20 16:38:30 -0700321 }
322 else
323 {
324 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +0530325 "%s: Scan Abort Successful" , __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700326 }
327#ifdef WLAN_BTAMP_FEATURE
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700328 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: disabling AMP", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700329 status = WLANBAP_StopAmp();
330 if(VOS_STATUS_SUCCESS != status )
331 {
332 pHddCtx->isAmpAllowed = VOS_TRUE;
333 hddLog(VOS_TRACE_LEVEL_FATAL,
334 "%s: Failed to stop AMP", __func__);
335 }
336 else
337 {
338 //a state m/c implementation in PAL is TBD to avoid this delay
339 msleep(500);
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700340 if ( pHddCtx->isAmpAllowed )
341 {
342 WLANBAP_DeregisterFromHCI();
343 pHddCtx->isAmpAllowed = VOS_FALSE;
344 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700345 }
346#endif //WLAN_BTAMP_FEATURE
347 break;
348
349 default:
350 break;
351 }
352
353 return NOTIFY_DONE;
354}
355
356struct notifier_block hdd_netdev_notifier = {
357 .notifier_call = hdd_netdev_notifier_call,
358};
359
360/*---------------------------------------------------------------------------
361 * Function definitions
362 *-------------------------------------------------------------------------*/
Jeff Johnson295189b2012-06-20 16:38:30 -0700363void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx);
364void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -0700365//variable to hold the insmod parameters
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700366static int con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -0700367#ifndef MODULE
368/* current con_mode - used only for statically linked driver
369 * con_mode is changed by userspace to indicate a mode change which will
370 * result in calling the module exit and init functions. The module
371 * exit function will clean up based on the value of con_mode prior to it
372 * being changed by userspace. So curr_con_mode records the current con_mode
373 * for exit when con_mode becomes the next mode for init
374 */
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700375static int curr_con_mode;
Jeff Johnson295189b2012-06-20 16:38:30 -0700376#endif
377
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -0800378/**---------------------------------------------------------------------------
379
380 \brief hdd_vos_trace_enable() - Configure initial VOS Trace enable
381
382 Called immediately after the cfg.ini is read in order to configure
383 the desired trace levels.
384
385 \param - moduleId - module whose trace level is being configured
386 \param - bitmask - bitmask of log levels to be enabled
387
388 \return - void
389
390 --------------------------------------------------------------------------*/
391static void hdd_vos_trace_enable(VOS_MODULE_ID moduleId, v_U32_t bitmask)
392{
393 wpt_tracelevel level;
394
395 /* if the bitmask is the default value, then a bitmask was not
396 specified in cfg.ini, so leave the logging level alone (it
397 will remain at the "compiled in" default value) */
398 if (CFG_VOS_TRACE_ENABLE_DEFAULT == bitmask)
399 {
400 return;
401 }
402
403 /* a mask was specified. start by disabling all logging */
404 vos_trace_setValue(moduleId, VOS_TRACE_LEVEL_NONE, 0);
405
406 /* now cycle through the bitmask until all "set" bits are serviced */
407 level = VOS_TRACE_LEVEL_FATAL;
408 while (0 != bitmask)
409 {
410 if (bitmask & 1)
411 {
412 vos_trace_setValue(moduleId, level, 1);
413 }
414 level++;
415 bitmask >>= 1;
416 }
417}
418
419
Jeff Johnson295189b2012-06-20 16:38:30 -0700420/**---------------------------------------------------------------------------
421
422 \brief hdd_wdi_trace_enable() - Configure initial WDI Trace enable
423
424 Called immediately after the cfg.ini is read in order to configure
425 the desired trace levels in the WDI.
426
427 \param - moduleId - module whose trace level is being configured
428 \param - bitmask - bitmask of log levels to be enabled
429
430 \return - void
431
432 --------------------------------------------------------------------------*/
433static void hdd_wdi_trace_enable(wpt_moduleid moduleId, v_U32_t bitmask)
434{
435 wpt_tracelevel level;
436
437 /* if the bitmask is the default value, then a bitmask was not
438 specified in cfg.ini, so leave the logging level alone (it
439 will remain at the "compiled in" default value) */
440 if (CFG_WDI_TRACE_ENABLE_DEFAULT == bitmask)
441 {
442 return;
443 }
444
445 /* a mask was specified. start by disabling all logging */
446 wpalTraceSetLevel(moduleId, eWLAN_PAL_TRACE_LEVEL_NONE, 0);
447
448 /* now cycle through the bitmask until all "set" bits are serviced */
449 level = eWLAN_PAL_TRACE_LEVEL_FATAL;
450 while (0 != bitmask)
451 {
452 if (bitmask & 1)
453 {
454 wpalTraceSetLevel(moduleId, level, 1);
455 }
456 level++;
457 bitmask >>= 1;
458 }
459}
Jeff Johnson295189b2012-06-20 16:38:30 -0700460
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530461/*
462 * FUNCTION: wlan_hdd_validate_context
463 * This function is used to check the HDD context
464 */
465int wlan_hdd_validate_context(hdd_context_t *pHddCtx)
466{
467 ENTER();
468
469 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
470 {
471 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
472 "%s: HDD context is Null", __func__);
473 return -ENODEV;
474 }
475
476 if (pHddCtx->isLogpInProgress)
477 {
478 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
479 "%s: LOGP in Progress. Ignore!!!", __func__);
480 return -EAGAIN;
481 }
482
Mihir Shete18156292014-03-11 15:38:30 +0530483 if (WLAN_HDD_IS_LOAD_UNLOAD_IN_PROGRESS(pHddCtx))
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530484 {
485 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
486 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
487 return -EAGAIN;
488 }
489 return 0;
490}
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700491#ifdef CONFIG_ENABLE_LINUX_REG
492void hdd_checkandupdate_phymode( hdd_context_t *pHddCtx)
493{
494 hdd_adapter_t *pAdapter = NULL;
495 hdd_station_ctx_t *pHddStaCtx = NULL;
496 eCsrPhyMode phyMode;
497 hdd_config_t *cfg_param = NULL;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530498
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700499 if (NULL == pHddCtx)
500 {
501 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
502 "HDD Context is null !!");
503 return ;
504 }
505
506 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
507 if (NULL == pAdapter)
508 {
509 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
510 "pAdapter is null !!");
511 return ;
512 }
513
514 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
515 if (NULL == pHddStaCtx)
516 {
517 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
518 "pHddStaCtx is null !!");
519 return ;
520 }
521
522 cfg_param = pHddCtx->cfg_ini;
523 if (NULL == cfg_param)
524 {
525 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
526 "cfg_params not available !!");
527 return ;
528 }
529
530 phyMode = sme_GetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter));
531
532 if (!pHddCtx->isVHT80Allowed)
533 {
534 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
535 (eCSR_DOT11_MODE_11ac == phyMode) ||
536 (eCSR_DOT11_MODE_11ac_ONLY == phyMode))
537 {
538 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
539 "Setting phymode to 11n!!");
540 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter), eCSR_DOT11_MODE_11n);
541 }
542 }
543 else
544 {
545 /*New country Supports 11ac as well resetting value back from .ini*/
546 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter),
547 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->dot11Mode));
548 return ;
549 }
550
551 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
552 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode) ||
553 (eCSR_CFG_DOT11_MODE_11AC == pHddStaCtx->conn_info.dot11Mode)))
554 {
555 VOS_STATUS vosStatus;
556
557 // need to issue a disconnect to CSR.
558 INIT_COMPLETION(pAdapter->disconnect_comp_var);
559 vosStatus = sme_RoamDisconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
560 pAdapter->sessionId,
561 eCSR_DISCONNECT_REASON_UNSPECIFIED );
562
563 if (VOS_STATUS_SUCCESS == vosStatus)
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530564 {
565 long ret;
566
567 ret = wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700568 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530569 if (0 >= ret)
570 hddLog(LOGE, FL("failure waiting for disconnect_comp_var %ld"),
571 ret);
572 }
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700573
574 }
575}
576#else
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530577void hdd_checkandupdate_phymode( hdd_adapter_t *pAdapter, char *country_code)
578{
579 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
580 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
581 hdd_config_t *cfg_param;
582 eCsrPhyMode phyMode;
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530583 long ret;
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530584
585 if (NULL == pHddCtx)
586 {
587 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
588 "HDD Context is null !!");
589 return ;
590 }
591
592 cfg_param = pHddCtx->cfg_ini;
593
594 if (NULL == cfg_param)
595 {
596 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
597 "cfg_params not available !!");
598 return ;
599 }
600
601 phyMode = sme_GetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter));
602
603 if (NULL != strstr(cfg_param->listOfNon11acCountryCode, country_code))
604 {
605 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
606 (eCSR_DOT11_MODE_11ac == phyMode) ||
607 (eCSR_DOT11_MODE_11ac_ONLY == phyMode))
608 {
609 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
610 "Setting phymode to 11n!!");
611 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter), eCSR_DOT11_MODE_11n);
612 }
613 }
614 else
615 {
616 /*New country Supports 11ac as well resetting value back from .ini*/
617 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter),
618 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->dot11Mode));
619 return ;
620 }
621
622 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
623 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode) ||
624 (eCSR_CFG_DOT11_MODE_11AC == pHddStaCtx->conn_info.dot11Mode)))
625 {
626 VOS_STATUS vosStatus;
627
628 // need to issue a disconnect to CSR.
629 INIT_COMPLETION(pAdapter->disconnect_comp_var);
630 vosStatus = sme_RoamDisconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
631 pAdapter->sessionId,
632 eCSR_DISCONNECT_REASON_UNSPECIFIED );
633
634 if (VOS_STATUS_SUCCESS == vosStatus)
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530635 {
636 ret = wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530637 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530638 if (ret <= 0)
639 {
640 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
641 "wait on disconnect_comp_var is failed %ld", ret);
642 }
643 }
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530644
645 }
646}
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700647#endif //CONFIG_ENABLE_LINUX_REG
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530648
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700649void hdd_checkandupdate_dfssetting( hdd_adapter_t *pAdapter, char *country_code)
650{
651 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
652 hdd_config_t *cfg_param;
653
654 if (NULL == pHddCtx)
655 {
656 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
657 "HDD Context is null !!");
658 return ;
659 }
660
661 cfg_param = pHddCtx->cfg_ini;
662
663 if (NULL == cfg_param)
664 {
665 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
666 "cfg_params not available !!");
667 return ;
668 }
669
670 if (NULL != strstr(cfg_param->listOfNonDfsCountryCode, country_code))
671 {
672 /*New country doesn't support DFS */
673 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), 0);
674 }
675 else
676 {
677 /*New country Supports DFS as well resetting value back from .ini*/
678 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), cfg_param->enableDFSChnlScan);
679 }
680
681}
682
Rajeev79dbe4c2013-10-05 11:03:42 +0530683#ifdef FEATURE_WLAN_BATCH_SCAN
684
685/**---------------------------------------------------------------------------
686
687 \brief hdd_extract_assigned_int_from_str() - Extracts assigned integer from
688 input string
689
690 This function extracts assigned integer from string in below format:
691 "STRING=10" : extracts integer 10 from this string
692
693 \param - pInPtr Pointer to input string
694 \param - base Base for string to int conversion(10 for decimal 16 for hex)
695 \param - pOutPtr Pointer to variable in which extracted integer needs to be
696 assigned
697 \param - pLastArg to tell whether it is last arguement in input string or
698 not
699
700 \return - NULL for failure cases
701 pointer to next arguement in input string for success cases
702 --------------------------------------------------------------------------*/
703static tANI_U8 *
704hdd_extract_assigned_int_from_str
705(
706 tANI_U8 *pInPtr,
707 tANI_U8 base,
708 tANI_U32 *pOutPtr,
709 tANI_U8 *pLastArg
710)
711{
712 int tempInt;
713 int v = 0;
714 char buf[32];
715 int val = 0;
716 *pLastArg = FALSE;
717
718 pInPtr = strnchr(pInPtr, strlen(pInPtr), EQUALS_TO_ASCII_VALUE);
719 if (NULL == pInPtr)
720 {
721 return NULL;
722 }
723
724 pInPtr++;
725
726 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
727
728 val = sscanf(pInPtr, "%32s ", buf);
729 if (val < 0 && val > strlen(pInPtr))
730 {
731 return NULL;
732 }
733 pInPtr += val;
734 v = kstrtos32(buf, base, &tempInt);
735 if (v < 0)
736 {
737 return NULL;
738 }
Rajeev Kumar4d93d842014-01-02 18:31:21 -0800739 if (tempInt < 0)
740 {
741 tempInt = 0;
742 }
Rajeev79dbe4c2013-10-05 11:03:42 +0530743 *pOutPtr = tempInt;
744
745 pInPtr = strnchr(pInPtr, strlen(pInPtr), SPACE_ASCII_VALUE);
746 if (NULL == pInPtr)
747 {
748 *pLastArg = TRUE;
749 return NULL;
750 }
751 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
752
753 return pInPtr;
754}
755
756/**---------------------------------------------------------------------------
757
758 \brief hdd_extract_assigned_char_from_str() - Extracts assigned char from
759 input string
760
761 This function extracts assigned character from string in below format:
762 "STRING=A" : extracts char 'A' from this string
763
764 \param - pInPtr Pointer to input string
765 \param - pOutPtr Pointer to variable in which extracted char needs to be
766 assigned
767 \param - pLastArg to tell whether it is last arguement in input string or
768 not
769
770 \return - NULL for failure cases
771 pointer to next arguement in input string for success cases
772 --------------------------------------------------------------------------*/
773static tANI_U8 *
774hdd_extract_assigned_char_from_str
775(
776 tANI_U8 *pInPtr,
777 tANI_U8 *pOutPtr,
778 tANI_U8 *pLastArg
779)
780{
781 *pLastArg = FALSE;
782
783 pInPtr = strnchr(pInPtr, strlen(pInPtr), EQUALS_TO_ASCII_VALUE);
784 if (NULL == pInPtr)
785 {
786 return NULL;
787 }
788
789 pInPtr++;
790
791 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
792
793 *pOutPtr = *pInPtr;
794
795 pInPtr = strnchr(pInPtr, strlen(pInPtr), SPACE_ASCII_VALUE);
796 if (NULL == pInPtr)
797 {
798 *pLastArg = TRUE;
799 return NULL;
800 }
801 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
802
803 return pInPtr;
804}
805
806
807/**---------------------------------------------------------------------------
808
809 \brief hdd_parse_set_batchscan_command () - HDD parse set batch scan command
810
811 This function parses set batch scan command in below format:
812 WLS_BATCHING_SET <space> followed by below arguements
813 "SCANFREQ=XX" : Optional defaults to 30 sec
814 "MSCAN=XX" : Required number of scans to attempt to batch
815 "BESTN=XX" : Best Network (RSSI) defaults to 16
816 "CHANNEL=<X,Y>" : optional defaults to all channels, can list 'A'or` B.
817 A. implies only 5 GHz , B. implies only 2.4GHz
818 "RTT=X" : optional defaults to 0
819 returns the MIN of MSCAN or the max # of scans firmware can cache or -1 on
820 error
821
822 For example input commands:
823 1) WLS_BATCHING_SET SCANFREQ=60 MSCAN=10 BESTN=20 CHANNEL=A RTT=0 -> This is
824 translated into set batch scan with following parameters:
825 a) Frequence 60 seconds
826 b) Batch 10 scans together
827 c) Best RSSI to be 20
828 d) 5GHz band only
829 e) RTT is equal to 0
830
831 \param - pValue Pointer to input channel list
832 \param - pHddSetBatchScanReq Pointer to HDD batch scan request structure
833
834 \return - 0 for success non-zero for failure
835
836 --------------------------------------------------------------------------*/
837static int
838hdd_parse_set_batchscan_command
839(
840 tANI_U8 *pValue,
841 tSirSetBatchScanReq *pHddSetBatchScanReq
842)
843{
844 tANI_U8 *inPtr = pValue;
845 tANI_U8 val = 0;
846 tANI_U8 lastArg = 0;
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800847 tANI_U32 nScanFreq;
848 tANI_U32 nMscan;
849 tANI_U32 nBestN;
850 tANI_U8 ucRfBand;
851 tANI_U32 nRtt;
Rajeev Kumarc933d982013-11-18 20:04:20 -0800852 tANI_U32 temp;
Rajeev79dbe4c2013-10-05 11:03:42 +0530853
854 /*initialize default values*/
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800855 nScanFreq = HDD_SET_BATCH_SCAN_DEFAULT_FREQ;
856 ucRfBand = HDD_SET_BATCH_SCAN_DEFAULT_BAND;
857 nRtt = 0;
858 nBestN = HDD_SET_BATCH_SCAN_BEST_NETWORK;
Rajeev79dbe4c2013-10-05 11:03:42 +0530859
860 /*go to space after WLS_BATCHING_SET command*/
861 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
862 /*no argument after the command*/
863 if (NULL == inPtr)
864 {
865 return -EINVAL;
866 }
867
868 /*no space after the command*/
869 else if (SPACE_ASCII_VALUE != *inPtr)
870 {
871 return -EINVAL;
872 }
873
874 /*removing empty spaces*/
875 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
876
877 /*no argument followed by spaces*/
878 if ('\0' == *inPtr)
879 {
880 return -EINVAL;
881 }
882
883 /*check and parse SCANFREQ*/
884 if ((strncmp(inPtr, "SCANFREQ", 8) == 0))
885 {
886 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumarc933d982013-11-18 20:04:20 -0800887 &temp, &lastArg);
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800888
Rajeev Kumarc933d982013-11-18 20:04:20 -0800889 if (0 != temp)
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800890 {
Rajeev Kumarc933d982013-11-18 20:04:20 -0800891 nScanFreq = temp;
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800892 }
893
Rajeev79dbe4c2013-10-05 11:03:42 +0530894 if ( (NULL == inPtr) || (TRUE == lastArg))
895 {
896 return -EINVAL;
897 }
898 }
899
900 /*check and parse MSCAN*/
901 if ((strncmp(inPtr, "MSCAN", 5) == 0))
902 {
903 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800904 &nMscan, &lastArg);
905
906 if (0 == nMscan)
907 {
908 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
909 "invalid MSCAN=%d", nMscan);
910 return -EINVAL;
911 }
912
Rajeev79dbe4c2013-10-05 11:03:42 +0530913 if (TRUE == lastArg)
914 {
915 goto done;
916 }
917 else if (NULL == inPtr)
918 {
919 return -EINVAL;
920 }
921 }
922 else
923 {
924 return -EINVAL;
925 }
926
927 /*check and parse BESTN*/
928 if ((strncmp(inPtr, "BESTN", 5) == 0))
929 {
930 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumarc933d982013-11-18 20:04:20 -0800931 &temp, &lastArg);
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800932
Rajeev Kumarc933d982013-11-18 20:04:20 -0800933 if (0 != temp)
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800934 {
Rajeev Kumarc933d982013-11-18 20:04:20 -0800935 nBestN = temp;
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800936 }
937
Rajeev79dbe4c2013-10-05 11:03:42 +0530938 if (TRUE == lastArg)
939 {
940 goto done;
941 }
942 else if (NULL == inPtr)
943 {
944 return -EINVAL;
945 }
946 }
947
948 /*check and parse CHANNEL*/
949 if ((strncmp(inPtr, "CHANNEL", 7) == 0))
950 {
951 inPtr = hdd_extract_assigned_char_from_str(inPtr, &val, &lastArg);
Rajeev Kumarc933d982013-11-18 20:04:20 -0800952
Rajeev79dbe4c2013-10-05 11:03:42 +0530953 if (('A' == val) || ('a' == val))
954 {
c_hpothuebf89732014-02-25 13:00:24 +0530955 ucRfBand = HDD_SET_BATCH_SCAN_5GHz_BAND_ONLY;
Rajeev79dbe4c2013-10-05 11:03:42 +0530956 }
957 else if (('B' == val) || ('b' == val))
958 {
c_hpothuebf89732014-02-25 13:00:24 +0530959 ucRfBand = HDD_SET_BATCH_SCAN_24GHz_BAND_ONLY;
Rajeev79dbe4c2013-10-05 11:03:42 +0530960 }
961 else
962 {
Rajeev Kumarc933d982013-11-18 20:04:20 -0800963 ucRfBand = HDD_SET_BATCH_SCAN_DEFAULT_BAND;
964 }
965
966 if (TRUE == lastArg)
967 {
968 goto done;
969 }
970 else if (NULL == inPtr)
971 {
Rajeev79dbe4c2013-10-05 11:03:42 +0530972 return -EINVAL;
973 }
974 }
975
976 /*check and parse RTT*/
977 if ((strncmp(inPtr, "RTT", 3) == 0))
978 {
979 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800980 &nRtt, &lastArg);
Rajeev79dbe4c2013-10-05 11:03:42 +0530981 if (TRUE == lastArg)
982 {
983 goto done;
984 }
985 if (NULL == inPtr)
986 {
987 return -EINVAL;
988 }
989 }
990
991
992done:
993
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800994 pHddSetBatchScanReq->scanFrequency = nScanFreq;
995 pHddSetBatchScanReq->numberOfScansToBatch = nMscan;
996 pHddSetBatchScanReq->bestNetwork = nBestN;
997 pHddSetBatchScanReq->rfBand = ucRfBand;
998 pHddSetBatchScanReq->rtt = nRtt;
999
Rajeev79dbe4c2013-10-05 11:03:42 +05301000 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1001 "Received WLS_BATCHING_SET with SCANFREQ=%d "
1002 "MSCAN=%d BESTN=%d CHANNEL=%d RTT=%d",
1003 pHddSetBatchScanReq->scanFrequency,
1004 pHddSetBatchScanReq->numberOfScansToBatch,
1005 pHddSetBatchScanReq->bestNetwork,
1006 pHddSetBatchScanReq->rfBand,
1007 pHddSetBatchScanReq->rtt);
1008
1009 return 0;
1010}/*End of hdd_parse_set_batchscan_command*/
1011
1012/**---------------------------------------------------------------------------
1013
1014 \brief hdd_set_batch_scan_req_callback () - This function is called after
1015 receiving set batch scan response from FW and it saves set batch scan
1016 response data FW to HDD context and sets the completion event on
1017 which hdd_ioctl is waiting
1018
1019 \param - callbackContext Pointer to HDD adapter
1020 \param - pRsp Pointer to set batch scan response data received from FW
1021
1022 \return - nothing
1023
1024 --------------------------------------------------------------------------*/
1025static void hdd_set_batch_scan_req_callback
1026(
1027 void *callbackContext,
1028 tSirSetBatchScanRsp *pRsp
1029)
1030{
1031 hdd_adapter_t* pAdapter = (hdd_adapter_t*)callbackContext;
1032 tSirSetBatchScanRsp *pHddSetBatchScanRsp;
1033
1034 /*sanity check*/
1035 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
1036 {
1037 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1038 "%s: Invalid pAdapter magic", __func__);
1039 VOS_ASSERT(0);
1040 return;
1041 }
1042 pHddSetBatchScanRsp = &pAdapter->hddSetBatchScanRsp;
1043
1044 /*save set batch scan response*/
1045 pHddSetBatchScanRsp->nScansToBatch = pRsp->nScansToBatch;
1046
1047 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1048 "Received set batch scan rsp from FW with nScansToBatch=%d",
1049 pHddSetBatchScanRsp->nScansToBatch);
1050
1051 pAdapter->hdd_wait_for_set_batch_scan_rsp = FALSE;
1052 complete(&pAdapter->hdd_set_batch_scan_req_var);
1053
1054 return;
1055}/*End of hdd_set_batch_scan_req_callback*/
1056
1057
1058/**---------------------------------------------------------------------------
1059
1060 \brief hdd_populate_batch_scan_rsp_queue () - This function stores AP meta
1061 info in hdd batch scan response queue
1062
1063 \param - pAdapter Pointer to hdd adapter
1064 \param - pAPMetaInfo Pointer to access point meta info
1065 \param - scanId scan ID of batch scan response
1066 \param - isLastAp tells whether AP is last AP in batch scan response or not
1067
1068 \return - nothing
1069
1070 --------------------------------------------------------------------------*/
1071static void hdd_populate_batch_scan_rsp_queue( hdd_adapter_t* pAdapter,
1072 tpSirBatchScanNetworkInfo pApMetaInfo, tANI_U32 scanId, v_BOOL_t isLastAp)
1073{
1074 tHddBatchScanRsp *pHead;
1075 tHddBatchScanRsp *pNode;
1076 tHddBatchScanRsp *pPrev;
1077 tHddBatchScanRsp *pTemp;
1078 tANI_U8 ssidLen;
1079
1080 /*head of hdd batch scan response queue*/
1081 pHead = pAdapter->pBatchScanRsp;
1082
1083 pNode = (tHddBatchScanRsp *)vos_mem_malloc(sizeof(tHddBatchScanRsp));
1084 if (NULL == pNode)
1085 {
1086 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1087 "%s: Could not allocate memory", __func__);
1088 VOS_ASSERT(0);
1089 return;
1090 }
1091
1092 vos_mem_copy(pNode->ApInfo.bssid, pApMetaInfo->bssid,
1093 sizeof(pNode->ApInfo.bssid));
1094 ssidLen = strlen(pApMetaInfo->ssid);
1095 if (SIR_MAX_SSID_SIZE < ssidLen)
1096 {
1097 /*invalid scan result*/
1098 vos_mem_free(pNode);
1099 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1100 "%s: Invalid AP meta info ssidlen %d", __func__, ssidLen);
1101 return;
1102 }
1103 vos_mem_copy(pNode->ApInfo.ssid, pApMetaInfo->ssid, ssidLen);
1104 /*null terminate ssid*/
1105 pNode->ApInfo.ssid[ssidLen] = '\0';
1106 pNode->ApInfo.ch = pApMetaInfo->ch;
1107 pNode->ApInfo.rssi = pApMetaInfo->rssi;
1108 pNode->ApInfo.age = pApMetaInfo->timestamp;
1109 pNode->ApInfo.batchId = scanId;
1110 pNode->ApInfo.isLastAp = isLastAp;
1111
1112 pNode->pNext = NULL;
1113 if (NULL == pHead)
1114 {
1115 pAdapter->pBatchScanRsp = pNode;
1116 }
1117 else
1118 {
1119 pTemp = pHead;
1120 while (NULL != pTemp)
1121 {
1122 pPrev = pTemp;
1123 pTemp = pTemp->pNext;
1124 }
1125 pPrev->pNext = pNode;
1126 }
1127
1128 return;
1129}/*End of hdd_populate_batch_scan_rsp_queue*/
1130
1131/**---------------------------------------------------------------------------
1132
1133 \brief hdd_batch_scan_result_ind_callback () - This function is called after
1134 receiving batch scan response indication from FW. It saves get batch scan
1135 response data in HDD batch scan response queue. This callback sets the
1136 completion event on which hdd_ioctl is waiting only after getting complete
1137 batch scan response data from FW
1138
1139 \param - callbackContext Pointer to HDD adapter
1140 \param - pRsp Pointer to get batch scan response data received from FW
1141
1142 \return - nothing
1143
1144 --------------------------------------------------------------------------*/
1145static void hdd_batch_scan_result_ind_callback
1146(
1147 void *callbackContext,
1148 void *pRsp
1149)
1150{
1151 v_BOOL_t isLastAp;
1152 tANI_U32 numApMetaInfo;
Rajeev Kumarce651e42013-10-21 18:57:15 -07001153 tANI_U32 numNetworkInScanList;
Rajeev79dbe4c2013-10-05 11:03:42 +05301154 tANI_U32 numberScanList;
1155 tANI_U32 nextScanListOffset;
1156 tANI_U32 nextApMetaInfoOffset;
1157 hdd_adapter_t* pAdapter;
1158 tpSirBatchScanList pScanList;
1159 tpSirBatchScanNetworkInfo pApMetaInfo;
1160 tpSirBatchScanResultIndParam pBatchScanRsp;/*batch scan rsp data from FW*/
1161 tSirSetBatchScanReq *pReq;
1162
1163 pAdapter = (hdd_adapter_t *)callbackContext;
1164 /*sanity check*/
Rajeev Kumar5286bb92013-12-05 11:52:10 -08001165 if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
Rajeev79dbe4c2013-10-05 11:03:42 +05301166 {
1167 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1168 "%s: Invalid pAdapter magic", __func__);
1169 VOS_ASSERT(0);
1170 return;
1171 }
1172
1173 /*initialize locals*/
1174 pReq = &pAdapter->hddSetBatchScanReq;
1175 pBatchScanRsp = (tpSirBatchScanResultIndParam)pRsp;
1176 isLastAp = FALSE;
1177 numApMetaInfo = 0;
Rajeev Kumarce651e42013-10-21 18:57:15 -07001178 numNetworkInScanList = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05301179 numberScanList = 0;
1180 nextScanListOffset = 0;
1181 nextApMetaInfoOffset = 0;
1182 pScanList = NULL;
1183 pApMetaInfo = NULL;
1184
1185 if ((NULL == pBatchScanRsp) || (NULL == pReq))
1186 {
1187 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1188 "%s: pBatchScanRsp is %p pReq %p", __func__, pBatchScanRsp, pReq);
1189 isLastAp = TRUE;
1190 goto done;
1191 }
1192
1193 pAdapter->numScanList = numberScanList = pBatchScanRsp->numScanLists;
1194 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1195 "Batch scan rsp: numberScalList %d", numberScanList);
1196
1197 if ((!numberScanList) || (numberScanList > pReq->numberOfScansToBatch))
1198 {
1199 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1200 "%s: numberScanList %d", __func__, numberScanList);
1201 isLastAp = TRUE;
1202 goto done;
1203 }
1204
1205 while (numberScanList)
1206 {
Rajeev Kumarce651e42013-10-21 18:57:15 -07001207 pScanList = (tpSirBatchScanList)((tANI_U8 *)pBatchScanRsp->scanResults +
Rajeev79dbe4c2013-10-05 11:03:42 +05301208 nextScanListOffset);
1209 if (NULL == pScanList)
1210 {
1211 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1212 "%s: pScanList is %p", __func__, pScanList);
1213 isLastAp = TRUE;
1214 goto done;
1215 }
Rajeev Kumarce651e42013-10-21 18:57:15 -07001216 numNetworkInScanList = numApMetaInfo = pScanList->numNetworksInScanList;
Rajeev79dbe4c2013-10-05 11:03:42 +05301217 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumarce651e42013-10-21 18:57:15 -07001218 "Batch scan rsp: numApMetaInfo %d scanId %d",
1219 numApMetaInfo, pScanList->scanId);
Rajeev79dbe4c2013-10-05 11:03:42 +05301220
1221 if ((!numApMetaInfo) || (numApMetaInfo > pReq->bestNetwork))
1222 {
1223 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1224 "%s: numApMetaInfo %d", __func__, numApMetaInfo);
1225 isLastAp = TRUE;
1226 goto done;
1227 }
1228
Rajeev Kumarce651e42013-10-21 18:57:15 -07001229 /*Initialize next AP meta info offset for next scan list*/
1230 nextApMetaInfoOffset = 0;
1231
Rajeev79dbe4c2013-10-05 11:03:42 +05301232 while (numApMetaInfo)
1233 {
1234 pApMetaInfo = (tpSirBatchScanNetworkInfo)(pScanList->scanList +
1235 nextApMetaInfoOffset);
1236 if (NULL == pApMetaInfo)
1237 {
1238 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1239 "%s: pApMetaInfo is %p", __func__, pApMetaInfo);
1240 isLastAp = TRUE;
1241 goto done;
1242 }
1243 /*calculate AP age*/
1244 pApMetaInfo->timestamp =
1245 pBatchScanRsp->timestamp - pApMetaInfo->timestamp;
1246
1247 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
Arif Hussaina7c8e412013-11-20 11:06:42 -08001248 "%s: bssId "MAC_ADDRESS_STR
1249 " ch %d rssi %d timestamp %d", __func__,
1250 MAC_ADDR_ARRAY(pApMetaInfo->bssid),
1251 pApMetaInfo->ch, pApMetaInfo->rssi,
1252 pApMetaInfo->timestamp);
Rajeev79dbe4c2013-10-05 11:03:42 +05301253
1254 /*mark last AP in batch scan response*/
1255 if ((TRUE == pBatchScanRsp->isLastResult) &&
1256 (1 == numberScanList) && (1 == numApMetaInfo))
1257 {
1258 isLastAp = TRUE;
1259 }
1260
1261 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1262 /*store batch scan repsonse in hdd queue*/
1263 hdd_populate_batch_scan_rsp_queue(pAdapter, pApMetaInfo,
1264 pScanList->scanId, isLastAp);
1265 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1266
1267 nextApMetaInfoOffset += sizeof(tSirBatchScanNetworkInfo);
1268 numApMetaInfo--;
1269 }
1270
Rajeev Kumarce651e42013-10-21 18:57:15 -07001271 nextScanListOffset += ((sizeof(tSirBatchScanList) - sizeof(tANI_U8))
1272 + (sizeof(tSirBatchScanNetworkInfo)
1273 * numNetworkInScanList));
Rajeev79dbe4c2013-10-05 11:03:42 +05301274 numberScanList--;
1275 }
1276
1277done:
1278
1279 /*notify hdd_ioctl only if complete batch scan rsp is received and it was
1280 requested from hdd_ioctl*/
1281 if ((TRUE == pAdapter->hdd_wait_for_get_batch_scan_rsp) &&
1282 (TRUE == isLastAp))
1283 {
1284 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
1285 complete(&pAdapter->hdd_get_batch_scan_req_var);
1286 }
1287
1288 return;
1289}/*End of hdd_batch_scan_result_ind_callback*/
1290
1291/**---------------------------------------------------------------------------
1292
1293 \brief hdd_format_batch_scan_rsp () - This function formats batch scan
1294 response as per batch scan FR request format by putting proper markers
1295
1296 \param - pDest pointer to destination buffer
1297 \param - cur_len current length
1298 \param - tot_len total remaining size which can be written to user space
1299 \param - pApMetaInfo Pointer to get batch scan response AP meta info
1300 \param - pAdapter Pointer to HDD adapter
1301
1302 \return - ret no of characters written
1303
1304 --------------------------------------------------------------------------*/
1305static tANI_U32
1306hdd_format_batch_scan_rsp
1307(
1308 tANI_U8 *pDest,
1309 tANI_U32 cur_len,
1310 tANI_U32 tot_len,
1311 tHddBatchScanRsp *pApMetaInfo,
1312 hdd_adapter_t* pAdapter
1313)
1314{
1315 tANI_U32 ret = 0;
1316 tANI_U32 rem_len = 0;
1317 tANI_U8 temp_len = 0;
1318 tANI_U8 temp_total_len = 0;
1319 tANI_U8 temp[HDD_BATCH_SCAN_AP_META_INFO_SIZE];
1320 tANI_U8 *pTemp = temp;
1321
1322 /*Batch scan reponse needs to be returned to user space in
1323 following format:
1324 "scancount=X\n" where X is the number of scans in current batch
1325 batch
1326 "trunc\n" optional present if current scan truncated
1327 "bssid=XX:XX:XX:XX:XX:XX\n"
1328 "ssid=XXXX\n"
1329 "freq=X\n" frequency in Mhz
1330 "level=XX\n"
1331 "age=X\n" ms
1332 "dist=X\n" cm (-1 if not available)
1333 "errror=X\n" (-1if not available)
1334 "====\n" (end of ap marker)
1335 "####\n" (end of scan marker)
1336 "----\n" (end of results)*/
1337 /*send scan result in above format to user space based on
1338 available length*/
1339 /*The GET response may have more data than the driver can return in its
1340 buffer. In that case the buffer should be filled to the nearest complete
1341 scan, ending with "%%%%".Subsequent callsshould return the remaining data
1342 starting with the next scan (optional .trunc\n., .apcount=X\n., etc).
1343 The final buffer should end with "----\n"*/
1344
1345 /*sanity*/
1346 if (cur_len > tot_len)
1347 {
1348 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1349 "%s: invaid cur_len %d tot_len %d", __func__, cur_len, tot_len);
1350 return 0;
1351 }
1352 else
1353 {
1354 rem_len = (tot_len - cur_len);
1355 }
1356
1357 /*end scan marker*/
1358 if (pApMetaInfo->ApInfo.batchId != pAdapter->prev_batch_id)
1359 {
1360 temp_len = snprintf(pTemp, sizeof(temp), "####\n");
1361 pTemp += temp_len;
1362 temp_total_len += temp_len;
1363 }
1364
1365 /*bssid*/
1366 temp_len = snprintf(pTemp, sizeof(temp),
1367 "bssid=0x%x:0x%x:0x%x:0x%x:0x%x:0x%x\n",
1368 pApMetaInfo->ApInfo.bssid[0], pApMetaInfo->ApInfo.bssid[1],
1369 pApMetaInfo->ApInfo.bssid[2], pApMetaInfo->ApInfo.bssid[3],
1370 pApMetaInfo->ApInfo.bssid[4], pApMetaInfo->ApInfo.bssid[5]);
1371 pTemp += temp_len;
1372 temp_total_len += temp_len;
1373
1374 /*ssid*/
1375 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "ssid=%s\n",
1376 pApMetaInfo->ApInfo.ssid);
1377 pTemp += temp_len;
1378 temp_total_len += temp_len;
1379
1380 /*freq*/
1381 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "freq=%d\n",
Rajeev Kumarc40f7512013-11-04 14:13:23 -08001382 sme_ChnToFreq(pApMetaInfo->ApInfo.ch));
Rajeev79dbe4c2013-10-05 11:03:42 +05301383 pTemp += temp_len;
1384 temp_total_len += temp_len;
1385
1386 /*level*/
1387 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "level=%d\n",
1388 pApMetaInfo->ApInfo.rssi);
1389 pTemp += temp_len;
1390 temp_total_len += temp_len;
1391
1392 /*age*/
Jeff Johnson02797792013-10-26 19:17:13 -07001393 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "age=%d\n",
Rajeev79dbe4c2013-10-05 11:03:42 +05301394 pApMetaInfo->ApInfo.age);
1395 pTemp += temp_len;
1396 temp_total_len += temp_len;
1397
1398 /*dist*/
1399 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "dist=-1\n");
1400 pTemp += temp_len;
1401 temp_total_len += temp_len;
1402
1403 /*error*/
1404 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "error=-1\n");
1405 pTemp += temp_len;
1406 temp_total_len += temp_len;
1407
1408 /*end AP marker*/
1409 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "====\n");
1410 pTemp += temp_len;
1411 temp_total_len += temp_len;
1412
1413 /*last AP in batch scan response*/
1414 if(TRUE == pApMetaInfo->ApInfo.isLastAp)
1415 {
1416 /*end scan marker*/
1417 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "####\n");
1418 pTemp += temp_len;
1419 temp_total_len += temp_len;
1420
1421 /*end batch scan result marker*/
1422 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "----\n");
1423 pTemp += temp_len;
1424 temp_total_len += temp_len;
Kiet Lamaa8e15a2014-02-11 23:30:06 -08001425
Rajeev79dbe4c2013-10-05 11:03:42 +05301426 }
1427
1428 if (temp_total_len < rem_len)
1429 {
1430 ret = temp_total_len + 1;
1431 strlcpy(pDest, temp, ret);
1432 pAdapter->isTruncated = FALSE;
1433 }
1434 else
1435 {
1436 pAdapter->isTruncated = TRUE;
1437 if (rem_len >= strlen("%%%%"))
1438 {
Rajeev Kumarc933d982013-11-18 20:04:20 -08001439 ret = snprintf(pDest, sizeof(temp), "%%%%");
Rajeev79dbe4c2013-10-05 11:03:42 +05301440 }
Rajeev Kumarc933d982013-11-18 20:04:20 -08001441 else
Rajeev79dbe4c2013-10-05 11:03:42 +05301442 {
1443 ret = 0;
1444 }
1445 }
1446
1447 return ret;
1448
1449}/*End of hdd_format_batch_scan_rsp*/
1450
1451/**---------------------------------------------------------------------------
1452
1453 \brief hdd_populate_user_batch_scan_rsp() - This function populates user data
1454 buffer starting with head of hdd batch scan response queue
1455
1456 \param - pAdapter Pointer to HDD adapter
1457 \param - pDest Pointer to user data buffer
1458 \param - cur_len current offset in user buffer
1459 \param - rem_len remaining no of bytes in user buffer
1460
1461 \return - number of bytes written in user buffer
1462
1463 --------------------------------------------------------------------------*/
1464
1465tANI_U32 hdd_populate_user_batch_scan_rsp
1466(
1467 hdd_adapter_t* pAdapter,
1468 tANI_U8 *pDest,
1469 tANI_U32 cur_len,
1470 tANI_U32 rem_len
1471)
1472{
1473 tHddBatchScanRsp *pHead;
1474 tHddBatchScanRsp *pPrev;
1475 tANI_U32 len;
1476
Rajeev79dbe4c2013-10-05 11:03:42 +05301477 pAdapter->isTruncated = FALSE;
1478
1479 /*head of hdd batch scan response queue*/
1480 pHead = pAdapter->pBatchScanRsp;
1481 while (pHead)
1482 {
1483 len = hdd_format_batch_scan_rsp(pDest, cur_len, rem_len, pHead,
1484 pAdapter);
1485 pDest += len;
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07001486 pDest--;
Rajeev79dbe4c2013-10-05 11:03:42 +05301487 cur_len += len;
1488 if(TRUE == pAdapter->isTruncated)
1489 {
1490 /*result is truncated return rest of scan rsp in next req*/
1491 cur_len = rem_len;
1492 break;
1493 }
1494 pPrev = pHead;
1495 pHead = pHead->pNext;
1496 pAdapter->pBatchScanRsp = pHead;
Rajeev Kumarbe17d8b2014-01-10 15:39:45 -08001497 if (TRUE == pPrev->ApInfo.isLastAp)
1498 {
1499 pAdapter->prev_batch_id = 0;
1500 }
1501 else
1502 {
1503 pAdapter->prev_batch_id = pPrev->ApInfo.batchId;
1504 }
Rajeev79dbe4c2013-10-05 11:03:42 +05301505 vos_mem_free(pPrev);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08001506 pPrev = NULL;
Rajeev79dbe4c2013-10-05 11:03:42 +05301507 }
1508
1509 return cur_len;
1510}/*End of hdd_populate_user_batch_scan_rsp*/
1511
1512/**---------------------------------------------------------------------------
1513
1514 \brief hdd_return_batch_scan_rsp_to_user () - This function returns batch
1515 scan response data from HDD queue to user space
1516 It does following in detail:
1517 a) if HDD has enough data in its queue then it 1st copies data to user
1518 space and then send get batch scan indication message to FW. In this
1519 case it does not wait on any event and batch scan response data will
1520 be populated in HDD response queue in MC thread context after receiving
1521 indication from FW
1522 b) else send get batch scan indication message to FW and wait on an event
1523 which will be set once HDD receives complete batch scan response from
1524 FW and then this function returns batch scan response to user space
1525
1526 \param - pAdapter Pointer to HDD adapter
1527 \param - pPrivData Pointer to priv_data
1528
1529 \return - 0 for success -EFAULT for failure
1530
1531 --------------------------------------------------------------------------*/
1532
1533int hdd_return_batch_scan_rsp_to_user
1534(
1535 hdd_adapter_t* pAdapter,
1536 hdd_priv_data_t *pPrivData,
1537 tANI_U8 *command
1538)
1539{
1540 tANI_U8 *pDest;
1541 tANI_U32 count = 0;
1542 tANI_U32 len = 0;
1543 tANI_U32 cur_len = 0;
1544 tANI_U32 rem_len = 0;
1545 eHalStatus halStatus;
1546 unsigned long rc;
1547 tSirTriggerBatchScanResultInd *pReq;
1548
1549 pReq = &pAdapter->hddTriggerBatchScanResultInd;
1550 pReq->param = 0;/*batch scan client*/
1551 pDest = (tANI_U8 *)(command + pPrivData->used_len);
1552 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
1553
1554 cur_len = pPrivData->used_len;
1555 if (pPrivData->total_len > pPrivData->used_len)
1556 {
1557 rem_len = pPrivData->total_len - pPrivData->used_len;
1558 }
1559 else
1560 {
1561 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1562 "%s: Invalid user data buffer total_len %d used_len %d",
1563 __func__, pPrivData->total_len, pPrivData->used_len);
1564 return -EFAULT;
1565 }
1566
1567 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1568 len = hdd_populate_user_batch_scan_rsp(pAdapter, pDest,
1569 cur_len, rem_len);
1570 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1571
1572 /*enough scan result available in cache to return to user space or
1573 scan result needs to be fetched 1st from fw and then return*/
Rajeev Kumar99db6262013-11-11 15:23:36 -08001574 if (len == cur_len)
Rajeev79dbe4c2013-10-05 11:03:42 +05301575 {
1576 pAdapter->hdd_wait_for_get_batch_scan_rsp = TRUE;
1577 halStatus = sme_TriggerBatchScanResultInd(
1578 WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
1579 pAdapter->sessionId, hdd_batch_scan_result_ind_callback,
1580 pAdapter);
1581 if ( eHAL_STATUS_SUCCESS == halStatus )
1582 {
1583 if (TRUE == pAdapter->hdd_wait_for_get_batch_scan_rsp)
1584 {
1585 INIT_COMPLETION(pAdapter->hdd_get_batch_scan_req_var);
1586 rc = wait_for_completion_timeout(
1587 &pAdapter->hdd_get_batch_scan_req_var,
1588 msecs_to_jiffies(HDD_GET_BATCH_SCAN_RSP_TIME_OUT));
1589 if (0 == rc)
1590 {
1591 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1592 "%s: Timeout waiting to fetch batch scan rsp from fw",
1593 __func__);
1594 return -EFAULT;
1595 }
1596 }
1597
1598 len = snprintf(pDest, HDD_BATCH_SCAN_AP_META_INFO_SIZE,
Jeff Johnson02797792013-10-26 19:17:13 -07001599 "scancount=%u\n", pAdapter->numScanList);
Rajeev79dbe4c2013-10-05 11:03:42 +05301600 pDest += len;
1601 cur_len += len;
1602
1603 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1604 len = hdd_populate_user_batch_scan_rsp(pAdapter, pDest,
1605 cur_len, rem_len);
1606 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1607
1608 count = 0;
1609 len = (len - pPrivData->used_len);
1610 pDest = (command + pPrivData->used_len);
1611 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar99db6262013-11-11 15:23:36 -08001612 "NEW BATCH SCAN RESULT:");
Rajeev79dbe4c2013-10-05 11:03:42 +05301613 while(count < len)
1614 {
1615 printk("%c", *(pDest + count));
1616 count++;
1617 }
1618 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1619 "%s: copy %d data to user buffer", __func__, len);
1620 if (copy_to_user(pPrivData->buf, pDest, len))
1621 {
1622 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1623 "%s: failed to copy data to user buffer", __func__);
1624 return -EFAULT;
1625 }
1626 }
1627 else
1628 {
1629 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1630 "sme_GetBatchScanScan returned failure halStatus %d",
1631 halStatus);
1632 return -EINVAL;
1633 }
1634 }
1635 else
1636 {
Rajeev79dbe4c2013-10-05 11:03:42 +05301637 count = 0;
1638 len = (len - pPrivData->used_len);
1639 pDest = (command + pPrivData->used_len);
1640 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar99db6262013-11-11 15:23:36 -08001641 "REMAINING TRUNCATED BATCH SCAN RESULT:");
Rajeev79dbe4c2013-10-05 11:03:42 +05301642 while(count < len)
1643 {
1644 printk("%c", *(pDest + count));
1645 count++;
1646 }
Rajeev Kumar99db6262013-11-11 15:23:36 -08001647 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1648 "%s: copy %d data to user buffer", __func__, len);
Rajeev79dbe4c2013-10-05 11:03:42 +05301649 if (copy_to_user(pPrivData->buf, pDest, len))
1650 {
1651 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1652 "%s: failed to copy data to user buffer", __func__);
1653 return -EFAULT;
1654 }
Rajeev79dbe4c2013-10-05 11:03:42 +05301655 }
1656
1657 return 0;
1658} /*End of hdd_return_batch_scan_rsp_to_user*/
1659
Rajeev Kumar8b373292014-01-08 20:36:55 -08001660
1661/**---------------------------------------------------------------------------
1662
1663 \brief hdd_handle_batch_scan_ioctl () - This function handles WLS_BATCHING
1664 IOCTLs from user space. Following BATCH SCAN DEV IOCTs are handled:
1665 WLS_BATCHING VERSION
1666 WLS_BATCHING SET
1667 WLS_BATCHING GET
1668 WLS_BATCHING STOP
1669
1670 \param - pAdapter Pointer to HDD adapter
1671 \param - pPrivdata Pointer to priv_data
1672 \param - command Pointer to command
1673
1674 \return - 0 for success -EFAULT for failure
1675
1676 --------------------------------------------------------------------------*/
1677
1678int hdd_handle_batch_scan_ioctl
1679(
1680 hdd_adapter_t *pAdapter,
1681 hdd_priv_data_t *pPrivdata,
1682 tANI_U8 *command
1683)
1684{
1685 int ret = 0;
Yue Mae36e3552014-03-05 17:06:20 -08001686 hdd_context_t *pHddCtx;
1687
1688 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
1689 ret = wlan_hdd_validate_context(pHddCtx);
1690 if (ret)
1691 {
1692 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1693 "%s: HDD context is not valid!", __func__);
1694 goto exit;
1695 }
Rajeev Kumar8b373292014-01-08 20:36:55 -08001696
1697 if (strncmp(command, "WLS_BATCHING VERSION", 20) == 0)
1698 {
1699 char extra[32];
1700 tANI_U8 len = 0;
1701 tANI_U8 version = HDD_BATCH_SCAN_VERSION;
1702
1703 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
1704 {
1705 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1706 "%s: Batch scan feature is not supported by FW", __func__);
1707 ret = -EINVAL;
1708 goto exit;
1709 }
1710
1711 len = scnprintf(extra, sizeof(extra), "WLS_BATCHING_VERSION %d",
1712 version);
1713 if (copy_to_user(pPrivdata->buf, &extra, len + 1))
1714 {
1715 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1716 "%s: failed to copy data to user buffer", __func__);
1717 ret = -EFAULT;
1718 goto exit;
1719 }
1720 ret = HDD_BATCH_SCAN_VERSION;
1721 }
1722 else if (strncmp(command, "WLS_BATCHING SET", 16) == 0)
1723 {
1724 int status;
1725 tANI_U8 *value = (command + 16);
1726 eHalStatus halStatus;
1727 unsigned long rc;
1728 tSirSetBatchScanReq *pReq = &pAdapter->hddSetBatchScanReq;
1729 tSirSetBatchScanRsp *pRsp = &pAdapter->hddSetBatchScanRsp;
1730
1731 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
1732 {
1733 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1734 "%s: Batch scan feature is not supported by FW", __func__);
1735 ret = -EINVAL;
1736 goto exit;
1737 }
1738
1739 if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) &&
1740 (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) &&
1741 (WLAN_HDD_P2P_GO != pAdapter->device_mode) &&
1742 (WLAN_HDD_P2P_DEVICE != pAdapter->device_mode))
1743 {
1744 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Sushant Kaushik8bc7df22014-04-09 17:55:29 +05301745 "Received WLS_BATCHING SET command in invalid mode %s (%d) "
Rajeev Kumar8b373292014-01-08 20:36:55 -08001746 "WLS_BATCHING_SET is only allowed in infra STA/P2P client mode",
Sushant Kaushik8bc7df22014-04-09 17:55:29 +05301747 hdd_device_modetoString(pAdapter->device_mode),
1748 pAdapter->device_mode);
Rajeev Kumar8b373292014-01-08 20:36:55 -08001749 ret = -EINVAL;
1750 goto exit;
1751 }
1752
1753 status = hdd_parse_set_batchscan_command(value, pReq);
1754 if (status)
1755 {
1756 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1757 "Invalid WLS_BATCHING SET command");
1758 ret = -EINVAL;
1759 goto exit;
1760 }
1761
1762
1763 pAdapter->hdd_wait_for_set_batch_scan_rsp = TRUE;
1764 halStatus = sme_SetBatchScanReq(WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
1765 pAdapter->sessionId, hdd_set_batch_scan_req_callback,
1766 pAdapter);
1767
1768 if ( eHAL_STATUS_SUCCESS == halStatus )
1769 {
Mahesh A Saptasagar5f568172014-05-14 17:02:33 +05301770 char extra[32];
1771 tANI_U8 len = 0;
1772 tANI_U8 mScan = 0;
1773
Rajeev Kumar8b373292014-01-08 20:36:55 -08001774 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1775 "sme_SetBatchScanReq returned success halStatus %d",
1776 halStatus);
1777 if (TRUE == pAdapter->hdd_wait_for_set_batch_scan_rsp)
1778 {
1779 INIT_COMPLETION(pAdapter->hdd_set_batch_scan_req_var);
1780 rc = wait_for_completion_timeout(
1781 &pAdapter->hdd_set_batch_scan_req_var,
1782 msecs_to_jiffies(HDD_SET_BATCH_SCAN_REQ_TIME_OUT));
1783 if (0 == rc)
1784 {
1785 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1786 "%s: Timeout waiting for set batch scan to complete",
1787 __func__);
1788 ret = -EINVAL;
1789 goto exit;
1790 }
1791 }
1792 if ( !pRsp->nScansToBatch )
1793 {
1794 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1795 "%s: Received set batch scan failure response from FW",
1796 __func__);
1797 ret = -EINVAL;
1798 goto exit;
1799 }
1800 /*As per the Batch Scan Framework API we should return the MIN of
1801 either MSCAN or the max # of scans firmware can cache*/
Mahesh A Saptasagar5f568172014-05-14 17:02:33 +05301802 mScan = MIN(pReq->numberOfScansToBatch , pRsp->nScansToBatch);
Rajeev Kumar8b373292014-01-08 20:36:55 -08001803
1804 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STARTED;
1805
1806 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1807 "%s: request MSCAN %d response MSCAN %d ret %d",
Mahesh A Saptasagar5f568172014-05-14 17:02:33 +05301808 __func__, pReq->numberOfScansToBatch, pRsp->nScansToBatch, mScan);
1809 len = scnprintf(extra, sizeof(extra), "%d", mScan);
1810 if (copy_to_user(pPrivdata->buf, &extra, len + 1))
1811 {
1812 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1813 "%s: failed to copy MSCAN value to user buffer", __func__);
1814 ret = -EFAULT;
1815 goto exit;
1816 }
Rajeev Kumar8b373292014-01-08 20:36:55 -08001817 }
1818 else
1819 {
1820 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1821 "sme_SetBatchScanReq returned failure halStatus %d",
1822 halStatus);
1823 ret = -EINVAL;
1824 goto exit;
1825 }
1826 }
1827 else if (strncmp(command, "WLS_BATCHING STOP", 17) == 0)
1828 {
1829 eHalStatus halStatus;
1830 tSirStopBatchScanInd *pInd = &pAdapter->hddStopBatchScanInd;
1831 pInd->param = 0;
1832
1833 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
1834 {
1835 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1836 "%s: Batch scan feature is not supported by FW", __func__);
1837 ret = -EINVAL;
1838 goto exit;
1839 }
1840
1841 if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState)
1842 {
1843 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1844 "Batch scan is not yet enabled batch scan state %d",
1845 pAdapter->batchScanState);
1846 ret = -EINVAL;
1847 goto exit;
1848 }
1849
Kiet Lamaa8e15a2014-02-11 23:30:06 -08001850 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1851 hdd_deinit_batch_scan(pAdapter);
1852 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1853
Rajeev Kumar8b373292014-01-08 20:36:55 -08001854 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
1855
1856 halStatus = sme_StopBatchScanInd(WLAN_HDD_GET_HAL_CTX(pAdapter), pInd,
1857 pAdapter->sessionId);
1858 if ( eHAL_STATUS_SUCCESS == halStatus )
1859 {
1860 ret = 0;
1861 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1862 "sme_StopBatchScanInd returned success halStatus %d",
1863 halStatus);
1864 }
1865 else
1866 {
1867 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1868 "sme_StopBatchScanInd returned failure halStatus %d",
1869 halStatus);
1870 ret = -EINVAL;
1871 goto exit;
1872 }
1873 }
1874 else if (strncmp(command, "WLS_BATCHING GET", 16) == 0)
1875 {
1876 tANI_U32 remain_len;
1877
1878 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
1879 {
1880 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1881 "%s: Batch scan feature is not supported by FW", __func__);
1882 ret = -EINVAL;
1883 goto exit;
1884 }
1885
1886 if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState)
1887 {
1888 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1889 "Batch scan is not yet enabled could not return results"
1890 "Batch Scan state %d",
1891 pAdapter->batchScanState);
1892 ret = -EINVAL;
1893 goto exit;
1894 }
1895
1896 pPrivdata->used_len = 16;
1897 remain_len = pPrivdata->total_len - pPrivdata->used_len;
1898 if (remain_len < pPrivdata->total_len)
1899 {
1900 /*Clear previous batch scan response data if any*/
1901 vos_mem_zero((tANI_U8 *)(command + pPrivdata->used_len), remain_len);
1902 }
1903 else
1904 {
1905 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1906 "Invalid total length from user space can't fetch batch"
1907 " scan response total_len %d used_len %d remain len %d",
1908 pPrivdata->total_len, pPrivdata->used_len, remain_len);
1909 ret = -EINVAL;
1910 goto exit;
1911 }
1912 ret = hdd_return_batch_scan_rsp_to_user(pAdapter, pPrivdata, command);
1913 }
1914
1915exit:
1916
1917 return ret;
1918}
1919
1920
Rajeev79dbe4c2013-10-05 11:03:42 +05301921#endif/*End of FEATURE_WLAN_BATCH_SCAN*/
1922
c_hpothu92367912014-05-01 15:18:17 +05301923static void getBcnMissRateCB(VOS_STATUS status, int bcnMissRate, void *data)
1924{
c_hpothu39eb1e32014-06-26 16:31:50 +05301925 bcnMissRateContext_t *pCBCtx;
1926
1927 if (NULL == data)
1928 {
1929 hddLog(VOS_TRACE_LEVEL_ERROR, FL("argument data is NULL"));
1930 return;
1931 }
c_hpothu92367912014-05-01 15:18:17 +05301932
1933 /* there is a race condition that exists between this callback
1934 function and the caller since the caller could time out either
1935 before or while this code is executing. we use a spinlock to
1936 serialize these actions */
1937 spin_lock(&hdd_context_lock);
1938
c_hpothu39eb1e32014-06-26 16:31:50 +05301939 pCBCtx = (bcnMissRateContext_t *)data;
c_hpothu92367912014-05-01 15:18:17 +05301940 gbcnMissRate = -1;
1941
c_hpothu39eb1e32014-06-26 16:31:50 +05301942 if (pCBCtx->magic != BCN_MISS_RATE_CONTEXT_MAGIC)
c_hpothu92367912014-05-01 15:18:17 +05301943 {
1944 hddLog(VOS_TRACE_LEVEL_ERROR,
c_hpothu39eb1e32014-06-26 16:31:50 +05301945 FL("invalid context magic: %08x"), pCBCtx->magic);
c_hpothu92367912014-05-01 15:18:17 +05301946 spin_unlock(&hdd_context_lock);
1947 return ;
1948 }
1949
1950 if (VOS_STATUS_SUCCESS == status)
1951 {
c_hpothu39eb1e32014-06-26 16:31:50 +05301952 gbcnMissRate = bcnMissRate;
c_hpothu92367912014-05-01 15:18:17 +05301953 }
c_hpothu39eb1e32014-06-26 16:31:50 +05301954 else
1955 {
1956 hddLog(VOS_TRACE_LEVEL_ERROR, FL("failed to get bcnMissRate"));
1957 }
1958
c_hpothu92367912014-05-01 15:18:17 +05301959 complete(&(pCBCtx->completion));
1960 spin_unlock(&hdd_context_lock);
1961
1962 return;
1963}
1964
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05301965static int hdd_get_dwell_time(hdd_config_t *pCfg, tANI_U8 *command, char *extra, tANI_U8 n, tANI_U8 *len)
1966{
1967 int ret = 0;
1968
1969 if (!pCfg || !command || !extra || !len)
1970 {
1971 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1972 "%s: argument passsed for GETDWELLTIME is incorrect", __func__);
1973 ret = -EINVAL;
1974 return ret;
1975 }
1976
1977 if (strncmp(command, "GETDWELLTIME ACTIVE MAX", 23) == 0)
1978 {
1979 *len = scnprintf(extra, n, "GETDWELLTIME ACTIVE MAX %u\n",
1980 (int)pCfg->nActiveMaxChnTime);
1981 return ret;
1982 }
1983 else if (strncmp(command, "GETDWELLTIME ACTIVE MIN", 23) == 0)
1984 {
1985 *len = scnprintf(extra, n, "GETDWELLTIME ACTIVE MIN %u\n",
1986 (int)pCfg->nActiveMinChnTime);
1987 return ret;
1988 }
1989 else if (strncmp(command, "GETDWELLTIME PASSIVE MAX", 24) == 0)
1990 {
1991 *len = scnprintf(extra, n, "GETDWELLTIME PASSIVE MAX %u\n",
1992 (int)pCfg->nPassiveMaxChnTime);
1993 return ret;
1994 }
1995 else if (strncmp(command, "GETDWELLTIME PASSIVE MIN", 24) == 0)
1996 {
1997 *len = scnprintf(extra, n, "GETDWELLTIME PASSIVE MIN %u\n",
1998 (int)pCfg->nPassiveMinChnTime);
1999 return ret;
2000 }
Rajesh Babu Prathipati0fd227e2014-07-05 12:50:00 +05302001 else if (strncmp(command, "GETDWELLTIME", 12) == 0)
2002 {
2003 *len = scnprintf(extra, n, "GETDWELLTIME %u \n",
2004 (int)pCfg->nActiveMaxChnTime);
2005 return ret;
2006 }
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302007 else
2008 {
2009 ret = -EINVAL;
2010 }
2011
2012 return ret;
2013}
2014
2015static int hdd_set_dwell_time(hdd_adapter_t *pAdapter, tANI_U8 *command)
2016{
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302017 tHalHandle hHal;
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302018 hdd_config_t *pCfg;
2019 tANI_U8 *value = command;
2020 int val = 0, ret = 0, temp = 0;
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302021 tSmeConfigParams smeConfig;
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302022
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302023 if (!pAdapter || !command || !(pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini)
2024 || !(hHal = (WLAN_HDD_GET_HAL_CTX(pAdapter))))
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302025 {
2026 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2027 "%s: argument passed for SETDWELLTIME is incorrect", __func__);
2028 ret = -EINVAL;
2029 return ret;
2030 }
2031
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302032 vos_mem_zero(&smeConfig, sizeof(smeConfig));
2033 sme_GetConfigParam(hHal, &smeConfig);
2034
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302035 if (strncmp(command, "SETDWELLTIME ACTIVE MAX", 23) == 0 )
2036 {
2037 value = value + 24;
2038 temp = kstrtou32(value, 10, &val);
2039 if (temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_MIN ||
2040 val > CFG_ACTIVE_MAX_CHANNEL_TIME_MAX )
2041 {
2042 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2043 "%s: argument passed for SETDWELLTIME ACTIVE MAX is incorrect", __func__);
2044 ret = -EFAULT;
2045 return ret;
2046 }
2047 pCfg->nActiveMaxChnTime = val;
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302048 smeConfig.csrConfig.nActiveMaxChnTime = val;
2049 sme_UpdateConfig(hHal, &smeConfig);
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302050 }
2051 else if (strncmp(command, "SETDWELLTIME ACTIVE MIN", 23) == 0)
2052 {
2053 value = value + 24;
2054 temp = kstrtou32(value, 10, &val);
2055 if (temp !=0 || val < CFG_ACTIVE_MIN_CHANNEL_TIME_MIN ||
2056 val > CFG_ACTIVE_MIN_CHANNEL_TIME_MAX )
2057 {
2058 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2059 "%s: argument passsed for SETDWELLTIME ACTIVE MIN is incorrect", __func__);
2060 ret = -EFAULT;
2061 return ret;
2062 }
2063 pCfg->nActiveMinChnTime = val;
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302064 smeConfig.csrConfig.nActiveMinChnTime = val;
2065 sme_UpdateConfig(hHal, &smeConfig);
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302066 }
2067 else if (strncmp(command, "SETDWELLTIME PASSIVE MAX", 24) == 0)
2068 {
2069 value = value + 25;
2070 temp = kstrtou32(value, 10, &val);
2071 if (temp != 0 || val < CFG_PASSIVE_MAX_CHANNEL_TIME_MIN ||
2072 val > CFG_PASSIVE_MAX_CHANNEL_TIME_MAX )
2073 {
2074 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2075 "%s: argument passed for SETDWELLTIME PASSIVE MAX is incorrect", __func__);
2076 ret = -EFAULT;
2077 return ret;
2078 }
2079 pCfg->nPassiveMaxChnTime = val;
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302080 smeConfig.csrConfig.nPassiveMaxChnTime = val;
2081 sme_UpdateConfig(hHal, &smeConfig);
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302082 }
2083 else if (strncmp(command, "SETDWELLTIME PASSIVE MIN", 24) == 0)
2084 {
2085 value = value + 25;
2086 temp = kstrtou32(value, 10, &val);
2087 if (temp != 0 || val < CFG_PASSIVE_MIN_CHANNEL_TIME_MIN ||
2088 val > CFG_PASSIVE_MIN_CHANNEL_TIME_MAX )
2089 {
2090 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2091 "%s: argument passed for SETDWELLTIME PASSIVE MIN is incorrect", __func__);
2092 ret = -EFAULT;
2093 return ret;
2094 }
2095 pCfg->nPassiveMinChnTime = val;
Rajesh Babu Prathipatib09815c2014-07-05 11:22:24 +05302096 smeConfig.csrConfig.nPassiveMinChnTime = val;
2097 sme_UpdateConfig(hHal, &smeConfig);
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302098 }
Rajesh Babu Prathipati0fd227e2014-07-05 12:50:00 +05302099 else if (strncmp(command, "SETDWELLTIME", 12) == 0)
2100 {
2101 value = value + 13;
2102 temp = kstrtou32(value, 10, &val);
2103 if (temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_MIN ||
2104 val > CFG_ACTIVE_MAX_CHANNEL_TIME_MAX )
2105 {
2106 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2107 "%s: argument passed for SETDWELLTIME is incorrect", __func__);
2108 ret = -EFAULT;
2109 return ret;
2110 }
2111 pCfg->nActiveMaxChnTime = val;
2112 smeConfig.csrConfig.nActiveMaxChnTime = val;
2113 sme_UpdateConfig(hHal, &smeConfig);
2114 }
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05302115 else
2116 {
2117 ret = -EINVAL;
2118 }
2119
2120 return ret;
2121}
2122
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002123static int hdd_driver_command(hdd_adapter_t *pAdapter,
2124 hdd_priv_data_t *ppriv_data)
Jeff Johnson295189b2012-06-20 16:38:30 -07002125{
Jeff Johnson295189b2012-06-20 16:38:30 -07002126 hdd_priv_data_t priv_data;
2127 tANI_U8 *command = NULL;
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002128 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07002129
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002130 /*
2131 * Note that valid pointers are provided by caller
2132 */
Jeff Johnson295189b2012-06-20 16:38:30 -07002133
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002134 /* copy to local struct to avoid numerous changes to legacy code */
2135 priv_data = *ppriv_data;
Jeff Johnson295189b2012-06-20 16:38:30 -07002136
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002137 if (priv_data.total_len <= 0 ||
2138 priv_data.total_len > WLAN_PRIV_DATA_MAX_LEN)
Sameer Thalappil8ef3a0e2013-04-05 14:36:04 -07002139 {
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002140 hddLog(VOS_TRACE_LEVEL_WARN,
2141 "%s:invalid priv_data.total_len(%d)!!!", __func__,
2142 priv_data.total_len);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07002143 ret = -EINVAL;
2144 goto exit;
2145 }
2146
2147 /* Allocate +1 for '\0' */
2148 command = kmalloc(priv_data.total_len + 1, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07002149 if (!command)
2150 {
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002151 hddLog(VOS_TRACE_LEVEL_ERROR,
2152 "%s: failed to allocate memory", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002153 ret = -ENOMEM;
2154 goto exit;
2155 }
2156
2157 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
2158 {
2159 ret = -EFAULT;
2160 goto exit;
2161 }
2162
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002163 /* Make sure the command is NUL-terminated */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07002164 command[priv_data.total_len] = '\0';
2165
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002166 /* at one time the following block of code was conditional. braces
2167 * have been retained to avoid re-indenting the legacy code
2168 */
Jeff Johnson295189b2012-06-20 16:38:30 -07002169 {
2170 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2171
2172 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07002173 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -07002174
2175 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
2176 {
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302177 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2178 TRACE_CODE_HDD_P2P_DEV_ADDR_IOCTL,
2179 pAdapter->sessionId, (unsigned)
2180 (*(pHddCtx->p2pDeviceAddress.bytes+2)<<24 |
2181 *(pHddCtx->p2pDeviceAddress.bytes+3)<<16 |
2182 *(pHddCtx->p2pDeviceAddress.bytes+4)<<8 |
2183 *(pHddCtx->p2pDeviceAddress.bytes+5))));
Jeff Johnson295189b2012-06-20 16:38:30 -07002184 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
2185 sizeof(tSirMacAddr)))
2186 {
2187 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Arif Hussain6d2a3322013-11-17 19:50:10 -08002188 "%s: failed to copy data to user buffer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002189 ret = -EFAULT;
2190 }
2191 }
Amar Singhal0974e402013-02-12 14:27:46 -08002192 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07002193 {
Amar Singhal0974e402013-02-12 14:27:46 -08002194 tANI_U8 *ptr = command ;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002195
Jeff Johnson295189b2012-06-20 16:38:30 -07002196 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -08002197
2198 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -07002199 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07002200 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -08002201 "%s: SetBandCommand Info comm %s UL %d, TL %d", __func__, command, priv_data.used_len, priv_data.total_len);
Jeff Johnson295189b2012-06-20 16:38:30 -07002202 /* Change band request received */
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002203 ret = hdd_setBand_helper(pAdapter->dev, ptr);
Abhishek Singh2ec36ab2014-08-07 16:14:25 +05302204 if(ret < 0)
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302205 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002206 "%s: failed to set band ret=%d", __func__, ret);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002207 }
Kiet Lamf040f472013-11-20 21:15:23 +05302208 else if(strncmp(command, "SETWMMPS", 8) == 0)
2209 {
2210 tANI_U8 *ptr = command;
2211 ret = hdd_wmmps_helper(pAdapter, ptr);
2212 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07002213 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
2214 {
2215 char *country_code;
2216
2217 country_code = command + 8;
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07002218
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002219 INIT_COMPLETION(pAdapter->change_country_code);
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07002220 hdd_checkandupdate_dfssetting(pAdapter, country_code);
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -07002221#ifndef CONFIG_ENABLE_LINUX_REG
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +05302222 hdd_checkandupdate_phymode(pAdapter, country_code);
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -07002223#endif
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002224 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal,
2225 (void *)(tSmeChangeCountryCallback)
2226 wlan_hdd_change_country_code_callback,
Abhishek Singha306a442013-11-07 18:39:01 +05302227 country_code, pAdapter, pHddCtx->pvosContext, eSIR_TRUE, eSIR_TRUE);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002228 if (eHAL_STATUS_SUCCESS == ret)
2229 {
2230 ret = wait_for_completion_interruptible_timeout(
2231 &pAdapter->change_country_code,
2232 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
2233 if (0 >= ret)
2234 {
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002235 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: SME while setting country code timed out %d",
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302236 __func__, ret);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002237 }
2238 }
2239 else
Jeff Johnson32d95a32012-09-10 13:15:23 -07002240 {
2241 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002242 "%s: SME Change Country code fail ret=%d", __func__, ret);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002243 ret = -EINVAL;
Jeff Johnson32d95a32012-09-10 13:15:23 -07002244 }
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002245
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07002246 }
2247 /*
2248 command should be a string having format
2249 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
2250 */
Amar Singhal0974e402013-02-12 14:27:46 -08002251 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07002252 {
Amar Singhal0974e402013-02-12 14:27:46 -08002253 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07002254
2255 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002256 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07002257
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -08002258 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -07002259 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -08002260 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
2261 {
2262 int suspend = 0;
2263 tANI_U8 *ptr = (tANI_U8*)command + 15;
2264
2265 suspend = *ptr - '0';
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302266 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2267 TRACE_CODE_HDD_SETSUSPENDMODE_IOCTL,
2268 pAdapter->sessionId, suspend));
Sameer Thalappil45931fb2013-02-01 11:18:05 -08002269 hdd_set_wlan_suspend_mode(suspend);
2270 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002271#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
2272 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
2273 {
2274 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002275 tANI_S8 rssi = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002276 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
2277 eHalStatus status = eHAL_STATUS_SUCCESS;
2278
2279 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
2280 value = value + 15;
2281
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002282 /* Convert the value from ascii to integer */
2283 ret = kstrtos8(value, 10, &rssi);
2284 if (ret < 0)
2285 {
2286 /* If the input value is greater than max value of datatype, then also
2287 kstrtou8 fails */
2288 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2289 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdafa7157d2013-10-31 10:14:22 -07002290 __func__,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002291 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
2292 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
2293 ret = -EINVAL;
2294 goto exit;
2295 }
2296
Srinivas Girigowdade697412013-02-14 16:31:48 -08002297 lookUpThreshold = abs(rssi);
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002298
Srinivas Girigowdade697412013-02-14 16:31:48 -08002299 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
2300 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
2301 {
2302 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2303 "Neighbor lookup threshold value %d is out of range"
2304 " (Min: %d Max: %d)", lookUpThreshold,
2305 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
2306 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
2307 ret = -EINVAL;
2308 goto exit;
2309 }
2310
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302311 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2312 TRACE_CODE_HDD_SETROAMTRIGGER_IOCTL,
2313 pAdapter->sessionId, lookUpThreshold));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002314 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2315 "%s: Received Command to Set Roam trigger"
2316 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
2317
2318 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
2319 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
2320 if (eHAL_STATUS_SUCCESS != status)
2321 {
2322 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2323 "%s: Failed to set roam trigger, try again", __func__);
2324 ret = -EPERM;
2325 goto exit;
2326 }
2327
2328 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
mukul sharmad6e1fdd2014-06-23 19:19:09 +05302329 pHddCtx->cfg_ini->nNeighborReassocRssiThreshold = lookUpThreshold + 5;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002330 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
2331 }
2332 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
2333 {
2334 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
2335 int rssi = (-1) * lookUpThreshold;
2336 char extra[32];
2337 tANI_U8 len = 0;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302338 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2339 TRACE_CODE_HDD_GETROAMTRIGGER_IOCTL,
2340 pAdapter->sessionId, lookUpThreshold));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002341 len = scnprintf(extra, sizeof(extra), "%s %d", command, rssi);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002342 if (copy_to_user(priv_data.buf, &extra, len + 1))
2343 {
2344 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2345 "%s: failed to copy data to user buffer", __func__);
2346 ret = -EFAULT;
2347 goto exit;
2348 }
2349 }
2350 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
2351 {
2352 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002353 tANI_U8 roamScanPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002354 tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002355
Srinivas Girigowdade697412013-02-14 16:31:48 -08002356 /* input refresh period is in terms of seconds */
2357 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
2358 value = value + 18;
2359 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002360 ret = kstrtou8(value, 10, &roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002361 if (ret < 0)
2362 {
2363 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002364 kstrtou8 fails */
Srinivas Girigowdade697412013-02-14 16:31:48 -08002365 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002366 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdade697412013-02-14 16:31:48 -08002367 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07002368 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
2369 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002370 ret = -EINVAL;
2371 goto exit;
2372 }
2373
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002374 if ((roamScanPeriod < (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000)) ||
2375 (roamScanPeriod > (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000)))
Srinivas Girigowdade697412013-02-14 16:31:48 -08002376 {
2377 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002378 "Roam scan period value %d is out of range"
2379 " (Min: %d Max: %d)", roamScanPeriod,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07002380 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
2381 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002382 ret = -EINVAL;
2383 goto exit;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302384 }
2385 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2386 TRACE_CODE_HDD_SETROAMSCANPERIOD_IOCTL,
2387 pAdapter->sessionId, roamScanPeriod));
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002388 neighborEmptyScanRefreshPeriod = roamScanPeriod * 1000;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002389
2390 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2391 "%s: Received Command to Set roam scan period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002392 " (Empty Scan refresh period) = %d", __func__, roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002393
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002394 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod;
2395 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002396 }
2397 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
2398 {
2399 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
2400 char extra[32];
2401 tANI_U8 len = 0;
2402
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302403 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2404 TRACE_CODE_HDD_GETROAMSCANPERIOD_IOCTL,
2405 pAdapter->sessionId, nEmptyScanRefreshPeriod));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002406 len = scnprintf(extra, sizeof(extra), "%s %d",
2407 "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002408 /* Returned value is in units of seconds */
2409 if (copy_to_user(priv_data.buf, &extra, len + 1))
2410 {
2411 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2412 "%s: failed to copy data to user buffer", __func__);
2413 ret = -EFAULT;
2414 goto exit;
2415 }
2416 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002417 else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0)
2418 {
2419 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002420 tANI_U8 roamScanRefreshPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002421 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002422
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002423 /* input refresh period is in terms of seconds */
2424 /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */
2425 value = value + 25;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002426
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002427 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002428 ret = kstrtou8(value, 10, &roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002429 if (ret < 0)
2430 {
2431 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002432 kstrtou8 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002433 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002434 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002435 __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002436 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
2437 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
2438 ret = -EINVAL;
2439 goto exit;
2440 }
2441
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002442 if ((roamScanRefreshPeriod < (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000)) ||
2443 (roamScanRefreshPeriod > (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000)))
2444 {
2445 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2446 "Neighbor scan results refresh period value %d is out of range"
2447 " (Min: %d Max: %d)", roamScanRefreshPeriod,
2448 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
2449 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
2450 ret = -EINVAL;
2451 goto exit;
2452 }
2453 neighborScanRefreshPeriod = roamScanRefreshPeriod * 1000;
2454
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002455 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2456 "%s: Received Command to Set roam scan refresh period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002457 " (Scan refresh period) = %d", __func__, roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002458
2459 pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod;
2460 sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
2461 }
2462 else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0)
2463 {
2464 tANI_U16 value = sme_getNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
2465 char extra[32];
2466 tANI_U8 len = 0;
2467
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002468 len = scnprintf(extra, sizeof(extra), "%s %d",
2469 "GETROAMSCANREFRESHPERIOD", (value/1000));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002470 /* Returned value is in units of seconds */
2471 if (copy_to_user(priv_data.buf, &extra, len + 1))
2472 {
2473 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2474 "%s: failed to copy data to user buffer", __func__);
2475 ret = -EFAULT;
2476 goto exit;
2477 }
2478 }
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07002479#ifdef FEATURE_WLAN_LFR
2480 /* SETROAMMODE */
2481 else if (strncmp(command, "SETROAMMODE", SIZE_OF_SETROAMMODE) == 0)
2482 {
2483 tANI_U8 *value = command;
2484 tANI_BOOLEAN roamMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
2485
2486 /* Move pointer to ahead of SETROAMMODE<delimiter> */
2487 value = value + SIZE_OF_SETROAMMODE + 1;
2488
2489 /* Convert the value from ascii to integer */
2490 ret = kstrtou8(value, SIZE_OF_SETROAMMODE, &roamMode);
2491 if (ret < 0)
2492 {
2493 /* If the input value is greater than max value of datatype, then also
2494 kstrtou8 fails */
2495 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2496 "%s: kstrtou8 failed range [%d - %d]", __func__,
2497 CFG_LFR_FEATURE_ENABLED_MIN,
2498 CFG_LFR_FEATURE_ENABLED_MAX);
2499 ret = -EINVAL;
2500 goto exit;
2501 }
2502 if ((roamMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
2503 (roamMode > CFG_LFR_FEATURE_ENABLED_MAX))
2504 {
2505 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2506 "Roam Mode value %d is out of range"
2507 " (Min: %d Max: %d)", roamMode,
2508 CFG_LFR_FEATURE_ENABLED_MIN,
2509 CFG_LFR_FEATURE_ENABLED_MAX);
2510 ret = -EINVAL;
2511 goto exit;
2512 }
2513
2514 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2515 "%s: Received Command to Set Roam Mode = %d", __func__, roamMode);
2516 /*
2517 * Note that
2518 * SETROAMMODE 0 is to enable LFR while
2519 * SETROAMMODE 1 is to disable LFR, but
2520 * NotifyIsFastRoamIniFeatureEnabled 0/1 is to enable/disable.
2521 * So, we have to invert the value to call sme_UpdateIsFastRoamIniFeatureEnabled.
2522 */
2523 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
2524 roamMode = CFG_LFR_FEATURE_ENABLED_MAX; /* Roam enable */
2525 else
2526 roamMode = CFG_LFR_FEATURE_ENABLED_MIN; /* Roam disable */
2527
2528 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = roamMode;
2529 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), roamMode);
2530 }
2531 /* GETROAMMODE */
2532 else if (strncmp(priv_data.buf, "GETROAMMODE", SIZE_OF_GETROAMMODE) == 0)
2533 {
2534 tANI_BOOLEAN roamMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2535 char extra[32];
2536 tANI_U8 len = 0;
2537
2538 /*
2539 * roamMode value shall be inverted because the sementics is different.
2540 */
2541 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
2542 roamMode = CFG_LFR_FEATURE_ENABLED_MAX;
2543 else
2544 roamMode = CFG_LFR_FEATURE_ENABLED_MIN;
2545
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002546 len = scnprintf(extra, sizeof(extra), "%s %d", command, roamMode);
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07002547 if (copy_to_user(priv_data.buf, &extra, len + 1))
2548 {
2549 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2550 "%s: failed to copy data to user buffer", __func__);
2551 ret = -EFAULT;
2552 goto exit;
2553 }
2554 }
2555#endif
Srinivas Girigowdade697412013-02-14 16:31:48 -08002556#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002557#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -08002558 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
2559 {
2560 tANI_U8 *value = command;
2561 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
2562
2563 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
2564 value = value + 13;
2565 /* Convert the value from ascii to integer */
2566 ret = kstrtou8(value, 10, &roamRssiDiff);
2567 if (ret < 0)
2568 {
2569 /* If the input value is greater than max value of datatype, then also
2570 kstrtou8 fails */
2571 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2572 "%s: kstrtou8 failed range [%d - %d]", __func__,
2573 CFG_ROAM_RSSI_DIFF_MIN,
2574 CFG_ROAM_RSSI_DIFF_MAX);
2575 ret = -EINVAL;
2576 goto exit;
2577 }
2578
2579 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
2580 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
2581 {
2582 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2583 "Roam rssi diff value %d is out of range"
2584 " (Min: %d Max: %d)", roamRssiDiff,
2585 CFG_ROAM_RSSI_DIFF_MIN,
2586 CFG_ROAM_RSSI_DIFF_MAX);
2587 ret = -EINVAL;
2588 goto exit;
2589 }
2590
2591 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2592 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
2593
2594 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
2595 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
2596 }
2597 else if (strncmp(priv_data.buf, "GETROAMDELTA", 12) == 0)
2598 {
2599 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
2600 char extra[32];
2601 tANI_U8 len = 0;
2602
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302603 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2604 TRACE_CODE_HDD_GETROAMDELTA_IOCTL,
2605 pAdapter->sessionId, roamRssiDiff));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002606 len = scnprintf(extra, sizeof(extra), "%s %d",
2607 command, roamRssiDiff);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002608 if (copy_to_user(priv_data.buf, &extra, len + 1))
2609 {
2610 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2611 "%s: failed to copy data to user buffer", __func__);
2612 ret = -EFAULT;
2613 goto exit;
2614 }
2615 }
2616#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002617#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -08002618 else if (strncmp(command, "GETBAND", 7) == 0)
2619 {
2620 int band = -1;
2621 char extra[32];
2622 tANI_U8 len = 0;
2623 hdd_getBand_helper(pHddCtx, &band);
2624
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302625 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2626 TRACE_CODE_HDD_GETBAND_IOCTL,
2627 pAdapter->sessionId, band));
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002628 len = scnprintf(extra, sizeof(extra), "%s %d", command, band);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002629 if (copy_to_user(priv_data.buf, &extra, len + 1))
2630 {
2631 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2632 "%s: failed to copy data to user buffer", __func__);
2633 ret = -EFAULT;
2634 goto exit;
2635 }
2636 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002637 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
2638 {
2639 tANI_U8 *value = command;
2640 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2641 tANI_U8 numChannels = 0;
2642 eHalStatus status = eHAL_STATUS_SUCCESS;
2643
2644 status = hdd_parse_channellist(value, ChannelList, &numChannels);
2645 if (eHAL_STATUS_SUCCESS != status)
2646 {
2647 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2648 "%s: Failed to parse channel list information", __func__);
2649 ret = -EINVAL;
2650 goto exit;
2651 }
2652
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302653 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2654 TRACE_CODE_HDD_SETROAMSCANCHANNELS_IOCTL,
2655 pAdapter->sessionId, numChannels));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002656 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
2657 {
2658 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2659 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
2660 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
2661 ret = -EINVAL;
2662 goto exit;
2663 }
2664 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
2665 numChannels);
2666 if (eHAL_STATUS_SUCCESS != status)
2667 {
2668 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2669 "%s: Failed to update channel list information", __func__);
2670 ret = -EINVAL;
2671 goto exit;
2672 }
2673 }
2674 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
2675 {
2676 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2677 tANI_U8 numChannels = 0;
Jeff Johnson51b67782013-04-05 12:35:41 -07002678 tANI_U8 j = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002679 char extra[128] = {0};
Jeff Johnson51b67782013-04-05 12:35:41 -07002680 int len;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002681
2682 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
2683 ChannelList, &numChannels ))
2684 {
2685 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2686 "%s: failed to get roam scan channel list", __func__);
2687 ret = -EFAULT;
2688 goto exit;
2689 }
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302690 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2691 TRACE_CODE_HDD_GETROAMSCANCHANNELS_IOCTL,
2692 pAdapter->sessionId, numChannels));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002693 /* output channel list is of the format
2694 [Number of roam scan channels][Channel1][Channel2]... */
2695 /* copy the number of channels in the 0th index */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002696 len = scnprintf(extra, sizeof(extra), "%s %d", command, numChannels);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002697 for (j = 0; (j < numChannels); j++)
2698 {
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002699 len += scnprintf(extra + len, sizeof(extra) - len, " %d",
2700 ChannelList[j]);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002701 }
2702
2703 if (copy_to_user(priv_data.buf, &extra, len + 1))
2704 {
2705 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2706 "%s: failed to copy data to user buffer", __func__);
2707 ret = -EFAULT;
2708 goto exit;
2709 }
2710 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002711 else if (strncmp(command, "GETCCXMODE", 10) == 0)
2712 {
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002713 tANI_BOOLEAN eseMode = sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002714 char extra[32];
2715 tANI_U8 len = 0;
2716
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002717 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002718 then this operation is not permitted (return FAILURE) */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002719 if (eseMode &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002720 hdd_is_okc_mode_enabled(pHddCtx) &&
2721 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2722 {
2723 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002724 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002725 " hence this operation is not permitted!", __func__);
2726 ret = -EPERM;
2727 goto exit;
2728 }
2729
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002730 len = scnprintf(extra, sizeof(extra), "%s %d",
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002731 "GETCCXMODE", eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002732 if (copy_to_user(priv_data.buf, &extra, len + 1))
2733 {
2734 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2735 "%s: failed to copy data to user buffer", __func__);
2736 ret = -EFAULT;
2737 goto exit;
2738 }
2739 }
2740 else if (strncmp(command, "GETOKCMODE", 10) == 0)
2741 {
2742 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
2743 char extra[32];
2744 tANI_U8 len = 0;
2745
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002746 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002747 then this operation is not permitted (return FAILURE) */
2748 if (okcMode &&
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002749 sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002750 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2751 {
2752 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08002753 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002754 " hence this operation is not permitted!", __func__);
2755 ret = -EPERM;
2756 goto exit;
2757 }
2758
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002759 len = scnprintf(extra, sizeof(extra), "%s %d",
2760 "GETOKCMODE", okcMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002761 if (copy_to_user(priv_data.buf, &extra, len + 1))
2762 {
2763 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2764 "%s: failed to copy data to user buffer", __func__);
2765 ret = -EFAULT;
2766 goto exit;
2767 }
2768 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002769 else if (strncmp(command, "GETFASTROAM", 11) == 0)
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002770 {
2771 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2772 char extra[32];
2773 tANI_U8 len = 0;
2774
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002775 len = scnprintf(extra, sizeof(extra), "%s %d",
2776 "GETFASTROAM", lfrMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002777 if (copy_to_user(priv_data.buf, &extra, len + 1))
2778 {
2779 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2780 "%s: failed to copy data to user buffer", __func__);
2781 ret = -EFAULT;
2782 goto exit;
2783 }
2784 }
2785 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
2786 {
2787 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2788 char extra[32];
2789 tANI_U8 len = 0;
2790
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002791 len = scnprintf(extra, sizeof(extra), "%s %d",
2792 "GETFASTTRANSITION", ft);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002793 if (copy_to_user(priv_data.buf, &extra, len + 1))
2794 {
2795 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2796 "%s: failed to copy data to user buffer", __func__);
2797 ret = -EFAULT;
2798 goto exit;
2799 }
2800 }
2801 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
2802 {
2803 tANI_U8 *value = command;
2804 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
2805
2806 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
2807 value = value + 26;
2808 /* Convert the value from ascii to integer */
2809 ret = kstrtou8(value, 10, &minTime);
2810 if (ret < 0)
2811 {
2812 /* If the input value is greater than max value of datatype, then also
2813 kstrtou8 fails */
2814 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2815 "%s: kstrtou8 failed range [%d - %d]", __func__,
2816 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
2817 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
2818 ret = -EINVAL;
2819 goto exit;
2820 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002821 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
2822 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
2823 {
2824 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2825 "scan min channel time value %d is out of range"
2826 " (Min: %d Max: %d)", minTime,
2827 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
2828 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
2829 ret = -EINVAL;
2830 goto exit;
2831 }
2832
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302833 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2834 TRACE_CODE_HDD_SETROAMSCANCHANNELMINTIME_IOCTL,
2835 pAdapter->sessionId, minTime));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002836 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2837 "%s: Received Command to change channel min time = %d", __func__, minTime);
2838
2839 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
2840 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
2841 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002842 else if (strncmp(command, "SENDACTIONFRAME", 15) == 0)
2843 {
2844 tANI_U8 *value = command;
2845 tANI_U8 channel = 0;
2846 tANI_U8 dwellTime = 0;
2847 tANI_U8 bufLen = 0;
2848 tANI_U8 *buf = NULL;
2849 tSirMacAddr targetApBssid;
2850 eHalStatus status = eHAL_STATUS_SUCCESS;
2851 struct ieee80211_channel chan;
2852 tANI_U8 finalLen = 0;
2853 tANI_U8 *finalBuf = NULL;
2854 tANI_U8 temp = 0;
2855 u64 cookie;
2856 hdd_station_ctx_t *pHddStaCtx = NULL;
2857 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2858
2859 /* if not associated, no need to send action frame */
2860 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2861 {
2862 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2863 ret = -EINVAL;
2864 goto exit;
2865 }
2866
2867 status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel,
2868 &dwellTime, &buf, &bufLen);
2869 if (eHAL_STATUS_SUCCESS != status)
2870 {
2871 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2872 "%s: Failed to parse send action frame data", __func__);
2873 ret = -EINVAL;
2874 goto exit;
2875 }
2876
2877 /* if the target bssid is different from currently associated AP,
2878 then no need to send action frame */
2879 if (VOS_TRUE != vos_mem_compare(targetApBssid,
2880 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2881 {
2882 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__);
2883 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002884 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002885 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002886 goto exit;
2887 }
2888
2889 /* if the channel number is different from operating channel then
2890 no need to send action frame */
2891 if (channel != pHddStaCtx->conn_info.operationChannel)
2892 {
2893 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2894 "%s: channel(%d) is different from operating channel(%d)",
2895 __func__, channel, pHddStaCtx->conn_info.operationChannel);
2896 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002897 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002898 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002899 goto exit;
2900 }
2901 chan.center_freq = sme_ChnToFreq(channel);
2902
2903 finalLen = bufLen + 24;
2904 finalBuf = vos_mem_malloc(finalLen);
2905 if (NULL == finalBuf)
2906 {
2907 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__);
2908 ret = -ENOMEM;
Jeff Johnson11c33152013-04-16 17:52:40 -07002909 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002910 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002911 goto exit;
2912 }
2913 vos_mem_zero(finalBuf, finalLen);
2914
2915 /* Fill subtype */
2916 temp = SIR_MAC_MGMT_ACTION << 4;
2917 vos_mem_copy(finalBuf + 0, &temp, sizeof(temp));
2918
2919 /* Fill type */
2920 temp = SIR_MAC_MGMT_FRAME;
2921 vos_mem_copy(finalBuf + 2, &temp, sizeof(temp));
2922
2923 /* Fill destination address (bssid of the AP) */
2924 vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid));
2925
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07002926 /* Fill source address (STA mac address) */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002927 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
2928
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07002929 /* Fill BSSID (AP mac address) */
2930 vos_mem_copy(finalBuf + 16, targetApBssid, sizeof(targetApBssid));
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002931
2932 /* Fill received buffer from 24th address */
2933 vos_mem_copy(finalBuf + 24, buf, bufLen);
2934
Jeff Johnson11c33152013-04-16 17:52:40 -07002935 /* done with the parsed buffer */
2936 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002937 buf = NULL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002938
DARAM SUDHA39eede62014-02-12 11:16:40 +05302939 wlan_hdd_mgmt_tx( NULL,
Yue Maf49ba872013-08-19 12:04:25 -07002940#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2941 &(pAdapter->wdev),
2942#else
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07002943 pAdapter->dev,
Yue Maf49ba872013-08-19 12:04:25 -07002944#endif
2945 &chan, 0,
2946#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
2947 NL80211_CHAN_HT20, 1,
2948#endif
2949 dwellTime, finalBuf, finalLen, 1,
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002950 1, &cookie );
2951 vos_mem_free(finalBuf);
2952 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002953 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
2954 {
2955 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
2956 char extra[32];
2957 tANI_U8 len = 0;
2958
2959 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002960 len = scnprintf(extra, sizeof(extra), "%s %d",
2961 "GETROAMSCANCHANNELMINTIME", val);
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302962 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2963 TRACE_CODE_HDD_GETROAMSCANCHANNELMINTIME_IOCTL,
2964 pAdapter->sessionId, val));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002965 if (copy_to_user(priv_data.buf, &extra, len + 1))
2966 {
2967 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2968 "%s: failed to copy data to user buffer", __func__);
2969 ret = -EFAULT;
2970 goto exit;
2971 }
2972 }
2973 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
2974 {
2975 tANI_U8 *value = command;
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002976 tANI_U16 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002977
2978 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
2979 value = value + 19;
2980 /* Convert the value from ascii to integer */
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002981 ret = kstrtou16(value, 10, &maxTime);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002982 if (ret < 0)
2983 {
2984 /* If the input value is greater than max value of datatype, then also
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002985 kstrtou16 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002986 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002987 "%s: kstrtou16 failed range [%d - %d]", __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002988 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
2989 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
2990 ret = -EINVAL;
2991 goto exit;
2992 }
2993
2994 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
2995 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
2996 {
2997 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2998 "lfr mode value %d is out of range"
2999 " (Min: %d Max: %d)", maxTime,
3000 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
3001 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
3002 ret = -EINVAL;
3003 goto exit;
3004 }
3005
3006 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3007 "%s: Received Command to change channel max time = %d", __func__, maxTime);
3008
3009 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
3010 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
3011 }
3012 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
3013 {
3014 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
3015 char extra[32];
3016 tANI_U8 len = 0;
3017
3018 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003019 len = scnprintf(extra, sizeof(extra), "%s %d",
3020 "GETSCANCHANNELTIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003021 if (copy_to_user(priv_data.buf, &extra, len + 1))
3022 {
3023 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3024 "%s: failed to copy data to user buffer", __func__);
3025 ret = -EFAULT;
3026 goto exit;
3027 }
3028 }
3029 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
3030 {
3031 tANI_U8 *value = command;
3032 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
3033
3034 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
3035 value = value + 16;
3036 /* Convert the value from ascii to integer */
3037 ret = kstrtou16(value, 10, &val);
3038 if (ret < 0)
3039 {
3040 /* If the input value is greater than max value of datatype, then also
3041 kstrtou16 fails */
3042 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3043 "%s: kstrtou16 failed range [%d - %d]", __func__,
3044 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
3045 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
3046 ret = -EINVAL;
3047 goto exit;
3048 }
3049
3050 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
3051 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
3052 {
3053 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3054 "scan home time value %d is out of range"
3055 " (Min: %d Max: %d)", val,
3056 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
3057 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
3058 ret = -EINVAL;
3059 goto exit;
3060 }
3061
3062 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3063 "%s: Received Command to change scan home time = %d", __func__, val);
3064
3065 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
3066 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
3067 }
3068 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
3069 {
3070 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
3071 char extra[32];
3072 tANI_U8 len = 0;
3073
3074 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003075 len = scnprintf(extra, sizeof(extra), "%s %d",
3076 "GETSCANHOMETIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003077 if (copy_to_user(priv_data.buf, &extra, len + 1))
3078 {
3079 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3080 "%s: failed to copy data to user buffer", __func__);
3081 ret = -EFAULT;
3082 goto exit;
3083 }
3084 }
3085 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
3086 {
3087 tANI_U8 *value = command;
3088 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
3089
3090 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
3091 value = value + 17;
3092 /* Convert the value from ascii to integer */
3093 ret = kstrtou8(value, 10, &val);
3094 if (ret < 0)
3095 {
3096 /* If the input value is greater than max value of datatype, then also
3097 kstrtou8 fails */
3098 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3099 "%s: kstrtou8 failed range [%d - %d]", __func__,
3100 CFG_ROAM_INTRA_BAND_MIN,
3101 CFG_ROAM_INTRA_BAND_MAX);
3102 ret = -EINVAL;
3103 goto exit;
3104 }
3105
3106 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
3107 (val > CFG_ROAM_INTRA_BAND_MAX))
3108 {
3109 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3110 "intra band mode value %d is out of range"
3111 " (Min: %d Max: %d)", val,
3112 CFG_ROAM_INTRA_BAND_MIN,
3113 CFG_ROAM_INTRA_BAND_MAX);
3114 ret = -EINVAL;
3115 goto exit;
3116 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003117 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3118 "%s: Received Command to change intra band = %d", __func__, val);
3119
3120 pHddCtx->cfg_ini->nRoamIntraBand = val;
3121 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
3122 }
3123 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
3124 {
3125 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
3126 char extra[32];
3127 tANI_U8 len = 0;
3128
3129 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003130 len = scnprintf(extra, sizeof(extra), "%s %d",
3131 "GETROAMINTRABAND", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003132 if (copy_to_user(priv_data.buf, &extra, len + 1))
3133 {
3134 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3135 "%s: failed to copy data to user buffer", __func__);
3136 ret = -EFAULT;
3137 goto exit;
3138 }
3139 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003140 else if (strncmp(command, "SETSCANNPROBES", 14) == 0)
3141 {
3142 tANI_U8 *value = command;
3143 tANI_U8 nProbes = CFG_ROAM_SCAN_N_PROBES_DEFAULT;
3144
3145 /* Move pointer to ahead of SETSCANNPROBES<delimiter> */
3146 value = value + 15;
3147 /* Convert the value from ascii to integer */
3148 ret = kstrtou8(value, 10, &nProbes);
3149 if (ret < 0)
3150 {
3151 /* If the input value is greater than max value of datatype, then also
3152 kstrtou8 fails */
3153 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3154 "%s: kstrtou8 failed range [%d - %d]", __func__,
3155 CFG_ROAM_SCAN_N_PROBES_MIN,
3156 CFG_ROAM_SCAN_N_PROBES_MAX);
3157 ret = -EINVAL;
3158 goto exit;
3159 }
3160
3161 if ((nProbes < CFG_ROAM_SCAN_N_PROBES_MIN) ||
3162 (nProbes > CFG_ROAM_SCAN_N_PROBES_MAX))
3163 {
3164 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3165 "NProbes value %d is out of range"
3166 " (Min: %d Max: %d)", nProbes,
3167 CFG_ROAM_SCAN_N_PROBES_MIN,
3168 CFG_ROAM_SCAN_N_PROBES_MAX);
3169 ret = -EINVAL;
3170 goto exit;
3171 }
3172
3173 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3174 "%s: Received Command to Set nProbes = %d", __func__, nProbes);
3175
3176 pHddCtx->cfg_ini->nProbes = nProbes;
3177 sme_UpdateRoamScanNProbes((tHalHandle)(pHddCtx->hHal), nProbes);
3178 }
3179 else if (strncmp(priv_data.buf, "GETSCANNPROBES", 14) == 0)
3180 {
3181 tANI_U8 val = sme_getRoamScanNProbes((tHalHandle)(pHddCtx->hHal));
3182 char extra[32];
3183 tANI_U8 len = 0;
3184
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003185 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003186 if (copy_to_user(priv_data.buf, &extra, len + 1))
3187 {
3188 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3189 "%s: failed to copy data to user buffer", __func__);
3190 ret = -EFAULT;
3191 goto exit;
3192 }
3193 }
3194 else if (strncmp(command, "SETSCANHOMEAWAYTIME", 19) == 0)
3195 {
3196 tANI_U8 *value = command;
3197 tANI_U16 homeAwayTime = CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT;
3198
3199 /* Move pointer to ahead of SETSCANHOMEAWAYTIME<delimiter> */
3200 /* input value is in units of msec */
3201 value = value + 20;
3202 /* Convert the value from ascii to integer */
3203 ret = kstrtou16(value, 10, &homeAwayTime);
3204 if (ret < 0)
3205 {
3206 /* If the input value is greater than max value of datatype, then also
3207 kstrtou8 fails */
3208 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3209 "%s: kstrtou8 failed range [%d - %d]", __func__,
3210 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
3211 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
3212 ret = -EINVAL;
3213 goto exit;
3214 }
3215
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003216 if ((homeAwayTime < CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN) ||
3217 (homeAwayTime > CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX))
3218 {
3219 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3220 "homeAwayTime value %d is out of range"
3221 " (Min: %d Max: %d)", homeAwayTime,
3222 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
3223 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
3224 ret = -EINVAL;
3225 goto exit;
3226 }
3227
3228 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3229 "%s: Received Command to Set scan away time = %d", __func__, homeAwayTime);
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07003230 if (pHddCtx->cfg_ini->nRoamScanHomeAwayTime != homeAwayTime)
3231 {
3232 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
3233 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_TRUE);
3234 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003235 }
3236 else if (strncmp(priv_data.buf, "GETSCANHOMEAWAYTIME", 19) == 0)
3237 {
3238 tANI_U16 val = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
3239 char extra[32];
3240 tANI_U8 len = 0;
3241
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003242 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003243 if (copy_to_user(priv_data.buf, &extra, len + 1))
3244 {
3245 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3246 "%s: failed to copy data to user buffer", __func__);
3247 ret = -EFAULT;
3248 goto exit;
3249 }
3250 }
3251 else if (strncmp(command, "REASSOC", 7) == 0)
3252 {
3253 tANI_U8 *value = command;
3254 tANI_U8 channel = 0;
3255 tSirMacAddr targetApBssid;
3256 eHalStatus status = eHAL_STATUS_SUCCESS;
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07003257#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
3258 tCsrHandoffRequest handoffInfo;
3259#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003260 hdd_station_ctx_t *pHddStaCtx = NULL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003261 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3262
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003263 /* if not associated, no need to proceed with reassoc */
3264 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3265 {
3266 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
3267 ret = -EINVAL;
3268 goto exit;
3269 }
3270
3271 status = hdd_parse_reassoc_command_data(value, targetApBssid, &channel);
3272 if (eHAL_STATUS_SUCCESS != status)
3273 {
3274 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3275 "%s: Failed to parse reassoc command data", __func__);
3276 ret = -EINVAL;
3277 goto exit;
3278 }
3279
3280 /* if the target bssid is same as currently associated AP,
3281 then no need to proceed with reassoc */
3282 if (VOS_TRUE == vos_mem_compare(targetApBssid,
3283 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
3284 {
3285 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Reassoc BSSID is same as currently associated AP bssid",__func__);
3286 ret = -EINVAL;
3287 goto exit;
3288 }
3289
3290 /* Check channel number is a valid channel number */
3291 if(VOS_STATUS_SUCCESS !=
3292 wlan_hdd_validate_operation_channel(pAdapter, channel))
3293 {
3294 hddLog(VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08003295 "%s: Invalid Channel [%d]", __func__, channel);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003296 return -EINVAL;
3297 }
3298
3299 /* Proceed with reassoc */
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07003300#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
3301 handoffInfo.channel = channel;
3302 vos_mem_copy(handoffInfo.bssid, targetApBssid, sizeof(tSirMacAddr));
3303 sme_HandoffRequest(pHddCtx->hHal, &handoffInfo);
3304#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003305 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07003306 else if (strncmp(command, "SETWESMODE", 10) == 0)
3307 {
3308 tANI_U8 *value = command;
3309 tANI_BOOLEAN wesMode = CFG_ENABLE_WES_MODE_NAME_DEFAULT;
3310
3311 /* Move pointer to ahead of SETWESMODE<delimiter> */
3312 value = value + 11;
3313 /* Convert the value from ascii to integer */
3314 ret = kstrtou8(value, 10, &wesMode);
3315 if (ret < 0)
3316 {
3317 /* If the input value is greater than max value of datatype, then also
3318 kstrtou8 fails */
3319 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3320 "%s: kstrtou8 failed range [%d - %d]", __func__,
3321 CFG_ENABLE_WES_MODE_NAME_MIN,
3322 CFG_ENABLE_WES_MODE_NAME_MAX);
3323 ret = -EINVAL;
3324 goto exit;
3325 }
3326
3327 if ((wesMode < CFG_ENABLE_WES_MODE_NAME_MIN) ||
3328 (wesMode > CFG_ENABLE_WES_MODE_NAME_MAX))
3329 {
3330 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3331 "WES Mode value %d is out of range"
3332 " (Min: %d Max: %d)", wesMode,
3333 CFG_ENABLE_WES_MODE_NAME_MIN,
3334 CFG_ENABLE_WES_MODE_NAME_MAX);
3335 ret = -EINVAL;
3336 goto exit;
3337 }
3338 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3339 "%s: Received Command to Set WES Mode rssi diff = %d", __func__, wesMode);
3340
3341 pHddCtx->cfg_ini->isWESModeEnabled = wesMode;
3342 sme_UpdateWESMode((tHalHandle)(pHddCtx->hHal), wesMode);
3343 }
3344 else if (strncmp(priv_data.buf, "GETWESMODE", 10) == 0)
3345 {
3346 tANI_BOOLEAN wesMode = sme_GetWESMode((tHalHandle)(pHddCtx->hHal));
3347 char extra[32];
3348 tANI_U8 len = 0;
3349
Arif Hussain826d9412013-11-12 16:44:54 -08003350 len = scnprintf(extra, sizeof(extra), "%s %d", command, wesMode);
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07003351 if (copy_to_user(priv_data.buf, &extra, len + 1))
3352 {
3353 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3354 "%s: failed to copy data to user buffer", __func__);
3355 ret = -EFAULT;
3356 goto exit;
3357 }
3358 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003359#endif /* WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_ESE || FEATURE_WLAN_LFR */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003360#ifdef FEATURE_WLAN_LFR
3361 else if (strncmp(command, "SETFASTROAM", 11) == 0)
3362 {
3363 tANI_U8 *value = command;
3364 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
3365
3366 /* Move pointer to ahead of SETFASTROAM<delimiter> */
3367 value = value + 12;
3368 /* Convert the value from ascii to integer */
3369 ret = kstrtou8(value, 10, &lfrMode);
3370 if (ret < 0)
3371 {
3372 /* If the input value is greater than max value of datatype, then also
3373 kstrtou8 fails */
3374 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3375 "%s: kstrtou8 failed range [%d - %d]", __func__,
3376 CFG_LFR_FEATURE_ENABLED_MIN,
3377 CFG_LFR_FEATURE_ENABLED_MAX);
3378 ret = -EINVAL;
3379 goto exit;
3380 }
3381
3382 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
3383 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
3384 {
3385 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3386 "lfr mode value %d is out of range"
3387 " (Min: %d Max: %d)", lfrMode,
3388 CFG_LFR_FEATURE_ENABLED_MIN,
3389 CFG_LFR_FEATURE_ENABLED_MAX);
3390 ret = -EINVAL;
3391 goto exit;
3392 }
3393
3394 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3395 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
3396
3397 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
3398 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
3399 }
3400#endif
3401#ifdef WLAN_FEATURE_VOWIFI_11R
3402 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
3403 {
3404 tANI_U8 *value = command;
3405 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
3406
3407 /* Move pointer to ahead of SETFASTROAM<delimiter> */
3408 value = value + 18;
3409 /* Convert the value from ascii to integer */
3410 ret = kstrtou8(value, 10, &ft);
3411 if (ret < 0)
3412 {
3413 /* If the input value is greater than max value of datatype, then also
3414 kstrtou8 fails */
3415 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3416 "%s: kstrtou8 failed range [%d - %d]", __func__,
3417 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
3418 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
3419 ret = -EINVAL;
3420 goto exit;
3421 }
3422
3423 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
3424 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
3425 {
3426 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3427 "ft mode value %d is out of range"
3428 " (Min: %d Max: %d)", ft,
3429 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
3430 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
3431 ret = -EINVAL;
3432 goto exit;
3433 }
3434
3435 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3436 "%s: Received Command to change ft mode = %d", __func__, ft);
3437
3438 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
3439 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
3440 }
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05303441
3442 else if (strncmp(command, "FASTREASSOC", 11) == 0)
3443 {
3444 tANI_U8 *value = command;
3445 tSirMacAddr targetApBssid;
3446 tANI_U8 trigger = 0;
3447 eHalStatus status = eHAL_STATUS_SUCCESS;
3448 hdd_station_ctx_t *pHddStaCtx = NULL;
3449 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3450
3451 /* if not associated, no need to proceed with reassoc */
3452 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3453 {
3454 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
3455 ret = -EINVAL;
3456 goto exit;
3457 }
3458
3459 status = hdd_parse_reassoc_command_data(value, targetApBssid, &trigger);
3460 if (eHAL_STATUS_SUCCESS != status)
3461 {
3462 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3463 "%s: Failed to parse reassoc command data", __func__);
3464 ret = -EINVAL;
3465 goto exit;
3466 }
3467
3468 /* if the target bssid is same as currently associated AP,
3469 then no need to proceed with reassoc */
3470 if (VOS_TRUE == vos_mem_compare(targetApBssid,
3471 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
3472 {
3473 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3474 "%s:11r Reassoc BSSID is same as currently associated AP bssid",
3475 __func__);
3476 ret = -EINVAL;
3477 goto exit;
3478 }
3479
3480 /* Proceed with scan/roam */
3481 smeIssueFastRoamNeighborAPEvent(WLAN_HDD_GET_HAL_CTX(pAdapter),
3482 &targetApBssid[0],
3483 (tSmeFastRoamTrigger)(trigger));
3484 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003485#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003486#ifdef FEATURE_WLAN_ESE
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003487 else if (strncmp(command, "SETCCXMODE", 10) == 0)
3488 {
3489 tANI_U8 *value = command;
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003490 tANI_U8 eseMode = CFG_ESE_FEATURE_ENABLED_DEFAULT;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003491
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003492 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003493 then this operation is not permitted (return FAILURE) */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003494 if (sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003495 hdd_is_okc_mode_enabled(pHddCtx) &&
3496 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
3497 {
3498 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003499 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003500 " hence this operation is not permitted!", __func__);
3501 ret = -EPERM;
3502 goto exit;
3503 }
3504
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003505 /* Move pointer to ahead of SETCCXMODE<delimiter> */
3506 value = value + 11;
3507 /* Convert the value from ascii to integer */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003508 ret = kstrtou8(value, 10, &eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003509 if (ret < 0)
3510 {
3511 /* If the input value is greater than max value of datatype, then also
3512 kstrtou8 fails */
3513 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3514 "%s: kstrtou8 failed range [%d - %d]", __func__,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003515 CFG_ESE_FEATURE_ENABLED_MIN,
3516 CFG_ESE_FEATURE_ENABLED_MAX);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003517 ret = -EINVAL;
3518 goto exit;
3519 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003520 if ((eseMode < CFG_ESE_FEATURE_ENABLED_MIN) ||
3521 (eseMode > CFG_ESE_FEATURE_ENABLED_MAX))
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003522 {
3523 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003524 "Ese mode value %d is out of range"
3525 " (Min: %d Max: %d)", eseMode,
3526 CFG_ESE_FEATURE_ENABLED_MIN,
3527 CFG_ESE_FEATURE_ENABLED_MAX);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003528 ret = -EINVAL;
3529 goto exit;
3530 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003531 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003532 "%s: Received Command to change ese mode = %d", __func__, eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003533
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003534 pHddCtx->cfg_ini->isEseIniFeatureEnabled = eseMode;
3535 sme_UpdateIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal), eseMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003536 }
3537#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003538 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
3539 {
3540 tANI_U8 *value = command;
3541 tANI_BOOLEAN roamScanControl = 0;
3542
3543 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
3544 value = value + 19;
3545 /* Convert the value from ascii to integer */
3546 ret = kstrtou8(value, 10, &roamScanControl);
3547 if (ret < 0)
3548 {
3549 /* If the input value is greater than max value of datatype, then also
3550 kstrtou8 fails */
3551 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3552 "%s: kstrtou8 failed ", __func__);
3553 ret = -EINVAL;
3554 goto exit;
3555 }
3556
3557 if (0 != roamScanControl)
3558 {
3559 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3560 "roam scan control invalid value = %d",
3561 roamScanControl);
3562 ret = -EINVAL;
3563 goto exit;
3564 }
3565 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3566 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
3567
3568 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
3569 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003570#ifdef FEATURE_WLAN_OKC
3571 else if (strncmp(command, "SETOKCMODE", 10) == 0)
3572 {
3573 tANI_U8 *value = command;
3574 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
3575
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003576 /* Check if the features OKC/ESE/11R are supported simultaneously,
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003577 then this operation is not permitted (return FAILURE) */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003578 if (sme_getIsEseFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003579 hdd_is_okc_mode_enabled(pHddCtx) &&
3580 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
3581 {
3582 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003583 "%s: OKC/ESE/11R are supported simultaneously"
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003584 " hence this operation is not permitted!", __func__);
3585 ret = -EPERM;
3586 goto exit;
3587 }
3588
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003589 /* Move pointer to ahead of SETOKCMODE<delimiter> */
3590 value = value + 11;
3591 /* Convert the value from ascii to integer */
3592 ret = kstrtou8(value, 10, &okcMode);
3593 if (ret < 0)
3594 {
3595 /* If the input value is greater than max value of datatype, then also
3596 kstrtou8 fails */
3597 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3598 "%s: kstrtou8 failed range [%d - %d]", __func__,
3599 CFG_OKC_FEATURE_ENABLED_MIN,
3600 CFG_OKC_FEATURE_ENABLED_MAX);
3601 ret = -EINVAL;
3602 goto exit;
3603 }
3604
3605 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
3606 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
3607 {
3608 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3609 "Okc mode value %d is out of range"
3610 " (Min: %d Max: %d)", okcMode,
3611 CFG_OKC_FEATURE_ENABLED_MIN,
3612 CFG_OKC_FEATURE_ENABLED_MAX);
3613 ret = -EINVAL;
3614 goto exit;
3615 }
3616
3617 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3618 "%s: Received Command to change okc mode = %d", __func__, okcMode);
3619
3620 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
3621 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07003622#endif /* FEATURE_WLAN_OKC */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003623 else if (strncmp(priv_data.buf, "GETROAMSCANCONTROL", 18) == 0)
3624 {
3625 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
3626 char extra[32];
3627 tANI_U8 len = 0;
3628
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003629 len = scnprintf(extra, sizeof(extra), "%s %d",
3630 command, roamScanControl);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003631 if (copy_to_user(priv_data.buf, &extra, len + 1))
3632 {
3633 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3634 "%s: failed to copy data to user buffer", __func__);
3635 ret = -EFAULT;
3636 goto exit;
3637 }
3638 }
Gopichand Nakkala227c7f32013-06-26 22:44:57 +05303639#ifdef WLAN_FEATURE_PACKET_FILTERING
3640 else if (strncmp(command, "ENABLE_PKTFILTER_IPV6", 21) == 0)
3641 {
3642 tANI_U8 filterType = 0;
3643 tANI_U8 *value = command;
3644
3645 /* Move pointer to ahead of ENABLE_PKTFILTER_IPV6<delimiter> */
3646 value = value + 22;
3647
3648 /* Convert the value from ascii to integer */
3649 ret = kstrtou8(value, 10, &filterType);
3650 if (ret < 0)
3651 {
3652 /* If the input value is greater than max value of datatype,
3653 * then also kstrtou8 fails
3654 */
3655 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3656 "%s: kstrtou8 failed range ", __func__);
3657 ret = -EINVAL;
3658 goto exit;
3659 }
3660
3661 if (filterType != 0 && filterType != 1)
3662 {
3663 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3664 "%s: Accepted Values are 0 and 1 ", __func__);
3665 ret = -EINVAL;
3666 goto exit;
3667 }
3668 wlan_hdd_setIPv6Filter(WLAN_HDD_GET_CTX(pAdapter), filterType,
3669 pAdapter->sessionId);
3670 }
3671#endif
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303672 else if (strncmp(command, "BTCOEXMODE", 10) == 0 )
3673 {
Kiet Lamad161252014-07-22 11:23:32 -07003674 char *dhcpPhase;
Satyanarayana Dash1faea4f2014-09-22 16:21:04 +05303675 int ret;
3676
Kiet Lamad161252014-07-22 11:23:32 -07003677 dhcpPhase = command + 11;
3678 if ('1' == *dhcpPhase)
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303679 {
c_hpothu9b781ba2013-12-30 20:57:45 +05303680 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Kiet Lamad161252014-07-22 11:23:32 -07003681 FL("send DHCP START indication"));
c_hpothu9b781ba2013-12-30 20:57:45 +05303682
3683 pHddCtx->btCoexModeSet = TRUE;
Kiet Lamad161252014-07-22 11:23:32 -07003684
Satyanarayana Dash1faea4f2014-09-22 16:21:04 +05303685 ret = wlan_hdd_scan_abort(pAdapter);
3686 if (ret < 0)
3687 {
3688 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3689 FL("failed to abort existing scan %d"), ret);
3690 }
3691
Kiet Lamad161252014-07-22 11:23:32 -07003692 sme_DHCPStartInd(pHddCtx->hHal, pAdapter->device_mode,
3693 pAdapter->sessionId);
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303694 }
Kiet Lamad161252014-07-22 11:23:32 -07003695 else if ('2' == *dhcpPhase)
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303696 {
c_hpothu9b781ba2013-12-30 20:57:45 +05303697 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Kiet Lamad161252014-07-22 11:23:32 -07003698 FL("send DHCP STOP indication"));
c_hpothu9b781ba2013-12-30 20:57:45 +05303699
3700 pHddCtx->btCoexModeSet = FALSE;
Kiet Lamad161252014-07-22 11:23:32 -07003701
3702 sme_DHCPStopInd(pHddCtx->hHal, pAdapter->device_mode,
3703 pAdapter->sessionId);
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303704 }
3705 }
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07003706 else if (strncmp(command, "SCAN-ACTIVE", 11) == 0)
3707 {
c_hpothudbefd3e2014-04-28 15:59:47 +05303708 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3709 FL("making default scan to ACTIVE"));
3710 pHddCtx->scan_info.scan_mode = eSIR_ACTIVE_SCAN;
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07003711 }
3712 else if (strncmp(command, "SCAN-PASSIVE", 12) == 0)
3713 {
c_hpothudbefd3e2014-04-28 15:59:47 +05303714 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3715 FL("making default scan to PASSIVE"));
3716 pHddCtx->scan_info.scan_mode = eSIR_PASSIVE_SCAN;
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07003717 }
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303718 else if (strncmp(command, "GETDWELLTIME", 12) == 0)
3719 {
3720 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3721 char extra[32];
3722 tANI_U8 len = 0;
3723
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05303724 memset(extra, 0, sizeof(extra));
3725 ret = hdd_get_dwell_time(pCfg, command, extra, sizeof(extra), &len);
3726 if (ret != 0 || copy_to_user(priv_data.buf, &extra, len + 1))
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303727 {
3728 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3729 "%s: failed to copy data to user buffer", __func__);
3730 ret = -EFAULT;
3731 goto exit;
3732 }
3733 ret = len;
3734 }
3735 else if (strncmp(command, "SETDWELLTIME", 12) == 0)
3736 {
Rajesh Babu Prathipatic7baf6f2014-05-30 10:08:16 +05303737 ret = hdd_set_dwell_time(pAdapter, command);
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303738 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07003739 else if ( strncasecmp(command, "MIRACAST", 8) == 0 )
3740 {
3741 tANI_U8 filterType = 0;
3742 tANI_U8 *value;
3743 value = command + 9;
3744
3745 /* Convert the value from ascii to integer */
3746 ret = kstrtou8(value, 10, &filterType);
3747 if (ret < 0)
3748 {
3749 /* If the input value is greater than max value of datatype,
3750 * then also kstrtou8 fails
3751 */
3752 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3753 "%s: kstrtou8 failed range ", __func__);
3754 ret = -EINVAL;
3755 goto exit;
3756 }
3757 if ((filterType < WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL ) ||
3758 (filterType > WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL))
3759 {
3760 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3761 "%s: Accepted Values are 0 to 2. 0-Disabled, 1-Source,"
3762 " 2-Sink ", __func__);
3763 ret = -EINVAL;
3764 goto exit;
3765 }
3766 //Filtertype value should be either 0-Disabled, 1-Source, 2-sink
3767 pHddCtx->drvr_miracast = filterType;
3768 hdd_tx_rx_pkt_cnt_stat_timer_handler(pHddCtx);
Ganesh Kondabattini8f6e3b32014-08-25 16:07:54 +05303769 sme_SetMiracastMode(pHddCtx->hHal, pHddCtx->drvr_miracast);
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07003770 }
Leo Chang614d2072013-08-22 14:59:44 -07003771 else if (strncmp(command, "SETMCRATE", 9) == 0)
3772 {
Leo Chang614d2072013-08-22 14:59:44 -07003773 tANI_U8 *value = command;
3774 int targetRate;
Leo Chang1f98cbd2013-10-17 15:03:52 -07003775 tSirRateUpdateInd *rateUpdate;
3776 eHalStatus status;
Leo Chang614d2072013-08-22 14:59:44 -07003777
3778 /* Only valid for SAP mode */
3779 if (WLAN_HDD_SOFTAP != pAdapter->device_mode)
3780 {
3781 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3782 "%s: SAP mode is not running", __func__);
3783 ret = -EFAULT;
3784 goto exit;
3785 }
3786
3787 /* Move pointer to ahead of SETMCRATE<delimiter> */
3788 /* input value is in units of hundred kbps */
3789 value = value + 10;
3790 /* Convert the value from ascii to integer, decimal base */
3791 ret = kstrtouint(value, 10, &targetRate);
3792
Leo Chang1f98cbd2013-10-17 15:03:52 -07003793 rateUpdate = (tSirRateUpdateInd *)vos_mem_malloc(sizeof(tSirRateUpdateInd));
3794 if (NULL == rateUpdate)
Leo Chang614d2072013-08-22 14:59:44 -07003795 {
Leo Chang1f98cbd2013-10-17 15:03:52 -07003796 hddLog(VOS_TRACE_LEVEL_ERROR,
3797 "%s: SETMCRATE indication alloc fail", __func__);
3798 ret = -EFAULT;
3799 goto exit;
3800 }
3801 vos_mem_zero(rateUpdate, sizeof(tSirRateUpdateInd ));
3802
3803 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3804 "MC Target rate %d", targetRate);
3805 /* Ignore unicast */
3806 rateUpdate->ucastDataRate = -1;
3807 rateUpdate->mcastDataRate24GHz = targetRate;
3808 rateUpdate->mcastDataRate5GHz = targetRate;
3809 rateUpdate->mcastDataRate24GHzTxFlag = 0;
3810 rateUpdate->mcastDataRate5GHzTxFlag = 0;
3811 status = sme_SendRateUpdateInd(pHddCtx->hHal, rateUpdate);
3812 if (eHAL_STATUS_SUCCESS != status)
3813 {
3814 hddLog(VOS_TRACE_LEVEL_ERROR,
3815 "%s: SET_MC_RATE failed", __func__);
3816 vos_mem_free(rateUpdate);
3817 ret = -EFAULT;
3818 goto exit;
Leo Chang614d2072013-08-22 14:59:44 -07003819 }
3820 }
Rajeev79dbe4c2013-10-05 11:03:42 +05303821#ifdef FEATURE_WLAN_BATCH_SCAN
Rajeev Kumar8b373292014-01-08 20:36:55 -08003822 else if (strncmp(command, "WLS_BATCHING", 12) == 0)
Rajeev79dbe4c2013-10-05 11:03:42 +05303823 {
Rajeev Kumar8b373292014-01-08 20:36:55 -08003824 ret = hdd_handle_batch_scan_ioctl(pAdapter, &priv_data, command);
Rajeev79dbe4c2013-10-05 11:03:42 +05303825 }
3826#endif
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003827#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003828 else if (strncmp(command, "SETCCXROAMSCANCHANNELS", 22) == 0)
3829 {
3830 tANI_U8 *value = command;
3831 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
3832 tANI_U8 numChannels = 0;
3833 eHalStatus status = eHAL_STATUS_SUCCESS;
3834
3835 status = hdd_parse_channellist(value, ChannelList, &numChannels);
3836 if (eHAL_STATUS_SUCCESS != status)
3837 {
3838 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3839 "%s: Failed to parse channel list information", __func__);
3840 ret = -EINVAL;
3841 goto exit;
3842 }
3843
3844 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
3845 {
3846 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3847 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
3848 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
3849 ret = -EINVAL;
3850 goto exit;
3851 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003852 status = sme_SetEseRoamScanChannelList((tHalHandle)(pHddCtx->hHal),
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003853 ChannelList,
3854 numChannels);
3855 if (eHAL_STATUS_SUCCESS != status)
3856 {
3857 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3858 "%s: Failed to update channel list information", __func__);
3859 ret = -EINVAL;
3860 goto exit;
3861 }
3862 }
3863 else if (strncmp(command, "GETTSMSTATS", 11) == 0)
3864 {
3865 tANI_U8 *value = command;
3866 char extra[128] = {0};
3867 int len = 0;
3868 tANI_U8 tid = 0;
3869 hdd_station_ctx_t *pHddStaCtx = NULL;
3870 tAniTrafStrmMetrics tsmMetrics;
3871 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3872
3873 /* if not associated, return error */
3874 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3875 {
3876 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:Not associated!",__func__);
3877 ret = -EINVAL;
3878 goto exit;
3879 }
3880
3881 /* Move pointer to ahead of GETTSMSTATS<delimiter> */
3882 value = value + 12;
3883 /* Convert the value from ascii to integer */
3884 ret = kstrtou8(value, 10, &tid);
3885 if (ret < 0)
3886 {
3887 /* If the input value is greater than max value of datatype, then also
3888 kstrtou8 fails */
3889 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3890 "%s: kstrtou8 failed range [%d - %d]", __func__,
3891 TID_MIN_VALUE,
3892 TID_MAX_VALUE);
3893 ret = -EINVAL;
3894 goto exit;
3895 }
3896
3897 if ((tid < TID_MIN_VALUE) || (tid > TID_MAX_VALUE))
3898 {
3899 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3900 "tid value %d is out of range"
3901 " (Min: %d Max: %d)", tid,
3902 TID_MIN_VALUE,
3903 TID_MAX_VALUE);
3904 ret = -EINVAL;
3905 goto exit;
3906 }
3907
3908 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3909 "%s: Received Command to get tsm stats tid = %d", __func__, tid);
3910
3911 if (VOS_STATUS_SUCCESS != hdd_get_tsm_stats(pAdapter, tid, &tsmMetrics))
3912 {
3913 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3914 "%s: failed to get tsm stats", __func__);
3915 ret = -EFAULT;
3916 goto exit;
3917 }
3918
3919 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3920 "UplinkPktQueueDly(%d)\n"
3921 "UplinkPktQueueDlyHist[0](%d)\n"
3922 "UplinkPktQueueDlyHist[1](%d)\n"
3923 "UplinkPktQueueDlyHist[2](%d)\n"
3924 "UplinkPktQueueDlyHist[3](%d)\n"
Arun Kumar Khandavallie8768212014-02-17 16:43:34 +05303925 "UplinkPktTxDly(%u)\n"
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003926 "UplinkPktLoss(%d)\n"
3927 "UplinkPktCount(%d)\n"
3928 "RoamingCount(%d)\n"
3929 "RoamingDly(%d)", tsmMetrics.UplinkPktQueueDly,
3930 tsmMetrics.UplinkPktQueueDlyHist[0],
3931 tsmMetrics.UplinkPktQueueDlyHist[1],
3932 tsmMetrics.UplinkPktQueueDlyHist[2],
3933 tsmMetrics.UplinkPktQueueDlyHist[3],
3934 tsmMetrics.UplinkPktTxDly, tsmMetrics.UplinkPktLoss,
3935 tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount, tsmMetrics.RoamingDly);
3936
3937 /* Output TSM stats is of the format
3938 GETTSMSTATS [PktQueueDly] [PktQueueDlyHist[0]]:[PktQueueDlyHist[1]] ...[RoamingDly]
3939 eg., GETTSMSTATS 10 1:0:0:161 20 1 17 8 39800 */
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003940 len = scnprintf(extra, sizeof(extra), "%s %d %d:%d:%d:%d %u %d %d %d %d", command,
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003941 tsmMetrics.UplinkPktQueueDly, tsmMetrics.UplinkPktQueueDlyHist[0],
3942 tsmMetrics.UplinkPktQueueDlyHist[1], tsmMetrics.UplinkPktQueueDlyHist[2],
3943 tsmMetrics.UplinkPktQueueDlyHist[3], tsmMetrics.UplinkPktTxDly,
3944 tsmMetrics.UplinkPktLoss, tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount,
3945 tsmMetrics.RoamingDly);
3946
3947 if (copy_to_user(priv_data.buf, &extra, len + 1))
3948 {
3949 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3950 "%s: failed to copy data to user buffer", __func__);
3951 ret = -EFAULT;
3952 goto exit;
3953 }
3954 }
3955 else if (strncmp(command, "SETCCKMIE", 9) == 0)
3956 {
3957 tANI_U8 *value = command;
3958 tANI_U8 *cckmIe = NULL;
3959 tANI_U8 cckmIeLen = 0;
3960 eHalStatus status = eHAL_STATUS_SUCCESS;
3961
3962 status = hdd_parse_get_cckm_ie(value, &cckmIe, &cckmIeLen);
3963 if (eHAL_STATUS_SUCCESS != status)
3964 {
3965 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3966 "%s: Failed to parse cckm ie data", __func__);
3967 ret = -EINVAL;
3968 goto exit;
3969 }
3970
3971 if (cckmIeLen > DOT11F_IE_RSN_MAX_LEN)
3972 {
3973 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3974 "%s: CCKM Ie input length is more than max[%d]", __func__,
3975 DOT11F_IE_RSN_MAX_LEN);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08003976 vos_mem_free(cckmIe);
3977 cckmIe = NULL;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003978 ret = -EINVAL;
3979 goto exit;
3980 }
3981 sme_SetCCKMIe((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, cckmIe, cckmIeLen);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08003982 vos_mem_free(cckmIe);
3983 cckmIe = NULL;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003984 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003985 else if (strncmp(command, "CCXBEACONREQ", 12) == 0)
3986 {
3987 tANI_U8 *value = command;
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003988 tCsrEseBeaconReq eseBcnReq;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003989 eHalStatus status = eHAL_STATUS_SUCCESS;
Srinivas Girigowda0c6d7fe2014-05-28 18:18:10 -07003990
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003991 status = hdd_parse_ese_beacon_req(value, &eseBcnReq);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003992 if (eHAL_STATUS_SUCCESS != status)
3993 {
3994 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08003995 "%s: Failed to parse ese beacon req", __func__);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003996 ret = -EINVAL;
3997 goto exit;
3998 }
Srinivas Girigowda0c6d7fe2014-05-28 18:18:10 -07003999 if (!hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))) {
4000 hddLog(VOS_TRACE_LEVEL_INFO, FL("Not associated"));
4001 hdd_indicateEseBcnReportNoResults (pAdapter,
4002 eseBcnReq.bcnReq[0].measurementToken,
4003 0x02, //BIT(1) set for measurement done
4004 0); // no BSS
4005 goto exit;
4006 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004007
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004008 status = sme_SetEseBeaconRequest((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, &eseBcnReq);
4009 if (eHAL_STATUS_SUCCESS != status)
4010 {
4011 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4012 "%s: sme_SetEseBeaconRequest failed (%d)", __func__, status);
4013 ret = -EINVAL;
4014 goto exit;
4015 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004016 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004017#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
c_hpothu92367912014-05-01 15:18:17 +05304018 else if (strncmp(command, "GETBCNMISSRATE", 14) == 0)
4019 {
4020 eHalStatus status;
4021 char buf[32], len;
4022 long waitRet;
4023 bcnMissRateContext_t getBcnMissRateCtx;
4024
4025 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4026
4027 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
4028 {
4029 hddLog(VOS_TRACE_LEVEL_WARN,
4030 FL("GETBCNMISSRATE: STA is not in connected state"));
4031 ret = -1;
4032 goto exit;
4033 }
4034
4035 init_completion(&(getBcnMissRateCtx.completion));
4036 getBcnMissRateCtx.magic = BCN_MISS_RATE_CONTEXT_MAGIC;
4037
4038 status = sme_getBcnMissRate((tHalHandle)(pHddCtx->hHal),
4039 pAdapter->sessionId,
4040 (void *)getBcnMissRateCB,
4041 (void *)(&getBcnMissRateCtx));
4042 if( eHAL_STATUS_SUCCESS != status)
4043 {
4044 hddLog(VOS_TRACE_LEVEL_INFO,
4045 FL("GETBCNMISSRATE: fail to post WDA cmd"));
4046 ret = -EINVAL;
4047 goto exit;
4048 }
4049
4050 waitRet = wait_for_completion_interruptible_timeout
4051 (&getBcnMissRateCtx.completion, BCN_MISS_RATE_TIME);
4052 if(waitRet <= 0)
4053 {
4054 hddLog(VOS_TRACE_LEVEL_ERROR,
4055 FL("failed to wait on bcnMissRateComp %d"), ret);
4056
4057 //Make magic number to zero so that callback is not called.
4058 spin_lock(&hdd_context_lock);
4059 getBcnMissRateCtx.magic = 0x0;
4060 spin_unlock(&hdd_context_lock);
4061 ret = -EINVAL;
4062 goto exit;
4063 }
4064
4065 hddLog(VOS_TRACE_LEVEL_INFO,
4066 FL("GETBCNMISSRATE: bcnMissRate: %d"), gbcnMissRate);
4067
4068 len = snprintf(buf, sizeof(buf), "GETBCNMISSRATE %d", gbcnMissRate);
4069 if (copy_to_user(priv_data.buf, &buf, len + 1))
4070 {
4071 hddLog(VOS_TRACE_LEVEL_ERROR,
4072 "%s: failed to copy data to user buffer", __func__);
4073 ret = -EFAULT;
4074 goto exit;
4075 }
4076 ret = len;
4077 }
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07004078 else {
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05304079 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
4080 TRACE_CODE_HDD_UNSUPPORTED_IOCTL,
4081 pAdapter->sessionId, 0));
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07004082 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
4083 __func__, command);
4084 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004085 }
4086exit:
4087 if (command)
4088 {
4089 kfree(command);
4090 }
4091 return ret;
4092}
4093
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07004094#ifdef CONFIG_COMPAT
4095static int hdd_driver_compat_ioctl(hdd_adapter_t *pAdapter, struct ifreq *ifr)
4096{
4097 struct {
4098 compat_uptr_t buf;
4099 int used_len;
4100 int total_len;
4101 } compat_priv_data;
4102 hdd_priv_data_t priv_data;
4103 int ret = 0;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004104
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07004105 /*
4106 * Note that pAdapter and ifr have already been verified by caller,
4107 * and HDD context has also been validated
4108 */
4109 if (copy_from_user(&compat_priv_data, ifr->ifr_data,
4110 sizeof(compat_priv_data))) {
4111 ret = -EFAULT;
4112 goto exit;
4113 }
4114 priv_data.buf = compat_ptr(compat_priv_data.buf);
4115 priv_data.used_len = compat_priv_data.used_len;
4116 priv_data.total_len = compat_priv_data.total_len;
4117 ret = hdd_driver_command(pAdapter, &priv_data);
4118 exit:
4119 return ret;
4120}
4121#else /* CONFIG_COMPAT */
4122static int hdd_driver_compat_ioctl(hdd_adapter_t *pAdapter, struct ifreq *ifr)
4123{
4124 /* will never be invoked */
4125 return 0;
4126}
4127#endif /* CONFIG_COMPAT */
4128
4129static int hdd_driver_ioctl(hdd_adapter_t *pAdapter, struct ifreq *ifr)
4130{
4131 hdd_priv_data_t priv_data;
4132 int ret = 0;
4133
4134 /*
4135 * Note that pAdapter and ifr have already been verified by caller,
4136 * and HDD context has also been validated
4137 */
4138 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(priv_data))) {
4139 ret = -EFAULT;
4140 } else {
4141 ret = hdd_driver_command(pAdapter, &priv_data);
4142 }
4143 return ret;
4144}
4145
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05304146int __hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
Jeff Johnsond6e7b3f2014-03-20 12:12:11 -07004147{
4148 hdd_adapter_t *pAdapter;
4149 hdd_context_t *pHddCtx;
4150 int ret;
4151
4152 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4153 if (NULL == pAdapter) {
4154 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4155 "%s: HDD adapter context is Null", __func__);
4156 ret = -ENODEV;
4157 goto exit;
4158 }
4159 if (dev != pAdapter->dev) {
4160 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4161 "%s: HDD adapter/dev inconsistency", __func__);
4162 ret = -ENODEV;
4163 goto exit;
4164 }
4165
4166 if ((!ifr) || (!ifr->ifr_data)) {
4167 ret = -EINVAL;
4168 goto exit;
4169 }
4170
4171 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4172 ret = wlan_hdd_validate_context(pHddCtx);
4173 if (ret) {
4174 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4175 "%s: invalid context", __func__);
4176 ret = -EBUSY;
4177 goto exit;
4178 }
4179
4180 switch (cmd) {
4181 case (SIOCDEVPRIVATE + 1):
4182 if (is_compat_task())
4183 ret = hdd_driver_compat_ioctl(pAdapter, ifr);
4184 else
4185 ret = hdd_driver_ioctl(pAdapter, ifr);
4186 break;
4187 default:
4188 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unknown ioctl %d",
4189 __func__, cmd);
4190 ret = -EINVAL;
4191 break;
4192 }
4193 exit:
4194 return ret;
4195}
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004196
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05304197int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
4198{
4199 int ret;
4200
4201 vos_ssr_protect(__func__);
4202 ret = __hdd_ioctl(dev, ifr, cmd);
4203 vos_ssr_unprotect(__func__);
4204
4205 return ret;
4206}
4207
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004208#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004209/**---------------------------------------------------------------------------
4210
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004211 \brief hdd_parse_ese_beacon_req() - Parse ese beacon request
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004212
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004213 This function parses the ese beacon request passed in the format
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004214 CCXBEACONREQ<space><Number of fields><space><Measurement token>
4215 <space>Channel 1<space>Scan Mode <space>Meas Duration<space>Channel N
4216 <space>Scan Mode N<space>Meas Duration N
4217 if the Number of bcn req fields (N) does not match with the actual number of fields passed
4218 then take N.
4219 <Meas Token><Channel><Scan Mode> and <Meas Duration> are treated as one pair
4220 For example, CCXBEACONREQ 2 1 1 1 30 2 44 0 40.
4221 This function does not take care of removing duplicate channels from the list
4222
4223 \param - pValue Pointer to data
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004224 \param - pEseBcnReq output pointer to store parsed ie information
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004225
4226 \return - 0 for success non-zero for failure
4227
4228 --------------------------------------------------------------------------*/
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004229static VOS_STATUS hdd_parse_ese_beacon_req(tANI_U8 *pValue,
4230 tCsrEseBeaconReq *pEseBcnReq)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004231{
4232 tANI_U8 *inPtr = pValue;
4233 int tempInt = 0;
4234 int j = 0, i = 0, v = 0;
4235 char buf[32];
4236
4237 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4238 /*no argument after the command*/
4239 if (NULL == inPtr)
4240 {
4241 return -EINVAL;
4242 }
4243 /*no space after the command*/
4244 else if (SPACE_ASCII_VALUE != *inPtr)
4245 {
4246 return -EINVAL;
4247 }
4248
4249 /*removing empty spaces*/
4250 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
4251
4252 /*no argument followed by spaces*/
4253 if ('\0' == *inPtr) return -EINVAL;
4254
4255 /*getting the first argument ie measurement token*/
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004256 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004257 if (1 != v) return -EINVAL;
4258
4259 v = kstrtos32(buf, 10, &tempInt);
4260 if ( v < 0) return -EINVAL;
4261
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004262 pEseBcnReq->numBcnReqIe = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004263
4264 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004265 "Number of Bcn Req Ie fields(%d)", pEseBcnReq->numBcnReqIe);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004266
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004267 for (j = 0; j < (pEseBcnReq->numBcnReqIe); j++)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004268 {
4269 for (i = 0; i < 4; i++)
4270 {
4271 /*inPtr pointing to the beginning of first space after number of ie fields*/
4272 inPtr = strpbrk( inPtr, " " );
4273 /*no ie data after the number of ie fields argument*/
4274 if (NULL == inPtr) return -EINVAL;
4275
4276 /*removing empty space*/
4277 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
4278
4279 /*no ie data after the number of ie fields argument and spaces*/
4280 if ( '\0' == *inPtr ) return -EINVAL;
4281
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004282 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004283 if (1 != v) return -EINVAL;
4284
4285 v = kstrtos32(buf, 10, &tempInt);
4286 if (v < 0) return -EINVAL;
4287
4288 switch (i)
4289 {
4290 case 0: /* Measurement token */
4291 if (tempInt <= 0)
4292 {
4293 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4294 "Invalid Measurement Token(%d)", tempInt);
4295 return -EINVAL;
4296 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004297 pEseBcnReq->bcnReq[j].measurementToken = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004298 break;
4299
4300 case 1: /* Channel number */
4301 if ((tempInt <= 0) ||
4302 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4303 {
4304 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4305 "Invalid Channel Number(%d)", tempInt);
4306 return -EINVAL;
4307 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004308 pEseBcnReq->bcnReq[j].channel = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004309 break;
4310
4311 case 2: /* Scan mode */
Varun Reddy Yeturu0b18d5a2013-12-04 11:42:23 -08004312 if ((tempInt < eSIR_PASSIVE_SCAN) || (tempInt > eSIR_BEACON_TABLE))
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004313 {
4314 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4315 "Invalid Scan Mode(%d) Expected{0|1|2}", tempInt);
4316 return -EINVAL;
4317 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004318 pEseBcnReq->bcnReq[j].scanMode= tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004319 break;
4320
4321 case 3: /* Measurement duration */
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004322 if (((tempInt <= 0) && (pEseBcnReq->bcnReq[j].scanMode != eSIR_BEACON_TABLE)) ||
4323 ((tempInt < 0) && (pEseBcnReq->bcnReq[j].scanMode == eSIR_BEACON_TABLE)))
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004324 {
4325 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4326 "Invalid Measurement Duration(%d)", tempInt);
4327 return -EINVAL;
4328 }
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004329 pEseBcnReq->bcnReq[j].measurementDuration = tempInt;
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004330 break;
4331 }
4332 }
4333 }
4334
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004335 for (j = 0; j < pEseBcnReq->numBcnReqIe; j++)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004336 {
4337 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arun Kumar Khandavallie8768212014-02-17 16:43:34 +05304338 "Index(%d) Measurement Token(%u)Channel(%u) Scan Mode(%u) Measurement Duration(%u)\n",
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004339 j,
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004340 pEseBcnReq->bcnReq[j].measurementToken,
4341 pEseBcnReq->bcnReq[j].channel,
4342 pEseBcnReq->bcnReq[j].scanMode,
4343 pEseBcnReq->bcnReq[j].measurementDuration);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08004344 }
4345
4346 return VOS_STATUS_SUCCESS;
4347}
4348
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004349static void hdd_GetTsmStatsCB( tAniTrafStrmMetrics tsmMetrics, const tANI_U32 staId, void *pContext )
4350{
4351 struct statsContext *pStatsContext = NULL;
4352 hdd_adapter_t *pAdapter = NULL;
4353
4354 if (NULL == pContext)
4355 {
4356 hddLog(VOS_TRACE_LEVEL_ERROR,
4357 "%s: Bad param, pContext [%p]",
4358 __func__, pContext);
4359 return;
4360 }
4361
Jeff Johnson72a40512013-12-19 10:14:15 -08004362 /* there is a race condition that exists between this callback
4363 function and the caller since the caller could time out either
4364 before or while this code is executing. we use a spinlock to
4365 serialize these actions */
4366 spin_lock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004367
4368 pStatsContext = pContext;
4369 pAdapter = pStatsContext->pAdapter;
4370 if ((NULL == pAdapter) || (STATS_CONTEXT_MAGIC != pStatsContext->magic))
4371 {
4372 /* the caller presumably timed out so there is nothing we can do */
Jeff Johnson72a40512013-12-19 10:14:15 -08004373 spin_unlock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004374 hddLog(VOS_TRACE_LEVEL_WARN,
4375 "%s: Invalid context, pAdapter [%p] magic [%08x]",
4376 __func__, pAdapter, pStatsContext->magic);
4377 return;
4378 }
4379
Jeff Johnson72a40512013-12-19 10:14:15 -08004380 /* context is valid so caller is still waiting */
4381
4382 /* paranoia: invalidate the magic */
4383 pStatsContext->magic = 0;
4384
4385 /* copy over the tsm stats */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004386 pAdapter->tsmStats.UplinkPktQueueDly = tsmMetrics.UplinkPktQueueDly;
4387 vos_mem_copy(pAdapter->tsmStats.UplinkPktQueueDlyHist,
4388 tsmMetrics.UplinkPktQueueDlyHist,
4389 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
4390 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
4391 pAdapter->tsmStats.UplinkPktTxDly = tsmMetrics.UplinkPktTxDly;
4392 pAdapter->tsmStats.UplinkPktLoss = tsmMetrics.UplinkPktLoss;
4393 pAdapter->tsmStats.UplinkPktCount = tsmMetrics.UplinkPktCount;
4394 pAdapter->tsmStats.RoamingCount = tsmMetrics.RoamingCount;
4395 pAdapter->tsmStats.RoamingDly = tsmMetrics.RoamingDly;
4396
Jeff Johnson72a40512013-12-19 10:14:15 -08004397 /* notify the caller */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004398 complete(&pStatsContext->completion);
Jeff Johnson72a40512013-12-19 10:14:15 -08004399
4400 /* serialization is complete */
4401 spin_unlock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004402}
4403
4404
4405
4406static VOS_STATUS hdd_get_tsm_stats(hdd_adapter_t *pAdapter, const tANI_U8 tid,
4407 tAniTrafStrmMetrics* pTsmMetrics)
4408{
4409 hdd_station_ctx_t *pHddStaCtx = NULL;
4410 eHalStatus hstatus;
Jeff Johnson72a40512013-12-19 10:14:15 -08004411 VOS_STATUS vstatus = VOS_STATUS_SUCCESS;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004412 long lrc;
4413 struct statsContext context;
4414 hdd_context_t *pHddCtx = NULL;
4415
4416 if (NULL == pAdapter)
4417 {
4418 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: pAdapter is NULL", __func__);
4419 return VOS_STATUS_E_FAULT;
4420 }
4421
4422 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
4423 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
4424
4425 /* we are connected prepare our callback context */
4426 init_completion(&context.completion);
4427 context.pAdapter = pAdapter;
4428 context.magic = STATS_CONTEXT_MAGIC;
4429
4430 /* query tsm stats */
4431 hstatus = sme_GetTsmStats(pHddCtx->hHal, hdd_GetTsmStatsCB,
4432 pHddStaCtx->conn_info.staId[ 0 ],
4433 pHddStaCtx->conn_info.bssId,
4434 &context, pHddCtx->pvosContext, tid);
4435
4436 if (eHAL_STATUS_SUCCESS != hstatus)
4437 {
Jeff Johnson72a40512013-12-19 10:14:15 -08004438 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unable to retrieve statistics",
4439 __func__);
4440 vstatus = VOS_STATUS_E_FAULT;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004441 }
4442 else
4443 {
4444 /* request was sent -- wait for the response */
4445 lrc = wait_for_completion_interruptible_timeout(&context.completion,
4446 msecs_to_jiffies(WLAN_WAIT_TIME_STATS));
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004447 if (lrc <= 0)
4448 {
4449 hddLog(VOS_TRACE_LEVEL_ERROR,
4450 "%s: SME %s while retrieving statistics",
4451 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson72a40512013-12-19 10:14:15 -08004452 vstatus = VOS_STATUS_E_TIMEOUT;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004453 }
4454 }
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004455
Jeff Johnson72a40512013-12-19 10:14:15 -08004456 /* either we never sent a request, we sent a request and received a
4457 response or we sent a request and timed out. if we never sent a
4458 request or if we sent a request and got a response, we want to
4459 clear the magic out of paranoia. if we timed out there is a
4460 race condition such that the callback function could be
4461 executing at the same time we are. of primary concern is if the
4462 callback function had already verified the "magic" but had not
4463 yet set the completion variable when a timeout occurred. we
4464 serialize these activities by invalidating the magic while
4465 holding a shared spinlock which will cause us to block if the
4466 callback is currently executing */
4467 spin_lock(&hdd_context_lock);
4468 context.magic = 0;
4469 spin_unlock(&hdd_context_lock);
4470
4471 if (VOS_STATUS_SUCCESS == vstatus)
4472 {
4473 pTsmMetrics->UplinkPktQueueDly = pAdapter->tsmStats.UplinkPktQueueDly;
4474 vos_mem_copy(pTsmMetrics->UplinkPktQueueDlyHist,
4475 pAdapter->tsmStats.UplinkPktQueueDlyHist,
4476 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
4477 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
4478 pTsmMetrics->UplinkPktTxDly = pAdapter->tsmStats.UplinkPktTxDly;
4479 pTsmMetrics->UplinkPktLoss = pAdapter->tsmStats.UplinkPktLoss;
4480 pTsmMetrics->UplinkPktCount = pAdapter->tsmStats.UplinkPktCount;
4481 pTsmMetrics->RoamingCount = pAdapter->tsmStats.RoamingCount;
4482 pTsmMetrics->RoamingDly = pAdapter->tsmStats.RoamingDly;
4483 }
4484 return vstatus;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004485}
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004486#endif /*FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004487
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004488#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
Srinivas Girigowdade697412013-02-14 16:31:48 -08004489void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
4490{
4491 eCsrBand band = -1;
4492 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
4493 switch (band)
4494 {
4495 case eCSR_BAND_ALL:
4496 *pBand = WLAN_HDD_UI_BAND_AUTO;
4497 break;
4498
4499 case eCSR_BAND_24:
4500 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
4501 break;
4502
4503 case eCSR_BAND_5G:
4504 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
4505 break;
4506
4507 default:
4508 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
4509 *pBand = -1;
4510 break;
4511 }
4512}
4513
4514/**---------------------------------------------------------------------------
4515
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004516 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
4517
4518 This function parses the send action frame data passed in the format
4519 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
4520
Srinivas Girigowda56076852013-08-20 14:00:50 -07004521 \param - pValue Pointer to input data
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004522 \param - pTargetApBssid Pointer to target Ap bssid
4523 \param - pChannel Pointer to the Target AP channel
4524 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
4525 \param - pBuf Pointer to data
4526 \param - pBufLen Pointer to data length
4527
4528 \return - 0 for success non-zero for failure
4529
4530 --------------------------------------------------------------------------*/
4531VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
4532 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
4533{
4534 tANI_U8 *inPtr = pValue;
4535 tANI_U8 *dataEnd;
4536 int tempInt;
4537 int j = 0;
4538 int i = 0;
4539 int v = 0;
4540 tANI_U8 tempBuf[32];
4541 tANI_U8 tempByte = 0;
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004542 /* 12 hexa decimal digits, 5 ':' and '\0' */
4543 tANI_U8 macAddress[18];
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004544
4545 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4546 /*no argument after the command*/
4547 if (NULL == inPtr)
4548 {
4549 return -EINVAL;
4550 }
4551
4552 /*no space after the command*/
4553 else if (SPACE_ASCII_VALUE != *inPtr)
4554 {
4555 return -EINVAL;
4556 }
4557
4558 /*removing empty spaces*/
4559 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4560
4561 /*no argument followed by spaces*/
4562 if ('\0' == *inPtr)
4563 {
4564 return -EINVAL;
4565 }
4566
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004567 v = sscanf(inPtr, "%17s", macAddress);
4568 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004569 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004570 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4571 "Invalid MAC address or All hex inputs are not read (%d)", v);
4572 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004573 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004574
4575 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
4576 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
4577 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
4578 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
4579 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
4580 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004581
4582 /* point to the next argument */
4583 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4584 /*no argument after the command*/
4585 if (NULL == inPtr) return -EINVAL;
4586
4587 /*removing empty spaces*/
4588 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4589
4590 /*no argument followed by spaces*/
4591 if ('\0' == *inPtr)
4592 {
4593 return -EINVAL;
4594 }
4595
4596 /*getting the next argument ie the channel number */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004597 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004598 if (1 != v) return -EINVAL;
4599
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004600 v = kstrtos32(tempBuf, 10, &tempInt);
Agarwal Ashish353b3a82014-04-08 14:55:11 +05304601 if ( v < 0 || tempInt <= 0 || tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX )
Kiet Lambe150c22013-11-21 16:30:32 +05304602 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004603
4604 *pChannel = tempInt;
4605
4606 /* point to the next argument */
4607 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4608 /*no argument after the command*/
4609 if (NULL == inPtr) return -EINVAL;
4610 /*removing empty spaces*/
4611 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4612
4613 /*no argument followed by spaces*/
4614 if ('\0' == *inPtr)
4615 {
4616 return -EINVAL;
4617 }
4618
4619 /*getting the next argument ie the dwell time */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004620 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004621 if (1 != v) return -EINVAL;
4622
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004623 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda5a6e0672014-01-09 14:42:57 -08004624 if ( v < 0 || tempInt < 0) return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004625
4626 *pDwellTime = tempInt;
4627
4628 /* point to the next argument */
4629 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4630 /*no argument after the command*/
4631 if (NULL == inPtr) return -EINVAL;
4632 /*removing empty spaces*/
4633 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4634
4635 /*no argument followed by spaces*/
4636 if ('\0' == *inPtr)
4637 {
4638 return -EINVAL;
4639 }
4640
4641 /* find the length of data */
4642 dataEnd = inPtr;
4643 while(('\0' != *dataEnd) )
4644 {
4645 dataEnd++;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004646 }
Kiet Lambe150c22013-11-21 16:30:32 +05304647 *pBufLen = dataEnd - inPtr ;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004648 if ( *pBufLen <= 0) return -EINVAL;
4649
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07004650 /* Allocate the number of bytes based on the number of input characters
4651 whether it is even or odd.
4652 if the number of input characters are even, then we need N/2 byte.
4653 if the number of input characters are odd, then we need do (N+1)/2 to
4654 compensate rounding off.
4655 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
4656 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
4657 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004658 if (NULL == *pBuf)
4659 {
4660 hddLog(VOS_TRACE_LEVEL_FATAL,
4661 "%s: vos_mem_alloc failed ", __func__);
4662 return -EINVAL;
4663 }
4664
4665 /* the buffer received from the upper layer is character buffer,
4666 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
4667 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
4668 and f0 in 3rd location */
4669 for (i = 0, j = 0; j < *pBufLen; j += 2)
4670 {
Kiet Lambe150c22013-11-21 16:30:32 +05304671 if( j+1 == *pBufLen)
4672 {
4673 tempByte = hdd_parse_hex(inPtr[j]);
4674 }
4675 else
4676 {
4677 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
4678 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004679 (*pBuf)[i++] = tempByte;
4680 }
4681 *pBufLen = i;
4682 return VOS_STATUS_SUCCESS;
4683}
4684
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004685/**---------------------------------------------------------------------------
4686
Srinivas Girigowdade697412013-02-14 16:31:48 -08004687 \brief hdd_parse_channellist() - HDD Parse channel list
4688
4689 This function parses the channel list passed in the format
4690 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004691 if the Number of channels (N) does not match with the actual number of channels passed
4692 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
4693 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
4694 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
4695 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08004696
4697 \param - pValue Pointer to input channel list
4698 \param - ChannelList Pointer to local output array to record channel list
4699 \param - pNumChannels Pointer to number of roam scan channels
4700
4701 \return - 0 for success non-zero for failure
4702
4703 --------------------------------------------------------------------------*/
4704VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
4705{
4706 tANI_U8 *inPtr = pValue;
4707 int tempInt;
4708 int j = 0;
4709 int v = 0;
4710 char buf[32];
4711
4712 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4713 /*no argument after the command*/
4714 if (NULL == inPtr)
4715 {
4716 return -EINVAL;
4717 }
4718
4719 /*no space after the command*/
4720 else if (SPACE_ASCII_VALUE != *inPtr)
4721 {
4722 return -EINVAL;
4723 }
4724
4725 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004726 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08004727
4728 /*no argument followed by spaces*/
4729 if ('\0' == *inPtr)
4730 {
4731 return -EINVAL;
4732 }
4733
4734 /*getting the first argument ie the number of channels*/
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004735 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004736 if (1 != v) return -EINVAL;
4737
Srinivas Girigowdade697412013-02-14 16:31:48 -08004738 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004739 if ((v < 0) ||
4740 (tempInt <= 0) ||
4741 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
4742 {
4743 return -EINVAL;
4744 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004745
4746 *pNumChannels = tempInt;
4747
4748 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
4749 "Number of channels are: %d", *pNumChannels);
4750
4751 for (j = 0; j < (*pNumChannels); j++)
4752 {
4753 /*inPtr pointing to the beginning of first space after number of channels*/
4754 inPtr = strpbrk( inPtr, " " );
4755 /*no channel list after the number of channels argument*/
4756 if (NULL == inPtr)
4757 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004758 if (0 != j)
4759 {
4760 *pNumChannels = j;
4761 return VOS_STATUS_SUCCESS;
4762 }
4763 else
4764 {
4765 return -EINVAL;
4766 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004767 }
4768
4769 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004770 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08004771
4772 /*no channel list after the number of channels argument and spaces*/
4773 if ( '\0' == *inPtr )
4774 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004775 if (0 != j)
4776 {
4777 *pNumChannels = j;
4778 return VOS_STATUS_SUCCESS;
4779 }
4780 else
4781 {
4782 return -EINVAL;
4783 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004784 }
4785
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004786 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004787 if (1 != v) return -EINVAL;
4788
Srinivas Girigowdade697412013-02-14 16:31:48 -08004789 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004790 if ((v < 0) ||
4791 (tempInt <= 0) ||
4792 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4793 {
4794 return -EINVAL;
4795 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004796 pChannelList[j] = tempInt;
4797
4798 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
4799 "Channel %d added to preferred channel list",
4800 pChannelList[j] );
4801 }
4802
Srinivas Girigowdade697412013-02-14 16:31:48 -08004803 return VOS_STATUS_SUCCESS;
4804}
4805
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004806
4807/**---------------------------------------------------------------------------
4808
4809 \brief hdd_parse_reassoc_command_data() - HDD Parse reassoc command data
4810
4811 This function parses the reasoc command data passed in the format
4812 REASSOC<space><bssid><space><channel>
4813
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004814 \param - pValue Pointer to input data (its a NUL terminated string)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004815 \param - pTargetApBssid Pointer to target Ap bssid
4816 \param - pChannel Pointer to the Target AP channel
4817
4818 \return - 0 for success non-zero for failure
4819
4820 --------------------------------------------------------------------------*/
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004821VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue,
4822 tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004823{
4824 tANI_U8 *inPtr = pValue;
4825 int tempInt;
4826 int v = 0;
4827 tANI_U8 tempBuf[32];
Kiet Lamaa8e15a2014-02-11 23:30:06 -08004828 /* 12 hexa decimal digits, 5 ':' and '\0' */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004829 tANI_U8 macAddress[18];
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004830
4831 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4832 /*no argument after the command*/
4833 if (NULL == inPtr)
4834 {
4835 return -EINVAL;
4836 }
4837
4838 /*no space after the command*/
4839 else if (SPACE_ASCII_VALUE != *inPtr)
4840 {
4841 return -EINVAL;
4842 }
4843
4844 /*removing empty spaces*/
4845 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4846
4847 /*no argument followed by spaces*/
4848 if ('\0' == *inPtr)
4849 {
4850 return -EINVAL;
4851 }
4852
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004853 v = sscanf(inPtr, "%17s", macAddress);
4854 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004855 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004856 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4857 "Invalid MAC address or All hex inputs are not read (%d)", v);
4858 return -EINVAL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004859 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004860
4861 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
4862 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
4863 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
4864 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
4865 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
4866 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004867
4868 /* point to the next argument */
4869 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4870 /*no argument after the command*/
4871 if (NULL == inPtr) return -EINVAL;
4872
4873 /*removing empty spaces*/
4874 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4875
4876 /*no argument followed by spaces*/
4877 if ('\0' == *inPtr)
4878 {
4879 return -EINVAL;
4880 }
4881
4882 /*getting the next argument ie the channel number */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004883 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004884 if (1 != v) return -EINVAL;
4885
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004886 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004887 if ((v < 0) ||
4888 (tempInt <= 0) ||
4889 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4890 {
4891 return -EINVAL;
4892 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004893
4894 *pChannel = tempInt;
4895 return VOS_STATUS_SUCCESS;
4896}
4897
4898#endif
4899
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004900#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004901/**---------------------------------------------------------------------------
4902
4903 \brief hdd_parse_get_cckm_ie() - HDD Parse and fetch the CCKM IE
4904
4905 This function parses the SETCCKM IE command
4906 SETCCKMIE<space><ie data>
4907
4908 \param - pValue Pointer to input data
4909 \param - pCckmIe Pointer to output cckm Ie
4910 \param - pCckmIeLen Pointer to output cckm ie length
4911
4912 \return - 0 for success non-zero for failure
4913
4914 --------------------------------------------------------------------------*/
4915VOS_STATUS hdd_parse_get_cckm_ie(tANI_U8 *pValue, tANI_U8 **pCckmIe,
4916 tANI_U8 *pCckmIeLen)
4917{
4918 tANI_U8 *inPtr = pValue;
4919 tANI_U8 *dataEnd;
4920 int j = 0;
4921 int i = 0;
4922 tANI_U8 tempByte = 0;
4923
4924 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4925 /*no argument after the command*/
4926 if (NULL == inPtr)
4927 {
4928 return -EINVAL;
4929 }
4930
4931 /*no space after the command*/
4932 else if (SPACE_ASCII_VALUE != *inPtr)
4933 {
4934 return -EINVAL;
4935 }
4936
4937 /*removing empty spaces*/
4938 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4939
4940 /*no argument followed by spaces*/
4941 if ('\0' == *inPtr)
4942 {
4943 return -EINVAL;
4944 }
4945
4946 /* find the length of data */
4947 dataEnd = inPtr;
4948 while(('\0' != *dataEnd) )
4949 {
4950 dataEnd++;
4951 ++(*pCckmIeLen);
4952 }
4953 if ( *pCckmIeLen <= 0) return -EINVAL;
4954
4955 /* Allocate the number of bytes based on the number of input characters
4956 whether it is even or odd.
4957 if the number of input characters are even, then we need N/2 byte.
4958 if the number of input characters are odd, then we need do (N+1)/2 to
4959 compensate rounding off.
4960 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
4961 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
4962 *pCckmIe = vos_mem_malloc((*pCckmIeLen + 1)/2);
4963 if (NULL == *pCckmIe)
4964 {
4965 hddLog(VOS_TRACE_LEVEL_FATAL,
4966 "%s: vos_mem_alloc failed ", __func__);
4967 return -EINVAL;
4968 }
4969 vos_mem_zero(*pCckmIe, (*pCckmIeLen + 1)/2);
4970 /* the buffer received from the upper layer is character buffer,
4971 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
4972 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
4973 and f0 in 3rd location */
4974 for (i = 0, j = 0; j < *pCckmIeLen; j += 2)
4975 {
4976 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
4977 (*pCckmIe)[i++] = tempByte;
4978 }
4979 *pCckmIeLen = i;
4980
4981 return VOS_STATUS_SUCCESS;
4982}
Varun Reddy Yeturu5d5e2c62014-02-27 13:31:29 -08004983#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004984
Jeff Johnson295189b2012-06-20 16:38:30 -07004985/**---------------------------------------------------------------------------
4986
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004987 \brief hdd_is_valid_mac_address() - Validate MAC address
4988
4989 This function validates whether the given MAC address is valid or not
4990 Expected MAC address is of the format XX:XX:XX:XX:XX:XX
4991 where X is the hexa decimal digit character and separated by ':'
4992 This algorithm works even if MAC address is not separated by ':'
4993
4994 This code checks given input string mac contains exactly 12 hexadecimal digits.
4995 and a separator colon : appears in the input string only after
4996 an even number of hex digits.
4997
4998 \param - pMacAddr pointer to the input MAC address
4999 \return - 1 for valid and 0 for invalid
5000
5001 --------------------------------------------------------------------------*/
5002
5003v_BOOL_t hdd_is_valid_mac_address(const tANI_U8 *pMacAddr)
5004{
5005 int xdigit = 0;
5006 int separator = 0;
5007 while (*pMacAddr)
5008 {
5009 if (isxdigit(*pMacAddr))
5010 {
5011 xdigit++;
5012 }
5013 else if (':' == *pMacAddr)
5014 {
5015 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
5016 break;
5017
5018 ++separator;
5019 }
5020 else
5021 {
5022 separator = -1;
5023 /* Invalid MAC found */
5024 return 0;
5025 }
5026 ++pMacAddr;
5027 }
5028 return (xdigit == 12 && (separator == 5 || separator == 0));
5029}
5030
5031/**---------------------------------------------------------------------------
5032
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305033 \brief __hdd_open() - HDD Open function
Jeff Johnson295189b2012-06-20 16:38:30 -07005034
5035 \param - dev Pointer to net_device structure
5036
5037 \return - 0 for success non-zero for failure
5038
5039 --------------------------------------------------------------------------*/
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305040int __hdd_open(struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07005041{
5042 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5043 hdd_context_t *pHddCtx;
5044 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5045 VOS_STATUS status;
5046 v_BOOL_t in_standby = TRUE;
5047
5048 if (NULL == pAdapter)
5049 {
5050 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Agarwal Ashish971c2882013-10-30 20:11:12 +05305051 "%s: pAdapter is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005052 return -ENODEV;
5053 }
5054
5055 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05305056 MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_OPEN_REQUEST,
5057 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson295189b2012-06-20 16:38:30 -07005058 if (NULL == pHddCtx)
5059 {
5060 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005061 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005062 return -ENODEV;
5063 }
5064
5065 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5066 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
5067 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07005068 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
5069 {
5070 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305071 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07005072 in_standby = FALSE;
5073 break;
5074 }
5075 else
5076 {
5077 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5078 pAdapterNode = pNext;
5079 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005080 }
5081
5082 if (TRUE == in_standby)
5083 {
5084 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
5085 {
5086 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
5087 "wlan out of power save", __func__);
5088 return -EINVAL;
5089 }
5090 }
5091
Jeff Johnson6a81ca42013-04-05 10:37:08 -07005092 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07005093 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
5094 {
5095 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005096 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005097 /* Enable TX queues only when we are connected */
5098 netif_tx_start_all_queues(dev);
5099 }
5100
5101 return 0;
5102}
5103
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305104/**---------------------------------------------------------------------------
5105
5106 \brief hdd_open() - Wrapper function for __hdd_open to protect it from SSR
5107
5108 This is called in response to ifconfig up
5109
5110 \param - dev Pointer to net_device structure
5111
5112 \return - 0 for success non-zero for failure
5113
5114 --------------------------------------------------------------------------*/
5115int hdd_open(struct net_device *dev)
5116{
5117 int ret;
5118
5119 vos_ssr_protect(__func__);
5120 ret = __hdd_open(dev);
5121 vos_ssr_unprotect(__func__);
5122
5123 return ret;
5124}
5125
Jeff Johnson295189b2012-06-20 16:38:30 -07005126int hdd_mon_open (struct net_device *dev)
5127{
5128 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5129
5130 if(pAdapter == NULL) {
5131 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005132 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08005133 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005134 }
5135
5136 netif_start_queue(dev);
5137
5138 return 0;
5139}
5140/**---------------------------------------------------------------------------
5141
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305142 \brief __hdd_stop() - HDD stop function
Jeff Johnson295189b2012-06-20 16:38:30 -07005143
5144 \param - dev Pointer to net_device structure
5145
5146 \return - 0 for success non-zero for failure
5147
5148 --------------------------------------------------------------------------*/
5149
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305150int __hdd_stop (struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07005151{
5152 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5153 hdd_context_t *pHddCtx;
5154 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5155 VOS_STATUS status;
5156 v_BOOL_t enter_standby = TRUE;
5157
5158 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07005159 if (NULL == pAdapter)
5160 {
5161 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Agarwal Ashish971c2882013-10-30 20:11:12 +05305162 "%s: pAdapter is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005163 return -ENODEV;
5164 }
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05305165 MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_OPEN_REQUEST,
5166 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson295189b2012-06-20 16:38:30 -07005167 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
5168 if (NULL == pHddCtx)
5169 {
5170 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005171 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005172 return -ENODEV;
5173 }
5174
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05305175 /* Nothing to be done if the interface is not opened */
5176 if (VOS_FALSE == test_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags))
5177 {
5178 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5179 "%s: NETDEV Interface is not OPENED", __func__);
5180 return -ENODEV;
5181 }
5182
5183 /* Make sure the interface is marked as closed */
Jeff Johnson6a81ca42013-04-05 10:37:08 -07005184 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07005185 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05305186
5187 /* Disable TX on the interface, after this hard_start_xmit() will not
5188 * be called on that interface
5189 */
Jeff Johnson295189b2012-06-20 16:38:30 -07005190 netif_tx_disable(pAdapter->dev);
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05305191
5192 /* Mark the interface status as "down" for outside world */
Jeff Johnson295189b2012-06-20 16:38:30 -07005193 netif_carrier_off(pAdapter->dev);
5194
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05305195 /* The interface is marked as down for outside world (aka kernel)
5196 * But the driver is pretty much alive inside. The driver needs to
5197 * tear down the existing connection on the netdev (session)
5198 * cleanup the data pipes and wait until the control plane is stabilized
5199 * for this interface. The call also needs to wait until the above
5200 * mentioned actions are completed before returning to the caller.
5201 * Notice that the hdd_stop_adapter is requested not to close the session
5202 * That is intentional to be able to scan if it is a STA/P2P interface
5203 */
5204 hdd_stop_adapter(pHddCtx, pAdapter, VOS_FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -07005205
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05305206 /* DeInit the adapter. This ensures datapath cleanup as well */
5207 hdd_deinit_adapter(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005208 /* SoftAP ifaces should never go in power save mode
5209 making sure same here. */
5210 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
5211 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07005212 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07005213 )
5214 {
5215 /* SoftAP mode, so return from here */
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305216 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5217 "%s: In SAP MODE", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005218 EXIT();
5219 return 0;
5220 }
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05305221 /* Find if any iface is up. If any iface is up then can't put device to
5222 * sleep/power save mode
5223 */
Jeff Johnson295189b2012-06-20 16:38:30 -07005224 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5225 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
5226 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07005227 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
5228 {
5229 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05305230 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07005231 enter_standby = FALSE;
5232 break;
5233 }
5234 else
5235 {
5236 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5237 pAdapterNode = pNext;
5238 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005239 }
5240
5241 if (TRUE == enter_standby)
5242 {
5243 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
5244 "entering standby", __func__);
5245 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
5246 {
5247 /*log and return success*/
5248 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
5249 "wlan in power save", __func__);
5250 }
5251 }
5252
5253 EXIT();
5254 return 0;
5255}
5256
5257/**---------------------------------------------------------------------------
5258
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305259 \brief hdd_stop() - wrapper_function for __hdd_stop to protect it from SSR
Jeff Johnson295189b2012-06-20 16:38:30 -07005260
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305261 This is called in response to ifconfig down
5262
5263 \param - dev Pointer to net_device structure
5264
5265 \return - 0 for success non-zero for failure
5266-----------------------------------------------------------------------------*/
5267int hdd_stop (struct net_device *dev)
5268{
5269 int ret;
5270
5271 vos_ssr_protect(__func__);
5272 ret = __hdd_stop(dev);
5273 vos_ssr_unprotect(__func__);
5274
5275 return ret;
5276}
5277
5278/**---------------------------------------------------------------------------
5279
5280 \brief __hdd_uninit() - HDD uninit function
Jeff Johnson295189b2012-06-20 16:38:30 -07005281
5282 \param - dev Pointer to net_device structure
5283
5284 \return - void
5285
5286 --------------------------------------------------------------------------*/
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305287static void __hdd_uninit (struct net_device *dev)
Jeff Johnson295189b2012-06-20 16:38:30 -07005288{
5289 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5290
5291 ENTER();
5292
5293 do
5294 {
5295 if (NULL == pAdapter)
5296 {
5297 hddLog(VOS_TRACE_LEVEL_FATAL,
5298 "%s: NULL pAdapter", __func__);
5299 break;
5300 }
5301
5302 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
5303 {
5304 hddLog(VOS_TRACE_LEVEL_FATAL,
5305 "%s: Invalid magic", __func__);
5306 break;
5307 }
5308
5309 if (NULL == pAdapter->pHddCtx)
5310 {
5311 hddLog(VOS_TRACE_LEVEL_FATAL,
5312 "%s: NULL pHddCtx", __func__);
5313 break;
5314 }
5315
5316 if (dev != pAdapter->dev)
5317 {
5318 hddLog(VOS_TRACE_LEVEL_FATAL,
5319 "%s: Invalid device reference", __func__);
5320 /* we haven't validated all cases so let this go for now */
5321 }
5322
5323 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
5324
5325 /* after uninit our adapter structure will no longer be valid */
5326 pAdapter->dev = NULL;
5327 pAdapter->magic = 0;
5328 } while (0);
5329
5330 EXIT();
5331}
5332
5333/**---------------------------------------------------------------------------
5334
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305335 \brief hdd_uninit() - Wrapper function to protect __hdd_uninit from SSR
5336
5337 This is called during the netdev unregister to uninitialize all data
5338associated with the device
5339
5340 \param - dev Pointer to net_device structure
5341
5342 \return - void
5343
5344 --------------------------------------------------------------------------*/
5345static void hdd_uninit (struct net_device *dev)
5346{
5347 vos_ssr_protect(__func__);
5348 __hdd_uninit(dev);
5349 vos_ssr_unprotect(__func__);
5350}
5351
5352/**---------------------------------------------------------------------------
5353
Jeff Johnson295189b2012-06-20 16:38:30 -07005354 \brief hdd_release_firmware() -
5355
5356 This function calls the release firmware API to free the firmware buffer.
5357
5358 \param - pFileName Pointer to the File Name.
5359 pCtx - Pointer to the adapter .
5360
5361
5362 \return - 0 for success, non zero for failure
5363
5364 --------------------------------------------------------------------------*/
5365
5366VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
5367{
5368 VOS_STATUS status = VOS_STATUS_SUCCESS;
5369 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
5370 ENTER();
5371
5372
5373 if (!strcmp(WLAN_FW_FILE, pFileName)) {
5374
5375 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
5376
5377 if(pHddCtx->fw) {
5378 release_firmware(pHddCtx->fw);
5379 pHddCtx->fw = NULL;
5380 }
5381 else
5382 status = VOS_STATUS_E_FAILURE;
5383 }
5384 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
5385 if(pHddCtx->nv) {
5386 release_firmware(pHddCtx->nv);
5387 pHddCtx->nv = NULL;
5388 }
5389 else
5390 status = VOS_STATUS_E_FAILURE;
5391
5392 }
5393
5394 EXIT();
5395 return status;
5396}
5397
5398/**---------------------------------------------------------------------------
5399
5400 \brief hdd_request_firmware() -
5401
5402 This function reads the firmware file using the request firmware
5403 API and returns the the firmware data and the firmware file size.
5404
5405 \param - pfileName - Pointer to the file name.
5406 - pCtx - Pointer to the adapter .
5407 - ppfw_data - Pointer to the pointer of the firmware data.
5408 - pSize - Pointer to the file size.
5409
5410 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
5411
5412 --------------------------------------------------------------------------*/
5413
5414
5415VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
5416{
5417 int status;
5418 VOS_STATUS retval = VOS_STATUS_SUCCESS;
5419 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
5420 ENTER();
5421
5422 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
5423
5424 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
5425
5426 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
5427 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
5428 __func__, pfileName);
5429 retval = VOS_STATUS_E_FAILURE;
5430 }
5431
5432 else {
5433 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
5434 *pSize = pHddCtx->fw->size;
5435 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
5436 __func__, *pSize);
5437 }
5438 }
5439 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
5440
5441 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
5442
5443 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
5444 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
5445 __func__, pfileName);
5446 retval = VOS_STATUS_E_FAILURE;
5447 }
5448
5449 else {
5450 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
5451 *pSize = pHddCtx->nv->size;
5452 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
5453 __func__, *pSize);
5454 }
5455 }
5456
5457 EXIT();
5458 return retval;
5459}
5460/**---------------------------------------------------------------------------
5461 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
5462
5463 This is the function invoked by SME to inform the result of a full power
5464 request issued by HDD
5465
5466 \param - callbackcontext - Pointer to cookie
5467 status - result of request
5468
5469 \return - None
5470
5471--------------------------------------------------------------------------*/
5472void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
5473{
5474 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
5475
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07005476 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07005477 if(&pHddCtx->full_pwr_comp_var)
5478 {
5479 complete(&pHddCtx->full_pwr_comp_var);
5480 }
5481}
5482
5483/**---------------------------------------------------------------------------
5484
5485 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
5486
5487 This is the function invoked by SME to inform the result of BMPS
5488 request issued by HDD
5489
5490 \param - callbackcontext - Pointer to cookie
5491 status - result of request
5492
5493 \return - None
5494
5495--------------------------------------------------------------------------*/
5496void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
5497{
5498
5499 struct completion *completion_var = (struct completion*) callbackContext;
5500
Arif Hussain6d2a3322013-11-17 19:50:10 -08005501 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07005502 if(completion_var != NULL)
5503 {
5504 complete(completion_var);
5505 }
5506}
5507
5508/**---------------------------------------------------------------------------
5509
5510 \brief hdd_get_cfg_file_size() -
5511
5512 This function reads the configuration file using the request firmware
5513 API and returns the configuration file size.
5514
5515 \param - pCtx - Pointer to the adapter .
5516 - pFileName - Pointer to the file name.
5517 - pBufSize - Pointer to the buffer size.
5518
5519 \return - 0 for success, non zero for failure
5520
5521 --------------------------------------------------------------------------*/
5522
5523VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
5524{
5525 int status;
5526 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
5527
5528 ENTER();
5529
5530 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
5531
5532 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
5533 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
5534 status = VOS_STATUS_E_FAILURE;
5535 }
5536 else {
5537 *pBufSize = pHddCtx->fw->size;
5538 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
5539 release_firmware(pHddCtx->fw);
5540 pHddCtx->fw = NULL;
5541 }
5542
5543 EXIT();
5544 return VOS_STATUS_SUCCESS;
5545}
5546
5547/**---------------------------------------------------------------------------
5548
5549 \brief hdd_read_cfg_file() -
5550
5551 This function reads the configuration file using the request firmware
5552 API and returns the cfg data and the buffer size of the configuration file.
5553
5554 \param - pCtx - Pointer to the adapter .
5555 - pFileName - Pointer to the file name.
5556 - pBuffer - Pointer to the data buffer.
5557 - pBufSize - Pointer to the buffer size.
5558
5559 \return - 0 for success, non zero for failure
5560
5561 --------------------------------------------------------------------------*/
5562
5563VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
5564 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
5565{
5566 int status;
5567 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
5568
5569 ENTER();
5570
5571 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
5572
5573 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
5574 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
5575 return VOS_STATUS_E_FAILURE;
5576 }
5577 else {
5578 if(*pBufSize != pHddCtx->fw->size) {
5579 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
5580 "file size", __func__);
5581 release_firmware(pHddCtx->fw);
5582 pHddCtx->fw = NULL;
5583 return VOS_STATUS_E_FAILURE;
5584 }
5585 else {
5586 if(pBuffer) {
5587 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
5588 }
5589 release_firmware(pHddCtx->fw);
5590 pHddCtx->fw = NULL;
5591 }
5592 }
5593
5594 EXIT();
5595
5596 return VOS_STATUS_SUCCESS;
5597}
5598
5599/**---------------------------------------------------------------------------
5600
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305601 \brief __hdd_set_mac_address() -
Jeff Johnson295189b2012-06-20 16:38:30 -07005602
5603 This function sets the user specified mac address using
5604 the command ifconfig wlanX hw ether <mac adress>.
5605
5606 \param - dev - Pointer to the net device.
5607 - addr - Pointer to the sockaddr.
5608 \return - 0 for success, non zero for failure
5609
5610 --------------------------------------------------------------------------*/
5611
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305612static int __hdd_set_mac_address(struct net_device *dev, void *addr)
Jeff Johnson295189b2012-06-20 16:38:30 -07005613{
5614 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5615 struct sockaddr *psta_mac_addr = addr;
5616 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5617
5618 ENTER();
5619
5620 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
Jeff Johnson295189b2012-06-20 16:38:30 -07005621 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
5622
5623 EXIT();
5624 return halStatus;
5625}
5626
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05305627/**---------------------------------------------------------------------------
5628
5629 \brief hdd_set_mac_address() -
5630
5631 Wrapper function to protect __hdd_set_mac_address() function from ssr
5632
5633 \param - dev - Pointer to the net device.
5634 - addr - Pointer to the sockaddr.
5635 \return - 0 for success, non zero for failure
5636
5637 --------------------------------------------------------------------------*/
5638static int hdd_set_mac_address(struct net_device *dev, void *addr)
5639{
5640 int ret;
5641
5642 vos_ssr_protect(__func__);
5643 ret = __hdd_set_mac_address(dev, addr);
5644 vos_ssr_unprotect(__func__);
5645
5646 return ret;
5647}
5648
Jeff Johnson295189b2012-06-20 16:38:30 -07005649tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
5650{
5651 int i;
5652 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5653 {
Abhishek Singheb183782014-02-06 13:37:21 +05305654 if( 0 == ((pHddCtx->cfg_ini->intfAddrMask) & (1 << i)) )
Jeff Johnson295189b2012-06-20 16:38:30 -07005655 break;
5656 }
5657
5658 if( VOS_MAX_CONCURRENCY_PERSONA == i)
5659 return NULL;
5660
5661 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
5662 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
5663}
5664
5665void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
5666{
5667 int i;
5668 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5669 {
5670 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
5671 {
5672 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
5673 break;
5674 }
5675 }
5676 return;
5677}
5678
5679#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
5680 static struct net_device_ops wlan_drv_ops = {
5681 .ndo_open = hdd_open,
5682 .ndo_stop = hdd_stop,
5683 .ndo_uninit = hdd_uninit,
5684 .ndo_start_xmit = hdd_hard_start_xmit,
5685 .ndo_tx_timeout = hdd_tx_timeout,
5686 .ndo_get_stats = hdd_stats,
5687 .ndo_do_ioctl = hdd_ioctl,
5688 .ndo_set_mac_address = hdd_set_mac_address,
5689 .ndo_select_queue = hdd_select_queue,
5690#ifdef WLAN_FEATURE_PACKET_FILTERING
5691#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
5692 .ndo_set_rx_mode = hdd_set_multicast_list,
5693#else
5694 .ndo_set_multicast_list = hdd_set_multicast_list,
5695#endif //LINUX_VERSION_CODE
5696#endif
5697 };
Jeff Johnson295189b2012-06-20 16:38:30 -07005698 static struct net_device_ops wlan_mon_drv_ops = {
5699 .ndo_open = hdd_mon_open,
5700 .ndo_stop = hdd_stop,
5701 .ndo_uninit = hdd_uninit,
5702 .ndo_start_xmit = hdd_mon_hard_start_xmit,
5703 .ndo_tx_timeout = hdd_tx_timeout,
5704 .ndo_get_stats = hdd_stats,
5705 .ndo_do_ioctl = hdd_ioctl,
5706 .ndo_set_mac_address = hdd_set_mac_address,
5707 };
Jeff Johnson295189b2012-06-20 16:38:30 -07005708
5709#endif
5710
5711void hdd_set_station_ops( struct net_device *pWlanDev )
5712{
5713#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
Jeff Johnson295189b2012-06-20 16:38:30 -07005714 pWlanDev->netdev_ops = &wlan_drv_ops;
5715#else
5716 pWlanDev->open = hdd_open;
5717 pWlanDev->stop = hdd_stop;
5718 pWlanDev->uninit = hdd_uninit;
5719 pWlanDev->hard_start_xmit = NULL;
5720 pWlanDev->tx_timeout = hdd_tx_timeout;
5721 pWlanDev->get_stats = hdd_stats;
5722 pWlanDev->do_ioctl = hdd_ioctl;
Jeff Johnson295189b2012-06-20 16:38:30 -07005723 pWlanDev->set_mac_address = hdd_set_mac_address;
5724#endif
5725}
5726
Jeff Johnsoneed415b2013-01-18 16:11:20 -08005727static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07005728{
5729 struct net_device *pWlanDev = NULL;
5730 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005731 /*
5732 * cfg80211 initialization and registration....
5733 */
5734 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
5735
Jeff Johnson295189b2012-06-20 16:38:30 -07005736 if(pWlanDev != NULL)
5737 {
5738
5739 //Save the pointer to the net_device in the HDD adapter
5740 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
5741
Jeff Johnson295189b2012-06-20 16:38:30 -07005742 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
5743
5744 pAdapter->dev = pWlanDev;
5745 pAdapter->pHddCtx = pHddCtx;
5746 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
Agarwal Ashish47d18112014-08-04 19:55:07 +05305747 spin_lock_init(&pAdapter->lock_for_active_session);
Jeff Johnson295189b2012-06-20 16:38:30 -07005748
5749 init_completion(&pAdapter->session_open_comp_var);
5750 init_completion(&pAdapter->session_close_comp_var);
5751 init_completion(&pAdapter->disconnect_comp_var);
5752 init_completion(&pAdapter->linkup_event_var);
5753 init_completion(&pAdapter->cancel_rem_on_chan_var);
5754 init_completion(&pAdapter->rem_on_chan_ready_event);
Vinay Krishna Erannaf0e523b2014-03-01 21:00:16 +05305755 init_completion(&pAdapter->pno_comp_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07005756#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
5757 init_completion(&pAdapter->offchannel_tx_event);
5758#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005759 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005760#ifdef FEATURE_WLAN_TDLS
5761 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07005762 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08005763 init_completion(&pAdapter->tdls_mgmt_comp);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05305764 init_completion(&pAdapter->tdls_link_establish_req_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005765#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005766 init_completion(&pHddCtx->mc_sus_event_var);
5767 init_completion(&pHddCtx->tx_sus_event_var);
Gopichand Nakkala05621412013-06-19 19:37:38 +05305768 init_completion(&pHddCtx->rx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07005769 init_completion(&pAdapter->ula_complete);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07005770 init_completion(&pAdapter->change_country_code);
Jeff Johnson295189b2012-06-20 16:38:30 -07005771
Rajeev79dbe4c2013-10-05 11:03:42 +05305772#ifdef FEATURE_WLAN_BATCH_SCAN
5773 init_completion(&pAdapter->hdd_set_batch_scan_req_var);
5774 init_completion(&pAdapter->hdd_get_batch_scan_req_var);
5775 pAdapter->pBatchScanRsp = NULL;
5776 pAdapter->numScanList = 0;
Rajeev Kumar20140c12013-10-21 19:39:02 -07005777 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
Kiet Lamaa8e15a2014-02-11 23:30:06 -08005778 pAdapter->prev_batch_id = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05305779 mutex_init(&pAdapter->hdd_batch_scan_lock);
5780#endif
5781
Jeff Johnson295189b2012-06-20 16:38:30 -07005782 pAdapter->isLinkUpSvcNeeded = FALSE;
5783 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
5784 //Init the net_device structure
5785 strlcpy(pWlanDev->name, name, IFNAMSIZ);
5786
5787 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
5788 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
5789 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
5790 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
5791
5792 hdd_set_station_ops( pAdapter->dev );
5793
5794 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07005795 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
5796 pAdapter->wdev.wiphy = pHddCtx->wiphy;
5797 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07005798 /* set pWlanDev's parent to underlying device */
5799 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
Kumar Anand82c009f2014-05-29 00:29:42 -07005800
5801 hdd_wmm_init( pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07005802 }
5803
5804 return pAdapter;
5805}
5806
5807VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
5808{
5809 struct net_device *pWlanDev = pAdapter->dev;
5810 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
5811 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
5812 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5813
5814 if( rtnl_lock_held )
5815 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08005816 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07005817 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
5818 {
5819 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
5820 return VOS_STATUS_E_FAILURE;
5821 }
5822 }
5823 if (register_netdevice(pWlanDev))
5824 {
5825 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
5826 return VOS_STATUS_E_FAILURE;
5827 }
5828 }
5829 else
5830 {
5831 if(register_netdev(pWlanDev))
5832 {
5833 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
5834 return VOS_STATUS_E_FAILURE;
5835 }
5836 }
5837 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
5838
5839 return VOS_STATUS_SUCCESS;
5840}
5841
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005842static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07005843{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005844 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07005845
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005846 if (NULL == pAdapter)
5847 {
5848 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
5849 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07005850 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005851
5852 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
5853 {
5854 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
5855 return eHAL_STATUS_NOT_INITIALIZED;
5856 }
5857
5858 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
5859
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005860#ifndef WLAN_OPEN_SOURCE
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005861 /* need to make sure all of our scheduled work has completed.
5862 * This callback is called from MC thread context, so it is safe to
5863 * to call below flush workqueue API from here.
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005864 *
5865 * Even though this is called from MC thread context, if there is a faulty
5866 * work item in the system, that can hang this call forever. So flushing
5867 * this global work queue is not safe; and now we make sure that
5868 * individual work queues are stopped correctly. But the cancel work queue
5869 * is a GPL only API, so the proprietary version of the driver would still
5870 * rely on the global work queue flush.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005871 */
5872 flush_scheduled_work();
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005873#endif
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005874
5875 /* We can be blocked while waiting for scheduled work to be
5876 * flushed, and the adapter structure can potentially be freed, in
5877 * which case the magic will have been reset. So make sure the
5878 * magic is still good, and hence the adapter structure is still
5879 * valid, before signaling completion */
5880 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
5881 {
5882 complete(&pAdapter->session_close_comp_var);
5883 }
5884
Jeff Johnson295189b2012-06-20 16:38:30 -07005885 return eHAL_STATUS_SUCCESS;
5886}
5887
5888VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
5889{
5890 struct net_device *pWlanDev = pAdapter->dev;
5891 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
5892 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
5893 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5894 VOS_STATUS status = VOS_STATUS_E_FAILURE;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305895 long rc = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07005896
5897 INIT_COMPLETION(pAdapter->session_open_comp_var);
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07005898 sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07005899 //Open a SME session for future operation
5900 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07005901 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07005902 if ( !HAL_STATUS_SUCCESS( halStatus ) )
5903 {
5904 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005905 "sme_OpenSession() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005906 halStatus, halStatus );
5907 status = VOS_STATUS_E_FAILURE;
5908 goto error_sme_open;
5909 }
5910
5911 //Block on a completion variable. Can't wait forever though.
Vinay Krishna Eranna0fe2e7c2014-04-09 21:32:08 +05305912 rc = wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07005913 &pAdapter->session_open_comp_var,
5914 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305915 if (rc <= 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07005916 {
5917 hddLog(VOS_TRACE_LEVEL_FATAL,
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305918 "Session is not opened within timeout period code %ld", rc );
Jeff Johnson295189b2012-06-20 16:38:30 -07005919 status = VOS_STATUS_E_FAILURE;
5920 goto error_sme_open;
5921 }
5922
5923 // Register wireless extensions
5924 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
5925 {
5926 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005927 "hdd_register_wext() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005928 halStatus, halStatus );
5929 status = VOS_STATUS_E_FAILURE;
5930 goto error_register_wext;
5931 }
5932 //Safe to register the hard_start_xmit function again
5933#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
5934 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
5935#else
5936 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
5937#endif
5938
5939 //Set the Connection State to Not Connected
Abhishek Singhf4669da2014-05-26 15:07:49 +05305940 hddLog(VOS_TRACE_LEVEL_INFO,
5941 "%s: Set HDD connState to eConnectionState_NotConnected",
5942 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005943 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
5944
5945 //Set the default operation channel
5946 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
5947
5948 /* Make the default Auth Type as OPEN*/
5949 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
5950
5951 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
5952 {
5953 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005954 "hdd_init_tx_rx() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005955 status, status );
5956 goto error_init_txrx;
5957 }
5958
5959 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5960
5961 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
5962 {
5963 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005964 "hdd_wmm_adapter_init() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005965 status, status );
5966 goto error_wmm_init;
5967 }
5968
5969 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5970
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005971#ifdef FEATURE_WLAN_TDLS
Agarwal Ashish4b87f922014-06-18 03:03:21 +05305972 if(0 != wlan_hdd_sta_tdls_init(pAdapter))
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005973 {
5974 status = VOS_STATUS_E_FAILURE;
Agarwal Ashish4b87f922014-06-18 03:03:21 +05305975 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_sta_tdls_init failed",__func__);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005976 goto error_tdls_init;
5977 }
5978 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
5979#endif
5980
Jeff Johnson295189b2012-06-20 16:38:30 -07005981 return VOS_STATUS_SUCCESS;
5982
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005983#ifdef FEATURE_WLAN_TDLS
5984error_tdls_init:
5985 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5986 hdd_wmm_adapter_close(pAdapter);
5987#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005988error_wmm_init:
5989 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5990 hdd_deinit_tx_rx(pAdapter);
5991error_init_txrx:
5992 hdd_UnregisterWext(pWlanDev);
5993error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005994 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07005995 {
5996 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005997 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07005998 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005999 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07006000 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306001 unsigned long rc;
6002
Jeff Johnson295189b2012-06-20 16:38:30 -07006003 //Block on a completion variable. Can't wait forever though.
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306004 rc = wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07006005 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07006006 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306007 if (rc <= 0)
6008 hddLog(VOS_TRACE_LEVEL_ERROR,
6009 FL("Session is not opened within timeout period code %ld"), rc);
Jeff Johnson295189b2012-06-20 16:38:30 -07006010 }
6011}
6012error_sme_open:
6013 return status;
6014}
6015
Jeff Johnson295189b2012-06-20 16:38:30 -07006016void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
6017{
6018 hdd_cfg80211_state_t *cfgState;
6019
6020 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
6021
6022 if( NULL != cfgState->buf )
6023 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306024 long rc;
Jeff Johnson295189b2012-06-20 16:38:30 -07006025 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
6026 rc = wait_for_completion_interruptible_timeout(
6027 &pAdapter->tx_action_cnf_event,
6028 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306029 if (rc <= 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07006030 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08006031 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306032 "%s ERROR: HDD Wait for Action Confirmation Failed!! %ld"
6033 , __func__, rc);
Jeff Johnson295189b2012-06-20 16:38:30 -07006034 }
6035 }
6036 return;
6037}
Jeff Johnson295189b2012-06-20 16:38:30 -07006038
6039void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
6040{
6041 ENTER();
6042 switch ( pAdapter->device_mode )
6043 {
6044 case WLAN_HDD_INFRA_STATION:
6045 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006046 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07006047 {
6048 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
6049 {
6050 hdd_deinit_tx_rx( pAdapter );
6051 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
6052 }
6053
6054 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
6055 {
6056 hdd_wmm_adapter_close( pAdapter );
6057 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
6058 }
6059
Jeff Johnson295189b2012-06-20 16:38:30 -07006060 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08006061#ifdef FEATURE_WLAN_TDLS
6062 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
6063 {
6064 wlan_hdd_tdls_exit(pAdapter);
6065 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
6066 }
6067#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006068
6069 break;
6070 }
6071
6072 case WLAN_HDD_SOFTAP:
6073 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07006074 {
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05306075
6076 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
6077 {
6078 hdd_wmm_adapter_close( pAdapter );
6079 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
6080 }
6081
Jeff Johnson295189b2012-06-20 16:38:30 -07006082 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07006083
6084 hdd_unregister_hostapd(pAdapter);
6085 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07006086 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07006087 break;
6088 }
6089
6090 case WLAN_HDD_MONITOR:
6091 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006092 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07006093 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
6094 {
6095 hdd_deinit_tx_rx( pAdapter );
6096 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
6097 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006098 if(NULL != pAdapterforTx)
6099 {
6100 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
6101 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006102 break;
6103 }
6104
6105
6106 default:
6107 break;
6108 }
6109
6110 EXIT();
6111}
6112
6113void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
6114{
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -08006115 struct net_device *pWlanDev = NULL;
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05306116
6117 ENTER();
6118 if (NULL == pAdapter)
6119 {
6120 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6121 "%s: HDD adapter is Null", __func__);
6122 return;
6123 }
6124
6125 pWlanDev = pAdapter->dev;
Jeff Johnson295189b2012-06-20 16:38:30 -07006126
Rajeev79dbe4c2013-10-05 11:03:42 +05306127#ifdef FEATURE_WLAN_BATCH_SCAN
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05306128 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
6129 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Rajeev Kumarf999e582014-01-09 17:33:29 -08006130 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05306131 || (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)
6132 )
6133 {
Rajeev Kumarf999e582014-01-09 17:33:29 -08006134 if (pAdapter)
Rajeev79dbe4c2013-10-05 11:03:42 +05306135 {
Rajeev Kumarf999e582014-01-09 17:33:29 -08006136 if (eHDD_BATCH_SCAN_STATE_STARTED == pAdapter->batchScanState)
6137 {
6138 hdd_deinit_batch_scan(pAdapter);
6139 }
Rajeev79dbe4c2013-10-05 11:03:42 +05306140 }
Rajeev Kumarf999e582014-01-09 17:33:29 -08006141 }
Rajeev79dbe4c2013-10-05 11:03:42 +05306142#endif
6143
Jeff Johnson295189b2012-06-20 16:38:30 -07006144 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
6145 if( rtnl_held )
6146 {
6147 unregister_netdevice(pWlanDev);
6148 }
6149 else
6150 {
6151 unregister_netdev(pWlanDev);
6152 }
6153 // note that the pAdapter is no longer valid at this point
6154 // since the memory has been reclaimed
6155 }
6156
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05306157 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07006158}
6159
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006160void hdd_set_pwrparams(hdd_context_t *pHddCtx)
6161{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306162 VOS_STATUS status;
6163 hdd_adapter_t *pAdapter = NULL;
6164 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006165
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306166 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006167
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306168 /*loop through all adapters.*/
6169 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006170 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306171 pAdapter = pAdapterNode->pAdapter;
6172 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
6173 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006174
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306175 { // we skip this registration for modes other than STA and P2P client modes.
6176 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6177 pAdapterNode = pNext;
6178 continue;
6179 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006180
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306181 //Apply Dynamic DTIM For P2P
6182 //Only if ignoreDynamicDtimInP2pMode is not set in ini
6183 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
6184 pHddCtx->cfg_ini->enableModulatedDTIM) &&
6185 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
6186 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
6187 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
6188 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
6189 (eConnectionState_Associated ==
6190 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
6191 (pHddCtx->cfg_ini->fIsBmpsEnabled))
6192 {
6193 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006194
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306195 powerRequest.uIgnoreDTIM = 1;
6196 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
6197
6198 if (pHddCtx->cfg_ini->enableModulatedDTIM)
6199 {
6200 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
6201 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
6202 }
6203 else
6204 {
6205 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
6206 }
6207
6208 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
6209 * specified during Enter/Exit BMPS when LCD off*/
6210 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
6211 NULL, eANI_BOOLEAN_FALSE);
6212 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
6213 NULL, eANI_BOOLEAN_FALSE);
6214
6215 /* switch to the DTIM specified in cfg.ini */
6216 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6217 "Switch to DTIM %d", powerRequest.uListenInterval);
6218 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
6219 break;
6220
6221 }
6222
6223 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6224 pAdapterNode = pNext;
6225 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006226}
6227
6228void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
6229{
6230 /*Switch back to DTIM 1*/
6231 tSirSetPowerParamsReq powerRequest = { 0 };
6232
6233 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
6234 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07006235 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08006236
6237 /* Update ignoreDTIM and ListedInterval in CFG with default values */
6238 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
6239 NULL, eANI_BOOLEAN_FALSE);
6240 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
6241 NULL, eANI_BOOLEAN_FALSE);
6242
6243 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
6244 "Switch to DTIM%d",powerRequest.uListenInterval);
6245 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
6246
6247}
6248
Jeff Johnson295189b2012-06-20 16:38:30 -07006249VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
6250{
6251 VOS_STATUS status = VOS_STATUS_SUCCESS;
6252
6253 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
6254 {
6255 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
6256 }
6257
6258 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
6259 {
6260 sme_StartAutoBmpsTimer(pHddCtx->hHal);
6261 }
6262
6263 if (pHddCtx->cfg_ini->fIsImpsEnabled)
6264 {
6265 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
6266 }
6267
6268 return status;
6269}
6270
6271VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
6272{
6273 hdd_adapter_t *pAdapter = NULL;
6274 eHalStatus halStatus;
6275 VOS_STATUS status = VOS_STATUS_E_INVAL;
6276 v_BOOL_t disableBmps = FALSE;
6277 v_BOOL_t disableImps = FALSE;
6278
6279 switch(session_type)
6280 {
6281 case WLAN_HDD_INFRA_STATION:
6282 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07006283 case WLAN_HDD_P2P_CLIENT:
6284 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07006285 //Exit BMPS -> Is Sta/P2P Client is already connected
6286 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
6287 if((NULL != pAdapter)&&
6288 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
6289 {
6290 disableBmps = TRUE;
6291 }
6292
6293 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
6294 if((NULL != pAdapter)&&
6295 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
6296 {
6297 disableBmps = TRUE;
6298 }
6299
6300 //Exit both Bmps and Imps incase of Go/SAP Mode
6301 if((WLAN_HDD_SOFTAP == session_type) ||
6302 (WLAN_HDD_P2P_GO == session_type))
6303 {
6304 disableBmps = TRUE;
6305 disableImps = TRUE;
6306 }
6307
6308 if(TRUE == disableImps)
6309 {
6310 if (pHddCtx->cfg_ini->fIsImpsEnabled)
6311 {
6312 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
6313 }
6314 }
6315
6316 if(TRUE == disableBmps)
6317 {
6318 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
6319 {
6320 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
6321
6322 if(eHAL_STATUS_SUCCESS != halStatus)
6323 {
6324 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08006325 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006326 VOS_ASSERT(0);
6327 return status;
6328 }
6329 }
6330
6331 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
6332 {
6333 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
6334
6335 if(eHAL_STATUS_SUCCESS != halStatus)
6336 {
6337 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08006338 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006339 VOS_ASSERT(0);
6340 return status;
6341 }
6342 }
6343 }
6344
6345 if((TRUE == disableBmps) ||
6346 (TRUE == disableImps))
6347 {
6348 /* Now, get the chip into Full Power now */
6349 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
6350 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
6351 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
6352
6353 if(halStatus != eHAL_STATUS_SUCCESS)
6354 {
6355 if(halStatus == eHAL_STATUS_PMC_PENDING)
6356 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306357 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07006358 //Block on a completion variable. Can't wait forever though
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306359 ret = wait_for_completion_interruptible_timeout(
6360 &pHddCtx->full_pwr_comp_var,
6361 msecs_to_jiffies(1000));
6362 if (ret <= 0)
6363 {
6364 hddLog(VOS_TRACE_LEVEL_ERROR,
6365 "%s: wait on full_pwr_comp_var failed %ld",
6366 __func__, ret);
6367 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006368 }
6369 else
6370 {
6371 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08006372 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006373 VOS_ASSERT(0);
6374 return status;
6375 }
6376 }
6377
6378 status = VOS_STATUS_SUCCESS;
6379 }
6380
6381 break;
6382 }
6383 return status;
6384}
6385
6386hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08006387 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07006388 tANI_U8 rtnl_held )
6389{
6390 hdd_adapter_t *pAdapter = NULL;
6391 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
6392 VOS_STATUS status = VOS_STATUS_E_FAILURE;
6393 VOS_STATUS exitbmpsStatus;
6394
Arif Hussain6d2a3322013-11-17 19:50:10 -08006395 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d",__func__,iface_name,session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006396
Nirav Shah436658f2014-02-28 17:05:45 +05306397 if(macAddr == NULL)
6398 {
6399 /* Not received valid macAddr */
6400 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6401 "%s:Unable to add virtual intf: Not able to get"
6402 "valid mac address",__func__);
6403 return NULL;
6404 }
6405
Jeff Johnson295189b2012-06-20 16:38:30 -07006406 //Disable BMPS incase of Concurrency
6407 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
6408
6409 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
6410 {
6411 //Fail to Exit BMPS
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306412 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Exit BMPS", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006413 VOS_ASSERT(0);
6414 return NULL;
6415 }
6416
6417 switch(session_type)
6418 {
6419 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07006420 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006421 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07006422 {
6423 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
6424
6425 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306426 {
6427 hddLog(VOS_TRACE_LEVEL_FATAL,
6428 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006429 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306430 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006431
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306432#ifdef FEATURE_WLAN_TDLS
6433 /* A Mutex Lock is introduced while changing/initializing the mode to
6434 * protect the concurrent access for the Adapters by TDLS module.
6435 */
Rajesh Chauhana34c6e62014-03-25 16:37:58 +05306436 mutex_lock(&pHddCtx->tdls_lock);
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306437#endif
6438
Jeff Johnsone7245742012-09-05 17:12:55 -07006439 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
6440 NL80211_IFTYPE_P2P_CLIENT:
6441 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07006442
Jeff Johnson295189b2012-06-20 16:38:30 -07006443 pAdapter->device_mode = session_type;
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306444#ifdef FEATURE_WLAN_TDLS
6445 mutex_unlock(&pHddCtx->tdls_lock);
6446#endif
Sunil Dutt66485cb2013-12-19 19:05:03 +05306447
6448 status = hdd_init_station_mode( pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07006449 if( VOS_STATUS_SUCCESS != status )
6450 goto err_free_netdev;
6451
6452 status = hdd_register_interface( pAdapter, rtnl_held );
6453 if( VOS_STATUS_SUCCESS != status )
6454 {
6455 hdd_deinit_adapter(pHddCtx, pAdapter);
6456 goto err_free_netdev;
6457 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306458
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05306459 // Workqueue which gets scheduled in IPv4 notification callback.
6460 INIT_WORK(&pAdapter->ipv4NotifierWorkQueue, hdd_ipv4_notifier_work_queue);
6461
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306462#ifdef WLAN_NS_OFFLOAD
6463 // Workqueue which gets scheduled in IPv6 notification callback.
6464 INIT_WORK(&pAdapter->ipv6NotifierWorkQueue, hdd_ipv6_notifier_work_queue);
6465#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006466 //Stop the Interface TX queue.
6467 netif_tx_disable(pAdapter->dev);
6468 //netif_tx_disable(pWlanDev);
6469 netif_carrier_off(pAdapter->dev);
6470
6471 break;
6472 }
6473
Jeff Johnson295189b2012-06-20 16:38:30 -07006474 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07006475 case WLAN_HDD_SOFTAP:
6476 {
6477 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
6478 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306479 {
6480 hddLog(VOS_TRACE_LEVEL_FATAL,
6481 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006482 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306483 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006484
Jeff Johnson295189b2012-06-20 16:38:30 -07006485 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
6486 NL80211_IFTYPE_AP:
6487 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07006488 pAdapter->device_mode = session_type;
6489
6490 status = hdd_init_ap_mode(pAdapter);
6491 if( VOS_STATUS_SUCCESS != status )
6492 goto err_free_netdev;
6493
6494 status = hdd_register_hostapd( pAdapter, rtnl_held );
6495 if( VOS_STATUS_SUCCESS != status )
6496 {
6497 hdd_deinit_adapter(pHddCtx, pAdapter);
6498 goto err_free_netdev;
6499 }
6500
6501 netif_tx_disable(pAdapter->dev);
6502 netif_carrier_off(pAdapter->dev);
6503
6504 hdd_set_conparam( 1 );
6505 break;
6506 }
6507 case WLAN_HDD_MONITOR:
6508 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006509 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
6510 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306511 {
6512 hddLog(VOS_TRACE_LEVEL_FATAL,
6513 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006514 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306515 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006516
6517 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
6518 pAdapter->device_mode = session_type;
6519 status = hdd_register_interface( pAdapter, rtnl_held );
6520#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
6521 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
6522#else
6523 pAdapter->dev->open = hdd_mon_open;
6524 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
6525#endif
6526 hdd_init_tx_rx( pAdapter );
6527 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
6528 //Set adapter to be used for data tx. It will use either GO or softap.
6529 pAdapter->sessionCtx.monitor.pAdapterForTx =
6530 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07006531 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
6532 {
6533 pAdapter->sessionCtx.monitor.pAdapterForTx =
6534 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
6535 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006536 /* This workqueue will be used to transmit management packet over
6537 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07006538 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
6539 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
6540 return NULL;
6541 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07006542
Jeff Johnson295189b2012-06-20 16:38:30 -07006543 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
6544 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07006545 }
6546 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07006547 case WLAN_HDD_FTM:
6548 {
6549 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
6550
6551 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306552 {
6553 hddLog(VOS_TRACE_LEVEL_FATAL,
6554 FL("failed to allocate adapter for session %d"), session_type);
6555 return NULL;
6556 }
6557
Jeff Johnson295189b2012-06-20 16:38:30 -07006558 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
6559 * message while loading driver in FTM mode. */
6560 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
6561 pAdapter->device_mode = session_type;
6562 status = hdd_register_interface( pAdapter, rtnl_held );
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05306563
6564 hdd_init_tx_rx( pAdapter );
6565
6566 //Stop the Interface TX queue.
6567 netif_tx_disable(pAdapter->dev);
6568 netif_carrier_off(pAdapter->dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07006569 }
6570 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07006571 default:
6572 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306573 hddLog(VOS_TRACE_LEVEL_FATAL,"%s Invalid session type %d",
6574 __func__, session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006575 VOS_ASSERT(0);
6576 return NULL;
6577 }
6578 }
6579
Jeff Johnson295189b2012-06-20 16:38:30 -07006580 if( VOS_STATUS_SUCCESS == status )
6581 {
6582 //Add it to the hdd's session list.
6583 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
6584 if( NULL == pHddAdapterNode )
6585 {
6586 status = VOS_STATUS_E_NOMEM;
6587 }
6588 else
6589 {
6590 pHddAdapterNode->pAdapter = pAdapter;
6591 status = hdd_add_adapter_back ( pHddCtx,
6592 pHddAdapterNode );
6593 }
6594 }
6595
6596 if( VOS_STATUS_SUCCESS != status )
6597 {
6598 if( NULL != pAdapter )
6599 {
6600 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
6601 pAdapter = NULL;
6602 }
6603 if( NULL != pHddAdapterNode )
6604 {
6605 vos_mem_free( pHddAdapterNode );
6606 }
6607
6608 goto resume_bmps;
6609 }
6610
6611 if(VOS_STATUS_SUCCESS == status)
6612 {
6613 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
6614
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07006615 //Initialize the WoWL service
6616 if(!hdd_init_wowl(pAdapter))
6617 {
6618 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
6619 goto err_free_netdev;
6620 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006621 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006622 return pAdapter;
6623
6624err_free_netdev:
6625 free_netdev(pAdapter->dev);
6626 wlan_hdd_release_intf_addr( pHddCtx,
6627 pAdapter->macAddressCurrent.bytes );
6628
6629resume_bmps:
6630 //If bmps disabled enable it
6631 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
6632 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306633 if (pHddCtx->hdd_wlan_suspended)
6634 {
6635 hdd_set_pwrparams(pHddCtx);
6636 }
6637 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07006638 }
6639 return NULL;
6640}
6641
6642VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
6643 tANI_U8 rtnl_held )
6644{
6645 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
6646 VOS_STATUS status;
6647
6648 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
6649 if( VOS_STATUS_SUCCESS != status )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306650 {
6651 hddLog(VOS_TRACE_LEVEL_WARN,"%s: adapter list empty %d",
6652 __func__, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07006653 return status;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306654 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006655
6656 while ( pCurrent->pAdapter != pAdapter )
6657 {
6658 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
6659 if( VOS_STATUS_SUCCESS != status )
6660 break;
6661
6662 pCurrent = pNext;
6663 }
6664 pAdapterNode = pCurrent;
6665 if( VOS_STATUS_SUCCESS == status )
6666 {
6667 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
6668 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306669
6670#ifdef FEATURE_WLAN_TDLS
6671
6672 /* A Mutex Lock is introduced while changing/initializing the mode to
6673 * protect the concurrent access for the Adapters by TDLS module.
6674 */
Rajesh Chauhana34c6e62014-03-25 16:37:58 +05306675 mutex_lock(&pHddCtx->tdls_lock);
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306676#endif
6677
Jeff Johnson295189b2012-06-20 16:38:30 -07006678 hdd_remove_adapter( pHddCtx, pAdapterNode );
6679 vos_mem_free( pAdapterNode );
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08006680 pAdapterNode = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006681
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306682#ifdef FEATURE_WLAN_TDLS
6683 mutex_unlock(&pHddCtx->tdls_lock);
6684#endif
6685
Jeff Johnson295189b2012-06-20 16:38:30 -07006686
6687 /* If there is a single session of STA/P2P client, re-enable BMPS */
Agarwal Ashish51325b52014-06-16 16:50:49 +05306688 if ((!vos_concurrent_open_sessions_running()) &&
6689 ((pHddCtx->no_of_open_sessions[VOS_STA_MODE] >= 1) ||
6690 (pHddCtx->no_of_open_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
Jeff Johnson295189b2012-06-20 16:38:30 -07006691 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306692 if (pHddCtx->hdd_wlan_suspended)
6693 {
6694 hdd_set_pwrparams(pHddCtx);
6695 }
6696 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07006697 }
6698
6699 return VOS_STATUS_SUCCESS;
6700 }
6701
6702 return VOS_STATUS_E_FAILURE;
6703}
6704
6705VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
6706{
6707 hdd_adapter_list_node_t *pHddAdapterNode;
6708 VOS_STATUS status;
6709
6710 ENTER();
6711
6712 do
6713 {
6714 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
6715 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
6716 {
6717 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
6718 vos_mem_free( pHddAdapterNode );
6719 }
6720 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
6721
6722 EXIT();
6723
6724 return VOS_STATUS_SUCCESS;
6725}
6726
6727void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
6728{
6729 v_U8_t addIE[1] = {0};
6730
6731 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6732 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
6733 eANI_BOOLEAN_FALSE) )
6734 {
6735 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006736 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006737 }
6738
6739 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6740 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
6741 eANI_BOOLEAN_FALSE) )
6742 {
6743 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006744 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006745 }
6746
6747 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6748 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
6749 eANI_BOOLEAN_FALSE) )
6750 {
6751 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006752 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006753 }
6754}
6755
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05306756VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
6757 const v_BOOL_t bCloseSession )
Jeff Johnson295189b2012-06-20 16:38:30 -07006758{
6759 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
6760 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6761 union iwreq_data wrqu;
Kaushik, Sushant7005e372014-04-08 11:36:54 +05306762 v_U8_t retry = 0;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306763 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07006764
6765 ENTER();
6766
6767 switch(pAdapter->device_mode)
6768 {
6769 case WLAN_HDD_INFRA_STATION:
6770 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006771 case WLAN_HDD_P2P_DEVICE:
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05306772 {
6773 hdd_station_ctx_t *pstation = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6774 if( hdd_connIsConnected(pstation) ||
6775 (pstation->conn_info.connState == eConnectionState_Connecting) )
Jeff Johnson295189b2012-06-20 16:38:30 -07006776 {
6777 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
6778 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
6779 pAdapter->sessionId,
6780 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
6781 else
6782 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
6783 pAdapter->sessionId,
6784 eCSR_DISCONNECT_REASON_UNSPECIFIED);
6785 //success implies disconnect command got queued up successfully
6786 if(halStatus == eHAL_STATUS_SUCCESS)
6787 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306788 ret = wait_for_completion_interruptible_timeout(
6789 &pAdapter->disconnect_comp_var,
6790 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6791 if (ret <= 0)
6792 {
6793 hddLog(VOS_TRACE_LEVEL_ERROR,
6794 "%s: wait on disconnect_comp_var failed %ld",
6795 __func__, ret);
6796 }
6797 }
6798 else
6799 {
6800 hddLog(LOGE, "%s: failed to post disconnect event to SME",
6801 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006802 }
6803 memset(&wrqu, '\0', sizeof(wrqu));
6804 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
6805 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
6806 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
6807 }
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05306808 else if(pstation->conn_info.connState ==
6809 eConnectionState_Disconnecting)
6810 {
6811 ret = wait_for_completion_interruptible_timeout(
6812 &pAdapter->disconnect_comp_var,
6813 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6814 if (ret <= 0)
6815 {
6816 hddLog(VOS_TRACE_LEVEL_ERROR,
6817 FL("wait on disconnect_comp_var failed %ld"), ret);
6818 }
6819 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006820 else
6821 {
Srinivas, Dasari138af4f2014-02-07 11:13:45 +05306822 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
6823 eCSR_SCAN_ABORT_DEFAULT);
Jeff Johnson295189b2012-06-20 16:38:30 -07006824 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +05306825 if (pAdapter->device_mode != WLAN_HDD_INFRA_STATION)
6826 {
6827 while (pAdapter->is_roc_inprogress)
6828 {
6829 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6830 "%s: ROC in progress for session %d!!!",
6831 __func__, pAdapter->sessionId);
6832 // waiting for ROC to expire
6833 msleep(500);
6834 /* In GO present case , if retry exceeds 3,
6835 it means something went wrong. */
6836 if ( retry++ > MAX_WAIT_FOR_ROC_COMPLETION )
6837 {
6838 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6839 "%s: ROC completion is not received.!!!", __func__);
6840 sme_CancelRemainOnChannel(WLAN_HDD_GET_HAL_CTX(pAdapter),
6841 pAdapter->sessionId);
6842 wait_for_completion_interruptible_timeout(
6843 &pAdapter->cancel_rem_on_chan_var,
6844 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
6845 break;
6846 }
6847 }
6848 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306849#ifdef WLAN_NS_OFFLOAD
Vinay Krishna Eranna941360f2014-01-16 15:38:22 +05306850#ifdef WLAN_OPEN_SOURCE
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306851 cancel_work_sync(&pAdapter->ipv6NotifierWorkQueue);
6852#endif
Vinay Krishna Eranna941360f2014-01-16 15:38:22 +05306853 if (pAdapter->ipv6_notifier_registered)
6854 {
6855 hddLog(LOG1, FL("Unregistered IPv6 notifier"));
6856 unregister_inet6addr_notifier(&pAdapter->ipv6_notifier);
6857 pAdapter->ipv6_notifier_registered = false;
6858 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306859#endif
Vinay Krishna Erannad9cbdb32014-01-16 12:59:10 +05306860 if (pAdapter->ipv4_notifier_registered)
6861 {
6862 hddLog(LOG1, FL("Unregistered IPv4 notifier"));
6863 unregister_inetaddr_notifier(&pAdapter->ipv4_notifier);
6864 pAdapter->ipv4_notifier_registered = false;
6865 }
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05306866#ifdef WLAN_OPEN_SOURCE
6867 cancel_work_sync(&pAdapter->ipv4NotifierWorkQueue);
6868#endif
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05306869 /* It is possible that the caller of this function does not
6870 * wish to close the session
6871 */
6872 if (VOS_TRUE == bCloseSession &&
6873 test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07006874 {
6875 INIT_COMPLETION(pAdapter->session_close_comp_var);
6876 if (eHAL_STATUS_SUCCESS ==
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05306877 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
6878 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07006879 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306880 unsigned long ret;
6881
Jeff Johnson295189b2012-06-20 16:38:30 -07006882 //Block on a completion variable. Can't wait forever though.
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306883 ret = wait_for_completion_timeout(
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05306884 &pAdapter->session_close_comp_var,
6885 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306886 if ( 0 >= ret)
6887 {
6888 hddLog(LOGE, "%s: failure waiting for session_close_comp_var %ld",
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05306889 __func__, ret);
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306890 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006891 }
6892 }
Vinay Krishna Erannab09d3e72014-03-26 21:23:55 +05306893 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006894 break;
6895
6896 case WLAN_HDD_SOFTAP:
6897 case WLAN_HDD_P2P_GO:
6898 //Any softap specific cleanup here...
Kaushik, Sushant7005e372014-04-08 11:36:54 +05306899 if (pAdapter->device_mode == WLAN_HDD_P2P_GO) {
6900 while (pAdapter->is_roc_inprogress) {
6901 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6902 "%s: ROC in progress for session %d!!!",
6903 __func__, pAdapter->sessionId);
6904 msleep(500);
6905 if ( retry++ > MAX_WAIT_FOR_ROC_COMPLETION ) {
6906 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6907 "%s: ROC completion is not received.!!!", __func__);
6908 WLANSAP_CancelRemainOnChannel(
6909 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
6910 wait_for_completion_interruptible_timeout(
6911 &pAdapter->cancel_rem_on_chan_var,
6912 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
6913 break;
6914 }
6915 }
6916 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006917 mutex_lock(&pHddCtx->sap_lock);
6918 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
6919 {
6920 VOS_STATUS status;
6921 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6922
6923 //Stop Bss.
6924 status = WLANSAP_StopBss(pHddCtx->pvosContext);
6925 if (VOS_IS_STATUS_SUCCESS(status))
6926 {
6927 hdd_hostapd_state_t *pHostapdState =
6928 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6929
6930 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
6931
6932 if (!VOS_IS_STATUS_SUCCESS(status))
6933 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306934 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss %d",
6935 __func__, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07006936 }
6937 }
6938 else
6939 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006940 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006941 }
6942 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
Agarwal Ashish51325b52014-06-16 16:50:49 +05306943 wlan_hdd_decr_active_session(pHddCtx, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07006944
6945 if (eHAL_STATUS_FAILURE ==
6946 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
6947 0, NULL, eANI_BOOLEAN_FALSE))
6948 {
6949 hddLog(LOGE,
6950 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006951 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006952 }
6953
6954 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
6955 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
6956 eANI_BOOLEAN_FALSE) )
6957 {
6958 hddLog(LOGE,
6959 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
6960 }
6961
6962 // Reset WNI_CFG_PROBE_RSP Flags
6963 wlan_hdd_reset_prob_rspies(pAdapter);
6964 kfree(pAdapter->sessionCtx.ap.beacon);
6965 pAdapter->sessionCtx.ap.beacon = NULL;
6966 }
6967 mutex_unlock(&pHddCtx->sap_lock);
6968 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006969
Jeff Johnson295189b2012-06-20 16:38:30 -07006970 case WLAN_HDD_MONITOR:
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006971#ifdef WLAN_OPEN_SOURCE
6972 cancel_work_sync(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue);
6973#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006974 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006975
Jeff Johnson295189b2012-06-20 16:38:30 -07006976 default:
6977 break;
6978 }
6979
6980 EXIT();
6981 return VOS_STATUS_SUCCESS;
6982}
6983
6984VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
6985{
6986 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6987 VOS_STATUS status;
6988 hdd_adapter_t *pAdapter;
6989
6990 ENTER();
6991
6992 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6993
6994 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6995 {
6996 pAdapter = pAdapterNode->pAdapter;
6997 netif_tx_disable(pAdapter->dev);
6998 netif_carrier_off(pAdapter->dev);
6999
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05307000 hdd_stop_adapter( pHddCtx, pAdapter, VOS_TRUE );
Jeff Johnson295189b2012-06-20 16:38:30 -07007001
7002 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7003 pAdapterNode = pNext;
7004 }
7005
7006 EXIT();
7007
7008 return VOS_STATUS_SUCCESS;
7009}
7010
Rajeev Kumarf999e582014-01-09 17:33:29 -08007011
7012#ifdef FEATURE_WLAN_BATCH_SCAN
7013/**---------------------------------------------------------------------------
7014
7015 \brief hdd_deinit_batch_scan () - This function cleans up batch scan data
7016 structures
7017
7018 \param - pAdapter Pointer to HDD adapter
7019
7020 \return - None
7021
7022 --------------------------------------------------------------------------*/
7023void hdd_deinit_batch_scan(hdd_adapter_t *pAdapter)
7024{
7025 tHddBatchScanRsp *pNode;
7026 tHddBatchScanRsp *pPrev;
7027
Siddharth Bhalb3e9b792014-02-24 15:14:16 +05307028 if (NULL == pAdapter)
Rajeev Kumarf999e582014-01-09 17:33:29 -08007029 {
Siddharth Bhalb3e9b792014-02-24 15:14:16 +05307030 hddLog(VOS_TRACE_LEVEL_ERROR,
7031 "%s: Adapter context is Null", __func__);
7032 return;
7033 }
7034
7035 pNode = pAdapter->pBatchScanRsp;
7036 while (pNode)
7037 {
7038 pPrev = pNode;
7039 pNode = pNode->pNext;
7040 vos_mem_free((v_VOID_t * )pPrev);
Rajeev Kumarf999e582014-01-09 17:33:29 -08007041 }
7042
7043 pAdapter->pBatchScanRsp = NULL;
7044 pAdapter->numScanList = 0;
7045 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
7046 pAdapter->prev_batch_id = 0;
7047
7048 return;
7049}
7050#endif
7051
7052
Jeff Johnson295189b2012-06-20 16:38:30 -07007053VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
7054{
7055 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7056 VOS_STATUS status;
7057 hdd_adapter_t *pAdapter;
7058
7059 ENTER();
7060
7061 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7062
7063 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7064 {
7065 pAdapter = pAdapterNode->pAdapter;
7066 netif_tx_disable(pAdapter->dev);
7067 netif_carrier_off(pAdapter->dev);
7068
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07007069 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
7070
Jeff Johnson295189b2012-06-20 16:38:30 -07007071 hdd_deinit_tx_rx(pAdapter);
Agarwal Ashish6267caa2014-08-06 19:16:21 +05307072
7073 wlan_hdd_decr_active_session(pHddCtx, pAdapter->device_mode);
7074
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05307075 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
7076 {
7077 hdd_wmm_adapter_close( pAdapter );
7078 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
7079 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007080
Rajeev Kumarf999e582014-01-09 17:33:29 -08007081#ifdef FEATURE_WLAN_BATCH_SCAN
7082 if (eHDD_BATCH_SCAN_STATE_STARTED == pAdapter->batchScanState)
7083 {
7084 hdd_deinit_batch_scan(pAdapter);
7085 }
7086#endif
7087
Jeff Johnson295189b2012-06-20 16:38:30 -07007088 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7089 pAdapterNode = pNext;
7090 }
7091
7092 EXIT();
7093
7094 return VOS_STATUS_SUCCESS;
7095}
7096
7097VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
7098{
7099 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7100 VOS_STATUS status;
7101 hdd_adapter_t *pAdapter;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05307102 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -07007103
7104 ENTER();
7105
7106 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7107
7108 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7109 {
7110 pAdapter = pAdapterNode->pAdapter;
7111
Kumar Anand82c009f2014-05-29 00:29:42 -07007112 hdd_wmm_init( pAdapter );
7113
Jeff Johnson295189b2012-06-20 16:38:30 -07007114 switch(pAdapter->device_mode)
7115 {
7116 case WLAN_HDD_INFRA_STATION:
7117 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07007118 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05307119
7120 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
7121
Jeff Johnson295189b2012-06-20 16:38:30 -07007122 hdd_init_station_mode(pAdapter);
7123 /* Open the gates for HDD to receive Wext commands */
7124 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07007125 pHddCtx->scan_info.mScanPending = FALSE;
7126 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07007127
7128 //Trigger the initial scan
7129 hdd_wlan_initial_scan(pAdapter);
7130
7131 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05307132 if (eConnectionState_Associated == connState ||
7133 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -07007134 {
7135 union iwreq_data wrqu;
7136 memset(&wrqu, '\0', sizeof(wrqu));
7137 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
7138 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
7139 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07007140 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07007141
Jeff Johnson295189b2012-06-20 16:38:30 -07007142 /* indicate disconnected event to nl80211 */
7143 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
7144 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07007145 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05307146 else if (eConnectionState_Connecting == connState)
7147 {
7148 /*
7149 * Indicate connect failure to supplicant if we were in the
7150 * process of connecting
7151 */
7152 cfg80211_connect_result(pAdapter->dev, NULL,
7153 NULL, 0, NULL, 0,
7154 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
7155 GFP_KERNEL);
7156 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007157 break;
7158
7159 case WLAN_HDD_SOFTAP:
7160 /* softAP can handle SSR */
7161 break;
7162
7163 case WLAN_HDD_P2P_GO:
Sameer Thalappiledf0d792013-08-09 14:31:03 -07007164 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send stop ap to supplicant",
Jeff Johnson295189b2012-06-20 16:38:30 -07007165 __func__);
Sameer Thalappiledf0d792013-08-09 14:31:03 -07007166 cfg80211_ap_stopped(pAdapter->dev, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07007167 break;
7168
7169 case WLAN_HDD_MONITOR:
7170 /* monitor interface start */
7171 break;
7172 default:
7173 break;
7174 }
7175
7176 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7177 pAdapterNode = pNext;
7178 }
7179
7180 EXIT();
7181
7182 return VOS_STATUS_SUCCESS;
7183}
7184
7185VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
7186{
7187 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7188 hdd_adapter_t *pAdapter;
7189 VOS_STATUS status;
7190 v_U32_t roamId;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307191 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07007192
7193 ENTER();
7194
7195 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7196
7197 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7198 {
7199 pAdapter = pAdapterNode->pAdapter;
7200
7201 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
7202 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
7203 {
7204 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7205 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
7206
Abhishek Singhf4669da2014-05-26 15:07:49 +05307207 hddLog(VOS_TRACE_LEVEL_INFO,
7208 "%s: Set HDD connState to eConnectionState_NotConnected",
7209 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007210 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
7211 init_completion(&pAdapter->disconnect_comp_var);
7212 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
7213 eCSR_DISCONNECT_REASON_UNSPECIFIED);
7214
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307215 ret = wait_for_completion_interruptible_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07007216 &pAdapter->disconnect_comp_var,
7217 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307218 if (0 >= ret)
7219 hddLog(LOGE, "%s: failure waiting for disconnect_comp_var %ld",
7220 __func__, ret);
Jeff Johnson295189b2012-06-20 16:38:30 -07007221
7222 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
7223 pHddCtx->isAmpAllowed = VOS_FALSE;
7224 sme_RoamConnect(pHddCtx->hHal,
7225 pAdapter->sessionId, &(pWextState->roamProfile),
7226 &roamId);
7227 }
7228
7229 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7230 pAdapterNode = pNext;
7231 }
7232
7233 EXIT();
7234
7235 return VOS_STATUS_SUCCESS;
7236}
7237
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07007238void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
7239{
7240 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7241 VOS_STATUS status;
7242 hdd_adapter_t *pAdapter;
7243 hdd_station_ctx_t *pHddStaCtx;
7244 hdd_ap_ctx_t *pHddApCtx;
7245 hdd_hostapd_state_t * pHostapdState;
7246 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
7247 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
7248 const char *p2pMode = "DEV";
7249 const char *ccMode = "Standalone";
7250 int n;
7251
7252 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7253 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7254 {
7255 pAdapter = pAdapterNode->pAdapter;
7256 switch (pAdapter->device_mode) {
7257 case WLAN_HDD_INFRA_STATION:
7258 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7259 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
7260 staChannel = pHddStaCtx->conn_info.operationChannel;
7261 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
7262 }
7263 break;
7264 case WLAN_HDD_P2P_CLIENT:
7265 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
7266 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
7267 p2pChannel = pHddStaCtx->conn_info.operationChannel;
7268 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
7269 p2pMode = "CLI";
7270 }
7271 break;
7272 case WLAN_HDD_P2P_GO:
7273 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
7274 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
7275 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
7276 p2pChannel = pHddApCtx->operatingChannel;
7277 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
7278 }
7279 p2pMode = "GO";
7280 break;
7281 case WLAN_HDD_SOFTAP:
7282 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
7283 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
7284 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
7285 apChannel = pHddApCtx->operatingChannel;
7286 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
7287 }
7288 break;
7289 default:
7290 break;
7291 }
7292 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7293 pAdapterNode = pNext;
7294 }
7295 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
7296 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
7297 }
7298 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
7299 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
7300 if (p2pChannel > 0) {
7301 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
7302 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
7303 }
7304 if (apChannel > 0) {
7305 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
7306 apChannel, MAC_ADDR_ARRAY(apBssid));
7307 }
7308
7309 if (p2pChannel > 0 && apChannel > 0) {
7310 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
7311 }
7312}
7313
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07007314bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07007315{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07007316 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07007317}
7318
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07007319/* Once SSR is disabled then it cannot be set. */
7320void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07007321{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07007322 if (HDD_SSR_DISABLED == isSsrRequired)
7323 return;
7324
Jeff Johnson295189b2012-06-20 16:38:30 -07007325 isSsrRequired = value;
7326}
7327
7328VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
7329 hdd_adapter_list_node_t** ppAdapterNode)
7330{
7331 VOS_STATUS status;
7332 spin_lock(&pHddCtx->hddAdapters.lock);
7333 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
7334 (hdd_list_node_t**) ppAdapterNode );
7335 spin_unlock(&pHddCtx->hddAdapters.lock);
7336 return status;
7337}
7338
7339VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
7340 hdd_adapter_list_node_t* pAdapterNode,
7341 hdd_adapter_list_node_t** pNextAdapterNode)
7342{
7343 VOS_STATUS status;
7344 spin_lock(&pHddCtx->hddAdapters.lock);
7345 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
7346 (hdd_list_node_t*) pAdapterNode,
7347 (hdd_list_node_t**)pNextAdapterNode );
7348
7349 spin_unlock(&pHddCtx->hddAdapters.lock);
7350 return status;
7351}
7352
7353VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
7354 hdd_adapter_list_node_t* pAdapterNode)
7355{
7356 VOS_STATUS status;
7357 spin_lock(&pHddCtx->hddAdapters.lock);
7358 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
7359 &pAdapterNode->node );
7360 spin_unlock(&pHddCtx->hddAdapters.lock);
7361 return status;
7362}
7363
7364VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
7365 hdd_adapter_list_node_t** ppAdapterNode)
7366{
7367 VOS_STATUS status;
7368 spin_lock(&pHddCtx->hddAdapters.lock);
7369 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
7370 (hdd_list_node_t**) ppAdapterNode );
7371 spin_unlock(&pHddCtx->hddAdapters.lock);
7372 return status;
7373}
7374
7375VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
7376 hdd_adapter_list_node_t* pAdapterNode)
7377{
7378 VOS_STATUS status;
7379 spin_lock(&pHddCtx->hddAdapters.lock);
7380 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
7381 (hdd_list_node_t*) pAdapterNode );
7382 spin_unlock(&pHddCtx->hddAdapters.lock);
7383 return status;
7384}
7385
7386VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
7387 hdd_adapter_list_node_t* pAdapterNode)
7388{
7389 VOS_STATUS status;
7390 spin_lock(&pHddCtx->hddAdapters.lock);
7391 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
7392 (hdd_list_node_t*) pAdapterNode );
7393 spin_unlock(&pHddCtx->hddAdapters.lock);
7394 return status;
7395}
7396
7397hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
7398 tSirMacAddr macAddr )
7399{
7400 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7401 hdd_adapter_t *pAdapter;
7402 VOS_STATUS status;
7403
7404 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7405
7406 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7407 {
7408 pAdapter = pAdapterNode->pAdapter;
7409
7410 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
7411 macAddr, sizeof(tSirMacAddr) ) )
7412 {
7413 return pAdapter;
7414 }
7415 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7416 pAdapterNode = pNext;
7417 }
7418
7419 return NULL;
7420
7421}
7422
7423hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
7424{
7425 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7426 hdd_adapter_t *pAdapter;
7427 VOS_STATUS status;
7428
7429 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7430
7431 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7432 {
7433 pAdapter = pAdapterNode->pAdapter;
7434
7435 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
7436 IFNAMSIZ ) )
7437 {
7438 return pAdapter;
7439 }
7440 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7441 pAdapterNode = pNext;
7442 }
7443
7444 return NULL;
7445
7446}
7447
7448hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
7449{
7450 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7451 hdd_adapter_t *pAdapter;
7452 VOS_STATUS status;
7453
7454 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7455
7456 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7457 {
7458 pAdapter = pAdapterNode->pAdapter;
7459
7460 if( pAdapter && (mode == pAdapter->device_mode) )
7461 {
7462 return pAdapter;
7463 }
7464 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7465 pAdapterNode = pNext;
7466 }
7467
7468 return NULL;
7469
7470}
7471
7472//Remove this function later
7473hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
7474{
7475 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7476 hdd_adapter_t *pAdapter;
7477 VOS_STATUS status;
7478
7479 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7480
7481 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7482 {
7483 pAdapter = pAdapterNode->pAdapter;
7484
7485 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
7486 {
7487 return pAdapter;
7488 }
7489
7490 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7491 pAdapterNode = pNext;
7492 }
7493
7494 return NULL;
7495
7496}
7497
Jeff Johnson295189b2012-06-20 16:38:30 -07007498/**---------------------------------------------------------------------------
7499
7500 \brief hdd_set_monitor_tx_adapter() -
7501
7502 This API initializes the adapter to be used while transmitting on monitor
7503 adapter.
7504
7505 \param - pHddCtx - Pointer to the HDD context.
7506 pAdapter - Adapter that will used for TX. This can be NULL.
7507 \return - None.
7508 --------------------------------------------------------------------------*/
7509void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
7510{
7511 hdd_adapter_t *pMonAdapter;
7512
7513 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
7514
7515 if( NULL != pMonAdapter )
7516 {
7517 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
7518 }
7519}
Jeff Johnson295189b2012-06-20 16:38:30 -07007520/**---------------------------------------------------------------------------
7521
Mahesh A Saptasgar64534612014-09-23 13:13:33 +05307522 \brief hdd_get_operating_channel() -
Jeff Johnson295189b2012-06-20 16:38:30 -07007523
7524 This API returns the operating channel of the requested device mode
7525
7526 \param - pHddCtx - Pointer to the HDD context.
7527 - mode - Device mode for which operating channel is required
7528 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
7529 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
7530 \return - channel number. "0" id the requested device is not found OR it is not connected.
7531 --------------------------------------------------------------------------*/
7532v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
7533{
7534 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7535 VOS_STATUS status;
7536 hdd_adapter_t *pAdapter;
7537 v_U8_t operatingChannel = 0;
7538
7539 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7540
7541 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7542 {
7543 pAdapter = pAdapterNode->pAdapter;
7544
7545 if( mode == pAdapter->device_mode )
7546 {
7547 switch(pAdapter->device_mode)
7548 {
7549 case WLAN_HDD_INFRA_STATION:
7550 case WLAN_HDD_P2P_CLIENT:
7551 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
7552 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
7553 break;
7554 case WLAN_HDD_SOFTAP:
7555 case WLAN_HDD_P2P_GO:
7556 /*softap connection info */
7557 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
7558 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
7559 break;
7560 default:
7561 break;
7562 }
7563
7564 break; //Found the device of interest. break the loop
7565 }
7566
7567 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7568 pAdapterNode = pNext;
7569 }
7570 return operatingChannel;
7571}
7572
7573#ifdef WLAN_FEATURE_PACKET_FILTERING
7574/**---------------------------------------------------------------------------
7575
7576 \brief hdd_set_multicast_list() -
7577
7578 This used to set the multicast address list.
7579
7580 \param - dev - Pointer to the WLAN device.
7581 - skb - Pointer to OS packet (sk_buff).
7582 \return - success/fail
7583
7584 --------------------------------------------------------------------------*/
7585static void hdd_set_multicast_list(struct net_device *dev)
7586{
7587 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07007588 int mc_count;
7589 int i = 0;
7590 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307591
7592 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07007593 {
7594 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307595 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007596 return;
7597 }
7598
7599 if (dev->flags & IFF_ALLMULTI)
7600 {
7601 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007602 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307603 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07007604 }
7605 else
7606 {
7607 mc_count = netdev_mc_count(dev);
7608 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007609 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07007610 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
7611 {
7612 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007613 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307614 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07007615 return;
7616 }
7617
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307618 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07007619
7620 netdev_for_each_mc_addr(ha, dev) {
7621 if (i == mc_count)
7622 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307623 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
7624 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
Arif Hussain6d2a3322013-11-17 19:50:10 -08007625 hddLog(VOS_TRACE_LEVEL_INFO, "%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07007626 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307627 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07007628 i++;
7629 }
7630 }
7631 return;
7632}
7633#endif
7634
7635/**---------------------------------------------------------------------------
7636
7637 \brief hdd_select_queue() -
7638
7639 This function is registered with the Linux OS for network
7640 core to decide which queue to use first.
7641
7642 \param - dev - Pointer to the WLAN device.
7643 - skb - Pointer to OS packet (sk_buff).
7644 \return - ac, Queue Index/access category corresponding to UP in IP header
7645
7646 --------------------------------------------------------------------------*/
7647v_U16_t hdd_select_queue(struct net_device *dev,
7648 struct sk_buff *skb)
7649{
7650 return hdd_wmm_select_queue(dev, skb);
7651}
7652
7653
7654/**---------------------------------------------------------------------------
7655
7656 \brief hdd_wlan_initial_scan() -
7657
7658 This function triggers the initial scan
7659
7660 \param - pAdapter - Pointer to the HDD adapter.
7661
7662 --------------------------------------------------------------------------*/
7663void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
7664{
7665 tCsrScanRequest scanReq;
7666 tCsrChannelInfo channelInfo;
7667 eHalStatus halStatus;
Jeff Johnson02797792013-10-26 19:17:13 -07007668 tANI_U32 scanId;
Jeff Johnson295189b2012-06-20 16:38:30 -07007669 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7670
7671 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
7672 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
7673 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
7674
7675 if(sme_Is11dSupported(pHddCtx->hHal))
7676 {
7677 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
7678 if ( HAL_STATUS_SUCCESS( halStatus ) )
7679 {
7680 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
7681 if( !scanReq.ChannelInfo.ChannelList )
7682 {
7683 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
7684 vos_mem_free(channelInfo.ChannelList);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08007685 channelInfo.ChannelList = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007686 return;
7687 }
7688 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
7689 channelInfo.numOfChannels);
7690 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
7691 vos_mem_free(channelInfo.ChannelList);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08007692 channelInfo.ChannelList = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007693 }
7694
7695 scanReq.scanType = eSIR_PASSIVE_SCAN;
7696 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
7697 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
7698 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
7699 }
7700 else
7701 {
7702 scanReq.scanType = eSIR_ACTIVE_SCAN;
7703 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
7704 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
7705 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
7706 }
7707
7708 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
7709 if ( !HAL_STATUS_SUCCESS( halStatus ) )
7710 {
7711 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
7712 __func__, halStatus );
7713 }
7714
7715 if(sme_Is11dSupported(pHddCtx->hHal))
7716 vos_mem_free(scanReq.ChannelInfo.ChannelList);
7717}
7718
Jeff Johnson295189b2012-06-20 16:38:30 -07007719/**---------------------------------------------------------------------------
7720
7721 \brief hdd_full_power_callback() - HDD full power callback function
7722
7723 This is the function invoked by SME to inform the result of a full power
7724 request issued by HDD
7725
7726 \param - callbackcontext - Pointer to cookie
7727 \param - status - result of request
7728
7729 \return - None
7730
7731 --------------------------------------------------------------------------*/
7732static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
7733{
Jeff Johnson72a40512013-12-19 10:14:15 -08007734 struct statsContext *pContext = callbackContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07007735
7736 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307737 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07007738
7739 if (NULL == callbackContext)
7740 {
7741 hddLog(VOS_TRACE_LEVEL_ERROR,
7742 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007743 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07007744 return;
7745 }
7746
Jeff Johnson72a40512013-12-19 10:14:15 -08007747 /* there is a race condition that exists between this callback
7748 function and the caller since the caller could time out either
7749 before or while this code is executing. we use a spinlock to
7750 serialize these actions */
7751 spin_lock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07007752
7753 if (POWER_CONTEXT_MAGIC != pContext->magic)
7754 {
7755 /* the caller presumably timed out so there is nothing we can do */
Jeff Johnson72a40512013-12-19 10:14:15 -08007756 spin_unlock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07007757 hddLog(VOS_TRACE_LEVEL_WARN,
7758 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007759 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07007760 return;
7761 }
7762
Jeff Johnson72a40512013-12-19 10:14:15 -08007763 /* context is valid so caller is still waiting */
7764
7765 /* paranoia: invalidate the magic */
7766 pContext->magic = 0;
7767
7768 /* notify the caller */
Jeff Johnson295189b2012-06-20 16:38:30 -07007769 complete(&pContext->completion);
Jeff Johnson72a40512013-12-19 10:14:15 -08007770
7771 /* serialization is complete */
7772 spin_unlock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07007773}
7774
7775/**---------------------------------------------------------------------------
7776
7777 \brief hdd_wlan_exit() - HDD WLAN exit function
7778
7779 This is the driver exit point (invoked during rmmod)
7780
7781 \param - pHddCtx - Pointer to the HDD Context
7782
7783 \return - None
7784
7785 --------------------------------------------------------------------------*/
7786void hdd_wlan_exit(hdd_context_t *pHddCtx)
7787{
7788 eHalStatus halStatus;
7789 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
7790 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05307791 struct wiphy *wiphy = pHddCtx->wiphy;
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -08007792 hdd_adapter_t* pAdapter = NULL;
Jeff Johnson72a40512013-12-19 10:14:15 -08007793 struct statsContext powerContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07007794 long lrc;
c_hpothu5ab05e92014-06-13 17:34:05 +05307795 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007796
7797 ENTER();
7798
Jeff Johnson88ba7742013-02-27 14:36:02 -08007799 if (VOS_FTM_MODE != hdd_get_conparam())
7800 {
7801 // Unloading, restart logic is no more required.
7802 wlan_hdd_restart_deinit(pHddCtx);
Jeff Johnsone7245742012-09-05 17:12:55 -07007803
c_hpothu5ab05e92014-06-13 17:34:05 +05307804 vosStatus = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7805 while (NULL != pAdapterNode && VOS_STATUS_E_EMPTY != vosStatus)
Jeff Johnson295189b2012-06-20 16:38:30 -07007806 {
c_hpothu5ab05e92014-06-13 17:34:05 +05307807 pAdapter = pAdapterNode->pAdapter;
7808 if (NULL != pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07007809 {
c_hpothu5ab05e92014-06-13 17:34:05 +05307810 if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode ||
7811 WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)
7812 {
7813 wlan_hdd_cfg80211_deregister_frames(pAdapter);
7814 hdd_UnregisterWext(pAdapter->dev);
7815 }
7816 // Cancel any outstanding scan requests. We are about to close all
7817 // of our adapters, but an adapter structure is what SME passes back
7818 // to our callback function. Hence if there are any outstanding scan
7819 // requests then there is a race condition between when the adapter
7820 // is closed and when the callback is invoked.We try to resolve that
7821 // race condition here by canceling any outstanding scans before we
7822 // close the adapters.
7823 // Note that the scans may be cancelled in an asynchronous manner,
7824 // so ideally there needs to be some kind of synchronization. Rather
7825 // than introduce a new synchronization here, we will utilize the
7826 // fact that we are about to Request Full Power, and since that is
7827 // synchronized, the expectation is that by the time Request Full
7828 // Power has completed all scans will be cancelled.
7829 if (pHddCtx->scan_info.mScanPending)
7830 {
7831 hddLog(VOS_TRACE_LEVEL_INFO,
7832 FL("abort scan mode: %d sessionId: %d"),
7833 pAdapter->device_mode,
7834 pAdapter->sessionId);
7835 hdd_abort_mac_scan(pHddCtx,
7836 pAdapter->sessionId,
7837 eCSR_SCAN_ABORT_DEFAULT);
7838 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007839 }
c_hpothu5ab05e92014-06-13 17:34:05 +05307840 vosStatus = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7841 pAdapterNode = pNext;
Jeff Johnson295189b2012-06-20 16:38:30 -07007842 }
7843 }
c_hpothu5ab05e92014-06-13 17:34:05 +05307844 else
Jeff Johnson88ba7742013-02-27 14:36:02 -08007845 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307846 hddLog(VOS_TRACE_LEVEL_INFO,"%s: FTM MODE",__func__);
Jeff Johnson88ba7742013-02-27 14:36:02 -08007847 wlan_hdd_ftm_close(pHddCtx);
7848 goto free_hdd_ctx;
7849 }
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307850
Jeff Johnson295189b2012-06-20 16:38:30 -07007851 /* DeRegister with platform driver as client for Suspend/Resume */
7852 vosStatus = hddDeregisterPmOps(pHddCtx);
7853 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
7854 {
7855 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
7856 VOS_ASSERT(0);
7857 }
7858
7859 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
7860 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
7861 {
7862 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
7863 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007864
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07007865 //Stop the traffic monitor timer
7866 if ( VOS_TIMER_STATE_RUNNING ==
7867 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr))
7868 {
7869 vos_timer_stop(&pHddCtx->tx_rx_trafficTmr);
7870 }
7871
7872 // Destroy the traffic monitor timer
7873 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
7874 &pHddCtx->tx_rx_trafficTmr)))
7875 {
7876 hddLog(VOS_TRACE_LEVEL_ERROR,
7877 "%s: Cannot deallocate Traffic monitor timer", __func__);
7878 }
7879
Jeff Johnson295189b2012-06-20 16:38:30 -07007880 //Disable IMPS/BMPS as we do not want the device to enter any power
7881 //save mode during shutdown
7882 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
7883 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
7884 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
7885
7886 //Ensure that device is in full power as we will touch H/W during vos_Stop
7887 init_completion(&powerContext.completion);
7888 powerContext.magic = POWER_CONTEXT_MAGIC;
7889
7890 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
7891 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
7892
7893 if (eHAL_STATUS_SUCCESS != halStatus)
7894 {
7895 if (eHAL_STATUS_PMC_PENDING == halStatus)
7896 {
7897 /* request was sent -- wait for the response */
7898 lrc = wait_for_completion_interruptible_timeout(
7899 &powerContext.completion,
7900 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
Jeff Johnson295189b2012-06-20 16:38:30 -07007901 if (lrc <= 0)
7902 {
7903 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007904 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07007905 }
7906 }
7907 else
7908 {
7909 hddLog(VOS_TRACE_LEVEL_ERROR,
7910 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007911 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07007912 /* continue -- need to clean up as much as possible */
7913 }
7914 }
7915
Jeff Johnson72a40512013-12-19 10:14:15 -08007916 /* either we never sent a request, we sent a request and received a
7917 response or we sent a request and timed out. if we never sent a
7918 request or if we sent a request and got a response, we want to
7919 clear the magic out of paranoia. if we timed out there is a
7920 race condition such that the callback function could be
7921 executing at the same time we are. of primary concern is if the
7922 callback function had already verified the "magic" but had not
7923 yet set the completion variable when a timeout occurred. we
7924 serialize these activities by invalidating the magic while
7925 holding a shared spinlock which will cause us to block if the
7926 callback is currently executing */
7927 spin_lock(&hdd_context_lock);
7928 powerContext.magic = 0;
7929 spin_unlock(&hdd_context_lock);
7930
Yue Ma0d4891e2013-08-06 17:01:45 -07007931 hdd_debugfs_exit(pHddCtx);
7932
Jeff Johnson295189b2012-06-20 16:38:30 -07007933 // Unregister the Net Device Notifier
7934 unregister_netdevice_notifier(&hdd_netdev_notifier);
7935
Jeff Johnson295189b2012-06-20 16:38:30 -07007936 hdd_stop_all_adapters( pHddCtx );
7937
Jeff Johnson295189b2012-06-20 16:38:30 -07007938#ifdef WLAN_BTAMP_FEATURE
7939 vosStatus = WLANBAP_Stop(pVosContext);
7940 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
7941 {
7942 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7943 "%s: Failed to stop BAP",__func__);
7944 }
7945#endif //WLAN_BTAMP_FEATURE
7946
7947 //Stop all the modules
7948 vosStatus = vos_stop( pVosContext );
7949 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
7950 {
7951 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7952 "%s: Failed to stop VOSS",__func__);
7953 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7954 }
7955
Jeff Johnson295189b2012-06-20 16:38:30 -07007956 //Assert Deep sleep signal now to put Libra HW in lowest power state
7957 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
7958 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7959
7960 //Vote off any PMIC voltage supplies
7961 vos_chipPowerDown(NULL, NULL, NULL);
7962
7963 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
7964
Leo Chang59cdc7e2013-07-10 10:08:21 -07007965
Jeff Johnson295189b2012-06-20 16:38:30 -07007966 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07007967 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07007968
7969 //Close the scheduler before calling vos_close to make sure no thread is
7970 // scheduled after the each module close is called i.e after all the data
7971 // structures are freed.
7972 vosStatus = vos_sched_close( pVosContext );
7973 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
7974 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
7975 "%s: Failed to close VOSS Scheduler",__func__);
7976 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7977 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007978#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07007979#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
7980 /* Destroy the wake lock */
7981 wake_lock_destroy(&pHddCtx->rx_wake_lock);
7982#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08007983 /* Destroy the wake lock */
7984 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007985#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007986
Mihir Shete7a24b5f2013-12-21 12:18:31 +05307987#ifdef CONFIG_ENABLE_LINUX_REG
7988 vosStatus = vos_nv_close();
7989 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
7990 {
7991 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7992 "%s: Failed to close NV", __func__);
7993 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7994 }
7995#endif
7996
Jeff Johnson295189b2012-06-20 16:38:30 -07007997 //Close VOSS
7998 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
7999 vos_close(pVosContext);
8000
Jeff Johnson295189b2012-06-20 16:38:30 -07008001 //Close Watchdog
8002 if(pHddCtx->cfg_ini->fIsLogpEnabled)
8003 vos_watchdog_close(pVosContext);
8004
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05308005 //Clean up HDD Nlink Service
8006 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05308007
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05308008#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05308009 if (pHddCtx->cfg_ini->wlanLoggingEnable)
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05308010 {
8011 wlan_logging_sock_deactivate_svc();
8012 }
8013#endif
8014
Vinay Krishna Erannaef30b522014-08-26 17:48:16 +05308015#ifdef WLAN_KD_READY_NOTIFIER
8016 nl_srv_exit(pHddCtx->ptt_pid);
8017#else
8018 nl_srv_exit();
8019#endif /* WLAN_KD_READY_NOTIFIER */
8020
8021
Jeff Johnson295189b2012-06-20 16:38:30 -07008022 /* Cancel the vote for XO Core ON.
8023 * This is done here to ensure there is no race condition since MC, TX and WD threads have
8024 * exited at this point
8025 */
8026 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
Arif Hussain6d2a3322013-11-17 19:50:10 -08008027 " when WLAN is turned OFF");
Jeff Johnson295189b2012-06-20 16:38:30 -07008028 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
8029 {
8030 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
8031 " Not returning failure."
Arif Hussain6d2a3322013-11-17 19:50:10 -08008032 " Power consumed will be high");
Jeff Johnson295189b2012-06-20 16:38:30 -07008033 }
8034
8035 hdd_close_all_adapters( pHddCtx );
8036
Jeff Johnson295189b2012-06-20 16:38:30 -07008037 /* free the power on lock from platform driver */
8038 if (free_riva_power_on_lock("wlan"))
8039 {
8040 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
8041 __func__);
8042 }
8043
Jeff Johnson88ba7742013-02-27 14:36:02 -08008044free_hdd_ctx:
c_hpothu78c7b602014-05-17 17:35:49 +05308045
8046 //Free up dynamically allocated members inside HDD Adapter
8047 if (pHddCtx->cfg_ini)
8048 {
8049 kfree(pHddCtx->cfg_ini);
8050 pHddCtx->cfg_ini= NULL;
8051 }
8052
Leo Changf04ddad2013-09-18 13:46:38 -07008053 /* FTM mode, WIPHY did not registered
8054 If un-register here, system crash will happen */
8055 if (VOS_FTM_MODE != hdd_get_conparam())
8056 {
8057 wiphy_unregister(wiphy) ;
8058 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008059 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07008060 if (hdd_is_ssr_required())
8061 {
8062 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07008063 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07008064 msleep(5000);
8065 }
8066 hdd_set_ssr_required (VOS_FALSE);
8067}
8068
8069
8070/**---------------------------------------------------------------------------
8071
8072 \brief hdd_update_config_from_nv() - Function to update the contents of
8073 the running configuration with parameters taken from NV storage
8074
8075 \param - pHddCtx - Pointer to the HDD global context
8076
8077 \return - VOS_STATUS_SUCCESS if successful
8078
8079 --------------------------------------------------------------------------*/
8080static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
8081{
Jeff Johnson295189b2012-06-20 16:38:30 -07008082 v_BOOL_t itemIsValid = VOS_FALSE;
8083 VOS_STATUS status;
8084 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
8085 v_U8_t macLoop;
8086
8087 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
8088 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
8089 if(status != VOS_STATUS_SUCCESS)
8090 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08008091 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed");
Jeff Johnson295189b2012-06-20 16:38:30 -07008092 return VOS_STATUS_E_FAILURE;
8093 }
8094
8095 if (itemIsValid == VOS_TRUE)
8096 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08008097 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV");
Jeff Johnson295189b2012-06-20 16:38:30 -07008098 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
8099 VOS_MAX_CONCURRENCY_PERSONA);
8100 if(status != VOS_STATUS_SUCCESS)
8101 {
8102 /* Get MAC from NV fail, not update CFG info
8103 * INI MAC value will be used for MAC setting */
Arif Hussain6d2a3322013-11-17 19:50:10 -08008104 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed");
Jeff Johnson295189b2012-06-20 16:38:30 -07008105 return VOS_STATUS_E_FAILURE;
8106 }
8107
8108 /* If first MAC is not valid, treat all others are not valid
8109 * Then all MACs will be got from ini file */
8110 if(vos_is_macaddr_zero(&macFromNV[0]))
8111 {
8112 /* MAC address in NV file is not configured yet */
8113 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
8114 return VOS_STATUS_E_INVAL;
8115 }
8116
8117 /* Get MAC address from NV, update CFG info */
8118 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
8119 {
8120 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
8121 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05308122 hddLog(VOS_TRACE_LEVEL_ERROR,"not valid MAC from NV for %d", macLoop);
Jeff Johnson295189b2012-06-20 16:38:30 -07008123 /* This MAC is not valid, skip it
8124 * This MAC will be got from ini file */
8125 }
8126 else
8127 {
8128 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
8129 (v_U8_t *)&macFromNV[macLoop].bytes[0],
8130 VOS_MAC_ADDR_SIZE);
8131 }
8132 }
8133 }
8134 else
8135 {
8136 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
8137 return VOS_STATUS_E_FAILURE;
8138 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008139
Jeff Johnson295189b2012-06-20 16:38:30 -07008140
8141 return VOS_STATUS_SUCCESS;
8142}
8143
8144/**---------------------------------------------------------------------------
8145
8146 \brief hdd_post_voss_start_config() - HDD post voss start config helper
8147
8148 \param - pAdapter - Pointer to the HDD
8149
8150 \return - None
8151
8152 --------------------------------------------------------------------------*/
8153VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
8154{
8155 eHalStatus halStatus;
8156 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308157 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -07008158
Jeff Johnson295189b2012-06-20 16:38:30 -07008159
8160 // Send ready indication to the HDD. This will kick off the MAC
8161 // into a 'running' state and should kick off an initial scan.
8162 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
8163 if ( !HAL_STATUS_SUCCESS( halStatus ) )
8164 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308165 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07008166 "code %08d [x%08x]",__func__, halStatus, halStatus );
8167 return VOS_STATUS_E_FAILURE;
8168 }
8169
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308170 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -07008171 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
8172 // And RIVA will crash
8173 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
8174 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05308175 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
8176 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
8177
8178
Jeff Johnson295189b2012-06-20 16:38:30 -07008179 return VOS_STATUS_SUCCESS;
8180}
8181
Jeff Johnson295189b2012-06-20 16:38:30 -07008182/* wake lock APIs for HDD */
8183void hdd_prevent_suspend(void)
8184{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008185#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008186 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008187#else
8188 wcnss_prevent_suspend();
8189#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008190}
8191
8192void hdd_allow_suspend(void)
8193{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008194#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008195 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008196#else
8197 wcnss_allow_suspend();
8198#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008199}
8200
Mahesh A Saptasagarb9c50402014-01-16 15:49:22 +05308201void hdd_prevent_suspend_timeout(v_U32_t timeout)
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07008202{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008203#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07008204 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07008205#else
8206 /* Do nothing as there is no API in wcnss for timeout*/
8207#endif
8208}
8209
Jeff Johnson295189b2012-06-20 16:38:30 -07008210/**---------------------------------------------------------------------------
8211
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008212 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
8213 information between Host and Riva
8214
8215 This function gets reported version of FW
8216 It also finds the version of Riva headers used to compile the host
8217 It compares the above two and prints a warning if they are different
8218 It gets the SW and HW version string
8219 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
8220 indicating the features they support through a bitmap
8221
8222 \param - pHddCtx - Pointer to HDD context
8223
8224 \return - void
8225
8226 --------------------------------------------------------------------------*/
8227
8228void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
8229{
8230
8231 tSirVersionType versionCompiled;
8232 tSirVersionType versionReported;
8233 tSirVersionString versionString;
8234 tANI_U8 fwFeatCapsMsgSupported = 0;
8235 VOS_STATUS vstatus;
8236
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -08008237 memset(&versionCompiled, 0, sizeof(versionCompiled));
8238 memset(&versionReported, 0, sizeof(versionReported));
8239
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008240 /* retrieve and display WCNSS version information */
8241 do {
8242
8243 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
8244 &versionCompiled);
8245 if (!VOS_IS_STATUS_SUCCESS(vstatus))
8246 {
8247 hddLog(VOS_TRACE_LEVEL_FATAL,
8248 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008249 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008250 break;
8251 }
8252
8253 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
8254 &versionReported);
8255 if (!VOS_IS_STATUS_SUCCESS(vstatus))
8256 {
8257 hddLog(VOS_TRACE_LEVEL_FATAL,
8258 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008259 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008260 break;
8261 }
8262
8263 if ((versionCompiled.major != versionReported.major) ||
8264 (versionCompiled.minor != versionReported.minor) ||
8265 (versionCompiled.version != versionReported.version) ||
8266 (versionCompiled.revision != versionReported.revision))
8267 {
8268 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
8269 "Host expected %u.%u.%u.%u\n",
8270 WLAN_MODULE_NAME,
8271 (int)versionReported.major,
8272 (int)versionReported.minor,
8273 (int)versionReported.version,
8274 (int)versionReported.revision,
8275 (int)versionCompiled.major,
8276 (int)versionCompiled.minor,
8277 (int)versionCompiled.version,
8278 (int)versionCompiled.revision);
8279 }
8280 else
8281 {
8282 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
8283 WLAN_MODULE_NAME,
8284 (int)versionReported.major,
8285 (int)versionReported.minor,
8286 (int)versionReported.version,
8287 (int)versionReported.revision);
8288 }
8289
8290 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
8291 versionString,
8292 sizeof(versionString));
8293 if (!VOS_IS_STATUS_SUCCESS(vstatus))
8294 {
8295 hddLog(VOS_TRACE_LEVEL_FATAL,
8296 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008297 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008298 break;
8299 }
8300
8301 pr_info("%s: WCNSS software version %s\n",
8302 WLAN_MODULE_NAME, versionString);
8303
8304 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
8305 versionString,
8306 sizeof(versionString));
8307 if (!VOS_IS_STATUS_SUCCESS(vstatus))
8308 {
8309 hddLog(VOS_TRACE_LEVEL_FATAL,
8310 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008311 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008312 break;
8313 }
8314
8315 pr_info("%s: WCNSS hardware version %s\n",
8316 WLAN_MODULE_NAME, versionString);
8317
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07008318 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
8319 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008320 send the message only if it the riva is 1.1
8321 minor numbers for different riva branches:
8322 0 -> (1.0)Mainline Build
8323 1 -> (1.1)Mainline Build
8324 2->(1.04) Stability Build
8325 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07008326 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008327 ((versionReported.minor>=1) && (versionReported.version>=1)))
8328 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
8329 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07008330
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008331 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08008332 {
8333#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
8334 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
8335 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
8336#endif
Ravi Joshid2ca7c42013-07-23 08:37:49 -07008337 /* Indicate if IBSS heartbeat monitoring needs to be offloaded */
8338 if (!pHddCtx->cfg_ini->enableIbssHeartBeatOffload)
8339 {
8340 sme_disableFeatureCapablity(IBSS_HEARTBEAT_OFFLOAD);
8341 }
8342
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008343 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08008344 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008345
8346 } while (0);
8347
8348}
Neelansh Mittaledafed22014-09-04 18:54:39 +05308349void wlan_hdd_send_svc_nlink_msg(int type, void *data, int len)
8350{
8351 struct sk_buff *skb;
8352 struct nlmsghdr *nlh;
8353 tAniMsgHdr *ani_hdr;
8354
8355 skb = alloc_skb(NLMSG_SPACE(WLAN_NL_MAX_PAYLOAD), GFP_KERNEL);
8356
8357 if(skb == NULL) {
8358 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8359 "%s: alloc_skb failed", __func__);
8360 return;
8361 }
8362
8363 nlh = (struct nlmsghdr *)skb->data;
8364 nlh->nlmsg_pid = 0; /* from kernel */
8365 nlh->nlmsg_flags = 0;
8366 nlh->nlmsg_seq = 0;
8367 nlh->nlmsg_type = WLAN_NL_MSG_SVC;
8368
8369 ani_hdr = NLMSG_DATA(nlh);
8370 ani_hdr->type = type;
8371
8372 switch(type) {
8373 case WLAN_SVC_SAP_RESTART_IND:
8374 ani_hdr->length = 0;
8375 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr)));
8376 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr)));
8377 break;
8378 default:
8379 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
8380 "Attempt to send unknown nlink message %d", type);
8381 kfree_skb(skb);
8382 return;
8383 }
8384
8385 nl_srv_bcast(skb);
8386
8387 return;
8388}
8389
8390
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008391
8392/**---------------------------------------------------------------------------
8393
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308394 \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
8395
8396 \param - pHddCtx - Pointer to the hdd context
8397
8398 \return - true if hardware supports 5GHz
8399
8400 --------------------------------------------------------------------------*/
Vinay Krishna Erannafacf5e22014-02-24 13:16:25 +05308401boolean hdd_is_5g_supported(hdd_context_t * pHddCtx)
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308402{
8403 /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
8404 * then hardware support 5Ghz.
8405 */
8406 if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode())
8407 {
Agarwal Ashish971c2882013-10-30 20:11:12 +05308408 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Hardware supports 5Ghz", __func__);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308409 return true;
8410 }
8411 else
8412 {
Agarwal Ashish971c2882013-10-30 20:11:12 +05308413 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Hardware doesn't supports 5Ghz",
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308414 __func__);
8415 return false;
8416 }
8417}
8418
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308419/**---------------------------------------------------------------------------
8420
8421 \brief hdd_generate_iface_mac_addr_auto() - HDD Mac Interface Auto
8422 generate function
8423
8424 This is generate the random mac address for WLAN interface
8425
8426 \param - pHddCtx - Pointer to HDD context
8427 idx - Start interface index to get auto
8428 generated mac addr.
8429 mac_addr - Mac address
8430
8431 \return - 0 for success, < 0 for failure
8432
8433 --------------------------------------------------------------------------*/
8434
8435static int hdd_generate_iface_mac_addr_auto(hdd_context_t *pHddCtx,
8436 int idx, v_MACADDR_t mac_addr)
8437{
8438 int i;
8439 unsigned int serialno;
8440 serialno = wcnss_get_serial_number();
8441
8442 if (0 != serialno)
8443 {
8444 /* MAC address has 3 bytes of OUI so we have a maximum of 3
8445 bytes of the serial number that can be used to generate
8446 the other 3 bytes of the MAC address. Mask off all but
8447 the lower 3 bytes (this will also make sure we don't
8448 overflow in the next step) */
8449 serialno &= 0x00FFFFFF;
8450
8451 /* we need a unique address for each session */
8452 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
8453
8454 /* autogen other Mac addresses */
8455 for (i = idx; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
8456 {
8457 /* start with the entire default address */
8458 pHddCtx->cfg_ini->intfMacAddr[i] = mac_addr;
8459 /* then replace the lower 3 bytes */
8460 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
8461 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
8462 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
8463
8464 serialno++;
8465 hddLog(VOS_TRACE_LEVEL_ERROR,
8466 "%s: Derived Mac Addr: "
8467 MAC_ADDRESS_STR, __func__,
8468 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[i].bytes));
8469 }
8470
8471 }
8472 else
8473 {
8474 hddLog(LOGE, FL("Failed to Get Serial NO"));
8475 return -1;
8476 }
8477 return 0;
8478}
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308479
8480/**---------------------------------------------------------------------------
8481
Mihir Shetefc7ff5b2014-01-27 11:30:05 +05308482 \brief hdd_11d_scan_done - callback to be executed when 11d scan is
8483 completed to flush out the scan results
8484
8485 11d scan is done during driver load and is a passive scan on all
8486 channels supported by the device, 11d scans may find some APs on
8487 frequencies which are forbidden to be used in the regulatory domain
8488 the device is operating in. If these APs are notified to the supplicant
8489 it may try to connect to these APs, thus flush out all the scan results
8490 which are present in SME after 11d scan is done.
8491
8492 \return - eHalStatus
8493
8494 --------------------------------------------------------------------------*/
8495static eHalStatus hdd_11d_scan_done(tHalHandle halHandle, void *pContext,
8496 tANI_U32 scanId, eCsrScanStatus status)
8497{
8498 ENTER();
8499
8500 sme_ScanFlushResult(halHandle, 0);
8501
8502 EXIT();
8503
8504 return eHAL_STATUS_SUCCESS;
8505}
8506
8507/**---------------------------------------------------------------------------
8508
Jeff Johnson295189b2012-06-20 16:38:30 -07008509 \brief hdd_wlan_startup() - HDD init function
8510
8511 This is the driver startup code executed once a WLAN device has been detected
8512
8513 \param - dev - Pointer to the underlying device
8514
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08008515 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07008516
8517 --------------------------------------------------------------------------*/
8518
8519int hdd_wlan_startup(struct device *dev )
8520{
8521 VOS_STATUS status;
8522 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07008523 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07008524 hdd_context_t *pHddCtx = NULL;
8525 v_CONTEXT_t pVosContext= NULL;
8526#ifdef WLAN_BTAMP_FEATURE
8527 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
8528 WLANBAP_ConfigType btAmpConfig;
8529 hdd_config_t *pConfig;
8530#endif
8531 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07008532 struct wiphy *wiphy;
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308533 v_MACADDR_t mac_addr;
Jeff Johnson295189b2012-06-20 16:38:30 -07008534
8535 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07008536 /*
8537 * cfg80211: wiphy allocation
8538 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308539 wiphy = wlan_hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t)) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07008540
8541 if(wiphy == NULL)
8542 {
8543 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08008544 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07008545 }
8546
8547 pHddCtx = wiphy_priv(wiphy);
8548
Jeff Johnson295189b2012-06-20 16:38:30 -07008549 //Initialize the adapter context to zeros.
8550 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
8551
Jeff Johnson295189b2012-06-20 16:38:30 -07008552 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07008553 hdd_prevent_suspend();
Mihir Shete18156292014-03-11 15:38:30 +05308554 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_LOAD_IN_PROGRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -07008555
8556 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
8557
8558 /*Get vos context here bcoz vos_open requires it*/
8559 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
8560
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08008561 if(pVosContext == NULL)
8562 {
8563 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
8564 goto err_free_hdd_context;
8565 }
8566
Jeff Johnson295189b2012-06-20 16:38:30 -07008567 //Save the Global VOSS context in adapter context for future.
8568 pHddCtx->pvosContext = pVosContext;
8569
8570 //Save the adapter context in global context for future.
8571 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
8572
Jeff Johnson295189b2012-06-20 16:38:30 -07008573 pHddCtx->parent_dev = dev;
8574
8575 init_completion(&pHddCtx->full_pwr_comp_var);
8576 init_completion(&pHddCtx->standby_comp_var);
8577 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07008578 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08008579 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Kiet Lam46b8e4e2013-11-06 21:49:53 +05308580 init_completion(&pHddCtx->wiphy_channel_update_event);
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +05308581 init_completion(&pHddCtx->ssr_comp_var);
Amar Singhala49cbc52013-10-08 18:37:44 -07008582
8583#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhalfddc28c2013-09-05 13:03:40 -07008584 init_completion(&pHddCtx->linux_reg_req);
Amar Singhala49cbc52013-10-08 18:37:44 -07008585#else
8586 init_completion(&pHddCtx->driver_crda_req);
8587#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008588
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05308589 spin_lock_init(&pHddCtx->schedScan_lock);
8590
Jeff Johnson295189b2012-06-20 16:38:30 -07008591 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
8592
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05308593#ifdef FEATURE_WLAN_TDLS
8594 /* tdls_lock is initialized before an hdd_open_adapter ( which is
8595 * invoked by other instances also) to protect the concurrent
8596 * access for the Adapters by TDLS module.
8597 */
8598 mutex_init(&pHddCtx->tdls_lock);
8599#endif
Agarwal Ashish1f422872014-07-22 00:11:55 +05308600 /* By default Strict Regulatory For FCC should be false */
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05308601
Agarwal Ashish1f422872014-07-22 00:11:55 +05308602 pHddCtx->nEnableStrictRegulatoryForFCC = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07008603 // Load all config first as TL config is needed during vos_open
8604 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
8605 if(pHddCtx->cfg_ini == NULL)
8606 {
8607 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
8608 goto err_free_hdd_context;
8609 }
8610
8611 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
8612
8613 // Read and parse the qcom_cfg.ini file
8614 status = hdd_parse_config_ini( pHddCtx );
8615 if ( VOS_STATUS_SUCCESS != status )
8616 {
8617 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
8618 __func__, WLAN_INI_FILE);
8619 goto err_config;
8620 }
Arif Hussaind5218912013-12-05 01:10:55 -08008621#ifdef MEMORY_DEBUG
8622 if (pHddCtx->cfg_ini->IsMemoryDebugSupportEnabled)
8623 vos_mem_init();
8624
8625 hddLog(VOS_TRACE_LEVEL_INFO, "%s: gEnableMemoryDebug=%d",
8626 __func__, pHddCtx->cfg_ini->IsMemoryDebugSupportEnabled);
8627#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008628
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05308629 /* INI has been read, initialise the configuredMcastBcastFilter with
8630 * INI value as this will serve as the default value
8631 */
8632 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
8633 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
8634 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05308635
8636 if (false == hdd_is_5g_supported(pHddCtx))
8637 {
8638 //5Ghz is not supported.
8639 if (1 != pHddCtx->cfg_ini->nBandCapability)
8640 {
8641 hddLog(VOS_TRACE_LEVEL_INFO,
8642 "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__);
8643 pHddCtx->cfg_ini->nBandCapability = 1;
8644 }
8645 }
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05308646
8647 /* If SNR Monitoring is enabled, FW has to parse all beacons
8648 * for calcaluting and storing the average SNR, so set Nth beacon
8649 * filter to 1 to enable FW to parse all the beaocons
8650 */
8651 if (1 == pHddCtx->cfg_ini->fEnableSNRMonitoring)
8652 {
8653 /* The log level is deliberately set to WARN as overriding
8654 * nthBeaconFilter to 1 will increase power cosumption and this
8655 * might just prove helpful to detect the power issue.
8656 */
8657 hddLog(VOS_TRACE_LEVEL_WARN,
8658 "%s: Setting pHddCtx->cfg_ini->nthBeaconFilter = 1", __func__);
8659 pHddCtx->cfg_ini->nthBeaconFilter = 1;
8660 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008661 /*
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308662 * cfg80211: Initialization ...
Jeff Johnson295189b2012-06-20 16:38:30 -07008663 */
Manjunathappa Prakasheec4ddf2014-01-13 18:23:51 -08008664 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07008665 {
Manjunathappa Prakasheec4ddf2014-01-13 18:23:51 -08008666 if (0 < wlan_hdd_cfg80211_init(dev, wiphy, pHddCtx->cfg_ini))
8667 {
8668 hddLog(VOS_TRACE_LEVEL_FATAL,
8669 "%s: wlan_hdd_cfg80211_init return failure", __func__);
8670 goto err_config;
8671 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008672 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008673
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08008674 // Update VOS trace levels based upon the cfg.ini
8675 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
8676 pHddCtx->cfg_ini->vosTraceEnableBAP);
8677 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
8678 pHddCtx->cfg_ini->vosTraceEnableTL);
8679 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
8680 pHddCtx->cfg_ini->vosTraceEnableWDI);
8681 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
8682 pHddCtx->cfg_ini->vosTraceEnableHDD);
8683 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
8684 pHddCtx->cfg_ini->vosTraceEnableSME);
8685 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
8686 pHddCtx->cfg_ini->vosTraceEnablePE);
Katya Nigam70d68332013-09-16 16:49:45 +05308687 hdd_vos_trace_enable(VOS_MODULE_ID_PMC,
8688 pHddCtx->cfg_ini->vosTraceEnablePMC);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08008689 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
8690 pHddCtx->cfg_ini->vosTraceEnableWDA);
8691 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
8692 pHddCtx->cfg_ini->vosTraceEnableSYS);
8693 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
8694 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08008695 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
8696 pHddCtx->cfg_ini->vosTraceEnableSAP);
8697 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
8698 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08008699
Jeff Johnson295189b2012-06-20 16:38:30 -07008700 // Update WDI trace levels based upon the cfg.ini
8701 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
8702 pHddCtx->cfg_ini->wdiTraceEnableDAL);
8703 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
8704 pHddCtx->cfg_ini->wdiTraceEnableCTL);
8705 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
8706 pHddCtx->cfg_ini->wdiTraceEnableDAT);
8707 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
8708 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07008709
Jeff Johnson88ba7742013-02-27 14:36:02 -08008710 if (VOS_FTM_MODE == hdd_get_conparam())
8711 {
Jeff Johnson295189b2012-06-20 16:38:30 -07008712 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
8713 {
8714 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
8715 goto err_free_hdd_context;
8716 }
8717 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
c_hpothu2de0ef62014-04-15 16:16:15 +05308718
8719 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -07008720 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08008721 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008722
Jeff Johnson88ba7742013-02-27 14:36:02 -08008723 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07008724 if(pHddCtx->cfg_ini->fIsLogpEnabled)
8725 {
8726 status = vos_watchdog_open(pVosContext,
8727 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
8728
8729 if(!VOS_IS_STATUS_SUCCESS( status ))
8730 {
8731 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308732 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07008733 }
8734 }
8735
8736 pHddCtx->isLogpInProgress = FALSE;
8737 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
8738
Jeff Johnson295189b2012-06-20 16:38:30 -07008739 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
8740 if(!VOS_IS_STATUS_SUCCESS(status))
8741 {
8742 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008743 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07008744 }
8745
Amar Singhala49cbc52013-10-08 18:37:44 -07008746#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -07008747 /* initialize the NV module. This is required so that
8748 we can initialize the channel information in wiphy
8749 from the NV.bin data. The channel information in
8750 wiphy needs to be initialized before wiphy registration */
8751
8752 status = vos_nv_open();
8753 if (!VOS_IS_STATUS_SUCCESS(status))
8754 {
8755 /* NV module cannot be initialized */
8756 hddLog( VOS_TRACE_LEVEL_FATAL,
8757 "%s: vos_nv_open failed", __func__);
8758 goto err_clkvote;
8759 }
8760
8761 status = vos_init_wiphy_from_nv_bin();
8762 if (!VOS_IS_STATUS_SUCCESS(status))
8763 {
8764 /* NV module cannot be initialized */
8765 hddLog( VOS_TRACE_LEVEL_FATAL,
8766 "%s: vos_init_wiphy failed", __func__);
8767 goto err_vos_nv_close;
8768 }
8769
Amar Singhala49cbc52013-10-08 18:37:44 -07008770#endif
8771
Arun Kumar Khandavalliebb19482014-03-25 13:56:53 +05308772 status = vos_open( &pVosContext, pHddCtx->parent_dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07008773 if ( !VOS_IS_STATUS_SUCCESS( status ))
8774 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008775 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
Mihir Shetee1093ba2014-01-21 20:13:32 +05308776 goto err_vos_nv_close;
Jeff Johnson295189b2012-06-20 16:38:30 -07008777 }
8778
Jeff Johnson295189b2012-06-20 16:38:30 -07008779 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
8780
8781 if ( NULL == pHddCtx->hHal )
8782 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008783 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008784 goto err_vosclose;
8785 }
8786
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008787 status = vos_preStart( pHddCtx->pvosContext );
8788 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8789 {
8790 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05308791 goto err_vosclose;
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008792 }
Jeff Johnsone7245742012-09-05 17:12:55 -07008793
Arif Hussaineaf68602013-12-30 23:10:44 -08008794 if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan)
8795 {
8796 pHddCtx->cfg_ini->enableDFSChnlScan = enable_dfs_chan_scan;
8797 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_dfs_chan_scan set to %d",
8798 __func__, enable_dfs_chan_scan);
8799 }
8800 if (0 == enable_11d || 1 == enable_11d)
8801 {
8802 pHddCtx->cfg_ini->Is11dSupportEnabled = enable_11d;
8803 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_11d set to %d",
8804 __func__, enable_11d);
8805 }
8806
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008807 /* Note that the vos_preStart() sequence triggers the cfg download.
8808 The cfg download must occur before we update the SME config
8809 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07008810 status = hdd_set_sme_config( pHddCtx );
8811
8812 if ( VOS_STATUS_SUCCESS != status )
8813 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008814 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05308815 goto err_vosclose;
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008816 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008817
Jeff Johnson295189b2012-06-20 16:38:30 -07008818 /* In the integrated architecture we update the configuration from
8819 the INI file and from NV before vOSS has been started so that
8820 the final contents are available to send down to the cCPU */
8821
8822 // Apply the cfg.ini to cfg.dat
8823 if (FALSE == hdd_update_config_dat(pHddCtx))
8824 {
8825 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05308826 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07008827 }
8828
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308829 // Get mac addr from platform driver
8830 ret = wcnss_get_wlan_mac_address((char*)&mac_addr.bytes);
8831
8832 if ((0 == ret) && (!vos_is_macaddr_zero(&mac_addr)))
Jeff Johnson295189b2012-06-20 16:38:30 -07008833 {
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308834 /* Store the mac addr for first interface */
8835 pHddCtx->cfg_ini->intfMacAddr[0] = mac_addr;
8836
8837 hddLog(VOS_TRACE_LEVEL_ERROR,
8838 "%s: WLAN Mac Addr: "
8839 MAC_ADDRESS_STR, __func__,
8840 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
8841
8842 /* Here, passing Arg2 as 1 because we do not want to change the
8843 last 3 bytes (means non OUI bytes) of first interface mac
8844 addr.
8845 */
8846 if (0 != hdd_generate_iface_mac_addr_auto(pHddCtx, 1, mac_addr))
8847 {
8848 hddLog(VOS_TRACE_LEVEL_ERROR,
8849 "%s: Failed to generate wlan interface mac addr "
8850 "using MAC from ini file ", __func__);
8851 }
8852 }
8853 else if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
8854 {
8855 // Apply the NV to cfg.dat
8856 /* Prima Update MAC address only at here */
Jeff Johnson295189b2012-06-20 16:38:30 -07008857#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
8858 /* There was not a valid set of MAC Addresses in NV. See if the
8859 default addresses were modified by the cfg.ini settings. If so,
8860 we'll use them, but if not, we'll autogenerate a set of MAC
8861 addresses based upon the device serial number */
8862
8863 static const v_MACADDR_t default_address =
8864 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
Jeff Johnson295189b2012-06-20 16:38:30 -07008865
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308866 if (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
8867 sizeof(default_address)))
Jeff Johnson295189b2012-06-20 16:38:30 -07008868 {
8869 /* cfg.ini has the default address, invoke autogen logic */
8870
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308871 /* Here, passing Arg2 as 0 because we want to change the
8872 last 3 bytes (means non OUI bytes) of all the interfaces
8873 mac addr.
8874 */
8875 if (0 != hdd_generate_iface_mac_addr_auto(pHddCtx, 0,
8876 default_address))
Jeff Johnson295189b2012-06-20 16:38:30 -07008877 {
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308878 hddLog(VOS_TRACE_LEVEL_ERROR,
8879 "%s: Failed to generate wlan interface mac addr "
8880 "using MAC from ini file " MAC_ADDRESS_STR, __func__,
8881 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
Jeff Johnson295189b2012-06-20 16:38:30 -07008882 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008883 }
8884 else
8885#endif //WLAN_AUTOGEN_MACADDR_FEATURE
8886 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008887 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07008888 "%s: Invalid MAC address in NV, using MAC from ini file "
8889 MAC_ADDRESS_STR, __func__,
8890 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
8891 }
8892 }
8893 {
8894 eHalStatus halStatus;
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308895
8896 /* Set the MAC Address Currently this is used by HAL to
8897 * add self sta. Remove this once self sta is added as
8898 * part of session open.
8899 */
Jeff Johnson295189b2012-06-20 16:38:30 -07008900 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
8901 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
8902 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308903
Jeff Johnson295189b2012-06-20 16:38:30 -07008904 if (!HAL_STATUS_SUCCESS( halStatus ))
8905 {
8906 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
8907 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05308908 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07008909 }
8910 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008911
8912 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
8913 Note: Firmware image will be read and downloaded inside vos_start API */
8914 status = vos_start( pHddCtx->pvosContext );
8915 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8916 {
8917 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05308918 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07008919 }
8920
Leo Chang6cec3e22014-01-21 15:33:49 -08008921#ifdef FEATURE_WLAN_CH_AVOID
8922 /* Plug in avoid channel notification callback
8923 * This should happen before ADD_SELF_STA
8924 * FW will send first IND with ADD_SELF_STA REQ from host */
Pradeep Reddy POTTETI5c2e16d2014-06-27 16:47:38 +05308925
8926 /* check the Channel Avoidance is enabled */
8927 if (TRUE == pHddCtx->cfg_ini->fenableCHAvoidance)
8928 {
8929 sme_AddChAvoidCallback(pHddCtx->hHal,
8930 hdd_hostapd_ch_avoid_cb);
8931 }
Leo Chang6cec3e22014-01-21 15:33:49 -08008932#endif /* FEATURE_WLAN_CH_AVOID */
8933
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008934 /* Exchange capability info between Host and FW and also get versioning info from FW */
8935 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07008936
Agarwal Ashishad9281b2014-06-10 14:57:30 +05308937#ifdef CONFIG_ENABLE_LINUX_REG
8938 status = wlan_hdd_init_channels(pHddCtx);
8939 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8940 {
8941 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: wlan_hdd_init_channels failed",
8942 __func__);
8943 goto err_vosstop;
8944 }
8945#endif
8946
Jeff Johnson295189b2012-06-20 16:38:30 -07008947 status = hdd_post_voss_start_config( pHddCtx );
8948 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8949 {
8950 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
8951 __func__);
8952 goto err_vosstop;
8953 }
Amar Singhala49cbc52013-10-08 18:37:44 -07008954
8955#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308956 wlan_hdd_cfg80211_update_reg_info( wiphy );
8957
8958 /* registration of wiphy dev with cfg80211 */
8959 if (0 > wlan_hdd_cfg80211_register(wiphy))
8960 {
8961 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
8962 goto err_vosstop;
8963 }
Amar Singhala49cbc52013-10-08 18:37:44 -07008964#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008965
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05308966#ifdef CONFIG_ENABLE_LINUX_REG
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05308967 /* registration of wiphy dev with cfg80211 */
8968 if (0 > wlan_hdd_cfg80211_register(wiphy))
8969 {
8970 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
8971 goto err_vosstop;
8972 }
8973
8974 status = wlan_hdd_init_channels_for_cc(pHddCtx);
8975 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8976 {
8977 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: wlan_hdd_init_channels_for_cc failed",
8978 __func__);
8979 goto err_unregister_wiphy;
8980 }
8981#endif
8982
Jeff Johnson295189b2012-06-20 16:38:30 -07008983 if (VOS_STA_SAP_MODE == hdd_get_conparam())
8984 {
8985 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
8986 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
8987 }
8988 else
8989 {
Jeff Johnson295189b2012-06-20 16:38:30 -07008990 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
8991 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
8992 if (pAdapter != NULL)
8993 {
kaidde69982014-06-18 13:23:21 +08008994 if (pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated && !(pHddCtx->cfg_ini->intfMacAddr[0].bytes[0] &= 0x02))
Jeff Johnson295189b2012-06-20 16:38:30 -07008995 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05308996 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
8997 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
8998 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07008999
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05309000 /* Generate the P2P Device Address. This consists of the device's
9001 * primary MAC address with the locally administered bit set.
9002 */
9003 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07009004 }
9005 else
9006 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05309007 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
9008 if (p2p_dev_addr != NULL)
9009 {
9010 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
9011 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
9012 }
9013 else
9014 {
9015 hddLog(VOS_TRACE_LEVEL_FATAL,
9016 "%s: Failed to allocate mac_address for p2p_device",
9017 __func__);
9018 goto err_close_adapter;
9019 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009020 }
Jeff Johnsone7245742012-09-05 17:12:55 -07009021
9022 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
9023 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
9024 if ( NULL == pP2pAdapter )
9025 {
9026 hddLog(VOS_TRACE_LEVEL_FATAL,
9027 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07009028 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07009029 goto err_close_adapter;
9030 }
Jeff Johnsone7245742012-09-05 17:12:55 -07009031 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009032 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009033
9034 if( pAdapter == NULL )
9035 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08009036 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
9037 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07009038 }
Jeff Johnsone7245742012-09-05 17:12:55 -07009039
Arif Hussain66559122013-11-21 10:11:40 -08009040 if (country_code)
9041 {
9042 eHalStatus ret;
Arif Hussaincb607082013-12-20 11:57:42 -08009043 INIT_COMPLETION(pAdapter->change_country_code);
Arif Hussain66559122013-11-21 10:11:40 -08009044 hdd_checkandupdate_dfssetting(pAdapter, country_code);
9045#ifndef CONFIG_ENABLE_LINUX_REG
9046 hdd_checkandupdate_phymode(pAdapter, country_code);
9047#endif
Arif Hussaineaf68602013-12-30 23:10:44 -08009048 ret = sme_ChangeCountryCode(pHddCtx->hHal,
9049 (void *)(tSmeChangeCountryCallback)
9050 wlan_hdd_change_country_code_callback,
Arif Hussain66559122013-11-21 10:11:40 -08009051 country_code,
9052 pAdapter, pHddCtx->pvosContext,
Abhishek Singha306a442013-11-07 18:39:01 +05309053 eSIR_TRUE, eSIR_TRUE);
Arif Hussain66559122013-11-21 10:11:40 -08009054 if (eHAL_STATUS_SUCCESS == ret)
9055 {
Arif Hussaincb607082013-12-20 11:57:42 -08009056 ret = wait_for_completion_interruptible_timeout(
9057 &pAdapter->change_country_code,
9058 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
9059
9060 if (0 >= ret)
9061 {
9062 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
9063 "%s: SME while setting country code timed out", __func__);
9064 }
Arif Hussain66559122013-11-21 10:11:40 -08009065 }
9066 else
9067 {
Arif Hussaincb607082013-12-20 11:57:42 -08009068 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
9069 "%s: SME Change Country code from module param fail ret=%d",
9070 __func__, ret);
Arif Hussain66559122013-11-21 10:11:40 -08009071 }
9072 }
9073
Jeff Johnson295189b2012-06-20 16:38:30 -07009074#ifdef WLAN_BTAMP_FEATURE
9075 vStatus = WLANBAP_Open(pVosContext);
9076 if(!VOS_IS_STATUS_SUCCESS(vStatus))
9077 {
9078 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
9079 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07009080 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07009081 }
9082
9083 vStatus = BSL_Init(pVosContext);
9084 if(!VOS_IS_STATUS_SUCCESS(vStatus))
9085 {
9086 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
9087 "%s: Failed to Init BSL",__func__);
9088 goto err_bap_close;
9089 }
9090 vStatus = WLANBAP_Start(pVosContext);
9091 if (!VOS_IS_STATUS_SUCCESS(vStatus))
9092 {
9093 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
9094 "%s: Failed to start TL",__func__);
9095 goto err_bap_close;
9096 }
9097
9098 pConfig = pHddCtx->cfg_ini;
9099 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
9100 status = WLANBAP_SetConfig(&btAmpConfig);
9101
9102#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07009103
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07009104#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
9105 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
9106 {
9107 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
9108 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
9109 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
9110 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
9111 }
9112#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009113
Agarwal Ashish4b87f922014-06-18 03:03:21 +05309114 wlan_hdd_tdls_init(pHddCtx);
9115
Mihir Shetefc7ff5b2014-01-27 11:30:05 +05309116 sme_Register11dScanDoneCallback(pHddCtx->hHal, hdd_11d_scan_done);
9117
Jeff Johnson295189b2012-06-20 16:38:30 -07009118 /* Register with platform driver as client for Suspend/Resume */
9119 status = hddRegisterPmOps(pHddCtx);
9120 if ( !VOS_IS_STATUS_SUCCESS( status ) )
9121 {
9122 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
9123#ifdef WLAN_BTAMP_FEATURE
9124 goto err_bap_stop;
9125#else
Jeff Johnsone7245742012-09-05 17:12:55 -07009126 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07009127#endif //WLAN_BTAMP_FEATURE
9128 }
9129
Yue Ma0d4891e2013-08-06 17:01:45 -07009130 /* Open debugfs interface */
9131 if (VOS_STATUS_SUCCESS != hdd_debugfs_init(pAdapter))
9132 {
9133 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
9134 "%s: hdd_debugfs_init failed!", __func__);
Yue Ma0d4891e2013-08-06 17:01:45 -07009135 }
9136
Jeff Johnson295189b2012-06-20 16:38:30 -07009137 /* Register TM level change handler function to the platform */
9138 status = hddDevTmRegisterNotifyCallback(pHddCtx);
9139 if ( !VOS_IS_STATUS_SUCCESS( status ) )
9140 {
9141 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
9142 goto err_unregister_pmops;
9143 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009144
9145 /* register for riva power on lock to platform driver */
9146 if (req_riva_power_on_lock("wlan"))
9147 {
9148 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
9149 __func__);
9150 goto err_unregister_pmops;
9151 }
9152
Jeff Johnson295189b2012-06-20 16:38:30 -07009153 // register net device notifier for device change notification
9154 ret = register_netdevice_notifier(&hdd_netdev_notifier);
9155
9156 if(ret < 0)
9157 {
9158 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
9159 goto err_free_power_on_lock;
9160 }
9161
9162 //Initialize the nlink service
9163 if(nl_srv_init() != 0)
9164 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05309165 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009166 goto err_reg_netdev;
9167 }
9168
Leo Chang4ce1cc52013-10-21 18:27:15 -07009169#ifdef WLAN_KD_READY_NOTIFIER
9170 pHddCtx->kd_nl_init = 1;
9171#endif /* WLAN_KD_READY_NOTIFIER */
9172
Jeff Johnson295189b2012-06-20 16:38:30 -07009173 //Initialize the BTC service
9174 if(btc_activate_service(pHddCtx) != 0)
9175 {
9176 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
9177 goto err_nl_srv;
9178 }
9179
9180#ifdef PTT_SOCK_SVC_ENABLE
9181 //Initialize the PTT service
9182 if(ptt_sock_activate_svc(pHddCtx) != 0)
9183 {
9184 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
9185 goto err_nl_srv;
9186 }
9187#endif
9188
Vinay Krishna Erannad938c422014-03-10 17:14:21 +05309189#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9190 if(pHddCtx->cfg_ini && pHddCtx->cfg_ini->wlanLoggingEnable)
9191 {
9192 if(wlan_logging_sock_activate_svc(
9193 pHddCtx->cfg_ini->wlanLoggingFEToConsole,
9194 pHddCtx->cfg_ini->wlanLoggingNumBuf))
9195 {
9196 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wlan_logging_sock_activate_svc"
9197 " failed", __func__);
9198 goto err_nl_srv;
9199 }
9200 }
9201#endif
9202
Jeff Johnson295189b2012-06-20 16:38:30 -07009203 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07009204 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07009205 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07009206 /* Action frame registered in one adapter which will
9207 * applicable to all interfaces
9208 */
Agarwal Ashish8fa0e9a2014-05-23 00:40:12 +05309209 wlan_hdd_cfg80211_register_frames(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07009210 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009211
9212 mutex_init(&pHddCtx->sap_lock);
9213
Jeff Johnson295189b2012-06-20 16:38:30 -07009214
Sameer Thalappil50dc0092013-02-19 17:23:33 -08009215#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07009216#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
9217 /* Initialize the wake lcok */
9218 wake_lock_init(&pHddCtx->rx_wake_lock,
9219 WAKE_LOCK_SUSPEND,
9220 "qcom_rx_wakelock");
9221#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08009222 /* Initialize the wake lcok */
9223 wake_lock_init(&pHddCtx->sap_wake_lock,
9224 WAKE_LOCK_SUSPEND,
9225 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08009226#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07009227
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07009228 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
9229 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07009230
Katya Nigam5c306ea2014-06-19 15:39:54 +05309231 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_NO_LOAD_UNLOAD_IN_PROGRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -07009232 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
9233 hdd_allow_suspend();
Katya Nigam5c306ea2014-06-19 15:39:54 +05309234
9235#ifdef FEATURE_WLAN_SCAN_PNO
9236 /*SME must send channel update configuration to RIVA*/
9237 sme_UpdateChannelConfig(pHddCtx->hHal);
9238#endif
Abhishek Singhf644b272014-08-21 02:59:39 +05309239 /* Send the update default channel list to the FW*/
9240 sme_UpdateChannelList(pHddCtx->hHal);
Abhishek Singha306a442013-11-07 18:39:01 +05309241#ifndef CONFIG_ENABLE_LINUX_REG
9242 /*updating wiphy so that regulatory user hints can be processed*/
9243 if (wiphy)
9244 {
9245 regulatory_hint(wiphy, "00");
9246 }
9247#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07009248 // Initialize the restart logic
9249 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05309250
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07009251 //Register the traffic monitor timer now
9252 if ( pHddCtx->cfg_ini->dynSplitscan)
9253 {
9254 vos_timer_init(&pHddCtx->tx_rx_trafficTmr,
9255 VOS_TIMER_TYPE_SW,
9256 hdd_tx_rx_pkt_cnt_stat_timer_handler,
9257 (void *)pHddCtx);
9258 }
Dino Mycle6fb96c12014-06-10 11:52:40 +05309259#ifdef WLAN_FEATURE_EXTSCAN
9260 sme_EXTScanRegisterCallback(pHddCtx->hHal,
9261 wlan_hdd_cfg80211_extscan_callback,
9262 pHddCtx);
9263#endif /* WLAN_FEATURE_EXTSCAN */
Jeff Johnson295189b2012-06-20 16:38:30 -07009264 goto success;
9265
9266err_nl_srv:
Leo Chang59cdc7e2013-07-10 10:08:21 -07009267#ifdef WLAN_KD_READY_NOTIFIER
9268 nl_srv_exit(pHddCtx->ptt_pid);
9269#else
Jeff Johnson295189b2012-06-20 16:38:30 -07009270 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07009271#endif /* WLAN_KD_READY_NOTIFIER */
Jeff Johnson295189b2012-06-20 16:38:30 -07009272err_reg_netdev:
9273 unregister_netdevice_notifier(&hdd_netdev_notifier);
9274
9275err_free_power_on_lock:
9276 free_riva_power_on_lock("wlan");
9277
9278err_unregister_pmops:
9279 hddDevTmUnregisterNotifyCallback(pHddCtx);
9280 hddDeregisterPmOps(pHddCtx);
9281
Yue Ma0d4891e2013-08-06 17:01:45 -07009282 hdd_debugfs_exit(pHddCtx);
9283
Jeff Johnson295189b2012-06-20 16:38:30 -07009284#ifdef WLAN_BTAMP_FEATURE
9285err_bap_stop:
9286 WLANBAP_Stop(pVosContext);
9287#endif
9288
9289#ifdef WLAN_BTAMP_FEATURE
9290err_bap_close:
9291 WLANBAP_Close(pVosContext);
9292#endif
9293
Jeff Johnson295189b2012-06-20 16:38:30 -07009294err_close_adapter:
9295 hdd_close_all_adapters( pHddCtx );
Mahesh A Saptasagar9ecefe42014-07-15 18:43:49 +05309296#ifdef CONFIG_ENABLE_LINUX_REG
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +05309297err_unregister_wiphy:
Mahesh A Saptasagar9ecefe42014-07-15 18:43:49 +05309298#endif
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05309299 wiphy_unregister(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07009300err_vosstop:
9301 vos_stop(pVosContext);
9302
Amar Singhala49cbc52013-10-08 18:37:44 -07009303err_vosclose:
Jeff Johnson295189b2012-06-20 16:38:30 -07009304 status = vos_sched_close( pVosContext );
9305 if (!VOS_IS_STATUS_SUCCESS(status)) {
9306 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
9307 "%s: Failed to close VOSS Scheduler", __func__);
9308 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
9309 }
Amar Singhala49cbc52013-10-08 18:37:44 -07009310 vos_close(pVosContext );
9311
Amar Singhal0a402232013-10-11 20:57:16 -07009312err_vos_nv_close:
9313
c_hpothue6a36282014-03-19 12:27:38 +05309314#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -07009315 vos_nv_close();
9316
Jeff Johnson295189b2012-06-20 16:38:30 -07009317err_clkvote:
c_hpothu70f8d812014-03-22 22:59:23 +05309318#endif
Jeff Johnsonbc676b42013-02-14 16:04:08 -08009319 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07009320
9321err_wdclose:
9322 if(pHddCtx->cfg_ini->fIsLogpEnabled)
9323 vos_watchdog_close(pVosContext);
9324
Jeff Johnson295189b2012-06-20 16:38:30 -07009325err_config:
9326 kfree(pHddCtx->cfg_ini);
9327 pHddCtx->cfg_ini= NULL;
9328
9329err_free_hdd_context:
9330 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07009331 wiphy_free(wiphy) ;
9332 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07009333 VOS_BUG(1);
9334
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08009335 if (hdd_is_ssr_required())
9336 {
9337 /* WDI timeout had happened during load, so SSR is needed here */
9338 subsystem_restart("wcnss");
9339 msleep(5000);
9340 }
9341 hdd_set_ssr_required (VOS_FALSE);
9342
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08009343 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07009344
9345success:
9346 EXIT();
9347 return 0;
9348}
9349
9350/**---------------------------------------------------------------------------
9351
Jeff Johnson32d95a32012-09-10 13:15:23 -07009352 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07009353
Jeff Johnson32d95a32012-09-10 13:15:23 -07009354 This is the driver entry point - called in different timeline depending
9355 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07009356
9357 \param - None
9358
9359 \return - 0 for success, non zero for failure
9360
9361 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07009362static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07009363{
9364 VOS_STATUS status;
9365 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07009366 struct device *dev = NULL;
9367 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07009368#ifdef HAVE_WCNSS_CAL_DOWNLOAD
9369 int max_retries = 0;
9370#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009371
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05309372#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9373 wlan_logging_sock_init_svc();
9374#endif
9375
Jeff Johnson295189b2012-06-20 16:38:30 -07009376 ENTER();
9377
Sameer Thalappil50dc0092013-02-19 17:23:33 -08009378#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07009379 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07009380#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009381
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05309382 hddTraceInit();
Jeff Johnson295189b2012-06-20 16:38:30 -07009383 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
9384 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
9385
9386 //Power Up Libra WLAN card first if not already powered up
9387 status = vos_chipPowerUp(NULL,NULL,NULL);
9388 if (!VOS_IS_STATUS_SUCCESS(status))
9389 {
9390 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
9391 "exiting", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05309392#ifdef WLAN_OPEN_SOURCE
9393 wake_lock_destroy(&wlan_wake_lock);
9394#endif
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05309395
9396#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9397 wlan_logging_sock_deinit_svc();
9398#endif
9399
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08009400 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07009401 }
9402
Jeff Johnson295189b2012-06-20 16:38:30 -07009403#ifdef ANI_BUS_TYPE_PCI
9404
9405 dev = wcnss_wlan_get_device();
9406
9407#endif // ANI_BUS_TYPE_PCI
9408
9409#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07009410
9411#ifdef HAVE_WCNSS_CAL_DOWNLOAD
9412 /* wait until WCNSS driver downloads NV */
9413 while (!wcnss_device_ready() && 5 >= ++max_retries) {
9414 msleep(1000);
9415 }
9416 if (max_retries >= 5) {
9417 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05309418#ifdef WLAN_OPEN_SOURCE
9419 wake_lock_destroy(&wlan_wake_lock);
9420#endif
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05309421
9422#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9423 wlan_logging_sock_deinit_svc();
9424#endif
9425
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07009426 return -ENODEV;
9427 }
9428#endif
9429
Jeff Johnson295189b2012-06-20 16:38:30 -07009430 dev = wcnss_wlan_get_device();
9431#endif // ANI_BUS_TYPE_PLATFORM
9432
9433
9434 do {
9435 if (NULL == dev) {
9436 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
9437 ret_status = -1;
9438 break;
9439 }
9440
Jeff Johnson295189b2012-06-20 16:38:30 -07009441#ifdef TIMER_MANAGER
9442 vos_timer_manager_init();
9443#endif
9444
9445 /* Preopen VOSS so that it is ready to start at least SAL */
9446 status = vos_preOpen(&pVosContext);
9447
9448 if (!VOS_IS_STATUS_SUCCESS(status))
9449 {
9450 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
9451 ret_status = -1;
9452 break;
9453 }
9454
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009455#ifndef MODULE
9456 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
9457 */
9458 hdd_set_conparam((v_UINT_t)con_mode);
9459#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009460
9461 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08009462 if (hdd_wlan_startup(dev))
9463 {
Jeff Johnson295189b2012-06-20 16:38:30 -07009464 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08009465 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009466 vos_preClose( &pVosContext );
9467 ret_status = -1;
9468 break;
9469 }
9470
9471 /* Cancel the vote for XO Core ON
9472 * This is done here for safety purposes in case we re-initialize without turning
9473 * it OFF in any error scenario.
9474 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07009475 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07009476 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07009477 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07009478 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
9479 {
9480 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
Arif Hussain6d2a3322013-11-17 19:50:10 -08009481 " Power consumed will be high");
Jeff Johnson295189b2012-06-20 16:38:30 -07009482 }
9483 } while (0);
9484
9485 if (0 != ret_status)
9486 {
9487 //Assert Deep sleep signal now to put Libra HW in lowest power state
9488 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
9489 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
9490
9491 //Vote off any PMIC voltage supplies
9492 vos_chipPowerDown(NULL, NULL, NULL);
9493#ifdef TIMER_MANAGER
9494 vos_timer_exit();
9495#endif
9496#ifdef MEMORY_DEBUG
9497 vos_mem_exit();
9498#endif
9499
Sameer Thalappil50dc0092013-02-19 17:23:33 -08009500#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07009501 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07009502#endif
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05309503
9504#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9505 wlan_logging_sock_deinit_svc();
9506#endif
9507
Jeff Johnson295189b2012-06-20 16:38:30 -07009508 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
9509 }
9510 else
9511 {
9512 //Send WLAN UP indication to Nlink Service
9513 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
9514
9515 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Jeff Johnson295189b2012-06-20 16:38:30 -07009516 }
9517
9518 EXIT();
9519
9520 return ret_status;
9521}
9522
Jeff Johnson32d95a32012-09-10 13:15:23 -07009523/**---------------------------------------------------------------------------
9524
9525 \brief hdd_module_init() - Init Function
9526
9527 This is the driver entry point (invoked when module is loaded using insmod)
9528
9529 \param - None
9530
9531 \return - 0 for success, non zero for failure
9532
9533 --------------------------------------------------------------------------*/
9534#ifdef MODULE
9535static int __init hdd_module_init ( void)
9536{
9537 return hdd_driver_init();
9538}
Jeff Johnson32d95a32012-09-10 13:15:23 -07009539#else /* #ifdef MODULE */
9540static int __init hdd_module_init ( void)
9541{
9542 /* Driver initialization is delayed to fwpath_changed_handler */
9543 return 0;
9544}
Jeff Johnson32d95a32012-09-10 13:15:23 -07009545#endif /* #ifdef MODULE */
9546
Jeff Johnson295189b2012-06-20 16:38:30 -07009547
9548/**---------------------------------------------------------------------------
9549
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009550 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07009551
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009552 This is the driver exit point (invoked when module is unloaded using rmmod
9553 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07009554
9555 \param - None
9556
9557 \return - None
9558
9559 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009560static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07009561{
9562 hdd_context_t *pHddCtx = NULL;
9563 v_CONTEXT_t pVosContext = NULL;
Agarwal Ashish5e414792014-06-08 15:25:23 +05309564 v_REGDOMAIN_t regId;
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +05309565 unsigned long rc = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07009566
9567 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
9568
9569 //Get the global vos context
9570 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
9571
9572 if(!pVosContext)
9573 {
9574 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
9575 goto done;
9576 }
9577
9578 //Get the HDD context.
9579 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
9580
9581 if(!pHddCtx)
9582 {
9583 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
9584 }
9585 else
9586 {
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +05309587 INIT_COMPLETION(pHddCtx->ssr_comp_var);
9588
9589 if (pHddCtx->isLogpInProgress)
9590 {
Sameer Thalappil451ebb92013-06-28 15:49:58 -07009591 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +05309592 "%s:SSR in Progress; block rmmod !!!", __func__);
9593 rc = wait_for_completion_timeout(&pHddCtx->ssr_comp_var,
9594 msecs_to_jiffies(30000));
9595 if(!rc)
9596 {
9597 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
9598 "%s:SSR timedout, fatal error", __func__);
9599 VOS_BUG(0);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07009600 }
Arun Kumar Khandavallie0b046d2014-03-01 21:54:25 +05309601 }
Jeff Johnson295189b2012-06-20 16:38:30 -07009602
Mihir Shete18156292014-03-11 15:38:30 +05309603 pHddCtx->isLoadUnloadInProgress = WLAN_HDD_UNLOAD_IN_PROGRESS;
Jeff Johnson295189b2012-06-20 16:38:30 -07009604 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
9605
Agarwal Ashish8db39882014-07-30 21:56:07 +05309606 /* Driver Need to send country code 00 in below condition
9607 * 1) If gCountryCodePriority is set to 1; and last country
9608 * code set is through 11d. This needs to be done in case
9609 * when NV country code is 00.
9610 * This Needs to be done as when kernel store last country
9611 * code and if stored country code is not through 11d,
9612 * in sme_HandleChangeCountryCodeByUser we will disable 11d
9613 * in next load/unload as soon as we get any country through
9614 * 11d. In sme_HandleChangeCountryCodeByUser
9615 * pMsg->countryCode will be last countryCode and
9616 * pMac->scan.countryCode11d will be country through 11d so
9617 * due to mismatch driver will disable 11d.
9618 *
9619 * 2) When NV country Code is non-zero ;
9620 * There are chances that kernel last country and default
9621 * country can be same. In this case if Driver doesn't pass 00 to
9622 * kernel, at the time of driver loading next timer, driver will not
9623 * call any hint to kernel as country is same. This can add 3 sec
9624 * delay in driver loading.
9625 */
9626
9627 if ((eANI_BOOLEAN_TRUE == sme_Is11dCountrycode(pHddCtx->hHal) &&
Agarwal Ashish8dcd2862014-07-25 11:58:52 +05309628 pHddCtx->cfg_ini->fSupplicantCountryCodeHasPriority &&
Agarwal Ashish8db39882014-07-30 21:56:07 +05309629 sme_Is11dSupported(pHddCtx->hHal)) || (vos_is_nv_country_non_zero() ))
Agarwal Ashish5e414792014-06-08 15:25:23 +05309630 {
Agarwal Ashish8dcd2862014-07-25 11:58:52 +05309631 hddLog(VOS_TRACE_LEVEL_INFO,
9632 FL("CountryCode 00 is being set while unloading driver"));
Agarwal Ashish5e414792014-06-08 15:25:23 +05309633 vos_nv_getRegDomainFromCountryCode(&regId , "00", COUNTRY_USER);
9634 }
9635
Jeff Johnson295189b2012-06-20 16:38:30 -07009636 //Do all the cleanup before deregistering the driver
9637 hdd_wlan_exit(pHddCtx);
9638 }
9639
Jeff Johnson295189b2012-06-20 16:38:30 -07009640 vos_preClose( &pVosContext );
9641
9642#ifdef TIMER_MANAGER
9643 vos_timer_exit();
9644#endif
9645#ifdef MEMORY_DEBUG
9646 vos_mem_exit();
9647#endif
9648
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05309649#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
9650 wlan_logging_sock_deinit_svc();
9651#endif
9652
Jeff Johnson295189b2012-06-20 16:38:30 -07009653done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08009654#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07009655 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07009656#endif
Vinay Krishna Eranna273ec5a2014-05-10 18:05:25 +05309657
Jeff Johnson295189b2012-06-20 16:38:30 -07009658 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
9659}
9660
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009661/**---------------------------------------------------------------------------
9662
9663 \brief hdd_module_exit() - Exit function
9664
9665 This is the driver exit point (invoked when module is unloaded using rmmod)
9666
9667 \param - None
9668
9669 \return - None
9670
9671 --------------------------------------------------------------------------*/
9672static void __exit hdd_module_exit(void)
9673{
9674 hdd_driver_exit();
9675}
9676
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009677#ifdef MODULE
9678static int fwpath_changed_handler(const char *kmessage,
9679 struct kernel_param *kp)
9680{
Jeff Johnson76052702013-04-16 13:55:05 -07009681 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009682}
9683
9684static int con_mode_handler(const char *kmessage,
9685 struct kernel_param *kp)
9686{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07009687 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009688}
9689#else /* #ifdef MODULE */
9690/**---------------------------------------------------------------------------
9691
Jeff Johnson76052702013-04-16 13:55:05 -07009692 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009693
Jeff Johnson76052702013-04-16 13:55:05 -07009694 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009695 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07009696 - invoked when module parameter fwpath is modified from userspace to signal
9697 initializing the WLAN driver or when con_mode is modified from userspace
9698 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009699
9700 \return - 0 for success, non zero for failure
9701
9702 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07009703static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009704{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07009705 int ret_status;
9706
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009707 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07009708 ret_status = hdd_driver_init();
9709 wlan_hdd_inited = ret_status ? 0 : 1;
9710 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009711 }
9712
9713 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07009714
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009715 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07009716
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07009717 ret_status = hdd_driver_init();
9718 wlan_hdd_inited = ret_status ? 0 : 1;
9719 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009720}
9721
Jeff Johnson295189b2012-06-20 16:38:30 -07009722/**---------------------------------------------------------------------------
9723
Jeff Johnson76052702013-04-16 13:55:05 -07009724 \brief fwpath_changed_handler() - Handler Function
9725
9726 Handle changes to the fwpath parameter
9727
9728 \return - 0 for success, non zero for failure
9729
9730 --------------------------------------------------------------------------*/
9731static int fwpath_changed_handler(const char *kmessage,
9732 struct kernel_param *kp)
9733{
9734 int ret;
9735
9736 ret = param_set_copystring(kmessage, kp);
9737 if (0 == ret)
9738 ret = kickstart_driver();
9739 return ret;
9740}
9741
9742/**---------------------------------------------------------------------------
9743
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009744 \brief con_mode_handler() -
9745
9746 Handler function for module param con_mode when it is changed by userspace
9747 Dynamically linked - do nothing
9748 Statically linked - exit and init driver, as in rmmod and insmod
9749
Jeff Johnson76052702013-04-16 13:55:05 -07009750 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009751
Jeff Johnson76052702013-04-16 13:55:05 -07009752 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009753
9754 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07009755static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009756{
Jeff Johnson76052702013-04-16 13:55:05 -07009757 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009758
Jeff Johnson76052702013-04-16 13:55:05 -07009759 ret = param_set_int(kmessage, kp);
9760 if (0 == ret)
9761 ret = kickstart_driver();
9762 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009763}
9764#endif /* #ifdef MODULE */
9765
9766/**---------------------------------------------------------------------------
9767
Jeff Johnson295189b2012-06-20 16:38:30 -07009768 \brief hdd_get_conparam() -
9769
9770 This is the driver exit point (invoked when module is unloaded using rmmod)
9771
9772 \param - None
9773
9774 \return - tVOS_CON_MODE
9775
9776 --------------------------------------------------------------------------*/
9777tVOS_CON_MODE hdd_get_conparam ( void )
9778{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009779#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07009780 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009781#else
9782 return (tVOS_CON_MODE)curr_con_mode;
9783#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009784}
9785void hdd_set_conparam ( v_UINT_t newParam )
9786{
9787 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009788#ifndef MODULE
9789 curr_con_mode = con_mode;
9790#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009791}
9792/**---------------------------------------------------------------------------
9793
9794 \brief hdd_softap_sta_deauth() - function
9795
9796 This to take counter measure to handle deauth req from HDD
9797
9798 \param - pAdapter - Pointer to the HDD
9799
9800 \param - enable - boolean value
9801
9802 \return - None
9803
9804 --------------------------------------------------------------------------*/
9805
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009806VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07009807{
Jeff Johnson295189b2012-06-20 16:38:30 -07009808 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009809 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07009810
9811 ENTER();
9812
Rajesh Chauhan18488fc2013-08-22 10:15:03 -07009813 hddLog(LOG1, "hdd_softap_sta_deauth:(%p, false)",
9814 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07009815
9816 //Ignore request to deauth bcmc station
9817 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009818 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07009819
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009820 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07009821
9822 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009823 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07009824}
9825
9826/**---------------------------------------------------------------------------
9827
Rashmi Ramanna1f0948d2014-08-28 15:33:48 +05309828 \brief hdd_del_all_sta() - function
9829
9830 This function removes all the stations associated on stopping AP/P2P GO.
9831
9832 \param - pAdapter - Pointer to the HDD
9833
9834 \return - None
9835
9836 --------------------------------------------------------------------------*/
9837
9838int hdd_del_all_sta(hdd_adapter_t *pAdapter)
9839{
9840 v_U16_t i;
9841 VOS_STATUS vos_status;
9842
9843 ENTER();
9844
9845 hddLog(VOS_TRACE_LEVEL_INFO,
9846 "%s: Delete all STAs associated.",__func__);
9847 if ((pAdapter->device_mode == WLAN_HDD_SOFTAP)
9848 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
9849 )
9850 {
9851 for(i = 0; i < WLAN_MAX_STA_COUNT; i++)
9852 {
9853 if ((pAdapter->aStaInfo[i].isUsed) &&
9854 (!pAdapter->aStaInfo[i].isDeauthInProgress))
9855 {
9856 u8 *macAddr = pAdapter->aStaInfo[i].macAddrSTA.bytes;
9857 hddLog(VOS_TRACE_LEVEL_ERROR,
9858 "%s: Delete STA with staid = %d and MAC::"
9859 MAC_ADDRESS_STR,
9860 __func__, i, MAC_ADDR_ARRAY(macAddr));
9861 vos_status = hdd_softap_sta_deauth(pAdapter, macAddr);
9862 if (VOS_IS_STATUS_SUCCESS(vos_status))
9863 pAdapter->aStaInfo[i].isDeauthInProgress = TRUE;
9864 }
9865 }
9866 }
9867
9868 EXIT();
9869 return 0;
9870}
9871
9872/**---------------------------------------------------------------------------
9873
Jeff Johnson295189b2012-06-20 16:38:30 -07009874 \brief hdd_softap_sta_disassoc() - function
9875
9876 This to take counter measure to handle deauth req from HDD
9877
9878 \param - pAdapter - Pointer to the HDD
9879
9880 \param - enable - boolean value
9881
9882 \return - None
9883
9884 --------------------------------------------------------------------------*/
9885
9886void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
9887{
9888 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
9889
9890 ENTER();
9891
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05309892 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07009893
9894 //Ignore request to disassoc bcmc station
9895 if( pDestMacAddress[0] & 0x1 )
9896 return;
9897
9898 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
9899}
9900
9901void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
9902{
9903 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
9904
9905 ENTER();
9906
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05309907 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07009908
9909 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
9910}
9911
Jeff Johnson295189b2012-06-20 16:38:30 -07009912/**---------------------------------------------------------------------------
9913 *
9914 * \brief hdd_get__concurrency_mode() -
9915 *
9916 *
9917 * \param - None
9918 *
9919 * \return - CONCURRENCY MODE
9920 *
9921 * --------------------------------------------------------------------------*/
9922tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
9923{
9924 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
9925 hdd_context_t *pHddCtx;
9926
9927 if (NULL != pVosContext)
9928 {
9929 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
9930 if (NULL != pHddCtx)
9931 {
9932 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
9933 }
9934 }
9935
9936 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07009937 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009938 return VOS_STA;
9939}
Sushant Kaushikabb7ee62014-07-18 16:20:12 +05309940v_BOOL_t
9941wlan_hdd_is_GO_power_collapse_allowed (hdd_context_t* pHddCtx)
9942{
9943 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07009944
Sushant Kaushikabb7ee62014-07-18 16:20:12 +05309945 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_GO);
9946 if (pAdapter == NULL)
9947 {
9948 hddLog(VOS_TRACE_LEVEL_INFO,
9949 FL("GO doesn't exist"));
9950 return TRUE;
9951 }
9952 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
9953 {
9954 hddLog(VOS_TRACE_LEVEL_INFO,
9955 FL("GO started"));
9956 return TRUE;
9957 }
9958 else
9959 /* wait till GO changes its interface to p2p device */
9960 hddLog(VOS_TRACE_LEVEL_INFO,
9961 FL("Del_bss called, avoid apps suspend"));
9962 return FALSE;
9963
9964}
Jeff Johnson295189b2012-06-20 16:38:30 -07009965/* Decide whether to allow/not the apps power collapse.
9966 * Allow apps power collapse if we are in connected state.
9967 * if not, allow only if we are in IMPS */
9968v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
9969{
9970 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08009971 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08009972 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07009973 hdd_config_t *pConfig = pHddCtx->cfg_ini;
9974 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
9975 hdd_adapter_t *pAdapter = NULL;
9976 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08009977 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07009978
Jeff Johnson295189b2012-06-20 16:38:30 -07009979 if (VOS_STA_SAP_MODE == hdd_get_conparam())
9980 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07009981
Yathish9f22e662012-12-10 14:21:35 -08009982 concurrent_state = hdd_get_concurrency_mode();
9983
Sushant Kaushikabb7ee62014-07-18 16:20:12 +05309984 if ((concurrent_state == (VOS_STA | VOS_P2P_GO)) &&
9985 !(wlan_hdd_is_GO_power_collapse_allowed(pHddCtx)))
9986 return FALSE;
Yathish9f22e662012-12-10 14:21:35 -08009987#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
Sushant Kaushikabb7ee62014-07-18 16:20:12 +05309988
Yathish9f22e662012-12-10 14:21:35 -08009989 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
Sushant Kaushikabb7ee62014-07-18 16:20:12 +05309990 (concurrent_state == (VOS_STA | VOS_P2P_GO)))&&
Yathish9f22e662012-12-10 14:21:35 -08009991 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
9992 return TRUE;
9993#endif
9994
Jeff Johnson295189b2012-06-20 16:38:30 -07009995 /*loop through all adapters. TBD fix for Concurrency */
9996 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
9997 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
9998 {
9999 pAdapter = pAdapterNode->pAdapter;
10000 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
10001 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
10002 {
Srikant Kuppafef66a72013-01-30 17:32:44 -080010003 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
c_hpothu4e8faac2014-05-16 17:38:44 +053010004 && (pmcState != IMPS && pmcState != BMPS && pmcState != UAPSD
Srikant Kuppafef66a72013-01-30 17:32:44 -080010005 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -080010006 (eANI_BOOLEAN_TRUE == scanRspPending) ||
10007 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -070010008 {
Srikant Kuppafef66a72013-01-30 17:32:44 -080010009 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -080010010 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
10011 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -070010012 return FALSE;
10013 }
10014 }
10015 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10016 pAdapterNode = pNext;
10017 }
10018 return TRUE;
10019}
10020
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -080010021/* Decides whether to send suspend notification to Riva
10022 * if any adapter is in BMPS; then it is required */
10023v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
10024{
10025 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
10026 hdd_config_t *pConfig = pHddCtx->cfg_ini;
10027
10028 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
10029 {
10030 return TRUE;
10031 }
10032 return FALSE;
10033}
10034
Jeff Johnson295189b2012-06-20 16:38:30 -070010035void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
10036{
10037 switch(mode)
10038 {
Chilam Ngc4244af2013-04-01 15:37:32 -070010039 case VOS_STA_MODE:
10040 case VOS_P2P_CLIENT_MODE:
10041 case VOS_P2P_GO_MODE:
10042 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -070010043 pHddCtx->concurrency_mode |= (1 << mode);
Agarwal Ashish51325b52014-06-16 16:50:49 +053010044 pHddCtx->no_of_open_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -070010045 break;
10046 default:
10047 break;
Jeff Johnson295189b2012-06-20 16:38:30 -070010048 }
Agarwal Ashish51325b52014-06-16 16:50:49 +053010049 hddLog(VOS_TRACE_LEVEL_INFO, FL("concurrency_mode = 0x%x "
10050 "Number of open sessions for mode %d = %d"),
10051 pHddCtx->concurrency_mode, mode,
10052 pHddCtx->no_of_open_sessions[mode]);
Jeff Johnson295189b2012-06-20 16:38:30 -070010053}
10054
10055
10056void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
10057{
10058 switch(mode)
10059 {
Chilam Ngc4244af2013-04-01 15:37:32 -070010060 case VOS_STA_MODE:
10061 case VOS_P2P_CLIENT_MODE:
10062 case VOS_P2P_GO_MODE:
10063 case VOS_STA_SAP_MODE:
Agarwal Ashish51325b52014-06-16 16:50:49 +053010064 pHddCtx->no_of_open_sessions[mode]--;
10065 if (!(pHddCtx->no_of_open_sessions[mode]))
10066 pHddCtx->concurrency_mode &= (~(1 << mode));
Jeff Johnson295189b2012-06-20 16:38:30 -070010067 break;
10068 default:
10069 break;
10070 }
Agarwal Ashish51325b52014-06-16 16:50:49 +053010071 hddLog(VOS_TRACE_LEVEL_INFO, FL("concurrency_mode = 0x%x "
10072 "Number of open sessions for mode %d = %d"),
10073 pHddCtx->concurrency_mode, mode, pHddCtx->no_of_open_sessions[mode]);
10074
10075}
10076/**---------------------------------------------------------------------------
10077 *
10078 * \brief wlan_hdd_incr_active_session()
10079 *
10080 * This function increments the number of active sessions
10081 * maintained per device mode
10082 * Incase of STA/P2P CLI/IBSS upon connection indication it is incremented
10083 * Incase of SAP/P2P GO upon bss start it is incremented
10084 *
10085 * \param pHddCtx - HDD Context
10086 * \param mode - device mode
10087 *
10088 * \return - None
10089 *
10090 * --------------------------------------------------------------------------*/
10091void wlan_hdd_incr_active_session(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
10092{
10093 switch (mode) {
10094 case VOS_STA_MODE:
10095 case VOS_P2P_CLIENT_MODE:
10096 case VOS_P2P_GO_MODE:
10097 case VOS_STA_SAP_MODE:
10098 pHddCtx->no_of_active_sessions[mode]++;
10099 break;
10100 default:
10101 hddLog(VOS_TRACE_LEVEL_INFO, FL("Not Expected Mode %d"), mode);
10102 break;
10103 }
10104 hddLog(VOS_TRACE_LEVEL_INFO, FL("No.# of active sessions for mode %d = %d"),
10105 mode,
10106 pHddCtx->no_of_active_sessions[mode]);
10107}
10108
10109/**---------------------------------------------------------------------------
10110 *
10111 * \brief wlan_hdd_decr_active_session()
10112 *
10113 * This function decrements the number of active sessions
10114 * maintained per device mode
10115 * Incase of STA/P2P CLI/IBSS upon disconnection it is decremented
10116 * Incase of SAP/P2P GO upon bss stop it is decremented
10117 *
10118 * \param pHddCtx - HDD Context
10119 * \param mode - device mode
10120 *
10121 * \return - None
10122 *
10123 * --------------------------------------------------------------------------*/
10124void wlan_hdd_decr_active_session(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
10125{
10126 switch (mode) {
10127 case VOS_STA_MODE:
10128 case VOS_P2P_CLIENT_MODE:
10129 case VOS_P2P_GO_MODE:
10130 case VOS_STA_SAP_MODE:
Agarwal Ashish5325f522014-08-06 00:58:44 +053010131 if (pHddCtx->no_of_active_sessions[mode] > 0)
10132 pHddCtx->no_of_active_sessions[mode]--;
10133 else
10134 hddLog(VOS_TRACE_LEVEL_INFO, FL(" No.# of Active sessions"
10135 "is already Zero"));
Agarwal Ashish51325b52014-06-16 16:50:49 +053010136 break;
10137 default:
10138 hddLog(VOS_TRACE_LEVEL_INFO, FL("Not Expected Mode %d"), mode);
10139 break;
10140 }
10141 hddLog(VOS_TRACE_LEVEL_INFO, FL("No.# of active sessions for mode %d = %d"),
10142 mode,
10143 pHddCtx->no_of_active_sessions[mode]);
Jeff Johnson295189b2012-06-20 16:38:30 -070010144}
10145
Jeff Johnsone7245742012-09-05 17:12:55 -070010146/**---------------------------------------------------------------------------
10147 *
10148 * \brief wlan_hdd_restart_init
10149 *
10150 * This function initalizes restart timer/flag. An internal function.
10151 *
10152 * \param - pHddCtx
10153 *
10154 * \return - None
10155 *
10156 * --------------------------------------------------------------------------*/
10157
10158static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
10159{
10160 /* Initialize */
10161 pHddCtx->hdd_restart_retries = 0;
10162 atomic_set(&pHddCtx->isRestartInProgress, 0);
10163 vos_timer_init(&pHddCtx->hdd_restart_timer,
10164 VOS_TIMER_TYPE_SW,
10165 wlan_hdd_restart_timer_cb,
10166 pHddCtx);
10167}
10168/**---------------------------------------------------------------------------
10169 *
10170 * \brief wlan_hdd_restart_deinit
10171 *
10172 * This function cleans up the resources used. An internal function.
10173 *
10174 * \param - pHddCtx
10175 *
10176 * \return - None
10177 *
10178 * --------------------------------------------------------------------------*/
10179
10180static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
10181{
10182
10183 VOS_STATUS vos_status;
10184 /* Block any further calls */
10185 atomic_set(&pHddCtx->isRestartInProgress, 1);
10186 /* Cleanup */
10187 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
10188 if (!VOS_IS_STATUS_SUCCESS(vos_status))
c_hpothu6ff1c3c2013-10-01 19:01:57 +053010189 hddLog(LOGE, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -070010190 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
10191 if (!VOS_IS_STATUS_SUCCESS(vos_status))
c_hpothu6ff1c3c2013-10-01 19:01:57 +053010192 hddLog(LOGE, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -070010193
10194}
10195
10196/**---------------------------------------------------------------------------
10197 *
10198 * \brief wlan_hdd_framework_restart
10199 *
10200 * This function uses a cfg80211 API to start a framework initiated WLAN
10201 * driver module unload/load.
10202 *
10203 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
10204 *
10205 *
10206 * \param - pHddCtx
10207 *
10208 * \return - VOS_STATUS_SUCCESS: Success
10209 * VOS_STATUS_E_EMPTY: Adapter is Empty
10210 * VOS_STATUS_E_NOMEM: No memory
10211
10212 * --------------------------------------------------------------------------*/
10213
10214static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
10215{
10216 VOS_STATUS status = VOS_STATUS_SUCCESS;
10217 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -070010218 int len = (sizeof (struct ieee80211_mgmt));
10219 struct ieee80211_mgmt *mgmt = NULL;
10220
10221 /* Prepare the DEAUTH managment frame with reason code */
10222 mgmt = kzalloc(len, GFP_KERNEL);
10223 if(mgmt == NULL)
10224 {
10225 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
10226 "%s: memory allocation failed (%d bytes)", __func__, len);
10227 return VOS_STATUS_E_NOMEM;
10228 }
10229 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -070010230
10231 /* Iterate over all adapters/devices */
10232 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
10233 do
10234 {
10235 if( (status == VOS_STATUS_SUCCESS) &&
10236 pAdapterNode &&
10237 pAdapterNode->pAdapter)
10238 {
10239 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
10240 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
10241 pAdapterNode->pAdapter->dev->name,
10242 pAdapterNode->pAdapter->device_mode,
10243 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -070010244 /*
10245 * CFG80211 event to restart the driver
10246 *
10247 * 'cfg80211_send_unprot_deauth' sends a
10248 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
10249 * of SME(Linux Kernel) state machine.
10250 *
10251 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
10252 * the driver.
10253 *
10254 */
10255
10256 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -070010257 }
10258 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
10259 pAdapterNode = pNext;
10260 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
10261
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -070010262
10263 /* Free the allocated management frame */
10264 kfree(mgmt);
10265
Jeff Johnsone7245742012-09-05 17:12:55 -070010266 /* Retry until we unload or reach max count */
10267 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
10268 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
10269
10270 return status;
10271
10272}
10273/**---------------------------------------------------------------------------
10274 *
10275 * \brief wlan_hdd_restart_timer_cb
10276 *
10277 * Restart timer callback. An internal function.
10278 *
10279 * \param - User data:
10280 *
10281 * \return - None
10282 *
10283 * --------------------------------------------------------------------------*/
10284
10285void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
10286{
10287 hdd_context_t *pHddCtx = usrDataForCallback;
10288 wlan_hdd_framework_restart(pHddCtx);
10289 return;
10290
10291}
10292
10293
10294/**---------------------------------------------------------------------------
10295 *
10296 * \brief wlan_hdd_restart_driver
10297 *
10298 * This function sends an event to supplicant to restart the WLAN driver.
10299 *
10300 * This function is called from vos_wlanRestart.
10301 *
10302 * \param - pHddCtx
10303 *
10304 * \return - VOS_STATUS_SUCCESS: Success
10305 * VOS_STATUS_E_EMPTY: Adapter is Empty
10306 * VOS_STATUS_E_ALREADY: Request already in progress
10307
10308 * --------------------------------------------------------------------------*/
10309VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
10310{
10311 VOS_STATUS status = VOS_STATUS_SUCCESS;
10312
10313 /* A tight check to make sure reentrancy */
10314 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
10315 {
Mihir Shetefd528652014-06-23 19:07:50 +053010316 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnsone7245742012-09-05 17:12:55 -070010317 "%s: WLAN restart is already in progress", __func__);
10318
10319 return VOS_STATUS_E_ALREADY;
10320 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -070010321 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -080010322#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -070010323 wcnss_reset_intr();
10324#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -070010325
Jeff Johnsone7245742012-09-05 17:12:55 -070010326 return status;
10327}
10328
Mihir Shetee1093ba2014-01-21 20:13:32 +053010329/**---------------------------------------------------------------------------
10330 *
10331 * \brief wlan_hdd_init_channels
10332 *
10333 * This function is used to initialize the channel list in CSR
10334 *
10335 * This function is called from hdd_wlan_startup
10336 *
10337 * \param - pHddCtx: HDD context
10338 *
10339 * \return - VOS_STATUS_SUCCESS: Success
10340 * VOS_STATUS_E_FAULT: Failure reported by SME
10341
10342 * --------------------------------------------------------------------------*/
10343static VOS_STATUS wlan_hdd_init_channels(hdd_context_t *pHddCtx)
10344{
10345 eHalStatus status;
10346
10347 status = sme_InitChannels(pHddCtx->hHal);
10348 if (HAL_STATUS_SUCCESS(status))
10349 {
10350 return VOS_STATUS_SUCCESS;
10351 }
10352 else
10353 {
10354 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Channel initialization failed(%d)",
10355 __func__, status);
10356 return VOS_STATUS_E_FAULT;
10357 }
10358}
10359
Mahesh A Saptasagar74289d22014-05-14 12:43:37 +053010360static VOS_STATUS wlan_hdd_init_channels_for_cc(hdd_context_t *pHddCtx)
10361{
10362 eHalStatus status;
10363
10364 status = sme_InitChannelsForCC(pHddCtx->hHal);
10365 if (HAL_STATUS_SUCCESS(status))
10366 {
10367 return VOS_STATUS_SUCCESS;
10368 }
10369 else
10370 {
10371 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Issue reg hint failed(%d)",
10372 __func__, status);
10373 return VOS_STATUS_E_FAULT;
10374 }
10375}
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -070010376/*
10377 * API to find if there is any STA or P2P-Client is connected
10378 */
10379VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
10380{
10381 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
10382}
Jeff Johnsone7245742012-09-05 17:12:55 -070010383
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053010384int wlan_hdd_scan_abort(hdd_adapter_t *pAdapter)
10385{
10386 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10387 hdd_scaninfo_t *pScanInfo = NULL;
Girish Gowli4bf7a632014-06-12 13:42:11 +053010388 long status = 0;
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053010389
10390 pScanInfo = &pHddCtx->scan_info;
10391 if (pScanInfo->mScanPending)
10392 {
10393 INIT_COMPLETION(pScanInfo->abortscan_event_var);
10394 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
10395 eCSR_SCAN_ABORT_DEFAULT);
10396
10397 status = wait_for_completion_interruptible_timeout(
10398 &pScanInfo->abortscan_event_var,
10399 msecs_to_jiffies(5000));
Girish Gowli4bf7a632014-06-12 13:42:11 +053010400 if (0 >= status)
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053010401 {
10402 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Girish Gowli4bf7a632014-06-12 13:42:11 +053010403 "%s: Timeout or Interrupt occurred while waiting for abort"
10404 "scan, status- %ld", __func__, status);
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053010405 return -ETIMEDOUT;
10406 }
10407 }
Girish Gowli4bf7a632014-06-12 13:42:11 +053010408 return 0;
Mahesh A Saptasagar2395ee62014-05-21 19:12:21 +053010409}
10410
Jeff Johnson295189b2012-06-20 16:38:30 -070010411//Register the module init/exit functions
10412module_init(hdd_module_init);
10413module_exit(hdd_module_exit);
10414
10415MODULE_LICENSE("Dual BSD/GPL");
10416MODULE_AUTHOR("Qualcomm Atheros, Inc.");
10417MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
10418
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -070010419module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
10420 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -070010421
Jeff Johnson76052702013-04-16 13:55:05 -070010422module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -070010423 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Arif Hussain66559122013-11-21 10:11:40 -080010424
10425module_param(enable_dfs_chan_scan, int,
10426 S_IRUSR | S_IRGRP | S_IROTH);
10427
10428module_param(enable_11d, int,
10429 S_IRUSR | S_IRGRP | S_IROTH);
10430
10431module_param(country_code, charp,
10432 S_IRUSR | S_IRGRP | S_IROTH);